[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "# Adopt swift-format\nc9756e108351a1def2e2c83ff5ee6fb9bcbc3bbf\n"
  },
  {
    "path": ".gitattributes",
    "content": "Sources/CNIOHTTPParser/* linguist-vendored\nSources/CNIOSHA1/* linguist-vendored\nSources/CNIOLinux/ifaddrs-* linguist-vendored\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "content": "---\nname: Bug Report\nabout: File a bug report to help us improve\n---\n\n### Expected behavior\n_[what you expected to happen]_\n\n### Actual behavior\n_[what actually happened]_\n\n### Steps to reproduce\n\n1. ...\n2. ...\n\n### If possible, minimal yet complete reproducer code (or URL to code)\n\n_[anything to help us reproducing the issue]_\n\n### SwiftNIO version/commit hash\n\n_[the SwiftNIO tag/commit hash]_\n\n### System & version information\n\nPlease provide at the very least your operating system and Swift version\ninformation.\n\nIdeally, run\n\n```\nscripts/nio-diagnose -o nio-diagnose.md PID_OF_YOUR_NIO_PROGRAM\n```\n\nand attach (or paste) the resulting file `nio-diagnose.md` into this bug report\nor send it to the SwiftNIO maintainers privately.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "_[One line description of your change]_\n\n### Motivation:\n\n_[Explain here the context, and why you're making that change. What is the problem you're trying to solve.]_\n\n### Modifications:\n\n_[Describe the modifications you've done.]_\n\n### Result:\n\n_[After your change, what will change.]_\n"
  },
  {
    "path": ".github/actions/pull_request_semver_label_checker/action.yml",
    "content": "name: 'Pull request Semantic Version label checker'\n\ndescription: 'Checks that at least one Semantic Version label is applied to the pull request'\n\ninputs:\n  token:\n    description: 'A GitHub token'\n    type: string\n    default: ${{ github.token }}\n\nruns:\n  using: \"composite\"\n  steps:\n    - name: Check labels\n      if: ${{ !env.ACT }}\n      shell: bash\n      env:\n        GH_TOKEN: ${{ inputs.token }}\n      run: |\n        gh pr view ${{ github.event.number }} --repo ${{ github.repository }} --json labels \\\n        | jq -e '[.labels[].name] | any(. == \"⚠️ semver/major\" or . == \"🆕 semver/minor\" or . == \"🔨 semver/patch\" or . == \"semver/none\")'\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/release.yml",
    "content": "changelog:\n  categories:\n    - title: SemVer Major\n      labels:\n        - ⚠️ semver/major\n    - title: SemVer Minor\n      labels:\n        - 🆕 semver/minor\n    - title: SemVer Patch\n      labels:\n        - 🔨 semver/patch\n    - title: Other Changes\n      labels:\n        - semver/none\n"
  },
  {
    "path": ".github/workflows/android_swift_sdk.yml",
    "content": "name: Android Swift SDK\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      env_vars:\n        type: string\n        description: \"Environment variables for jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n      additional_command_arguments:\n        type: string\n        description: \"Additional arguments passed to swift build (the Android Swift SDK will be specified). Defaults to empty.\"\n        default: \"\"\n\njobs:\n  construct-matrix:\n    name: Construct Android Swift SDK matrix\n    runs-on: ubuntu-latest\n    outputs:\n      android-sdk-matrix: '${{ steps.generate-matrix.outputs.android-sdk-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate and use JSON environment variables directly\n          env_vars_json=\"$INPUT_ENV_VARS\"\n\n          # Validate JSON format\n          if ! echo \"$env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          # Generate matrix with parsed environment variables\n          cat >> \"$GITHUB_OUTPUT\" << EOM\n          android-sdk-matrix=$(echo '{\n            \"config\":[\n              {\n                \"name\":\"main Jammy\",\n                \"swift_version\":\"main\",\n                \"platform\":\"Linux\",\n                \"runner\":\"ubuntu-latest\",\n                \"image\":\"ubuntu:jammy\",\n                \"setup_command\":\"apt update -q && apt install -y -q curl jq tar && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_prerequisites.sh | bash && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_sdk.sh | INSTALL_SWIFT_BRANCH=main INSTALL_SWIFT_ARCH=x86_64 INSTALL_SWIFT_SDK=android-sdk bash && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_android_ndk.sh | bash && hash -r\",\n                \"command\":\"curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/swift-build-with-android-sdk.sh | bash -s --\",\n                \"command_arguments\":\"'\"$INPUT_ADDITIONAL_COMMAND_ARGUMENTS\"'\",\n                \"env\":'\"$env_vars_json\"'\n              }\n            ]\n          }' | jq -c)\n          EOM\n        env:\n          INPUT_ENV_VARS: ${{ inputs.env_vars }}\n          INPUT_ADDITIONAL_COMMAND_ARGUMENTS: ${{ inputs.additional_command_arguments }}\n\n  android-swift-sdk:\n    name: Android Swift SDK\n    needs: construct-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Android Swift SDK\"\n      matrix_string: '${{ needs.construct-matrix.outputs.android-sdk-matrix }}'\n"
  },
  {
    "path": ".github/workflows/benchmarks.yml",
    "content": "name: Benchmarks\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      benchmark_package_path:\n        type: string\n        description: \"Path to the directory containing the benchmarking package. Defaults to .\"\n        default: \".\"\n      swift_package_arguments:\n        type: string\n        description: \"Arguments to the switch package command invocation e.g. `--disable-sandbox`\"\n      linux_5_9_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.9 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_5_10_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.10 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.0 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.1 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.2 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: false\n      linux_nightly_6_1_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, use linux_nightly_next_enabled.\"\n        default: true\n      linux_nightly_next_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux nightly matrix job for the next Swift version. Defaults to true.\"\n        default: true\n      linux_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux nightly main Swift version matrix job. Defaults to true.\"\n        default: true\n\n      windows_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.0 Swift version matrix job. Currently has no effect!\"  # TODO: implement Windows benchmarking\n        default: false\n      windows_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.1 Swift version matrix job. Currently has no effect!\"  # TODO: implement Windows benchmarking\n        default: false\n      windows_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.2 Swift version matrix job. Currently has no effect!\"  # TODO: implement Windows benchmarking\n        default: false\n      windows_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"  # TODO: implement Windows benchmarking\n        default: false\n      windows_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows nightly main Swift version matrix job. Currently has no effect!\"  # TODO: implement Windows benchmarking\n        default: false\n\n      linux_env_vars:\n        type: string\n        description: \"Environment variables for Linux jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n\n      minimum_swift_version:\n        type: string\n        description: \"Minimum Swift version to include in the matrix. Leave empty for auto-detection from Package.swift, specify a version like '6.0' to override, or set to 'none' to disable filtering.\"\n        default: \"\"\n\njobs:\n  construct-matrix-linux:\n    name: Construct Linux Benchmarks matrix\n    runs-on: ubuntu-latest\n    outputs:\n      benchmarks-matrix: '${{ steps.generate-matrix.outputs.benchmarks-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate JSON environment variables\n          linux_env_vars_json=\"$INPUT_LINUX_ENV_VARS\"\n\n          if ! echo \"$linux_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: linux_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          echo \"benchmarks-matrix=$(curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | MATRIX_LINUX_ENV_VARS_JSON=\"${linux_env_vars_json}\" bash)\" >> \"$GITHUB_OUTPUT\"\n        env:\n          INPUT_LINUX_ENV_VARS: ${{ inputs.linux_env_vars }}\n          MATRIX_LINUX_COMMAND: \"curl -s https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check_benchmark_thresholds.sh | BENCHMARK_PACKAGE_PATH=${{ inputs.benchmark_package_path }} bash\"\n          MATRIX_LINUX_SETUP_COMMAND: \"swift --version && apt-get update -y -q && apt-get install -y -q curl libjemalloc-dev && git config --global --add safe.directory /$(basename ${{ github.workspace }})\"\n          MATRIX_MIN_SWIFT_VERSION: ${{ inputs.minimum_swift_version }}\n          MATRIX_LINUX_5_9_ENABLED: ${{ inputs.linux_5_9_enabled }}\n          MATRIX_LINUX_5_10_ENABLED: ${{ inputs.linux_5_10_enabled }}\n          MATRIX_LINUX_6_0_ENABLED: ${{ inputs.linux_6_0_enabled }}\n          MATRIX_LINUX_6_1_ENABLED: ${{ inputs.linux_6_1_enabled }}\n          MATRIX_LINUX_6_2_ENABLED: ${{ inputs.linux_6_2_enabled }}\n          MATRIX_LINUX_NIGHTLY_NEXT_ENABLED: ${{ inputs.linux_nightly_6_1_enabled && inputs.linux_nightly_next_enabled  }}\n          MATRIX_LINUX_NIGHTLY_MAIN_ENABLED: ${{ inputs.linux_nightly_main_enabled }}\n\n  benchmarks-linux:\n    name: Benchmarks\n    needs: construct-matrix-linux\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Benchmarks\"\n      matrix_string: '${{ needs.construct-matrix-linux.outputs.benchmarks-matrix }}'\n"
  },
  {
    "path": ".github/workflows/cmake_tests.yml",
    "content": "name: CMake build\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      update_cmake_lists_config:\n        type: string\n        description: \"The configuration used when updating the CMake lists.\"\n        required: true\n      cmake_build_target_directory:\n        type: string\n        description: \"The directory to pass to `cmake build`.\"\n        default: \".\"\n      cmake_version:\n        type: string\n        description: \"The version of CMake to install.\"\n        default: \"\"\n      image:\n        type: string\n        description: \"The docker image to run the checks in.\"\n        default: \"swift:6.0-jammy\"\n\njobs:\n  cmake-checks:\n    name: CMake checks\n    runs-on: ubuntu-latest\n    container:\n      image: ${{ inputs.image }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Mark the workspace as safe\n        # https://github.com/actions/checkout/issues/766\n        run: git config --global --add safe.directory ${GITHUB_WORKSPACE}\n      - name: Check CMakeLists files\n        run: |\n          which curl jq || apt -q update\n          which curl || apt -yq install curl\n          which jq || apt -yq install jq\n          curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/update-cmake-lists.sh | CONFIG_JSON=\"$INPUT_UPDATE_CMAKE_LISTS_CONFIG\" FAIL_ON_CHANGES=true bash\n        env:\n          INPUT_UPDATE_CMAKE_LISTS_CONFIG: ${{ inputs.update_cmake_lists_config }}\n      - name: CMake build\n        run: |\n          which curl cmake ninja || apt -q update\n          which curl || apt -yq install curl\n          which cmake || apt -yq install cmake\n          which ninja || apt -yq install ninja-build\n          curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/cmake-build.sh | TARGET_DIRECTORY=\"$INPUT_CMAKE_BUILD_TARGET_DIRECTORY\" CMAKE_VERSION=\"$INPUT_CMAKE_VERSION\" bash\n        env:\n          INPUT_CMAKE_BUILD_TARGET_DIRECTORY: ${{ inputs.cmake_build_target_directory }}\n          INPUT_CMAKE_VERSION: ${{ inputs.cmake_version }}\n"
  },
  {
    "path": ".github/workflows/cxx_interop.yml",
    "content": "name: Cxx interop\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      linux_5_9_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.9 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_5_10_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.10 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.0 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.1 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.2 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: false\n      linux_nightly_6_1_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, use linux_nightly_next_enabled.\"\n        default: true\n      linux_nightly_next_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux matrix job using the nightly build for the next Swift version. Defaults to true.\"\n        default: true\n      linux_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux nightly main Swift version matrix job. Defaults to true.\"\n        default: true\n\n      windows_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.0 Swift version matrix job. Defaults to false. Currently has no effect!\"  # TODO: implement Windows Cxx compat checking\n        default: false\n      windows_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.1 Swift version matrix job. Defaults to false. Currently has no effect!\"  # TODO: implement Windows Cxx compat checking\n        default: false\n      windows_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.2 Swift version matrix job. Defaults to false. Currently has no effect!\"  # TODO: implement Windows Cxx compat checking\n        default: false\n      windows_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"  # TODO: implement Windows Cxx compat checking\n        default: false\n      windows_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows nightly main Swift version matrix job. Defaults to false. Currently has no effect!\"  # TODO: implement Windows Cxx compat checking\n        default: false\n\n      linux_env_vars:\n        type: string\n        description: \"Environment variables for Linux jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n      windows_env_vars:\n        type: string\n        description: \"Environment variables for Windows jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n\n      minimum_swift_version:\n        type: string\n        description: \"Minimum Swift version to include in the matrix. Leave empty for auto-detection from Package.swift, specify a version like '6.0' to override, or set to 'none' to disable filtering.\"\n        default: \"\"\n\njobs:\n  construct-matrix:\n    name: Construct Cxx interop matrix\n    runs-on: ubuntu-latest\n    outputs:\n      cxx-interop-matrix: '${{ steps.generate-matrix.outputs.cxx-interop-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate JSON environment variables\n          linux_env_vars_json=\"$INPUT_LINUX_ENV_VARS\"\n          windows_env_vars_json=\"$INPUT_WINDOWS_ENV_VARS\"\n\n          if ! echo \"$linux_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: linux_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          if ! echo \"$windows_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: windows_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          echo \"cxx-interop-matrix=$(curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | MATRIX_LINUX_ENV_VARS_JSON=\"${linux_env_vars_json}\" MATRIX_WINDOWS_ENV_VARS_JSON=\"${windows_env_vars_json}\" bash)\" >> \"$GITHUB_OUTPUT\"\n        env:\n          INPUT_LINUX_ENV_VARS: ${{ inputs.linux_env_vars }}\n          INPUT_WINDOWS_ENV_VARS: ${{ inputs.windows_env_vars }}\n          MATRIX_LINUX_COMMAND: \"curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check-cxx-interop-compatibility.sh | bash\"\n          MATRIX_LINUX_SETUP_COMMAND: \"swift --version && apt-get update -y -q && apt-get install -y -q curl jq\"\n          MATRIX_MIN_SWIFT_VERSION: ${{ inputs.minimum_swift_version }}\n          MATRIX_LINUX_5_9_ENABLED: ${{ inputs.linux_5_9_enabled }}\n          MATRIX_LINUX_5_10_ENABLED: ${{ inputs.linux_5_10_enabled }}\n          MATRIX_LINUX_6_0_ENABLED: ${{ inputs.linux_6_0_enabled }}\n          MATRIX_LINUX_6_1_ENABLED: ${{ inputs.linux_6_1_enabled }}\n          MATRIX_LINUX_6_2_ENABLED: ${{ inputs.linux_6_2_enabled }}\n          MATRIX_LINUX_NIGHTLY_NEXT_ENABLED: ${{ inputs.linux_nightly_6_1_enabled && inputs.linux_nightly_next_enabled }}\n          MATRIX_LINUX_NIGHTLY_MAIN_ENABLED: ${{ inputs.linux_nightly_main_enabled }}\n\n  cxx-interop:\n    name: Cxx interop\n    needs: construct-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Cxx interop\"\n      matrix_string: '${{ needs.construct-matrix.outputs.cxx-interop-matrix }}'\n"
  },
  {
    "path": ".github/workflows/macos_benchmarks.yml",
    "content": "name: macOS benchmarks\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      benchmark_package_path:\n        type: string\n        description: \"Path to the directory containing the benchmarking package. Defaults to .\"\n        default: \".\"\n      swift_package_arguments:\n        type: string\n        description: \"Arguments to the switch package command invocation e.g. `--disable-sandbox`\"\n\n      macos_xcode_16_3_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Xcode 16.3 benchmark job. Defaults to false.\"\n        default: false\n      macos_xcode_16_4_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Xcode 16.4 benchmark job. Defaults to false.\"\n        default: false\n      macos_xcode_26_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Xcode 26.0 benchmark job. Defaults to false.\"\n        default: false\n      macos_xcode_26_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Xcode 26.1 benchmark job. Defaults to false.\"\n        default: false\n      macos_xcode_26_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Xcode 26.2 benchmark job. Defaults to false.\"\n        default: false\n      macos_xcode_latest_beta_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Xcode latest beta benchmark job. Defaults to false.\"\n        default: false\n\n      macos_swift_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Swift 6.1 benchmark job. Defaults to false.\"\n        default: false\n      macos_swift_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Swift 6.2 benchmark job. Defaults to false.\"\n        default: false\n      macos_swift_6_3_enabled:\n        type: boolean\n        description: \"Boolean to enable the macOS Swift 6.3 benchmark job. Defaults to false.\"\n        default: false\n\n      macos_runner_pool:\n        type: string\n        description: \"The runner pool which will be requested for macOS jobs.\"\n        default: \"nightly\"\n\n      macos_env_vars:\n        type: string\n        description: \"Environment variables for macOS jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n\n      minimum_swift_version:\n        type: string\n        description: \"Minimum Swift version to include in the matrix. Leave empty for auto-detection from Package.swift, specify a version like '6.0' to override, or set to 'none' to disable filtering.\"\n        default: \"\"\n\njobs:\n  construct-matrix-macos:\n    name: Construct macOS Benchmarks matrix\n    runs-on: ubuntu-latest\n    if: |\n      inputs.macos_xcode_16_3_enabled ||\n      inputs.macos_xcode_16_4_enabled ||\n      inputs.macos_xcode_26_0_enabled ||\n      inputs.macos_xcode_26_1_enabled ||\n      inputs.macos_xcode_26_2_enabled ||\n      inputs.macos_xcode_latest_beta_enabled ||\n      inputs.macos_swift_6_1_enabled ||\n      inputs.macos_swift_6_2_enabled ||\n      inputs.macos_swift_6_3_enabled\n    outputs:\n      macos-matrix: '${{ steps.generate-matrix.outputs.macos-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate JSON environment variables\n          macos_env_vars_json=\"$INPUT_MACOS_ENV_VARS\"\n\n          if ! echo \"$macos_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: macos_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          runner_pool=\"${MACOS_RUNNER_POOL}\"\n          xcode_16_3_enabled=\"${MACOS_XCODE_16_3_ENABLED}\"\n          xcode_16_4_enabled=\"${MACOS_XCODE_16_4_ENABLED}\"\n          xcode_26_0_enabled=\"${MACOS_XCODE_26_0_ENABLED}\"\n          xcode_26_1_enabled=\"${MACOS_XCODE_26_1_ENABLED}\"\n          xcode_26_2_enabled=\"${MACOS_XCODE_26_2_ENABLED}\"\n          xcode_latest_beta_enabled=\"${MACOS_XCODE_LATEST_BETA_ENABLED}\"\n          swift_6_1_enabled=\"${MACOS_SWIFT_6_1_ENABLED}\"\n          swift_6_2_enabled=\"${MACOS_SWIFT_6_2_ENABLED}\"\n          swift_6_3_enabled=\"${MACOS_SWIFT_6_3_ENABLED}\"\n\n          # Create matrix from inputs\n          matrix='{\"config\": []}'\n\n          if [[ \"$xcode_16_3_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Xcode 16.3)\", \"xcode_version\": \"16.3\", \"xcode_app\": \"Xcode_16.3.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$xcode_16_4_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Xcode 16.4)\", \"xcode_version\": \"16.4\", \"xcode_app\": \"Xcode_16.4.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$xcode_26_0_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Xcode 26.0)\", \"xcode_version\": \"26.0\", \"xcode_app\": \"Xcode_26.0.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$xcode_26_1_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Xcode 26.1)\", \"xcode_version\": \"26.1\", \"xcode_app\": \"Xcode_26.1.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$xcode_26_2_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Xcode 26.2)\", \"xcode_version\": \"26.2\", \"xcode_app\": \"Xcode_26.2.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$xcode_latest_beta_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Xcode latest beta)\", \"xcode_version\": \"latest beta\", \"xcode_app\": \"Xcode-latest.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$swift_6_1_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Swift 6.1)\", \"xcode_version\": \"swift 6.1\", \"xcode_app\": \"Xcode_swift_6.1.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$swift_6_2_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Swift 6.2)\", \"xcode_version\": \"swift 6.2\", \"xcode_app\": \"Xcode_swift_6.2.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          if [[ \"$swift_6_3_enabled\" == \"true\" ]]; then\n              matrix=$(echo \"$matrix\" | jq -c \\\n              --arg runner_pool \"$runner_pool\" \\\n              --argjson env_vars \"$macos_env_vars_json\" \\\n              '.config[.config| length] |= . + { \"name\": \"macOS (Swift 6.3)\", \"xcode_version\": \"swift 6.3\", \"xcode_app\": \"Xcode_swift_6.3.app\", \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n          fi\n\n          echo \"macos-matrix=$matrix\" >> \"$GITHUB_OUTPUT\"\n        env:\n          INPUT_MACOS_ENV_VARS: ${{ inputs.macos_env_vars }}\n          MACOS_RUNNER_POOL: ${{ inputs.macos_runner_pool }}\n          MACOS_XCODE_16_3_ENABLED: ${{ inputs.macos_xcode_16_3_enabled }}\n          MACOS_XCODE_16_4_ENABLED: ${{ inputs.macos_xcode_16_4_enabled }}\n          MACOS_XCODE_26_0_ENABLED: ${{ inputs.macos_xcode_26_0_enabled }}\n          MACOS_XCODE_26_1_ENABLED: ${{ inputs.macos_xcode_26_1_enabled }}\n          MACOS_XCODE_26_2_ENABLED: ${{ inputs.macos_xcode_26_2_enabled }}\n          MACOS_XCODE_LATEST_BETA_ENABLED: ${{ inputs.macos_xcode_latest_beta_enabled }}\n          MACOS_SWIFT_6_1_ENABLED: ${{ inputs.macos_swift_6_1_enabled }}\n          MACOS_SWIFT_6_2_ENABLED: ${{ inputs.macos_swift_6_2_enabled }}\n          MACOS_SWIFT_6_3_ENABLED: ${{ inputs.macos_swift_6_3_enabled }}\n\n  benchmarks-macos:\n    name: ${{ matrix.config.name }}\n    needs: construct-matrix-macos\n    runs-on: [self-hosted, macos, \"${{ matrix.config.os }}\", \"${{ matrix.config.arch }}\", \"${{ matrix.config.pool }}\"]\n    timeout-minutes: 30\n    strategy:\n      fail-fast: false\n      matrix: ${{ fromJson(needs.construct-matrix-macos.outputs.macos-matrix) }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Install jemalloc\n        run: |\n          brew install jemalloc\n      - name: Export environment variables\n        if: ${{ matrix.config.env != '' && matrix.config.env != '{}'}}\n        run: |\n          echo \"Exporting environment variables from matrix configuration...\"\n          echo \"$MATRIX_ENV_JSON\" | jq -r 'to_entries[] | \"\\(.key)=\\(.value)\"' >> $GITHUB_ENV\n          echo \"$MATRIX_ENV_JSON\" | jq -r 'to_entries[] | \"exporting \\(.key)=\\(.value)\"'\n        env:\n          MATRIX_ENV_JSON: ${{ toJSON(matrix.config.env) }}\n      - name: Run benchmarks script\n        run: |\n          curl -s https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check_benchmark_thresholds.sh | BENCHMARK_PACKAGE_PATH=\"$INPUT_BENCHMARK_PACKAGE_PATH\" bash -s -- --disable-sandbox --allow-writing-to-package-directory\n        env:\n          INPUT_BENCHMARK_PACKAGE_PATH: ${{ inputs.benchmark_package_path }}\n          DEVELOPER_DIR: \"/Applications/${{ matrix.config.xcode_app }}\"\n          SWIFT_VERSION: \"Xcode ${{ matrix.config.xcode_version }}\"\n"
  },
  {
    "path": ".github/workflows/macos_tests.yml",
    "content": "name: macOS tests\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      xcode_15_4_enabled:\n        type: boolean\n        description: \"⚠️ Jobs with this version of Xcode are deprecated.\"\n        default: false\n      xcode_15_4_test_arguments_override:\n        type: string\n        description: \"⚠️ Deprecated.\"\n        default: \"\"\n      xcode_16_0_enabled:\n        type: boolean\n        description: \"⚠️ Jobs with this version of Xcode are deprecated.\"\n        default: false\n      xcode_16_0_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the macOS 5.10 Swift version matrix job.\"\n        default: \"\"\n      xcode_16_0_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the macOS 5.10 Swift version matrix job.\"\n        default: \"\"\n      xcode_16_0_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_16_1_enabled:\n        type: boolean\n        description: \"⚠️ Jobs with this version of Xcode are deprecated.\"\n        default: false\n      xcode_16_1_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 16.1 job.\"\n        default: \"\"\n      xcode_16_1_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 16.1 job.\"\n        default: \"\"\n      xcode_16_1_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_16_2_enabled:\n        type: boolean\n        description: \"⚠️ Jobs with this version of Xcode are deprecated.\"\n        default: false\n      xcode_16_2_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 16.2 job.\"\n        default: \"\"\n      xcode_16_2_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 16.2 job.\"\n        default: \"\"\n      xcode_16_2_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_16_3_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode version 16.3 jobs. Defaults to true.\"\n        default: true\n      xcode_16_3_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 16.3 job.\"\n        default: \"\"\n      xcode_16_3_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 16.3 job.\"\n        default: \"\"\n      xcode_16_3_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_16_4_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode version 16.4 jobs. Defaults to true.\"\n        default: true\n      xcode_16_4_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 16.4 job.\"\n        default: \"\"\n      xcode_16_4_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 16.4 job.\"\n        default: \"\"\n      xcode_16_4_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_26_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode version 26.0 jobs. Defaults to true.\"\n        default: true\n      xcode_26_0_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 26.0 job.\"\n        default: \"\"\n      xcode_26_0_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 26.0 job.\"\n        default: \"\"\n      xcode_26_0_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_26_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode version 26.1 jobs. Defaults to true.\"\n        default: true\n      xcode_26_1_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 26.1 job.\"\n        default: \"\"\n      xcode_26_1_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 26.1 job.\"\n        default: \"\"\n      xcode_26_1_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_26_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode version 26.2 jobs. Defaults to true.\"\n        default: true\n      xcode_26_2_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode version 26.2 job.\"\n        default: \"\"\n      xcode_26_2_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode version 26.2 job.\"\n        default: \"\"\n      xcode_26_2_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      xcode_26_beta_enabled:\n        type: boolean\n        description: \"⚠️ Deprecated.\"\n        default: false\n      xcode_26_beta_1_build_arguments_override:\n        type: string\n        description: \"⚠️ Deprecated.\"\n        default: \"\"\n      xcode_26_beta_1_test_arguments_override:\n        type: string\n        description: \"⚠️ Deprecated.\"\n        default: \"\"\n      xcode_26_beta_1_setup_command:\n        type: string\n        description: \"⚠️ Deprecated.\"\n        default: \"\"\n      xcode_latest_beta_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode beta jobs (uses latest beta if one currently exists). Defaults to true.\"\n        default: false\n      xcode_latest_beta_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Xcode beta job.\"\n        default: \"\"\n      xcode_latest_beta_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Xcode beta job.\"\n        default: \"\"\n      xcode_latest_beta_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n\n      swift_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Swift 6.1 jobs. Defaults to false.\"\n        default: false\n      swift_6_1_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Swift 6.1 job.\"\n        default: \"\"\n      swift_6_1_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Swift 6.1 job.\"\n        default: \"\"\n      swift_6_1_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      swift_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Swift 6.2 jobs. Defaults to false.\"\n        default: false\n      swift_6_2_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Swift 6.2 job.\"\n        default: \"\"\n      swift_6_2_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Swift 6.2 job.\"\n        default: \"\"\n      swift_6_2_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n      swift_6_3_enabled:\n        type: boolean\n        description: \"Boolean to enable the Swift 6.3 jobs. Defaults to false.\"\n        default: false\n      swift_6_3_build_arguments_override:\n        type: string\n        description: \"The arguments passed to swift build in the Swift 6.3 job.\"\n        default: \"\"\n      swift_6_3_test_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Swift 6.3 job.\"\n        default: \"\"\n      swift_6_3_setup_command:\n        type: string\n        description: \"The command(s) to be executed before all other work.\"\n        default: \"\"\n\n      build_scheme:\n        type: string\n        description: \"The build scheme used in the Xcode builds.\"\n      swift_test_enabled:\n        type: boolean\n        description: \"Boolean to enable test execution with `swift test`. Defaults to true.\"\n        default: true\n      macos_xcode_build_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode build targeting macOS. Defaults to true.\"\n        default: true\n      macos_xcode_test_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode test targeting macOS. Defaults to false.\"\n        default: false\n      ios_xcode_build_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode build targeting iOS. Defaults to true.\"\n        default: true\n      ios_xcode_test_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode test targeting iOS. Defaults to false.\"\n        default: false\n      watchos_xcode_build_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode build targeting watchOS. Defaults to true.\"\n        default: true\n      watchos_xcode_test_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode test targeting watchOS. Defaults to false.\"\n        default: false\n      tvos_xcode_build_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode build targeting tvOS. Defaults to true.\"\n        default: true\n      tvos_xcode_test_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode test targeting tvOS. Defaults to false.\"\n        default: false\n      visionos_xcode_build_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode build targeting visionOS. Defaults to true.\"\n        default: true\n      visionos_xcode_test_enabled:\n        type: boolean\n        description: \"Boolean to enable the Xcode test targeting visionOS. Defaults to false.\"\n        default: false\n\n      runner_pool:\n        type: string\n        description: \"The runner pool which will be requested.\"\n        default: \"nightly\"\n\n      debug_output_enabled:\n        type: boolean\n        description: \"Boolean to enable debug output from xcodebuild by eliding -quiet. Defaults to false.\"\n        default: false\n\n      env_vars:\n        type: string\n        description: \"Environment variables for jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n\njobs:\n  construct-matrix:\n    name: Construct Darwin matrix\n    runs-on: ubuntu-latest\n    outputs:\n      darwin-matrix: '${{ steps.generate-matrix.outputs.darwin-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate and use JSON environment variables directly\n          env_vars_json=\"$INPUT_ENV_VARS\"\n\n          # Validate JSON format\n          if ! echo \"$env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          cat >> \"$GITHUB_OUTPUT\" << EOM\n          darwin-matrix=$(\n            runner_pool=\"${MATRIX_RUNNER_POOL:=\"nightly\"}\"\n            xcode_15_4_enabled=\"${MATRIX_MACOS_15_4_ENABLED:=true}\"\n            xcode_15_4_build_arguments_override=\"${MATRIX_MACOS_15_4_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_15_4_test_arguments_override=\"${MATRIX_MACOS_15_4_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_15_4_setup_command=\"${MATRIX_MACOS_15_4_SETUP_COMMAND:=\"\"}\"\n            xcode_16_0_enabled=\"${MATRIX_MACOS_16_0_ENABLED:=true}\"\n            xcode_16_0_build_arguments_override=\"${MATRIX_MACOS_16_0_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_0_test_arguments_override=\"${MATRIX_MACOS_16_0_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_0_setup_command=\"${MATRIX_MACOS_16_0_SETUP_COMMAND:=\"\"}\"\n            xcode_16_1_enabled=\"${MATRIX_MACOS_16_1_ENABLED:=true}\"\n            xcode_16_1_build_arguments_override=\"${MATRIX_MACOS_16_1_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_1_test_arguments_override=\"${MATRIX_MACOS_16_1_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_1_setup_command=\"${MATRIX_MACOS_16_1_SETUP_COMMAND:=\"\"}\"\n            xcode_16_2_enabled=\"${MATRIX_MACOS_16_2_ENABLED:=true}\"\n            xcode_16_2_build_arguments_override=\"${MATRIX_MACOS_16_2_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_2_test_arguments_override=\"${MATRIX_MACOS_16_2_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_2_setup_command=\"${MATRIX_MACOS_16_2_SETUP_COMMAND:=\"\"}\"\n            xcode_16_3_enabled=\"${MATRIX_MACOS_16_3_ENABLED:=true}\"\n            xcode_16_3_build_arguments_override=\"${MATRIX_MACOS_16_3_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_3_test_arguments_override=\"${MATRIX_MACOS_16_3_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_3_setup_command=\"${MATRIX_MACOS_16_3_SETUP_COMMAND:=\"\"}\"\n            xcode_16_4_enabled=\"${MATRIX_MACOS_16_4_ENABLED:=true}\"\n            xcode_16_4_build_arguments_override=\"${MATRIX_MACOS_16_4_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_4_test_arguments_override=\"${MATRIX_MACOS_16_4_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_16_4_setup_command=\"${MATRIX_MACOS_16_4_SETUP_COMMAND:=\"\"}\"\n            xcode_26_0_enabled=\"${MATRIX_MACOS_26_0_ENABLED:=true}\"\n            xcode_26_0_build_arguments_override=\"${MATRIX_MACOS_26_0_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_26_0_test_arguments_override=\"${MATRIX_MACOS_26_0_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_26_0_setup_command=\"${MATRIX_MACOS_26_0_SETUP_COMMAND:=\"\"}\"\n            xcode_26_1_enabled=\"${MATRIX_MACOS_26_1_ENABLED:=true}\"\n            xcode_26_1_build_arguments_override=\"${MATRIX_MACOS_26_1_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_26_1_test_arguments_override=\"${MATRIX_MACOS_26_1_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_26_1_setup_command=\"${MATRIX_MACOS_26_1_SETUP_COMMAND:=\"\"}\"\n            xcode_26_2_enabled=\"${MATRIX_MACOS_26_2_ENABLED:=true}\"\n            xcode_26_2_build_arguments_override=\"${MATRIX_MACOS_26_2_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_26_2_test_arguments_override=\"${MATRIX_MACOS_26_2_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_26_2_setup_command=\"${MATRIX_MACOS_26_2_SETUP_COMMAND:=\"\"}\"\n            xcode_latest_beta_enabled=\"${MATRIX_MACOS_26_BETA_1_ENABLED:=true}\" # TODO: remove once no repos use this\n            xcode_latest_beta_build_arguments_override=\"${MATRIX_MACOS_26_BETA_1_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\" # TODO: remove once no repos use this\n            xcode_latest_beta_test_arguments_override=\"${MATRIX_MACOS_26_BETA_1_TEST_ARGUMENTS_OVERRIDE:=\"\"}\" # TODO: remove once no repos use this\n            xcode_latest_beta_setup_command=\"${MATRIX_MACOS_26_BETA_1_SETUP_COMMAND:=\"\"}\" # TODO: remove once no repos use this\n            xcode_latest_beta_enabled=\"${MATRIX_MACOS_LATEST_BETA_ENABLED:=true}\"\n            xcode_latest_beta_build_arguments_override=\"${MATRIX_MACOS_LATEST_BETA_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_latest_beta_test_arguments_override=\"${MATRIX_MACOS_LATEST_BETA_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            xcode_latest_beta_setup_command=\"${MATRIX_MACOS_LATEST_BETA_SETUP_COMMAND:=\"\"}\"\n            swift_6_1_enabled=\"${MATRIX_SWIFT_6_1_ENABLED:=true}\"\n            swift_6_1_build_arguments_override=\"${MATRIX_SWIFT_6_1_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            swift_6_1_test_arguments_override=\"${MATRIX_SWIFT_6_1_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            swift_6_1_setup_command=\"${MATRIX_SWIFT_6_1_SETUP_COMMAND:=\"\"}\"\n            swift_6_2_enabled=\"${MATRIX_SWIFT_6_2_ENABLED:=true}\"\n            swift_6_2_build_arguments_override=\"${MATRIX_SWIFT_6_2_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            swift_6_2_test_arguments_override=\"${MATRIX_SWIFT_6_2_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            swift_6_2_setup_command=\"${MATRIX_SWIFT_6_2_SETUP_COMMAND:=\"\"}\"\n            swift_6_3_enabled=\"${MATRIX_SWIFT_6_3_ENABLED:=true}\"\n            swift_6_3_build_arguments_override=\"${MATRIX_SWIFT_6_3_BUILD_ARGUMENTS_OVERRIDE:=\"\"}\"\n            swift_6_3_test_arguments_override=\"${MATRIX_SWIFT_6_3_TEST_ARGUMENTS_OVERRIDE:=\"\"}\"\n            swift_6_3_setup_command=\"${MATRIX_SWIFT_6_3_SETUP_COMMAND:=\"\"}\"\n\n            # Create matrix from inputs\n            matrix='{\"config\": []}'\n\n            if [[ \"$xcode_15_4_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_15_4_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_15_4_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_15_4_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 15.4\", \"xcode_version\": \"15.4\", \"xcode_app\": \"Xcode_15.4.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_16_0_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_16_0_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_16_0_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_16_0_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 16.0\", \"xcode_version\": \"16.0\", \"xcode_app\": \"Xcode_16.0.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_16_1_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_16_1_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_16_1_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_16_1_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 16.1\", \"xcode_version\": \"16.1\", \"xcode_app\": \"Xcode_16.1.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_16_2_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_16_2_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_16_2_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_16_2_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 16.2\", \"xcode_version\": \"16.2\", \"xcode_app\": \"Xcode_16.2.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_16_3_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_16_3_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_16_3_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_16_3_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 16.3\", \"xcode_version\": \"16.3\", \"xcode_app\": \"Xcode_16.3.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_16_4_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_16_4_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_16_4_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_16_4_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 16.4\", \"xcode_version\": \"16.4\", \"xcode_app\": \"Xcode_16.4.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_26_0_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_26_0_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_26_0_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_26_0_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 26.0\", \"xcode_version\": \"26.0\", \"xcode_app\": \"Xcode_26.0.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_26_1_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_26_1_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_26_1_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_26_1_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 26.1\", \"xcode_version\": \"26.1\", \"xcode_app\": \"Xcode_26.1.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_26_2_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_26_2_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_26_2_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_26_2_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode 26.2\", \"xcode_version\": \"26.2\", \"xcode_app\": \"Xcode_26.2.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$xcode_latest_beta_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$xcode_latest_beta_setup_command\"  \\\n                --arg build_arguments_override \"$xcode_latest_beta_build_arguments_override\"  \\\n                --arg test_arguments_override \"$xcode_latest_beta_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Xcode latest beta\", \"xcode_version\": \"latest beta\", \"xcode_app\": \"Xcode-latest.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$swift_6_1_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$swift_6_1_setup_command\"  \\\n                --arg build_arguments_override \"$swift_6_1_build_arguments_override\"  \\\n                --arg test_arguments_override \"$swift_6_1_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Swift 6.1\", \"xcode_version\": \"swift 6.1\", \"xcode_app\": \"Xcode_swift_6.1.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$swift_6_2_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$swift_6_2_setup_command\"  \\\n                --arg build_arguments_override \"$swift_6_2_build_arguments_override\"  \\\n                --arg test_arguments_override \"$swift_6_2_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Swift 6.2\", \"xcode_version\": \"swift 6.2\", \"xcode_app\": \"Xcode_swift_6.2.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            if [[ \"$swift_6_3_enabled\" == \"true\" ]]; then\n                matrix=$(echo \"$matrix\" | jq -c \\\n                --arg setup_command \"$swift_6_3_setup_command\"  \\\n                --arg build_arguments_override \"$swift_6_3_build_arguments_override\"  \\\n                --arg test_arguments_override \"$swift_6_3_test_arguments_override\"  \\\n                --arg runner_pool \"$runner_pool\"  \\\n                --argjson env_vars \"$env_vars_json\" \\\n                '.config[.config| length] |= . + { \"name\": \"Swift 6.3\", \"xcode_version\": \"swift 6.3\", \"xcode_app\": \"Xcode_swift_6.3.app\", \"setup_command\": $setup_command, \"build_arguments_override\": $build_arguments_override, \"test_arguments_override\": $test_arguments_override, \"os\": \"tahoe\", \"arch\": \"ARM64\", \"pool\": $runner_pool, \"env\": $env_vars }')\n            fi\n\n            echo \"$matrix\" | jq -c\n          )\"\n          EOM\n        env:\n          INPUT_ENV_VARS: ${{ inputs.env_vars }}\n          MATRIX_RUNNER_POOL: ${{ inputs.runner_pool }}\n          MATRIX_MACOS_15_4_ENABLED: ${{ inputs.xcode_15_4_enabled }}\n          MATRIX_MACOS_15_4_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_15_4_build_arguments_override }}\n          MATRIX_MACOS_15_4_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_15_4_test_arguments_override }}\n          MATRIX_MACOS_15_4_SETUP_COMMAND: ${{ inputs.xcode_15_4_setup_command }}\n          MATRIX_MACOS_16_0_ENABLED: ${{ inputs.xcode_16_0_enabled }}\n          MATRIX_MACOS_16_0_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_0_build_arguments_override }}\n          MATRIX_MACOS_16_0_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_0_test_arguments_override }}\n          MATRIX_MACOS_16_0_SETUP_COMMAND: ${{ inputs.xcode_16_0_setup_command }}\n          MATRIX_MACOS_16_1_ENABLED: ${{ inputs.xcode_16_1_enabled }}\n          MATRIX_MACOS_16_1_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_1_build_arguments_override }}\n          MATRIX_MACOS_16_1_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_1_test_arguments_override }}\n          MATRIX_MACOS_16_1_SETUP_COMMAND: ${{ inputs.xcode_16_1_setup_command }}\n          MATRIX_MACOS_16_2_ENABLED: ${{ inputs.xcode_16_2_enabled }}\n          MATRIX_MACOS_16_2_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_2_build_arguments_override }}\n          MATRIX_MACOS_16_2_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_2_test_arguments_override }}\n          MATRIX_MACOS_16_2_SETUP_COMMAND: ${{ inputs.xcode_16_2_setup_command }}\n          MATRIX_MACOS_16_3_ENABLED: ${{ inputs.xcode_16_3_enabled }}\n          MATRIX_MACOS_16_3_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_3_build_arguments_override }}\n          MATRIX_MACOS_16_3_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_3_test_arguments_override }}\n          MATRIX_MACOS_16_3_SETUP_COMMAND: ${{ inputs.xcode_16_3_setup_command }}\n          MATRIX_MACOS_16_4_ENABLED: ${{ inputs.xcode_16_4_enabled }}\n          MATRIX_MACOS_16_4_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_4_build_arguments_override }}\n          MATRIX_MACOS_16_4_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_16_4_test_arguments_override }}\n          MATRIX_MACOS_16_4_SETUP_COMMAND: ${{ inputs.xcode_16_4_setup_command }}\n          MATRIX_MACOS_26_0_ENABLED: ${{ inputs.xcode_26_0_enabled }}\n          MATRIX_MACOS_26_0_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_0_build_arguments_override }}\n          MATRIX_MACOS_26_0_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_0_test_arguments_override }}\n          MATRIX_MACOS_26_0_SETUP_COMMAND: ${{ inputs.xcode_26_0_setup_command }}\n          MATRIX_MACOS_26_1_ENABLED: ${{ inputs.xcode_26_1_enabled }}\n          MATRIX_MACOS_26_1_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_1_build_arguments_override }}\n          MATRIX_MACOS_26_1_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_1_test_arguments_override }}\n          MATRIX_MACOS_26_1_SETUP_COMMAND: ${{ inputs.xcode_26_1_setup_command }}\n          MATRIX_MACOS_26_2_ENABLED: ${{ inputs.xcode_26_2_enabled }}\n          MATRIX_MACOS_26_2_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_2_build_arguments_override }}\n          MATRIX_MACOS_26_2_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_2_test_arguments_override }}\n          MATRIX_MACOS_26_2_SETUP_COMMAND: ${{ inputs.xcode_26_2_setup_command }}\n          MATRIX_MACOS_26_BETA_1_ENABLED: ${{ inputs.xcode_26_beta_1_enabled }}\n          MATRIX_MACOS_26_BETA_1_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_beta_1_build_arguments_override }}\n          MATRIX_MACOS_26_BETA_1_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_26_beta_1_test_arguments_override }}\n          MATRIX_MACOS_26_BETA_1_SETUP_COMMAND: ${{ inputs.xcode_26_beta_1_setup_command }}\n          MATRIX_MACOS_LATEST_BETA_ENABLED: ${{ inputs.xcode_latest_beta_enabled }}\n          MATRIX_MACOS_LATEST_BETA_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_latest_beta_build_arguments_override }}\n          MATRIX_MACOS_LATEST_BETA_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.xcode_latest_beta_test_arguments_override }}\n          MATRIX_MACOS_LATEST_BETA_SETUP_COMMAND: ${{ inputs.xcode_latest_beta_setup_command }}\n          MATRIX_SWIFT_6_1_ENABLED: ${{ inputs.swift_6_1_enabled }}\n          MATRIX_SWIFT_6_1_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.swift_6_1_build_arguments_override }}\n          MATRIX_SWIFT_6_1_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.swift_6_1_test_arguments_override }}\n          MATRIX_SWIFT_6_1_SETUP_COMMAND: ${{ inputs.swift_6_1_setup_command }}\n          MATRIX_SWIFT_6_2_ENABLED: ${{ inputs.swift_6_2_enabled }}\n          MATRIX_SWIFT_6_2_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.swift_6_2_build_arguments_override }}\n          MATRIX_SWIFT_6_2_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.swift_6_2_test_arguments_override }}\n          MATRIX_SWIFT_6_2_SETUP_COMMAND: ${{ inputs.swift_6_2_setup_command }}\n          MATRIX_SWIFT_6_3_ENABLED: ${{ inputs.swift_6_3_enabled }}\n          MATRIX_SWIFT_6_3_BUILD_ARGUMENTS_OVERRIDE: ${{ inputs.swift_6_3_build_arguments_override }}\n          MATRIX_SWIFT_6_3_TEST_ARGUMENTS_OVERRIDE: ${{ inputs.swift_6_3_test_arguments_override }}\n          MATRIX_SWIFT_6_3_SETUP_COMMAND: ${{ inputs.swift_6_3_setup_command }}\n\n  darwin-job:\n    name: ${{ matrix.config.name }}\n    needs: construct-matrix\n    if: github.repository_owner == 'apple'\n    runs-on: [self-hosted, macos, \"${{ matrix.config.os }}\", \"${{ matrix.config.arch }}\", \"${{ matrix.config.pool }}\"]\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix: ${{ fromJson(needs.construct-matrix.outputs.darwin-matrix) }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Export environment variables\n        if: ${{ matrix.config.env != '' && matrix.config.env != '{}'}}\n        run: |\n          echo \"Exporting environment variables from matrix configuration...\"\n          echo \"$MATRIX_ENV_JSON\" | jq -r 'to_entries[] | \"\\(.key)=\\(.value)\"' >> $GITHUB_ENV\n          echo \"$MATRIX_ENV_JSON\" | jq -r 'to_entries[] | \"exporting \\(.key)=\\(.value)\"'\n        env:\n          MATRIX_ENV_JSON: ${{ toJSON(matrix.config.env) }}\n      - name: Emit diagnostics\n        run: |\n          swift --version\n          /usr/bin/xcodebuild -version\n      - name: Setup command\n        if: ${{ matrix.config.setup_command != '' }}\n        run: bash -c \"$MATRIX_SETUP_COMMAND\"\n        env:\n          MATRIX_SETUP_COMMAND: ${{ matrix.config.setup_command }}\n      - name: Swift build\n        run: |\n          if [ -n \"$MATRIX_BUILD_ARGUMENTS_OVERRIDE\" ]; then\n            swift build $MATRIX_BUILD_ARGUMENTS_OVERRIDE\n          else\n            swift build --build-tests\n          fi\n        env:\n          MATRIX_BUILD_ARGUMENTS_OVERRIDE: ${{ matrix.config.build_arguments_override }}\n      - name: Swift test\n        if: 'inputs.swift_test_enabled'\n        run: |\n          if [ -n \"$MATRIX_TEST_ARGUMENTS_OVERRIDE\" ]; then\n            swift test $MATRIX_TEST_ARGUMENTS_OVERRIDE\n          else\n            swift test\n          fi\n        env:\n          MATRIX_TEST_ARGUMENTS_OVERRIDE: ${{ matrix.config.test_arguments_override }}\n      # see `xcodebuild -list` for schemes, `simctl list` for destinations\n      - name: macOS build\n        if: '!cancelled() && inputs.macos_xcode_build_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"generic/platform=macos,variant=macos\" build\n      - name: macOS test\n        if: '!cancelled() && inputs.macos_xcode_test_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"name=My Mac,variant=macos\" test\n      - name: macOS Catalyst build\n        if: '!cancelled() && inputs.macos_xcode_build_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"generic/platform=macos,variant=Mac Catalyst\" build\n      - name: macOS Catalyst test\n        if: '!cancelled() && inputs.macos_xcode_test_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"name=My Mac,variant=Mac Catalyst\" test\n      - name: iOS build\n        if: '!cancelled() && inputs.ios_xcode_build_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"generic/platform=ios\" build\n      - name: iOS test\n        if: '!cancelled() && inputs.ios_xcode_test_enabled'\n        run: |\n          /usr/bin/xcrun simctl shutdown all\n          /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"name=iPhone Air\" test\n      - name: watchOS build\n        if: '!cancelled() && inputs.watchos_xcode_build_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"generic/platform=watchos\" build\n      - name: watchOS test\n        if: '!cancelled() && inputs.watchos_xcode_test_enabled'\n        run: |\n          /usr/bin/xcrun simctl shutdown all\n          /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"name=Apple Watch Ultra 3 (49mm)\" test\n      - name: tvOS build\n        if: '!cancelled() && inputs.tvos_xcode_build_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"generic/platform=tvos\" build\n      - name: tvOS test\n        if: '!cancelled() && inputs.tvos_xcode_test_enabled'\n        run: |\n          /usr/bin/xcrun simctl shutdown all\n          /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"name=Apple TV 4K (3rd generation)\" test\n      - name: visionOS build  # arm only\n        if: '!cancelled() && inputs.visionos_xcode_build_enabled'\n        run: /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"generic/platform=visionos\" build\n      - name: visionOS test  # arm only\n        if: '!cancelled() && inputs.visionos_xcode_test_enabled'\n        run: |\n          /usr/bin/xcrun simctl shutdown all\n          /usr/bin/xcodebuild ${QUIET_ARG} -scheme ${BUILD_SCHEME} -destination \"name=Apple Vision Pro\" test\n    env:\n      XCODE_VERSION: ${{ matrix.config.xcode_version }}\n      DEVELOPER_DIR: \"/Applications/${{ matrix.config.xcode_app }}\"\n      BUILD_SCHEME: ${{ inputs.build_scheme }}\n      QUIET_ARG: ${{ inputs.debug_output_enabled && ' ' || '-quiet' }}\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: Main\n\npermissions:\n  contents: read\n\non:\n  push:\n    branches: [main]\n  schedule:\n    - cron: \"0 8,20 * * *\"\n\njobs:\n  unit-tests:\n    name: Unit tests\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/unit_tests.yml@main\n    with:\n      linux_5_10_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_6_0_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_6_1_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_6_2_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_nightly_6_1_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_nightly_main_arguments_override: \"--explicit-target-dependency-import-check error\"\n\n  cxx-interop:\n    name: Cxx interop\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main\n\n  benchmarks:\n    name: Benchmarks\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/benchmarks.yml@main\n    with:\n      benchmark_package_path: \"Benchmarks\"\n\n  construct-integration-test-matrix:\n    name: Construct integration test matrix\n    runs-on: ubuntu-latest\n    outputs:\n      integration-test-matrix: '${{ steps.generate-matrix.outputs.integration-test-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: echo \"integration-test-matrix=$(curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | bash)\" >> \"$GITHUB_OUTPUT\"\n        env:\n          MATRIX_LINUX_SETUP_COMMAND: \"apt-get update -y -q && apt-get install -y -q lsof dnsutils netcat-openbsd net-tools curl jq\"\n          MATRIX_LINUX_COMMAND: \"./scripts/integration_tests.sh\"\n          MATRIX_LINUX_ENV_VARS_JSON: '{\"NIO_ALLOC_COUNTER_TESTS_PARALLEL\": \"true\"}'\n\n  integration-tests:\n    name: Integration tests\n    needs: construct-integration-test-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Integration tests\"\n      matrix_string: '${{ needs.construct-integration-test-matrix.outputs.integration-test-matrix }}'\n\n  static-sdk:\n    name: Static Linux Swift SDK\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/static_sdk.yml@main\n\n  wasm-sdk:\n    name: WebAssembly Swift SDK\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/wasm_swift_sdk.yml@main\n    with:\n      additional_command_arguments: \"--target NIOCore\"\n\n  android-sdk:\n    name: Android Swift SDK\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/android_swift_sdk.yml@main\n\n  macos-tests:\n    name: macOS tests\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/macos_tests.yml@main\n    with:\n      runner_pool: nightly\n      build_scheme: swift-nio-Package\n      debug_output_enabled: true\n      xcode_16_3_enabled: false\n      xcode_16_4_enabled: false\n      xcode_26_0_enabled: false\n      xcode_26_1_enabled: false\n      xcode_26_2_enabled: false\n      swift_6_1_enabled: true\n      swift_6_2_enabled: true\n      swift_6_3_enabled: true\n      macos_xcode_test_enabled: false  # Disabled because of an issue\n      ios_xcode_test_enabled: true\n      watchos_xcode_test_enabled: true\n      tvos_xcode_test_enabled: true\n      visionos_xcode_test_enabled: true\n\n  release-builds:\n    name: Release builds\n    uses: apple/swift-nio/.github/workflows/release_builds.yml@main\n"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "content": "name: PR\n\npermissions:\n  contents: read\n\non:\n  pull_request:\n    types: [opened, reopened, synchronize]\n\njobs:\n  soundness:\n    name: Soundness\n    uses: swiftlang/github-workflows/.github/workflows/soundness.yml@0.0.7\n    with:\n      license_header_check_project_name: \"SwiftNIO\"\n      # Workaround https://github.com/swiftlang/swift-docc/issues/1280\n      docs_check_container_image: \"swift:6.1-noble\"\n\n  unit-tests:\n    name: Unit tests\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/unit_tests.yml@main\n    with:\n      linux_5_10_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_6_0_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_6_1_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_6_2_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_nightly_6_1_arguments_override: \"-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error\"\n      linux_nightly_main_arguments_override: \"--explicit-target-dependency-import-check error\"\n\n  benchmarks:\n    name: Benchmarks\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/benchmarks.yml@main\n    with:\n      benchmark_package_path: \"Benchmarks\"\n\n  cxx-interop:\n    name: Cxx interop\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main\n\n  construct-integration-test-matrix:\n    name: Construct integration test matrix\n    runs-on: ubuntu-latest\n    outputs:\n      integration-test-matrix: '${{ steps.generate-matrix.outputs.integration-test-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: echo \"integration-test-matrix=$(curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | bash)\" >> \"$GITHUB_OUTPUT\"\n        env:\n          MATRIX_LINUX_SETUP_COMMAND: \"apt-get update -y -q && apt-get install -y -q lsof dnsutils netcat-openbsd net-tools curl jq\"\n          MATRIX_LINUX_COMMAND: \"./scripts/integration_tests.sh\"\n          MATRIX_LINUX_ENV_VARS_JSON: '{\"NIO_ALLOC_COUNTER_TESTS_PARALLEL\": \"true\"}'\n\n  integration-tests:\n    name: Integration tests\n    needs: construct-integration-test-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Integration tests\"\n      matrix_string: '${{ needs.construct-integration-test-matrix.outputs.integration-test-matrix }}'\n\n  vsock-tests:\n    name: Vsock tests\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - name: Load vsock_loopback kernel module\n        run: sudo modprobe vsock_loopback\n      - name: Build package tests\n        run: swift build --build-tests\n      - name: Run Vsock tests\n        shell: bash  # explicitly choose bash, which ensures -o pipefail\n        run: swift test --filter \"(?i)vsock\" | tee test.out\n      - name: Check for skipped tests\n        run: test -r test.out && ! grep -i skipped test.out\n\n  macos-tests:\n    name: macOS tests\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/macos_tests.yml@main\n    with:\n      runner_pool: general\n      build_scheme: swift-nio-Package\n      xcode_16_3_enabled: false\n      xcode_16_4_enabled: false\n      xcode_26_0_enabled: false\n      xcode_26_1_enabled: false\n      xcode_26_2_enabled: false\n      swift_6_1_enabled: true\n      swift_6_2_enabled: true\n      swift_6_3_enabled: true\n\n  static-sdk:\n    name: Static Linux Swift SDK\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/static_sdk.yml@main\n\n  wasm-sdk:\n    name: WebAssembly Swift SDK\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/wasm_swift_sdk.yml@main\n    with:\n      additional_command_arguments: \"--target NIOCore\"\n\n  android-sdk:\n    name: Android Swift SDK\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/android_swift_sdk.yml@main\n\n  release-builds:\n    name: Release builds\n    uses: apple/swift-nio/.github/workflows/release_builds.yml@main\n"
  },
  {
    "path": ".github/workflows/pull_request_label.yml",
    "content": "name: PR label\n\npermissions:\n    contents: read\n\non:\n    pull_request:\n        types: [labeled, unlabeled, opened, reopened, synchronize]\n\njobs:\n    semver-label-check:\n        name: Semantic version label check\n        runs-on: ubuntu-latest\n        timeout-minutes: 1\n        steps:\n            - name: Checkout repository\n              uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n              with:\n                  persist-credentials: false\n            - name: Check for Semantic Version label\n              uses: ./.github/actions/pull_request_semver_label_checker/\n"
  },
  {
    "path": ".github/workflows/release_builds.yml",
    "content": "name: Release builds\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      linux_5_10_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.10 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_5_10_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 5.10 Swift version matrix job.\"\n        default: \"\"\n      linux_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.0 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_0_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 6.0 Swift version matrix job.\"\n        default: \"\"\n      linux_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.1 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_1_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 6.1 Swift version matrix job.\"\n        default: \"\"\n      linux_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.2 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_2_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 6.2 Swift version matrix job.\"\n        default: \"\"\n      linux_nightly_next_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux matrix job using the nightly build for the next Swift version. Defaults to true.\"\n        default: true\n      linux_nightly_next_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux matrix job using the nightly build for the next Swift version.\"\n        default: \"\"\n      linux_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux nightly main Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_nightly_main_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux nightly main Swift version matrix job.\"\n        default: \"\"\n\n      windows_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.0 Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_6_0_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows 6.0 Swift version matrix job.\"\n        default: \"\"\n      windows_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.1 Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_6_1_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows 6.1 Swift version matrix job.\"\n        default: \"\"\n      windows_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.2 Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_6_2_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows 6.2 Swift version matrix job.\"\n        default: \"\"\n      windows_nightly_next_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows matrix job using the nightly build for the next Swift version. Defaults to false.\"\n        default: false\n      windows_nightly_next_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows matrix job using the nightly build for the next Swift version.\"\n        default: \"\"\n      windows_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows nightly main Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_nightly_main_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows nightly main Swift version matrix job.\"\n        default: \"\"\n\n      linux_env_vars:\n        type: string\n        description: \"Environment variables for Linux jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n      windows_env_vars:\n        type: string\n        description: \"Environment variables for Windows jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n\n      minimum_swift_version:\n        type: string\n        description: \"Minimum Swift version to include in the matrix. Leave empty for auto-detection from Package.swift, specify a version like '6.0' to override, or set to 'none' to disable filtering.\"\n        default: \"\"\n\njobs:\n  construct-matrix:\n    name: Construct release build matrix\n    runs-on: ubuntu-latest\n    outputs:\n      release-build-matrix: '${{ steps.generate-matrix.outputs.release-build-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate JSON environment variables\n          linux_env_vars_json=\"$INPUT_LINUX_ENV_VARS\"\n          windows_env_vars_json=\"$INPUT_WINDOWS_ENV_VARS\"\n\n          if ! echo \"$linux_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: linux_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          if ! echo \"$windows_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: windows_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          echo \"release-build-matrix=$(curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | MATRIX_LINUX_ENV_VARS_JSON=\"${linux_env_vars_json}\" MATRIX_WINDOWS_ENV_VARS_JSON=\"${windows_env_vars_json}\" bash)\" >> \"$GITHUB_OUTPUT\"\n        env:\n          INPUT_LINUX_ENV_VARS: ${{ inputs.linux_env_vars }}\n          INPUT_WINDOWS_ENV_VARS: ${{ inputs.windows_env_vars }}\n          MATRIX_LINUX_SETUP_COMMAND: \"swift --version\"\n          MATRIX_LINUX_COMMAND: \"swift build -c release\"\n          MATRIX_MIN_SWIFT_VERSION: ${{ inputs.minimum_swift_version }}\n          MATRIX_LINUX_5_10_ENABLED: ${{ inputs.linux_5_10_enabled }}\n          MATRIX_LINUX_5_10_COMMAND_ARGUMENTS: ${{ inputs.linux_5_10_arguments_override }}\n          MATRIX_LINUX_6_0_ENABLED: ${{ inputs.linux_6_0_enabled }}\n          MATRIX_LINUX_6_0_COMMAND_ARGUMENTS: ${{ inputs.linux_6_0_arguments_override }}\n          MATRIX_LINUX_6_1_ENABLED: ${{ inputs.linux_6_1_enabled }}\n          MATRIX_LINUX_6_1_COMMAND_ARGUMENTS: ${{ inputs.linux_6_1_arguments_override }}\n          MATRIX_LINUX_6_2_ENABLED: ${{ inputs.linux_6_2_enabled }}\n          MATRIX_LINUX_6_2_COMMAND_ARGUMENTS: ${{ inputs.linux_6_2_arguments_override }}\n          MATRIX_LINUX_NIGHTLY_NEXT_ENABLED: ${{ inputs.linux_nightly_next_enabled }}\n          MATRIX_LINUX_NIGHTLY_NEXT_COMMAND_ARGUMENTS: ${{ inputs.linux_nightly_next_arguments_override }}\n          MATRIX_LINUX_NIGHTLY_MAIN_ENABLED: ${{ inputs.linux_nightly_main_enabled }}\n          MATRIX_LINUX_NIGHTLY_MAIN_COMMAND_ARGUMENTS: ${{ inputs.linux_nightly_main_arguments_override }}\n          MATRIX_WINDOWS_COMMAND: \"swift build -c release\"\n          MATRIX_WINDOWS_6_0_ENABLED: ${{ inputs.windows_6_0_enabled }}\n          MATRIX_WINDOWS_6_0_COMMAND_ARGUMENTS: ${{ inputs.windows_6_0_arguments_override }}\n          MATRIX_WINDOWS_6_1_ENABLED: ${{ inputs.windows_6_1_enabled }}\n          MATRIX_WINDOWS_6_1_COMMAND_ARGUMENTS: ${{ inputs.windows_6_1_arguments_override }}\n          MATRIX_WINDOWS_6_2_ENABLED: ${{ inputs.windows_6_2_enabled }}\n          MATRIX_WINDOWS_6_2_COMMAND_ARGUMENTS: ${{ inputs.windows_6_2_arguments_override }}\n          MATRIX_WINDOWS_NIGHTLY_NEXT_ENABLED: ${{ inputs.windows_nightly_next_enabled }}\n          MATRIX_WINDOWS_NIGHTLY_NEXT_COMMAND_ARGUMENTS: ${{ inputs.windows_nightly_next_arguments_override }}\n          MATRIX_WINDOWS_NIGHTLY_MAIN_ENABLED: ${{ inputs.windows_nightly_main_enabled }}\n          MATRIX_WINDOWS_NIGHTLY_MAIN_COMMAND_ARGUMENTS: ${{ inputs.windows_nightly_main_arguments_override }}\n\n  release-builds:\n    name: Release builds\n    needs: construct-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Release builds\"\n      matrix_string: '${{ needs.construct-matrix.outputs.release-build-matrix }}'\n"
  },
  {
    "path": ".github/workflows/static_sdk.yml",
    "content": "name: Static SDK\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      env_vars:\n        type: string\n        description: \"Environment variables for jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n      command_arguments:\n        type: string\n        description: \"The arguments passed to swift build. Defaults to '--swift-sdk x86_64-swift-linux-musl'.\"\n        default: \"--swift-sdk x86_64-swift-linux-musl\"\n\njobs:\n  construct-matrix:\n    name: Construct Static SDK matrix\n    runs-on: ubuntu-latest\n    outputs:\n      static-sdk-matrix: '${{ steps.generate-matrix.outputs.static-sdk-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate and use JSON environment variables directly\n          env_vars_json=\"$INPUT_ENV_VARS\"\n\n          # Validate JSON format\n          if ! echo \"$env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          # Generate matrix with parsed environment variables\n          cat >> \"$GITHUB_OUTPUT\" << EOM\n          static-sdk-matrix=$(echo '{\n            \"config\":[\n              {\n                \"name\":\"latest-release Jammy\",\n                \"swift_version\":\"latest-release\",\n                \"platform\":\"Linux\",\n                \"runner\":\"ubuntu-latest\",\n                \"image\":\"ubuntu:jammy\",\n                \"setup_command\":\"apt update -q && apt install -y -q curl jq tar && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_prerequisites.sh | bash && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_sdk.sh | INSTALL_SWIFT_VERSION=latest INSTALL_SWIFT_ARCH=x86_64 bash && hash -r\",\n                \"command\":\"swift build\",\n                \"command_arguments\":\"--swift-sdks-path /tmp/swiftsdks '\"$INPUT_COMMAND_ARGUMENTS\"'\",\n                \"env\":'\"$env_vars_json\"'\n              },\n              {\n                \"name\":\"main Jammy\",\n                \"swift_version\":\"main\",\n                \"platform\":\"Linux\",\n                \"runner\":\"ubuntu-latest\",\n                \"image\":\"ubuntu:jammy\",\n                \"setup_command\":\"apt update -q && apt install -y -q curl jq tar && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_prerequisites.sh | bash && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_sdk.sh | INSTALL_SWIFT_BRANCH=main INSTALL_SWIFT_ARCH=x86_64 bash && hash -r\",\n                \"command\":\"swift build\",\n                \"command_arguments\":\"--swift-sdks-path /tmp/swiftsdks '\"$INPUT_COMMAND_ARGUMENTS\"'\",\n                \"env\":'\"$env_vars_json\"'\n              }\n            ]\n          }' | jq -c)\n          EOM\n        env:\n          INPUT_ENV_VARS: ${{ inputs.env_vars }}\n          INPUT_COMMAND_ARGUMENTS: ${{ inputs.command_arguments }}\n\n  static-sdk:\n    name: Static SDK\n    needs: construct-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Static SDK\"\n      matrix_string: '${{ needs.construct-matrix.outputs.static-sdk-matrix }}'\n"
  },
  {
    "path": ".github/workflows/swift_6_language_mode.yml",
    "content": "name: Swift 6 language mode\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n\n# We are cancelling previously triggered workflow runs\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}-swift-6-language-mode\n  cancel-in-progress: true\n\njobs:\n  swift-6-language-mode:\n    name: Swift 6 language mode\n    runs-on: ubuntu-latest\n    container:\n      image: swift:6.0-jammy\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Set the language mode\n        run: swift package tools-version --set 6.0\n      - name: Build with Swift 6 language mode\n        run: swift build -Xswiftc -warnings-as-errors\n"
  },
  {
    "path": ".github/workflows/swift_load_test_matrix.yml",
    "content": "name: Matrix Load\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      name:\n        type: string\n        description: \"The name of the workflow used for the concurrency group.\"\n        required: true\n      matrix_path:\n        type: string\n        description: \"The path of the test matrix definition.\"\n        default: \"\"\n\njobs:\n  load-matrix:\n    name: Prepare matrices\n    runs-on: ubuntu-latest\n    outputs:\n      swift-matrix: ${{ steps.load-matrix.outputs.swift-matrix }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - name: Mark the workspace as safe\n        # https://github.com/actions/checkout/issues/766\n        run: git config --global --add safe.directory ${GITHUB_WORKSPACE}\n      - id: load-matrix\n        run: |\n            printf \"swift-matrix=%s\" \"$(jq -ec '.' \"$INPUT_MATRIX_PATH\")\" >> \"$GITHUB_OUTPUT\"\n        env:\n          INPUT_MATRIX_PATH: ${{ inputs.matrix_path }}\n\n\n  execute-matrix:\n    name: Execute matrix\n    needs: load-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: ${{ inputs.name }}\n      matrix_string: '${{ needs.load-matrix.outputs.swift-matrix }}'\n"
  },
  {
    "path": ".github/workflows/swift_matrix.yml",
    "content": "name: Matrix\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      name:\n        type: string\n        description: \"The name of the workflow used for the concurrency group.\"\n        required: true\n      matrix_linux_command:\n        type: string\n        description: \"The command of the current Swift version linux matrix job to execute.\"\n        required: true\n      matrix_linux_5_9_enabled:\n        type: boolean\n        description: \"Boolean to enable the 5.9 Swift version matrix job. Defaults to false.\"\n        default: false\n      matrix_linux_5_9_container_image:\n        type: string\n        description: \"Container image for the 5.9 Swift version matrix job. Defaults to matching Swift Ubuntu image.\"\n        default: \"swift:5.9-jammy\"\n      matrix_linux_5_9_command_override:\n        type: string\n        description: \"The command of the 5.9 Swift version linux matrix job to execute.\"\n      matrix_linux_5_10_enabled:\n        type: boolean\n        description: \"Boolean to enable the 5.10 Swift version matrix job. Defaults to false.\"\n        default: false\n      matrix_linux_5_10_container_image:\n        type: string\n        description: \"Container image for the 5.10 Swift version matrix job. Defaults to matching Swift Ubuntu image.\"\n        default: \"swift:5.10-jammy\"\n      matrix_linux_5_10_command_override:\n        type: string\n        description: \"The command of the 5.10 Swift version linux matrix job to execute.\"\n      matrix_linux_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the 6.0 Swift version matrix job. Defaults to true.\"\n        default: true\n      matrix_linux_6_0_container_image:\n        type: string\n        description: \"Container image for the 6.0 Swift version matrix job. Defaults to matching Swift Ubuntu image.\"\n        default: \"swift:6.0-jammy\"\n      matrix_linux_6_0_command_override:\n        type: string\n        description: \"The command of the 6.0 Swift version linux matrix job to execute.\"\n      matrix_linux_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: true\n      matrix_linux_nightly_6_0_container_image:\n        type: string\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: \"swiftlang/swift:nightly-6.0-jammy\"\n      matrix_linux_nightly_6_0_command_override:\n        type: string\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n      matrix_linux_nightly_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the nightly 6.1 Swift version matrix job. Defaults to true.\"\n        default: true\n      matrix_linux_nightly_6_1_container_image:\n        type: string\n        description: \"Container image for the nightly 6.1 Swift version matrix job. Defaults to matching Swift Ubuntu image.\"\n        default: \"swiftlang/swift:nightly-6.1-jammy\"\n      matrix_linux_nightly_6_1_command_override:\n        type: string\n        description: \"The command of the nightly 6.1 Swift version linux matrix job to execute.\"\n      matrix_linux_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the nightly main Swift version matrix job. Defaults to true.\"\n        default: true\n      matrix_linux_nightly_main_container_image:\n        type: string\n        description: \"Container image for the nightly main Swift version matrix job. Defaults to matching Swift Ubuntu image.\"\n        default: \"swiftlang/swift:nightly-main-jammy\"\n      matrix_linux_nightly_main_command_override:\n        type: string\n        description: \"The command of the nightly main Swift version linux matrix job to execute.\"\n\n      matrix_windows_command:\n        type: string\n        description: \"The command of the current Swift version windows matrix job to execute.\"\n        default: \"\"\n      matrix_windows_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the 6.0 Swift version matrix job. Defaults to true.\"\n        default: false\n      matrix_windows_6_0_command_override:\n        type: string\n        description: \"The command of the 6.0 Swift version windows matrix job to execute.\"\n      matrix_windows_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: false\n      matrix_windows_nightly_6_0_command_override:\n        type: string\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n      matrix_windows_nightly_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the nightly 6.1 Swift version matrix job. Defaults to true.\"\n        default: false\n      matrix_windows_nightly_6_1_command_override:\n        type: string\n        description: \"The command of the nightly 6.1 Swift version windows matrix job to execute.\"\n      matrix_windows_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the nightly main Swift version matrix job. Defaults to true.\"\n        default: false\n      matrix_windows_nightly_main_command_override:\n        type: string\n        description: \"The command of the nightly main Swift version windows matrix job to execute.\"\n\n# We are cancelling previously triggered workflow runs\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.name }}\n  cancel-in-progress: true\n\njobs:\n  linux:\n    name: Linux (${{ matrix.swift.swift_version }})\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        # We are specifying only the major and minor of the docker images to automatically pick up the latest patch release\n        swift:\n          - image: ${{ inputs.matrix_linux_5_9_container_image }}\n            swift_version: \"5.9\"\n            enabled: ${{ inputs.matrix_linux_5_9_enabled }}\n          - image: ${{ inputs.matrix_linux_5_10_container_image }}\n            swift_version: \"5.10\"\n            enabled: ${{ inputs.matrix_linux_5_10_enabled }}\n          - image: ${{ inputs.matrix_linux_6_0_container_image }}\n            swift_version: \"6.0\"\n            enabled: ${{ inputs.matrix_linux_6_0_enabled }}\n          - image: ${{ inputs.matrix_linux_nightly_6_1_container_image }}\n            swift_version: \"nightly-6.1\"\n            enabled: ${{ inputs.matrix_linux_nightly_6_1_enabled }}\n          - image: ${{ inputs.matrix_linux_nightly_main_container_image }}\n            swift_version: \"nightly-main\"\n            enabled: ${{ inputs.matrix_linux_nightly_main_enabled }}\n    container:\n      image: ${{ matrix.swift.image }}\n    steps:\n      - name: Checkout repository\n        if: ${{ matrix.swift.enabled }}\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Mark the workspace as safe\n        if: ${{ matrix.swift.enabled }}\n        # https://github.com/actions/checkout/issues/766\n        run: git config --global --add safe.directory ${GITHUB_WORKSPACE}\n      - name: Run matrix job\n        if: ${{ matrix.swift.enabled }}\n        env:\n          SWIFT_VERSION: ${{ matrix.swift.swift_version }}\n          COMMAND: ${{ inputs.matrix_linux_command }}\n          COMMAND_OVERRIDE_5_9: ${{ inputs.matrix_linux_5_9_command_override }}\n          COMMAND_OVERRIDE_5_10: ${{ inputs.matrix_linux_5_10_command_override }}\n          COMMAND_OVERRIDE_6_0: ${{ inputs.matrix_linux_6_0_command_override }}\n          COMMAND_OVERRIDE_NIGHTLY_6_1: ${{ inputs.matrix_linux_nightly_6_1_command_override }}\n          COMMAND_OVERRIDE_NIGHTLY_MAIN: ${{ inputs.matrix_linux_nightly_main_command_override }}\n        run: |\n          apt-get -qq update && apt-get -qq -y install curl\n          curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check-matrix-job.sh | bash\n\n  windows:\n    name: Windows (${{ matrix.swift.swift_version }})\n    runs-on: windows-2022\n    strategy:\n      fail-fast: false\n      matrix:\n        # We are specifying only the major and minor of the docker images to automatically pick up the latest patch release\n        swift:\n          - image: swift:6.0-windowsservercore-ltsc2022\n            swift_version: \"6.0\"\n            enabled: ${{ inputs.matrix_windows_6_0_enabled }}\n    steps:\n      - name: Wait for Docker daemon\n        if: ${{ matrix.swift.enabled }}\n        run: |\n          $maxAttempts = 30\n          $attempt = 0\n          do {\n            $attempt++\n            docker info 2>&1 | Out-Null\n            if ($LASTEXITCODE -eq 0) { break }\n            if ($attempt -ge $maxAttempts) {\n              Write-Error \"Docker daemon did not become ready after $maxAttempts attempts\"\n              exit 1\n            }\n            Start-Sleep -Seconds 6\n          } while ($true)\n        shell: pwsh\n      - name: Pull Docker image\n        if: ${{ matrix.swift.enabled }}\n        run: docker pull ${{ matrix.swift.image }}\n      - name: Checkout repository\n        if: ${{ matrix.swift.enabled }}\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - name: Donwload matrix script\n        if: ${{ matrix.swift.enabled }}\n        run: curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check-matrix-job.ps1 -o __check-matrix-job.ps1\n      - name: Run matrix job\n        if: ${{ matrix.swift.enabled }}\n        run: |\n          docker run --env SWIFT_VERSION=\"${{ matrix.swift.swift_version }}\" --env COMMAND=\"$env:INPUT_WINDOWS_COMMAND\" --env COMMAND_OVERRIDE_6_0=\"$env:INPUT_WINDOWS_6_0_OVERRIDE\" -v ${{ github.workspace }}:C:\\source ${{ matrix.swift.image }} cmd /s /c  \"swift --version & cd C:\\source\\ & powershell -File __check-matrix-job.ps1\"\n        env:\n          INPUT_WINDOWS_COMMAND: ${{ inputs.matrix_windows_command }}\n          INPUT_WINDOWS_6_0_OVERRIDE: ${{ inputs.matrix_windows_6_0_command_override }}\n\n  windows-nightly:\n    name: Windows (${{ matrix.swift.swift_version }})\n    runs-on: windows-2019\n    strategy:\n      fail-fast: false\n      matrix:\n        # We are specifying only the major and minor of the docker images to automatically pick up the latest patch release\n        swift:\n          - image: swiftlang/swift:nightly-6.1-windowsservercore-1809\n            swift_version: \"nightly-6.1\"\n            enabled: ${{ inputs.matrix_windows_nightly_6_1_enabled }}\n          - image: swiftlang/swift:nightly-main-windowsservercore-1809\n            swift_version: \"nightly-main\"\n            enabled: ${{ inputs.matrix_windows_nightly_main_enabled }}\n    steps:\n      - name: Wait for Docker daemon\n        if: ${{ matrix.swift.enabled }}\n        run: |\n          $maxAttempts = 30\n          $attempt = 0\n          do {\n            $attempt++\n            docker info 2>&1 | Out-Null\n            if ($LASTEXITCODE -eq 0) { break }\n            if ($attempt -ge $maxAttempts) {\n              Write-Error \"Docker daemon did not become ready after $maxAttempts attempts\"\n              exit 1\n            }\n            Start-Sleep -Seconds 6\n          } while ($true)\n        shell: pwsh\n      - name: Pull Docker image\n        if: ${{ matrix.swift.enabled }}\n        run: docker pull ${{ matrix.swift.image }}\n      - name: Checkout repository\n        if: ${{ matrix.swift.enabled }}\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Donwload matrix script\n        if: ${{ matrix.swift.enabled }}\n        run: curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check-matrix-job.ps1 -o __check-matrix-job.ps1\n      - name: Run matrix job\n        if: ${{ matrix.swift.enabled }}\n        run: |\n          docker run --env SWIFT_VERSION=\"${{ matrix.swift.swift_version }}\" --env COMMAND=\"$env:INPUT_WINDOWS_COMMAND\" --env COMMAND_OVERRIDE_NIGHTLY_6_1=\"$env:INPUT_WINDOWS_NIGHTLY_6_1_OVERRIDE\" --env COMMAND_OVERRIDE_NIGHTLY_MAIN=\"$env:INPUT_WINDOWS_NIGHTLY_MAIN_OVERRIDE\" -v ${{ github.workspace }}:C:\\source ${{ matrix.swift.image }} cmd /s /c  \"swift --version & cd C:\\source\\ & powershell -File __check-matrix-job.ps1\"\n        env:\n          INPUT_WINDOWS_COMMAND: ${{ inputs.matrix_windows_command }}\n          INPUT_WINDOWS_NIGHTLY_6_1_OVERRIDE: ${{ inputs.matrix_windows_nightly_6_1_command_override }}\n          INPUT_WINDOWS_NIGHTLY_MAIN_OVERRIDE: ${{ inputs.matrix_windows_nightly_main_command_override }}\n"
  },
  {
    "path": ".github/workflows/swift_test_matrix.yml",
    "content": "name: Matrix\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      name:\n        type: string\n        description: \"The name of the workflow used for the concurrency group.\"\n        required: true\n      matrix_string:\n        type: string\n        description: \"The test matrix definition.\"\n        required: true\n\n# We will cancel previously triggered workflow runs\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.name }}\n  cancel-in-progress: true\n\njobs:\n  execute-matrix:\n    name: ${{ matrix.config.platform }} (${{ matrix.config.name }})\n    runs-on: ${{ matrix.config.runner }}\n    strategy:\n      fail-fast: false\n      matrix: ${{ fromJson(inputs.matrix_string) }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: true\n      - name: Wait for Docker daemon (Windows)\n        if: ${{ matrix.config.platform == 'Windows' }}\n        run: |\n          $maxAttempts = 30\n          $attempt = 0\n          do {\n            $attempt++\n            docker info 2>&1 | Out-Null\n            if ($LASTEXITCODE -eq 0) { break }\n            if ($attempt -ge $maxAttempts) {\n              Write-Error \"Docker daemon did not become ready after $maxAttempts attempts\"\n              exit 1\n            }\n            Start-Sleep -Seconds 6\n          } while ($true)\n        shell: pwsh\n      - name: Pull Docker image\n        run: docker pull ${{ matrix.config.image }}\n      - name: Run matrix job\n        if: ${{ matrix.config.platform != 'Windows' }}\n        run: |\n          if [[ -n \"$MATRIX_SETUP_COMMAND\" ]]; then\n            setup_command_expression=\"$MATRIX_SETUP_COMMAND &&\"\n          else\n            setup_command_expression=\"\"\n          fi\n          workspace=\"/$(basename \"$GITHUB_WORKSPACE\")\"\n\n          docker_args=(\n            \"run\"\n            \"-v\" \"$GITHUB_WORKSPACE:$workspace\"\n            \"-w\" \"$workspace\"\n            \"-e\" \"CI=$CI\"\n            \"-e\" \"GITHUB_ACTIONS=$GITHUB_ACTIONS\"\n            \"-e\" \"SWIFT_VERSION=$MATRIX_SWIFT_VERSION\"\n            \"-e\" \"workspace=$workspace\"\n          )\n\n          if [[ \"$MATRIX_ENV_JSON\" != '{}' ]]; then\n            while IFS=\"=\" read -r key value; do\n              if [[ -n \"$key\" && -n \"$value\" ]]; then\n                docker_args+=(\"-e\" \"$key=$value\")\n              fi\n            done < <(echo \"$MATRIX_ENV_JSON\" | jq -r 'to_entries[] | \"\\(.key)=\\(.value)\"')\n          fi\n\n          docker_args+=(\"$MATRIX_IMAGE\")\n          docker_args+=(\"bash\" \"-c\" \"$setup_command_expression $MATRIX_COMMAND $MATRIX_COMMAND_ARGUMENTS\")\n\n          echo \"Executing Docker command: docker ${docker_args[*]}\"\n          docker \"${docker_args[@]}\"\n        env:\n          MATRIX_SETUP_COMMAND: ${{ matrix.config.setup_command }}\n          MATRIX_SWIFT_VERSION: ${{ matrix.config.swift_version }}\n          MATRIX_IMAGE: ${{ matrix.config.image }}\n          MATRIX_COMMAND: ${{ matrix.config.command }}\n          MATRIX_COMMAND_ARGUMENTS: ${{ matrix.config.command_arguments }}\n          MATRIX_ENV_JSON: ${{ toJson(matrix.config.env) }}\n          GITHUB_WORKSPACE: ${{ github.workspace }}\n      - name: Run matrix job (Windows)\n        if: ${{ matrix.config.platform == 'Windows' }}\n        run: |\n          if (-not [string]::IsNullOrEmpty(\"$env:MATRIX_SETUP_COMMAND\")) {\n              $setup_command_expression = \"$env:MATRIX_SETUP_COMMAND &\"\n          } else {\n              $setup_command_expression = \"\"\n          }\n          $workspace = \"C:\\\" + (Split-Path $env:GITHUB_WORKSPACE -Leaf)\n\n          $docker_args = @(\n              \"run\", \"-v\", \"$env:GITHUB_WORKSPACE`:$($workspace)\",\n              \"-w\", $workspace,\n              \"-e\", \"CI=$env:CI\",\n              \"-e\", \"GITHUB_ACTIONS=$env:GITHUB_ACTIONS\",\n              \"-e\", \"SWIFT_VERSION=$env:MATRIX_SWIFT_VERSION\"\n          )\n\n          $env_args = @()\n          $env_json = $env:MATRIX_ENV_JSON\n          if ($env_json -ne '{}') {\n              $env_obj = $env_json | ConvertFrom-Json\n              $env_obj.PSObject.Properties | ForEach-Object {\n                  $env_args += \"-e\"\n                  $env_args += \"$($_.Name)=$($_.Value)\"\n              }\n          }\n          $docker_args += $env_args\n\n          $docker_args += @(\"$env:MATRIX_IMAGE\", \"cmd\", \"/s\", \"/c\", \"swift --version & $($setup_command_expression) $env:MATRIX_COMMAND $env:MATRIX_COMMAND_ARGUMENTS\")\n\n          Write-Host \"Executing Docker command: docker $($docker_args -join ' ')\"\n          & docker @docker_args\n        env:\n          MATRIX_SETUP_COMMAND: ${{ matrix.config.setup_command }}\n          MATRIX_SWIFT_VERSION: ${{ matrix.config.swift_version }}\n          MATRIX_IMAGE: ${{ matrix.config.image }}\n          MATRIX_COMMAND: ${{ matrix.config.command }}\n          MATRIX_COMMAND_ARGUMENTS: ${{ matrix.config.command_arguments }}\n          MATRIX_ENV_JSON: ${{ toJson(matrix.config.env) }}\n          GITHUB_WORKSPACE: ${{ github.workspace }}\n    env:\n      SWIFT_VERSION: ${{ matrix.config.swift_version }}\n"
  },
  {
    "path": ".github/workflows/unit_tests.yml",
    "content": "name: Unit tests\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      linux_5_9_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.9 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_5_9_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 5.9 Swift version matrix job.\"\n        default: \"\"\n      linux_5_10_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 5.10 Swift version matrix job. Defaults to false.\"\n        default: false\n      linux_5_10_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 5.10 Swift version matrix job.\"\n        default: \"\"\n      linux_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.0 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_0_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 6.0 Swift version matrix job.\"\n        default: \"\"\n      linux_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.1 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_1_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 6.1 Swift version matrix job.\"\n        default: \"\"\n      linux_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux 6.2 Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_6_2_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux 6.2 Swift version matrix job.\"\n        default: \"\"\n      linux_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: true\n      linux_nightly_6_0_arguments_override:\n        type: string\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: \"\"\n      linux_nightly_6_1_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, use linux_nightly_next_enabled.\"\n        default: true\n      linux_nightly_6_1_arguments_override:\n        type: string\n        description: \"⚠️  Deprecated, use linux_nightly_next_arguments_override.\"\n        default: \"\"\n      linux_nightly_next_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux matrix job using the nightly build for the next Swift version. Defaults to true.\"\n        default: true\n      linux_nightly_next_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux matrix job using the nightly build for the next Swift version.\"\n        default: \"\"\n      linux_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Linux nightly main Swift version matrix job. Defaults to true.\"\n        default: true\n      linux_nightly_main_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Linux nightly main Swift version matrix job.\"\n        default: \"\"\n\n      windows_6_0_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.0 Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_6_0_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows 6.0 Swift version matrix job.\"\n        default: \"\"\n      windows_6_1_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.1 Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_6_1_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows 6.1 Swift version matrix job.\"\n        default: \"\"\n      windows_6_2_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows 6.2 Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_6_2_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows 6.2 Swift version matrix job.\"\n        default: \"\"\n      windows_nightly_6_0_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: false\n      windows_nightly_6_0_arguments_override:\n        type: string\n        description: \"⚠️  Deprecated, we no longer run against 6.0 nightly.\"\n        default: \"\"\n      windows_nightly_6_1_enabled:\n        type: boolean\n        description: \"⚠️  Deprecated, use windows_nightly_next_enabled.\"\n        default: false\n      windows_nightly_6_1_arguments_override:\n        type: string\n        description: \"⚠️  Deprecated, use windows_nightly_next_arguments_override.\"\n        default: \"\"\n      windows_nightly_next_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows matrix job using the nightly build for the next Swift version. Defaults to false.\"\n        default: false\n      windows_nightly_next_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows matrix job using the nightly build for the next Swift version.\"\n        default: \"\"\n      windows_nightly_main_enabled:\n        type: boolean\n        description: \"Boolean to enable the Windows nightly main Swift version matrix job. Defaults to false.\"\n        default: false\n      windows_nightly_main_arguments_override:\n        type: string\n        description: \"The arguments passed to swift test in the Windows nightly main Swift version matrix job.\"\n        default: \"\"\n\n      linux_env_vars:\n        type: string\n        description: \"Environment variables for Linux jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n      windows_env_vars:\n        type: string\n        description: \"Environment variables for Windows jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n\n      minimum_swift_version:\n        type: string\n        description: \"Minimum Swift version to include in the matrix. Leave empty for auto-detection from Package.swift, specify a version like '6.0' to override, or set to 'none' to disable filtering.\"\n        default: \"\"\n\njobs:\n  construct-matrix:\n    name: Construct unit test matrix\n    runs-on: ubuntu-latest\n    outputs:\n      unit-test-matrix: '${{ steps.generate-matrix.outputs.unit-test-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate and use JSON environment variables directly\n          linux_env_vars_json=\"$INPUT_LINUX_ENV_VARS\"\n          windows_env_vars_json=\"$INPUT_WINDOWS_ENV_VARS\"\n\n          # Validate JSON format\n          if ! echo \"$linux_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: linux_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          if ! echo \"$windows_env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: windows_env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          # Generate matrix\n          echo \"unit-test-matrix=$(curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | MATRIX_LINUX_ENV_VARS_JSON=\"${linux_env_vars_json}\" MATRIX_WINDOWS_ENV_VARS_JSON=\"${windows_env_vars_json}\" bash)\" >> \"$GITHUB_OUTPUT\"\n        env:\n          INPUT_LINUX_ENV_VARS: ${{ inputs.linux_env_vars }}\n          INPUT_WINDOWS_ENV_VARS: ${{ inputs.windows_env_vars }}\n          MATRIX_LINUX_SETUP_COMMAND: \"swift --version\"\n          MATRIX_LINUX_COMMAND: \"swift test\"\n          MATRIX_MIN_SWIFT_VERSION: ${{ inputs.minimum_swift_version }}\n          MATRIX_LINUX_5_9_ENABLED: ${{ inputs.linux_5_9_enabled }}\n          MATRIX_LINUX_5_9_COMMAND_ARGUMENTS: ${{ inputs.linux_5_9_arguments_override }}\n          MATRIX_LINUX_5_10_ENABLED: ${{ inputs.linux_5_10_enabled }}\n          MATRIX_LINUX_5_10_COMMAND_ARGUMENTS: ${{ inputs.linux_5_10_arguments_override }}\n          MATRIX_LINUX_6_0_ENABLED: ${{ inputs.linux_6_0_enabled }}\n          MATRIX_LINUX_6_0_COMMAND_ARGUMENTS: ${{ inputs.linux_6_0_arguments_override }}\n          MATRIX_LINUX_6_1_ENABLED: ${{ inputs.linux_6_1_enabled }}\n          MATRIX_LINUX_6_1_COMMAND_ARGUMENTS: ${{ inputs.linux_6_1_arguments_override }}\n          MATRIX_LINUX_6_2_ENABLED: ${{ inputs.linux_6_2_enabled }}\n          MATRIX_LINUX_6_2_COMMAND_ARGUMENTS: ${{ inputs.linux_6_2_arguments_override }}\n          MATRIX_LINUX_NIGHTLY_NEXT_ENABLED: ${{ inputs.linux_nightly_6_1_enabled || inputs.linux_nightly_next_enabled }}\n          MATRIX_LINUX_NIGHTLY_NEXT_COMMAND_ARGUMENTS: ${{ inputs.linux_nightly_6_1_arguments_override }} ${{ inputs.linux_nightly_next_arguments_override }}\n          MATRIX_LINUX_NIGHTLY_MAIN_ENABLED: ${{ inputs.linux_nightly_main_enabled }}\n          MATRIX_LINUX_NIGHTLY_MAIN_COMMAND_ARGUMENTS: ${{ inputs.linux_nightly_main_arguments_override }}\n          MATRIX_WINDOWS_COMMAND: \"swift test\"\n          MATRIX_WINDOWS_6_0_ENABLED: ${{ inputs.windows_6_0_enabled }}\n          MATRIX_WINDOWS_6_0_COMMAND_ARGUMENTS: ${{ inputs.windows_6_0_arguments_override }}\n          MATRIX_WINDOWS_6_1_ENABLED: ${{ inputs.windows_6_1_enabled }}\n          MATRIX_WINDOWS_6_1_COMMAND_ARGUMENTS: ${{ inputs.windows_6_1_arguments_override }}\n          MATRIX_WINDOWS_6_2_ENABLED: ${{ inputs.windows_6_2_enabled }}\n          MATRIX_WINDOWS_6_2_COMMAND_ARGUMENTS: ${{ inputs.windows_6_2_arguments_override }}\n          MATRIX_WINDOWS_NIGHTLY_NEXT_ENABLED: ${{ inputs.windows_nightly_6_1_enabled || inputs.windows_nightly_next_enabled }}\n          MATRIX_WINDOWS_NIGHTLY_NEXT_COMMAND_ARGUMENTS: ${{ inputs.windows_nightly_6_1_arguments_override }} ${{ inputs.windows_nightly_next_arguments_override }}\n          MATRIX_WINDOWS_NIGHTLY_MAIN_ENABLED: ${{ inputs.windows_nightly_main_enabled }}\n          MATRIX_WINDOWS_NIGHTLY_MAIN_COMMAND_ARGUMENTS: ${{ inputs.windows_nightly_main_arguments_override }}\n\n  unit-tests:\n    name: Unit tests\n    needs: construct-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"Unit tests\"\n      matrix_string: '${{ needs.construct-matrix.outputs.unit-test-matrix }}'\n"
  },
  {
    "path": ".github/workflows/wasm_swift_sdk.yml",
    "content": "name: WebAssembly Swift SDK\n\npermissions:\n  contents: read\n\non:\n  workflow_call:\n    inputs:\n      env_vars:\n        type: string\n        description: \"Environment variables for jobs as JSON (e.g., '{\\\"DEBUG\\\":\\\"1\\\",\\\"LOG_LEVEL\\\":\\\"info\\\"}').\"\n        default: \"{}\"\n      additional_command_arguments:\n        type: string\n        description: \"Additional arguments passed to swift build (the Wasm Swift SDK will be specified). Defaults to empty.\"\n        default: \"\"\n\njobs:\n  construct-matrix:\n    name: Construct WebAssembly Swift SDK matrix\n    runs-on: ubuntu-latest\n    outputs:\n      wasm-swift-sdk-matrix: '${{ steps.generate-matrix.outputs.wasm-swift-sdk-matrix }}'\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2\n        with:\n          persist-credentials: false\n      - id: generate-matrix\n        run: |\n          # Validate and use JSON environment variables directly\n          env_vars_json=\"$INPUT_ENV_VARS\"\n\n          # Validate JSON format\n          if ! echo \"$env_vars_json\" | jq empty 2>/dev/null; then\n            echo \"Error: env_vars is not valid JSON\"\n            exit 1\n          fi\n\n          # Generate matrix with parsed environment variables\n          cat >> \"$GITHUB_OUTPUT\" << EOM\n          wasm-swift-sdk-matrix=$(echo '{\n            \"config\":[\n              {\n                \"name\":\"main Jammy\",\n                \"swift_version\":\"main\",\n                \"platform\":\"Linux\",\n                \"runner\":\"ubuntu-latest\",\n                \"image\":\"ubuntu:jammy\",\n                \"setup_command\":\"apt update -q && apt install -y -q curl jq tar && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_prerequisites.sh | bash && curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/install_swift_sdk.sh | INSTALL_SWIFT_BRANCH=main INSTALL_SWIFT_ARCH=x86_64 INSTALL_SWIFT_SDK=wasm-sdk bash && hash -r\",\n                \"command\":\"curl -s --retry 3 https://raw.githubusercontent.com/apple/swift-nio/main/scripts/swift-build-with-wasm-sdk.sh | bash -s --\",\n                \"command_arguments\":\"'\"$INPUT_ADDITIONAL_COMMAND_ARGUMENTS\"'\",\n                \"env\":'\"$env_vars_json\"'\n              }\n            ]\n          }' | jq -c)\n          EOM\n        env:\n          INPUT_ENV_VARS: ${{ inputs.env_vars }}\n          INPUT_ADDITIONAL_COMMAND_ARGUMENTS: ${{ inputs.additional_command_arguments }}\n\n  wasm-swift-sdk:\n    name: WebAssembly Swift SDK\n    needs: construct-matrix\n    # Workaround https://github.com/nektos/act/issues/1875\n    uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main\n    with:\n      name: \"WebAssembly Swift SDK\"\n      matrix_string: '${{ needs.construct-matrix.outputs.wasm-swift-sdk-matrix }}'\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.build\n/.index-build\n/Packages\n/*.xcodeproj\nPackage.pins\n*.pem\n/docs/1.*\n/docs/2.*\nPackage.resolved\n.podspecs\nDerivedData\n.swiftpm\n.*.sw?\n.vscode/launch.json\n"
  },
  {
    "path": ".licenseignore",
    "content": ".gitignore\n**/.gitignore\n.licenseignore\n.gitattributes\n.git-blame-ignore-revs\n.mailfilter\n.mailmap\n.spi.yml\n.swift-format\n.editorconfig\n.github/*\n*.md\n*.txt\n*.yml\n*.yaml\n*.json\nPackage.swift\n**/Package.swift\nPackage@-*.swift\n**/Package@-*.swift\nPackage.resolved\n**/Package.resolved\nMakefile\n*.modulemap\n**/*.modulemap\n**/*.docc/*\n*.xcprivacy\n**/*.xcprivacy\n*.symlink\n**/*.symlink\nDockerfile\n**/Dockerfile\nSnippets/*\nSources/CNIOAtomics/src/cpp_magic.h\nSources/CNIOLLHTTP/LICENSE\nSources/CNIOLLHTTP/c_nio_api.c\nSources/CNIOLLHTTP/c_nio_http.c\nSources/CNIOLLHTTP/c_nio_llhttp.c\nSources/CNIOLLHTTP/include/c_nio_llhttp.h\nSources/CNIOSHA1/c_nio_sha1.c\nSources/CNIOSHA1/include/CNIOSHA1.h\ndev/alloc-limits-from-test-output\ndev/boxed-existentials.d\ndev/git.commit.template\ndev/lldb-smoker\ndev/make-single-file-spm\ndev/malloc-aggregation.d\ndev/malloc-aggregation.bt\ndev/update-alloc-limits-to-last-completed-ci-build\nscripts/nio-diagnose\n"
  },
  {
    "path": ".mailfilter",
    "content": "# This is a list of `shasum` hashed email addresses which are filtered from CONTRIBUTORS.txt, typically for privacy.\n# Lines can be generated by running `echo -n 'My Name <my@email>' | shasum | head -c 40`.\n\n38268a29b340ecfb435c5e6c5827a596acb71cc6\n886d1da6503c6de1d630beaf6acb667e4ce3e2a0\nf0c2beeae30f3012fa02257998baca1737540bda\n"
  },
  {
    "path": ".mailmap",
    "content": "Tomer Doron <tomerd@apple.com> <tomer.doron@gmail.com>\nTomer Doron <tomerd@apple.com>\nTomer Doron <tomerd@apple.com> tomer doron <tomer@apple.com>\nMax Moiseev <moiseev@apple.com>\nJohannes Weiss <johannesweiss@apple.com> <johannesweiss@apple.com>\nJohannes Weiss <johannesweiss@apple.com> <johannes@jweiss.io>\nJohannes Weiss <johannesweiss@apple.com> <github@tux4u.de>\nAdam Nemecek <adamnemecek@gmail.com>\nJim Dovey <jimdovey@mac.com> <jdovey@linkedin.com>\n<bas@basbroek.nl> <BasThomas@users.noreply.github.com>\n<daniel_dunbar@apple.com> <daniel@zuster.org>\n<norman_maurer@apple.com> <norman.maurer@googlemail.com>\n<cbenfield@apple.com> <lukasaoz@gmail.com>\n<cbenfield@apple.com> <lukasa@apple.com>\n<helge@alwaysrightinstitute.com> <devteam@zeezide.de>\nTim Condon <0xtimc@gmail.com> Tim <0xTim@users.noreply.github.com>\nTim Condon <0xtimc@gmail.com> <0xTim@users.noreply.github.com>\nTim Condon <0xtimc@gmail.com> Tim <0xtimc@gmail.com>\nGeorge Barnett <gbarnett@apple.com> <gbrntt@gmail.com>\nAlex Blewitt <alblue@apple.com> <alex.blewitt@gmail.com>\nBen Cohen <ben_cohen@apple.com> <airspeedswift@users.noreply.github.com>\nJason Toffaletti <jtoffaletti@apple.com> <toffaletti@gmail.com>\nGwynne Raskind <gwynne@vapor.codes> <graskind@apple.com>\nGwynne Raskind <gwynne@vapor.codes> <gwynne@darkrainfall.org>\nGwynne Raskind <gwynne@vapor.codes> <gwynne@users.noreply.github.com>\nKevin Sweeney <kevin_sweeney@apple.com> <kevin.t.sweeney@gmail.com>\nLev Walkin <lwalkin@apple.com> <vlm@lionet.info>\nLudovic Dewailly <ldewailly@apple.com> <me@ldewailly.com>\nKonrad `ktoso` Malawski <ktoso@apple.com> <konrad.malawski@project13.pl>\nKonrad `ktoso` Malawski <ktoso@apple.com> <konrad_malawski@apple.com>\nArtem Redkin <aredkin@apple.com> <artem@redkin.me>\nJovan Milenkovic <jovan.milenkovic@htecgroup.com> <jovanmilenkovic@live.com>\nNathan Harris <nathan@mordil.info> <Mordil@users.noreply.github.com>\nSergo Beruashvili <beruashvili@gmail.com> <2391557+ogres@users.noreply.github.com>\nSergej Jaskiewicz <jaskiewiczs@icloud.com> <broadwaylamb@users.noreply.github.com>\nSiemen Sikkema <s.h.sikkema@gmail.com> <siemensikkema@users.noreply.github.com>\nDario Rexin <drexin@apple.com> <dario.rexin@me.com>\nRomain Pouclet <rpouclet@apple.com> <romain.pouclet@gmail.com>\nJulian Lettner <julian.lettner@apple.com> <yln@users.noreply.github.com>\nMario Sangiorgio <msangiorgio@apple.com> <mariosangiorgio@gmail.com>\nMarli Oshlack <marli.oshlack@apple.com> <marli@oshlack.com>\nDavid Evans <d.evans@apple.com> <david.evans@blackpoint.co>\nJake Foster <jakef@fastmail.com> <2bjake@users.noreply.github.com>\nEmil Marashliev <marashliev@gmail.com> <emarashliev@users.noreply.github.com>\nHeidi Puk Hermann <heidi.puk@gmail.com> <32973281+heidipuk@users.noreply.github.com>\nJoachim M. <joachim.me86@gmail.com> <32777429+Lupurus@users.noreply.github.com>\nRichard Low <ral@apple.com> <richard@wentnet.com>\nPushparaj Zala <pr92zala@gmail.com> <przala@users.noreply.github.com>\nChristian Priebe <cpriebe@apple.com> <chr.priebe@gmail.com>\nPeter Adams <pp_adams@apple.com> <61008809+PeterAdams76@users.noreply.github.com>\nPeter Adams <pp_adams@apple.com> <63288215+PeterAdams-A@users.noreply.github.com>\nShekhar Rajak <shekhar_rajak@apple.com> <60732970+shekhar-rajak@users.noreply.github.com>\nLiam Flynn <l.flynn@live.co.uk> <l.flynn2@live.co.uk>\nAndrew Naylor <andrew_naylor@apple.com> <argon@mkbot.net>\nAndrius Aucinas <aaucinas@apple.com>\nAndrius Aucinas <aaucinas@apple.com> <andrius.aucinas@gmail.com>\nFabian Fett <fabianfett@apple.com> <fabianfett@gmail.com>\nFabian Fett <fabianfett@apple.com> <fabianfett@mac.com>\nGraeme Jenkinson <graeme_jenkinson@apple.com> <gcjenkinson@users.noreply.github.com>\nMax Desiatov <max@desiatov.com> <max.desiatov@gmail.com>\nJoshua Rutkowski <jr.rtkski@gmail.com> <54906829+joshrutkowski@users.noreply.github.com>\nRémi Doreau <remi.d45@gmail.com> <32459935+ayshiff@users.noreply.github.com>\nFranz Busch <f.busch@apple.com> <privat@franz-busch.de>\nDavid Nadoba <d_nadoba@apple.com> <dnadoba@gmail.com>\nSi Beaumont <beaumont@apple.com> <simonjbeaumont@gmail.com>\nBenedict St. <benedictst@icloud.com> <52418145+BenedictSt@users.noreply.github.com>\nAustin Payne <austin.payne.01@gmail.com> <Austinpayne@users.noreply.github.com>\nDonghyeon Kim <wplong11@gmail.com> <wplong11@users.noreply.github.com>\nGuillaume Lessard <guillaume.lessard@apple.com> <glessard@users.noreply.github.com>\nJoakim Hassila <jocke@ordo.one> <hassila@users.noreply.github.com>\nStepan Ulyanin <sulyanin@apple.com> <99296376+stepan-ulyanin@users.noreply.github.com>\nFinagolfin <butta@fastem.com> <repo@butta.fastem.com>\nPaul Schmiedmayer <paul.schmiedmayer@tum.de> <PSchmiedmayer@users.noreply.github.com>\nJohn Connolly <connoljo2@gmail.com> <jconnolly@touchbistro.com>\nRick Newton-Rogers <rnewtonrogers@apple.com> <104022490+rnro@users.noreply.github.com>\n"
  },
  {
    "path": ".spi.yml",
    "content": "version: 1\nbuilder:\n  configs:\n    - documentation_targets: [NIO, NIOConcurrencyHelpers, NIOCore, NIOEmbedded, NIOFoundationCompat, NIOHTTP1, NIOPosix, NIOTLS, NIOWebSocket, NIOTestUtils, _NIOFileSystem, NIOFileSystem]\n"
  },
  {
    "path": ".swift-format",
    "content": "{\n  \"version\" : 1,\n  \"indentation\" : {\n    \"spaces\" : 4\n  },\n  \"tabWidth\" : 4,\n  \"fileScopedDeclarationPrivacy\" : {\n    \"accessLevel\" : \"private\"\n  },\n  \"spacesAroundRangeFormationOperators\" : false,\n  \"indentConditionalCompilationBlocks\" : false,\n  \"indentSwitchCaseLabels\" : false,\n  \"lineBreakAroundMultilineExpressionChainComponents\" : false,\n  \"lineBreakBeforeControlFlowKeywords\" : false,\n  \"lineBreakBeforeEachArgument\" : true,\n  \"lineBreakBeforeEachGenericRequirement\" : true,\n  \"lineLength\" : 120,\n  \"maximumBlankLines\" : 1,\n  \"respectsExistingLineBreaks\" : true,\n  \"prioritizeKeepingFunctionOutputTogether\" : true,\n  \"rules\" : {\n    \"AllPublicDeclarationsHaveDocumentation\" : false,\n    \"AlwaysUseLiteralForEmptyCollectionInit\" : false,\n    \"AlwaysUseLowerCamelCase\" : false,\n    \"AmbiguousTrailingClosureOverload\" : true,\n    \"BeginDocumentationCommentWithOneLineSummary\" : false,\n    \"DoNotUseSemicolons\" : true,\n    \"DontRepeatTypeInStaticProperties\" : true,\n    \"FileScopedDeclarationPrivacy\" : true,\n    \"FullyIndirectEnum\" : true,\n    \"GroupNumericLiterals\" : true,\n    \"IdentifiersMustBeASCII\" : true,\n    \"NeverForceUnwrap\" : false,\n    \"NeverUseForceTry\" : false,\n    \"NeverUseImplicitlyUnwrappedOptionals\" : false,\n    \"NoAccessLevelOnExtensionDeclaration\" : true,\n    \"NoAssignmentInExpressions\" : true,\n    \"NoBlockComments\" : true,\n    \"NoCasesWithOnlyFallthrough\" : true,\n    \"NoEmptyTrailingClosureParentheses\" : true,\n    \"NoLabelsInCasePatterns\" : true,\n    \"NoLeadingUnderscores\" : false,\n    \"NoParensAroundConditions\" : true,\n    \"NoVoidReturnOnFunctionSignature\" : true,\n    \"OmitExplicitReturns\" : true,\n    \"OneCasePerLine\" : true,\n    \"OneVariableDeclarationPerLine\" : true,\n    \"OnlyOneTrailingClosureArgument\" : true,\n    \"OrderedImports\" : true,\n    \"ReplaceForEachWithForLoop\" : true,\n    \"ReturnVoidInsteadOfEmptyTuple\" : true,\n    \"UseEarlyExits\" : false,\n    \"UseExplicitNilCheckInConditions\" : false,\n    \"UseLetInEveryBoundCaseVariable\" : false,\n    \"UseShorthandTypeNames\" : true,\n    \"UseSingleLinePropertyGetter\" : false,\n    \"UseSynthesizedInitializer\" : false,\n    \"UseTripleSlashForDocumentationComments\" : true,\n    \"UseWhereClausesInForLoops\" : false,\n    \"ValidateDocumentationComments\" : false\n  }\n}\n"
  },
  {
    "path": "Benchmarks/.gitignore",
    "content": ".DS_Store\n/.build\n/Packages\nxcuserdata/\nDerivedData/\n.swiftpm/configuration/registries.json\n.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata\n.netrc\n.benchmarkBaselines/"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOCoreBenchmarks/Benchmarks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Benchmark\nimport NIOCore\nimport NIOEmbedded\n\n// MARK: - Handlers for AddressedEnvelope benchmarks\n\nprivate final class ByteBufferEnvelopeForwardingHandler: ChannelInboundHandler, Sendable {\n    typealias InboundIn = AddressedEnvelope<ByteBuffer>\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.fireChannelRead(data)\n    }\n}\n\nprivate final class StringEnvelopeForwardingHandler: ChannelInboundHandler, Sendable {\n    typealias InboundIn = AddressedEnvelope<String>\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.fireChannelRead(data)\n    }\n}\n\n// MARK: - Handlers for ChannelPipeline benchmarks\n\nprivate final class NoOpHandler: ChannelInboundHandler, Sendable {\n    typealias InboundIn = Any\n}\n\n// MARK: - Benchmarks\n\nlet benchmarks = {\n    #if LOCAL_TESTING\n    let defaultMetrics: [BenchmarkMetric] = [\n        .mallocCountTotal,\n        .contextSwitches,\n        .wallClock,\n        .instructions,\n    ]\n    #else\n    let defaultMetrics: [BenchmarkMetric] = [\n        .mallocCountTotal\n    ]\n    #endif\n\n    let leakMetrics: [BenchmarkMetric] = [\n        .mallocCountTotal,\n        .memoryLeaked,\n    ]\n\n    Benchmark(\n        \"NIOAsyncChannel.init\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 10\n        )\n    ) { benchmark in\n        // Elide the cost of the 'EmbeddedChannel'. It's only used for its pipeline.\n        var channels: [EmbeddedChannel] = []\n        channels.reserveCapacity(benchmark.scaledIterations.count)\n        for _ in 0..<benchmark.scaledIterations.count {\n            channels.append(EmbeddedChannel())\n        }\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n        for channel in channels {\n            let asyncChanel = try NIOAsyncChannel<ByteBuffer, ByteBuffer>(wrappingChannelSynchronously: channel)\n            blackHole(asyncChanel)\n        }\n    }\n\n    Benchmark(\n        \"WaitOnPromise\",\n        configuration: .init(\n            metrics: leakMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 10_000  // need 10k to get a signal\n        )\n    ) { benchmark in\n        // Elide the cost of the 'EmbeddedEventLoop'.\n        let el = EmbeddedEventLoop()\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            let p = el.makePromise(of: Int.self)\n            p.succeed(0)\n            do { _ = try! p.futureResult.wait() }\n        }\n    }\n\n    Benchmark(\n        \"AddressedEnvelope.ByteBuffer.noMetadata\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 10\n        )\n    ) { benchmark in\n        // Setup: Create channel with 20 forwarding handlers\n        let channel = EmbeddedChannel()\n        for _ in 0..<20 {\n            try! channel.pipeline.syncOperations.addHandler(ByteBufferEnvelopeForwardingHandler())\n        }\n\n        // Create the envelope without metadata\n        let address = try! SocketAddress(ipAddress: \"::1\", port: 8080)\n        let buffer = ByteBuffer(string: \"test data\")\n        let envelope = AddressedEnvelope(remoteAddress: address, data: buffer)\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            try! channel.writeInbound(envelope)\n            let result: AddressedEnvelope<ByteBuffer>? = try! channel.readInbound()\n            blackHole(result)\n        }\n    }\n\n    Benchmark(\n        \"AddressedEnvelope.ByteBuffer.withMetadata\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 10\n        )\n    ) { benchmark in\n        // Setup: Create channel with 20 forwarding handlers\n        let channel = EmbeddedChannel()\n        for _ in 0..<20 {\n            try! channel.pipeline.syncOperations.addHandler(ByteBufferEnvelopeForwardingHandler())\n        }\n\n        // Create the envelope with full metadata\n        let address = try! SocketAddress(ipAddress: \"::1\", port: 8080)\n        let buffer = ByteBuffer(string: \"test data\")\n        let metadata = AddressedEnvelope<ByteBuffer>.Metadata(\n            ecnState: .transportNotCapable,\n            packetInfo: NIOPacketInfo(destinationAddress: address, interfaceIndex: 1),\n            segmentSize: 1200\n        )\n        let envelope = AddressedEnvelope(remoteAddress: address, data: buffer, metadata: metadata)\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            try! channel.writeInbound(envelope)\n            let result: AddressedEnvelope<ByteBuffer>? = try! channel.readInbound()\n            blackHole(result)\n        }\n    }\n\n    Benchmark(\n        \"AddressedEnvelope.String.noMetadata\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 10\n        )\n    ) { benchmark in\n        // Setup: Create channel with 20 forwarding handlers\n        let channel = EmbeddedChannel()\n        for _ in 0..<20 {\n            try! channel.pipeline.syncOperations.addHandler(StringEnvelopeForwardingHandler())\n        }\n\n        // Create the envelope without metadata\n        let address = try! SocketAddress(ipAddress: \"::1\", port: 8080)\n        let envelope = AddressedEnvelope(remoteAddress: address, data: \"test data\")\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            try! channel.writeInbound(envelope)\n            let result: AddressedEnvelope<String>? = try! channel.readInbound()\n            blackHole(result)\n        }\n    }\n\n    Benchmark(\n        \"AddressedEnvelope.String.withMetadata\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 10\n        )\n    ) { benchmark in\n        // Setup: Create channel with 20 forwarding handlers\n        let channel = EmbeddedChannel()\n        for _ in 0..<20 {\n            try! channel.pipeline.syncOperations.addHandler(StringEnvelopeForwardingHandler())\n        }\n\n        // Create the envelope with full metadata\n        let address = try! SocketAddress(ipAddress: \"::1\", port: 8080)\n        let metadata = AddressedEnvelope<String>.Metadata(\n            ecnState: .transportNotCapable,\n            packetInfo: NIOPacketInfo(destinationAddress: address, interfaceIndex: 1),\n            segmentSize: 1200\n        )\n        let envelope = AddressedEnvelope(remoteAddress: address, data: \"test data\", metadata: metadata)\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            try! channel.writeInbound(envelope)\n            let result: AddressedEnvelope<String>? = try! channel.readInbound()\n            blackHole(result)\n        }\n    }\n\n    Benchmark(\n        \"ChannelPipeline.init(0 handlers)\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 1000\n        )\n    ) { benchmark in\n        let channel = EmbeddedChannel()\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            let pipeline = ChannelPipeline(channel: channel)\n            blackHole(pipeline)\n        }\n    }\n\n    Benchmark(\n        \"ChannelPipeline.init(1 handler)\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 1000\n        )\n    ) { benchmark in\n        let channel = EmbeddedChannel()\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            let pipeline = ChannelPipeline(channel: channel)\n            let syncOps = pipeline.syncOperations\n            for _ in 0..<1 {\n                try! syncOps.addHandler(NoOpHandler())\n            }\n            blackHole(pipeline)\n        }\n    }\n\n    Benchmark(\n        \"ChannelPipeline.init(3 handlers)\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 1000\n        )\n    ) { benchmark in\n        let channel = EmbeddedChannel()\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            let pipeline = ChannelPipeline(channel: channel)\n            let syncOps = pipeline.syncOperations\n            for _ in 0..<3 {\n                try! syncOps.addHandler(NoOpHandler())\n            }\n            blackHole(pipeline)\n        }\n    }\n\n    Benchmark(\n        \"ChannelPipeline.init(10 handlers)\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 1000\n        )\n    ) { benchmark in\n        let channel = EmbeddedChannel()\n\n        benchmark.startMeasurement()\n        defer {\n            benchmark.stopMeasurement()\n        }\n\n        for _ in 0..<benchmark.scaledIterations.count {\n            let pipeline = ChannelPipeline(channel: channel)\n            let syncOps = pipeline.syncOperations\n            for _ in 0..<10 {\n                try! syncOps.addHandler(NoOpHandler())\n            }\n            blackHole(pipeline)\n        }\n    }\n}\n"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOPosixBenchmarks/Benchmarks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Benchmark\nimport NIOCore\nimport NIOPosix\n\nprivate let eventLoop = MultiThreadedEventLoopGroup.singleton.next()\n\nlet benchmarks = {\n    let defaultMetrics: [BenchmarkMetric] = [\n        .mallocCountTotal,\n        .contextSwitches,\n        .wallClock,\n    ]\n\n    Benchmark(\n        \"TCPEcho\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .mega,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 5,\n            thresholds: [.mallocCountTotal: .init(absolute: [.p90: 50])]\n        )\n    ) { benchmark in\n        try runTCPEcho(\n            numberOfWrites: benchmark.scaledIterations.upperBound,\n            eventLoop: eventLoop\n        )\n    }\n\n    Benchmark(\n        \"TCPEchoAsyncChannel\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .mega,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 5,\n            // We are expecting a bit of allocation variance due to an allocation\n            // in the Concurrency runtime which happens when resuming a continuation.\n            thresholds: [.mallocCountTotal: .init(absolute: [.p90: 2000])],\n            setup: {\n                swiftTaskEnqueueGlobalHook = { job, _ in\n                    eventLoop.executor.enqueue(job)\n                }\n            },\n            teardown: {\n                swiftTaskEnqueueGlobalHook = nil\n            }\n        )\n    ) { benchmark in\n        try await runTCPEchoAsyncChannel(\n            numberOfWrites: benchmark.scaledIterations.upperBound,\n            eventLoop: eventLoop\n        )\n    }\n\n    Benchmark(\n        \"UDPEcho\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 5\n        )\n    ) { benchmark in\n        try runUDPEcho(\n            numberOfWrites: benchmark.scaledIterations.upperBound,\n            eventLoop: eventLoop\n        )\n    }\n\n    Benchmark(\n        \"UDPEchoPacketInfo\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 5\n        )\n    ) { benchmark in\n        try runUDPEchoPacketInfo(\n            numberOfWrites: benchmark.scaledIterations.upperBound,\n            eventLoop: eventLoop\n        )\n    }\n\n    Benchmark(\n        \"MTELG.scheduleTask(in:_:)\",\n        configuration: Benchmark.Configuration(\n            metrics: defaultMetrics,\n            scalingFactor: .mega,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 5\n        )\n    ) { benchmark in\n        for _ in benchmark.scaledIterations {\n            eventLoop.scheduleTask(in: .hours(1), {})\n        }\n    }\n\n    Benchmark(\n        \"MTELG.scheduleCallback(in:_:)\",\n        configuration: Benchmark.Configuration(\n            metrics: defaultMetrics,\n            scalingFactor: .mega,\n            maxDuration: .seconds(10_000_000),\n            maxIterations: 5\n        )\n    ) { benchmark in\n        final class Timer: NIOScheduledCallbackHandler {\n            func handleScheduledCallback(eventLoop: some EventLoop) {}\n        }\n        let timer = Timer()\n\n        benchmark.startMeasurement()\n        for _ in benchmark.scaledIterations {\n            let handle = try! eventLoop.scheduleCallback(in: .hours(1), handler: timer)\n        }\n    }\n\n    Benchmark(\n        \"Jump to EL and back using execute and unsafecontinuation\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo\n        )\n    ) { benchmark in\n        for _ in benchmark.scaledIterations {\n            await withUnsafeContinuation { (continuation: UnsafeContinuation<Void, Never>) in\n                eventLoop.execute {\n                    continuation.resume()\n                }\n            }\n        }\n    }\n\n    final actor Foo {\n        nonisolated public let unownedExecutor: UnownedSerialExecutor\n\n        init(eventLoop: any EventLoop) {\n            self.unownedExecutor = eventLoop.executor.asUnownedSerialExecutor()\n        }\n\n        func foo() {\n            blackHole(Void())\n        }\n    }\n\n    Benchmark(\n        \"Jump to EL and back using actor with EL executor\",\n        configuration: .init(\n            metrics: defaultMetrics,\n            scalingFactor: .kilo\n        )\n    ) { benchmark in\n        let actor = Foo(eventLoop: eventLoop)\n        for _ in benchmark.scaledIterations {\n            await actor.foo()\n        }\n    }\n\n    // MARK: - NIOThreadPool submit benchmarks\n\n    // Serial wakeup: submit one item, wait for completion, repeat.\n    // Every submit hits N sleeping threads — this is where wake-one\n    // vs wake-all (thundering herd) matters most.\n    let pool16 = NIOThreadPool(numberOfThreads: 16)\n    let pool4 = NIOThreadPool(numberOfThreads: 4)\n\n    Benchmark(\n        \"NIOThreadPool.serial_wakeup(16 threads)\",\n        configuration: .init(\n            metrics: [.wallClock, .cpuUser, .cpuSystem, .cpuTotal, .contextSwitches, .syscalls],\n            maxDuration: .seconds(30),\n            maxIterations: 30,\n            setup: { pool16.start() },\n            teardown: { try! pool16.syncShutdownGracefully() }\n        )\n    ) { _ in\n        runNIOThreadPoolSerialWakeup(pool: pool16, count: 10_000)\n    }\n\n    Benchmark(\n        \"NIOThreadPool.serial_wakeup(4 threads)\",\n        configuration: .init(\n            metrics: [.wallClock, .cpuUser, .cpuSystem, .cpuTotal, .contextSwitches, .syscalls],\n            maxDuration: .seconds(30),\n            maxIterations: 30,\n            setup: { pool4.start() },\n            teardown: { try! pool4.syncShutdownGracefully() }\n        )\n    ) { _ in\n        runNIOThreadPoolSerialWakeup(pool: pool4, count: 10_000)\n    }\n}\n"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOPosixBenchmarks/NIOThreadPoolBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nfunc runNIOThreadPoolSerialWakeup(pool: NIOThreadPool, count: Int) {\n    let sem = DispatchSemaphore(value: 0)\n    for _ in 0..<count {\n        pool.submit { state in\n            precondition(state == .active)\n            sem.signal()\n        }\n        sem.wait()\n    }\n}\n"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOPosixBenchmarks/TCPEcho.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class EchoChannelHandler: ChannelInboundHandler {\n    fileprivate typealias InboundIn = ByteBuffer\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.writeAndFlush(data, promise: nil)\n    }\n}\n\nprivate final class EchoRequestChannelHandler: ChannelInboundHandler {\n    fileprivate typealias InboundIn = ByteBuffer\n\n    private let messageSize = 10000\n    private let numberOfWrites: Int\n    private var batchCount = 0\n    private let data: NIOAny\n    private let readsCompletePromise: EventLoopPromise<Void>\n    private var receivedData = 0\n\n    init(numberOfWrites: Int, readsCompletePromise: EventLoopPromise<Void>) {\n        self.numberOfWrites = numberOfWrites\n        self.readsCompletePromise = readsCompletePromise\n        self.data = NIOAny(ByteBuffer(repeating: 0, count: self.messageSize))\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        for _ in 0..<self.numberOfWrites {\n            context.writeAndFlush(data, promise: nil)\n        }\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let buffer = Self.unwrapInboundIn(data)\n        self.receivedData += buffer.readableBytes\n\n        if self.receivedData == self.numberOfWrites * self.messageSize {\n            self.readsCompletePromise.succeed()\n        }\n    }\n}\n\nfunc runTCPEcho(numberOfWrites: Int, eventLoop: any EventLoop) throws {\n    let serverChannel = try ServerBootstrap(group: eventLoop)\n        .childChannelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHandler(EchoChannelHandler())\n            }\n        }\n        .bind(\n            host: \"127.0.0.1\",\n            port: 0\n        ).wait()\n\n    let readsCompletePromise = eventLoop.makePromise(of: Void.self)\n    let clientChannel = try ClientBootstrap(group: eventLoop)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                let echoRequestHandler = EchoRequestChannelHandler(\n                    numberOfWrites: numberOfWrites,\n                    readsCompletePromise: readsCompletePromise\n                )\n                try channel.pipeline.syncOperations.addHandler(echoRequestHandler)\n            }\n        }\n        .connect(\n            host: \"127.0.0.1\",\n            port: serverChannel.localAddress!.port!\n        ).wait()\n\n    // Waiting for the client to collect all echoed data.\n    try readsCompletePromise.futureResult.wait()\n    try serverChannel.close().wait()\n    try clientChannel.close().wait()\n}\n"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOPosixBenchmarks/TCPEchoAsyncChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nfunc runTCPEchoAsyncChannel(numberOfWrites: Int, eventLoop: EventLoop) async throws {\n    let serverChannel = try await ServerBootstrap(group: eventLoop)\n        .bind(\n            host: \"127.0.0.1\",\n            port: 0\n        ) { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try NIOAsyncChannel(\n                    wrappingChannelSynchronously: channel,\n                    configuration: .init(\n                        inboundType: ByteBuffer.self,\n                        outboundType: ByteBuffer.self\n                    )\n                )\n            }\n        }\n\n    let clientChannel = try await ClientBootstrap(group: eventLoop)\n        .connect(\n            host: \"127.0.0.1\",\n            port: serverChannel.channel.localAddress!.port!\n        ) { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try NIOAsyncChannel(\n                    wrappingChannelSynchronously: channel,\n                    configuration: .init(\n                        inboundType: ByteBuffer.self,\n                        outboundType: ByteBuffer.self\n                    )\n                )\n            }\n        }\n\n    let messageSize = 10000\n\n    try await withThrowingTaskGroup(of: Void.self) { group in\n        // This child task is echoing back the data on the server.\n        group.addTask {\n            try await serverChannel.executeThenClose { serverChannelInbound in\n                for try await connectionChannel in serverChannelInbound {\n                    try await connectionChannel.executeThenClose {\n                        connectionChannelInbound,\n                        connectionChannelOutbound in\n                        for try await inboundData in connectionChannelInbound {\n                            try await connectionChannelOutbound.write(inboundData)\n                        }\n                    }\n                }\n            }\n        }\n\n        try await clientChannel.executeThenClose { inbound, outbound in\n            // This child task is collecting the echoed back responses.\n            group.addTask {\n                var receivedData = 0\n                for try await inboundData in inbound {\n                    receivedData += inboundData.readableBytes\n\n                    if receivedData == numberOfWrites * messageSize {\n                        return\n                    }\n                }\n            }\n\n            // Let's start sending data.\n            let data = ByteBuffer(repeating: 0, count: messageSize)\n            for _ in 0..<numberOfWrites {\n                try await outbound.write(data)\n            }\n\n            // Waiting for the child task that collects the responses to finish.\n            try await group.next()\n\n            // Cancelling the server child task.\n            group.cancelAll()\n            try await serverChannel.channel.closeFuture.get()\n            try await clientChannel.channel.closeFuture.get()\n        }\n    }\n}\n"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOPosixBenchmarks/UDPEcho.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class UDPEchoHandler: ChannelInboundHandler {\n    typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.write(data, promise: nil)\n    }\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        context.flush()\n    }\n}\n\nprivate final class UDPEchoRequestHandler: ChannelInboundHandler {\n    typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n    private let buffer = ByteBuffer(repeating: 0, count: 512)\n    private let numberOfWrites: Int\n    private let remoteAddress: SocketAddress\n    private var receivedCount = 0\n    private let readsCompletePromise: EventLoopPromise<Void>\n\n    init(\n        numberOfWrites: Int,\n        remoteAddress: SocketAddress,\n        readsCompletePromise: EventLoopPromise<Void>\n    ) {\n        self.numberOfWrites = numberOfWrites\n        self.remoteAddress = remoteAddress\n        self.readsCompletePromise = readsCompletePromise\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        self.writeAgain(context: context)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.receivedCount += 1\n\n        if self.receivedCount == self.numberOfWrites {\n            self.readsCompletePromise.succeed()\n        } else {\n            self.writeAgain(context: context)\n        }\n    }\n\n    private func writeAgain(context: ChannelHandlerContext) {\n        let envelope = AddressedEnvelope(\n            remoteAddress: self.remoteAddress,\n            data: buffer\n        )\n        context.write(Self.wrapOutboundOut(envelope), promise: nil)\n        context.flush()\n    }\n}\n\nfunc runUDPEcho(numberOfWrites: Int, eventLoop: any EventLoop) throws {\n    let address = try SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0)\n\n    // Create server channel\n    let serverChannel = try DatagramBootstrap(group: eventLoop)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHandler(UDPEchoHandler())\n            }\n        }\n        .bind(to: address)\n        .wait()\n\n    let readsCompletePromise = eventLoop.makePromise(of: Void.self)\n\n    // Create client channel\n    let clientChannel = try DatagramBootstrap(group: eventLoop)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                let handler = UDPEchoRequestHandler(\n                    numberOfWrites: numberOfWrites,\n                    remoteAddress: serverChannel.localAddress!,\n                    readsCompletePromise: readsCompletePromise\n                )\n                try channel.pipeline.syncOperations.addHandler(handler)\n            }\n        }\n        .bind(to: address)\n        .wait()\n\n    // Wait for all echoes to complete\n    try readsCompletePromise.futureResult.wait()\n\n    // Cleanup\n    try serverChannel.close().wait()\n    try clientChannel.close().wait()\n}\n\nfunc runUDPEchoPacketInfo(numberOfWrites: Int, eventLoop: any EventLoop) throws {\n    let address = try SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0)\n\n    // Create server channel with receivePacketInfo enabled\n    let serverChannel = try DatagramBootstrap(group: eventLoop)\n        .channelOption(.receivePacketInfo, value: true)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHandler(UDPEchoHandler())\n            }\n        }\n        .bind(to: address)\n        .wait()\n\n    let readsCompletePromise = eventLoop.makePromise(of: Void.self)\n\n    // Create client channel with receivePacketInfo enabled\n    let clientChannel = try DatagramBootstrap(group: eventLoop)\n        .channelOption(.receivePacketInfo, value: true)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                let handler = UDPEchoRequestHandler(\n                    numberOfWrites: numberOfWrites,\n                    remoteAddress: serverChannel.localAddress!,\n                    readsCompletePromise: readsCompletePromise\n                )\n                try channel.pipeline.syncOperations.addHandler(handler)\n            }\n        }\n        .bind(to: address)\n        .wait()\n\n    // Wait for all echoes to complete\n    try readsCompletePromise.futureResult.wait()\n\n    // Cleanup\n    try serverChannel.close().wait()\n    try clientChannel.close().wait()\n}\n"
  },
  {
    "path": "Benchmarks/Benchmarks/NIOPosixBenchmarks/Util/GlobalExecutor.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin)\nimport Darwin.C\n#elseif canImport(Glibc)\nimport Glibc\n#else\n#error(\"Unsupported platform.\")\n#endif\n\n// This file allows us to hook the global executor which\n// we can use to mimic task executors for now.\ntypealias EnqueueGlobalHook = @convention(thin) (UnownedJob, @convention(thin) (UnownedJob) -> Void) -> Void\n\nvar swiftTaskEnqueueGlobalHook: EnqueueGlobalHook? {\n    get { _swiftTaskEnqueueGlobalHook.pointee }\n    set { _swiftTaskEnqueueGlobalHook.pointee = newValue }\n}\n\nprivate let _swiftTaskEnqueueGlobalHook: UnsafeMutablePointer<EnqueueGlobalHook?> =\n    dlsym(dlopen(nil, RTLD_LAZY), \"swift_task_enqueueGlobal_hook\").assumingMemoryBound(to: EnqueueGlobalHook?.self)\n"
  },
  {
    "path": "Benchmarks/Package.swift",
    "content": "// swift-tools-version:5.10\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"benchmarks\",\n    platforms: [\n        .macOS(\"14\")\n    ],\n    dependencies: [\n        .package(path: \"../\"),\n        .package(url: \"https://github.com/ordo-one/package-benchmark.git\", from: \"1.29.11\"),\n    ],\n    targets: [\n        .executableTarget(\n            name: \"NIOPosixBenchmarks\",\n            dependencies: [\n                .product(name: \"Benchmark\", package: \"package-benchmark\"),\n                .product(name: \"NIOCore\", package: \"swift-nio\"),\n                .product(name: \"NIOPosix\", package: \"swift-nio\"),\n            ],\n            path: \"Benchmarks/NIOPosixBenchmarks\",\n            plugins: [\n                .plugin(name: \"BenchmarkPlugin\", package: \"package-benchmark\")\n            ]\n        ),\n        .executableTarget(\n            name: \"NIOCoreBenchmarks\",\n            dependencies: [\n                .product(name: \"Benchmark\", package: \"package-benchmark\"),\n                .product(name: \"NIOCore\", package: \"swift-nio\"),\n                .product(name: \"NIOEmbedded\", package: \"swift-nio\"),\n            ],\n            path: \"Benchmarks/NIOCoreBenchmarks\",\n            plugins: [\n                .plugin(name: \"BenchmarkPlugin\", package: \"package-benchmark\")\n            ]\n        ),\n    ]\n)\n"
  },
  {
    "path": "Benchmarks/Thresholds/5.10/NIOCoreBenchmarks.NIOAsyncChannel.init.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 8000\n}"
  },
  {
    "path": "Benchmarks/Thresholds/5.10/NIOCoreBenchmarks.WaitOnPromise.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 6000,\n  \"memoryLeaked\" : 0\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/5.10/NIOPosixBenchmarks.TCPEcho.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 108\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/5.10/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 164375\n}"
  },
  {
    "path": "Benchmarks/Thresholds/6.0/NIOCoreBenchmarks.NIOAsyncChannel.init.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 8000\n}"
  },
  {
    "path": "Benchmarks/Thresholds/6.0/NIOPosixBenchmarks.TCPEcho.p90.json",
    "content": "{\n  \"mallocCountTotal\": 108\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/6.0/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json",
    "content": "{\n  \"mallocCountTotal\": 82754\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/6.1/NIOCoreBenchmarks.NIOAsyncChannel.init.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 8000\n}"
  },
  {
    "path": "Benchmarks/Thresholds/6.1/NIOPosixBenchmarks.TCPEcho.p90.json",
    "content": "{\n  \"mallocCountTotal\": 108\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/6.1/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json",
    "content": "{\n  \"mallocCountTotal\": 82614\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/6.2/NIOCoreBenchmarks.NIOAsyncChannel.init.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 8000\n}"
  },
  {
    "path": "Benchmarks/Thresholds/6.2/NIOPosixBenchmarks.TCPEcho.p90.json",
    "content": "{\n  \"mallocCountTotal\": 603\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/6.2/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json",
    "content": "{\n  \"mallocCountTotal\": 387\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/nightly-main/NIOCoreBenchmarks.NIOAsyncChannel.init.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 8000\n}"
  },
  {
    "path": "Benchmarks/Thresholds/nightly-main/NIOPosixBenchmarks.TCPEcho.p90.json",
    "content": "{\n  \"mallocCountTotal\": 107\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/nightly-main/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json",
    "content": "{\n  \"mallocCountTotal\": 389\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/nightly-next/NIOCoreBenchmarks.NIOAsyncChannel.init.p90.json",
    "content": "{\n  \"mallocCountTotal\" : 8000\n}"
  },
  {
    "path": "Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEcho.p90.json",
    "content": "{\n  \"mallocCountTotal\": 108\n}\n"
  },
  {
    "path": "Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json",
    "content": "{\n  \"mallocCountTotal\": 391\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\nThe code of conduct for this project can be found at https://swift.org/code-of-conduct.\n\n<!-- Copyright (c) 2023 Apple Inc and the Swift Project authors. All Rights Reserved. -->\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Legal\n\nBy submitting a pull request, you represent that you have the right to license\nyour contribution to Apple and the community, and agree by submitting the patch\nthat your contributions are licensed under the Apache 2.0 license (see\n`LICENSE.txt`).\n\n## How to submit a bug report\n\nPlease ensure to specify the following:\n\n* SwiftNIO commit hash\n* Contextual information (e.g. what you were trying to achieve with SwiftNIO)\n* Simplest possible steps to reproduce\n  * More complex the steps are, lower the priority will be.\n  * A pull request with failing test case is preferred, but it's just fine to paste the test case into the issue description.\n* Anything that might be relevant in your opinion, such as:\n  * Swift version or the output of `swift --version`\n  * OS version and the output of `uname -a`\n  * Network configuration\n\n### Example\n\n```\nSwiftNIO commit hash: 22ec043dc9d24bb011b47ece4f9ee97ee5be2757\n\nContext:\nWhile load testing my HTTP web server written with SwiftNIO, I noticed\nthat one file descriptor is leaked per request.\n\nSteps to reproduce:\n1. ...\n2. ...\n3. ...\n4. ...\n\n$ swift --version\nSwift version 4.0.2 (swift-4.0.2-RELEASE)\nTarget: x86_64-unknown-linux-gnu\n\nOperating system: Ubuntu Linux 16.04 64-bit\n\n$ uname -a\nLinux beefy.machine 4.4.0-101-generic #124-Ubuntu SMP Fri Nov 10 18:29:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux\n\nMy system has IPv6 disabled.\n```\n\n## Writing a Patch\n\nA good SwiftNIO patch is:\n\n1. Concise, and contains as few changes as needed to achieve the end result.\n2. Tested, ensuring that any tests provided failed before the patch and pass after it.\n3. Documented, adding API documentation as needed to cover new functions and properties.\n4. Accompanied by a great commit message, using our commit message template.\n\n### Commit Message Template\n\nWe require that your commit messages match our template. The easiest way to do that is to get git to help you by explicitly using the template. To do that, `cd` to the root of our repository and run:\n\n    git config commit.template dev/git.commit.template\n\nThe default policy for taking contributions is “Squash and Merge” - because of this the commit message format rule above applies to the PR rather than every commit contained within it.\n\n### Make sure your patch works for all supported versions of swift\n\nThe CI will do this for you, but a project maintainer must kick it off for you.  Currently all versions of Swift >= 5.9 are supported.\n\nIf you wish to test this locally use [act](https://github.com/nektos/act).\n\n#### Act\n\n[Install act](https://nektosact.com/installation/) and then you can run the full suite of checks via:\n```\nact pull_request\n```\nNote that SwiftNIO matrix testing makes use of nightly builds, so you may want to make use of the ```--action-offline-mode``` to avoid repulling those.\n\n### Make sure your code is performant\n\nSwiftNIO has been created to be high performance.  The integration tests cover some measures of performance including allocations which should be avoided if possible.  For help with allocation problems refer to the guide to [allocation debugging](./docs/debugging-allocations.md)\n\n### Formatting\n\nTry to keep your lines less than 120 characters long so GitHub can correctly display your changes.\n\nSwiftNIO uses the [swift-format](https://github.com/swiftlang/swift-format) tool to bring consistency to code formatting.  There is a specific [.swift-format](./.swift-format) configuration file.  This will be checked and enforced on PRs.  Note that the check will run on the current most recent stable version target which may not match that in your own local development environment.\n\nIf you want to apply the formatting to your local repo before you commit then you can either run [check-swift-format.sh](https://github.com/swiftlang/github-workflows/blob/main/.github/workflows/scripts/check-swift-format.sh) which will use your current toolchain, or to match the CI checks exactly you can use `act` (see [act section](#act)):\n```\nact --action-offline-mode --bind workflow_call --job soundness --input format_check_enabled=true\n```\n\nIf you're using a machine with an ARM64 architecture (such as an Apple Silicon Mac) then\nyou'll also need to specify the container architecture:\n```\nact --container-architecture linux/amd64 --action-offline-mode --bind workflow_call --job soundness --input format_check_enabled=true\n```\n\nThis will run the format checks, binding to your local checkout so the edits made are to your own source.\n\n### Extensibility\n\nTry to make sure your code is robust to future extensions.  The public interface is very hard to change after release - please refer to the [API guidelines](./docs/public-api.md)\n\n## How to contribute your work\n\nPlease open a pull request at https://github.com/apple/swift-nio. Make sure the CI passes, and then wait for code review.\n\nAfter review you may be asked to make changes.  When you are ready, use the request re-review feature of GitHub or mention the reviewers by name in a comment.\n"
  },
  {
    "path": "CONTRIBUTORS.txt",
    "content": "For the purpose of tracking copyright, this is the list of individuals and\norganizations who have contributed source code to SwiftNIO.\n\nFor employees of an organization/company where the copyright of work done\nby employees of that company is held by the company itself, only the company\nneeds to be listed here.\n\n## COPYRIGHT HOLDERS\n\n- Apple Inc. (all contributors with '@apple.com')\n\n### Contributors\n\n- 0xflotus <0xflotus@gmail.com>\n- Adam Fowler <adamfowler71@gmail.com>\n- Adam Nemecek <adamnemecek@gmail.com>\n- Ahmad Alhashemi <ahmad@ahmadh.com>\n- Albert Aleksieiev <albert.aleksieiev@gmail.com>\n- Alex Blewitt <alblue@apple.com>\n- Alex Reilly <fabiobean2@gmail.com>\n- Andrew Edwards <andrewangeta@gmail.com>\n- Andrew Naylor <andrew_naylor@apple.com>\n- Andrew Trick <atrick@apple.com>\n- Andrius Aucinas <aaucinas@apple.com>\n- Anish Aggarwal <anish17122000@gmail.com>\n- Ankit Aggarwal <ankit_aggarwal@apple.com>\n- Antoine Cœur <coeur@gmx.fr>\n- Antwan van Houdt <jabwd@exurion.com>\n- Arjun Nayini <aanayini@gmail.com>\n- Artem Redkin <aredkin@apple.com>\n- Austin Payne <austin.payne.01@gmail.com>\n- Bas Broek <bas@basbroek.nl>\n- Bastian Inuk Christensen <bastian@inuk.blog>\n- Ben Cohen <ben_cohen@apple.com>\n- Benedict St. <benedictst@icloud.com>\n- Boby <73424060+bobychaudhary@users.noreply.github.com>\n- Bouke Haarsma <bouke@haarsma.eu>\n- Chris Eidhof <chris@eidhof.nl>\n- Christian Priebe <cpriebe@apple.com>\n- Christian Weinberger <christian.weinberger@me.com>\n- Cory Benfield <cbenfield@apple.com>\n- Cotton Hou <himcotton@gmail.com>\n- Damiaan Dufaux <damiaan@dpro.be>\n- Daniel Alm <Daniel.Alm@ForumD.net>\n- Daniel Dunbar <daniel_dunbar@apple.com>\n- Dario Rexin <drexin@apple.com>\n- David Evans <d.evans@apple.com>\n- David Nadoba <d_nadoba@apple.com>\n- David Skrundz <david.skrundz@gmail.com>\n- Donghyeon Kim <wplong11@gmail.com>\n- Doug Friedman <dfriedm3@gmail.com>\n- Emil Marashliev <marashliev@gmail.com>\n- Esteban Torres <me@estebantorr.es>\n- Eugen <eugenf78@gmail.com>\n- Fabian Fett <fabianfett@apple.com>\n- Felix Schlegel <fefefe152@gmail.com>\n- Felix Schlegel <schlegel@apple.com>\n- Finagolfin <butta@fastem.com>\n- Florian Friedrich <ffried@me.com>\n- Frank Kair <frankkair@gmail.com>\n- Franz Busch <f.busch@apple.com>\n- Gautier Delorme <gautier.delorme@gmail.com>\n- George Barnett <gbarnett@apple.com>\n- Gopal Sharma <gopal@the-sharmas.org>\n- Graeme Jenkinson <graeme_jenkinson@apple.com>\n- Gregor Milos (Grzegorz Miłoś) <gmilos@apple.com>\n- GuangGuang <lihansey163@163.com>\n- Guillaume Lessard <guillaume.lessard@apple.com>\n- Gwynne Raskind <gwynne@vapor.codes>\n- Hailong <hailongzh@hotmail.com>\n- Heidi Puk Hermann <heidi.puk@gmail.com>\n- Helder Sérvio <41337686+heldersrvio@users.noreply.github.com>\n- Helge Heß <helge@alwaysrightinstitute.com>\n- Ian Partridge <i.partridge@uk.ibm.com>\n- Ilya Puchka <ilyapuchka@gmail.com>\n- JP Simard <jp@jpsim.com>\n- Jake Foster <jakef@fastmail.com>\n- Jake Prickett <jprickett821@gmail.com>\n- Jari (LotU) <j.koopman@jarict.nl>\n- Jason Toffaletti <jtoffaletti@apple.com>\n- Jim Dovey <jimdovey@mac.com>\n- Joachim M. <joachim.me86@gmail.com>\n- Joakim Hassila <jocke@ordo.one>\n- Joe Smith <yasumoto7@gmail.com>\n- Johannes Weiss <johannesweiss@apple.com>\n- John Connolly <connoljo2@gmail.com>\n- John Holdsworth <github@johnholdsworth.com>\n- John Lin <johnlinvc@gmail.com>\n- Joshua Rutkowski <jr.rtkski@gmail.com>\n- Jovan Milenkovic <jovan.milenkovic@htecgroup.com>\n- Julian Lettner <julian.lettner@apple.com>\n- Kaitlin Mahar <kaitlinmahar@gmail.com>\n- Kamil Borzym <kamil.borzym@gmail.com>\n- Karim ElNaggar <karimfarid.naggar@gmail.com>\n- Kevin Clark <kevin.clark@apple.com>\n- Kevin Sweeney <kevin_sweeney@apple.com>\n- Kim de Vos <kimdevos12@hotmail.com>\n- Konrad `ktoso` Malawski <ktoso@apple.com>\n- Kushal Pisavadia <kushal.p@apple.com>\n- Kyle Bashour <kylebshr@me.com>\n- Kyle Browning <kylebrowning@me.com>\n- Kyle Jessup <kyle@perfect.org>\n- Lev Walkin <lwalkin@apple.com>\n- Liam Flynn <l.flynn@live.co.uk>\n- Ludovic Dewailly <ldewailly@apple.com>\n- Luo Xiu <luoxiustm@gmail.com>\n- Mahdi Bahrami <github@mahdibm.com>\n- Marcus Liotta <marcus@liotta.se>\n- Mario Sangiorgio <msangiorgio@apple.com>\n- Markus Jais <markusjais@googlemail.com>\n- Markus Kieselmann <markus@kieselmann.eu>\n- Marli Oshlack <marli.oshlack@apple.com>\n- Matt Eaton <agnosticdev@gmail.com>\n- Matt Hope <matt_hope@apple.com>\n- Matteo Comisso <matteo.comisso@me.com>\n- Max Desiatov <m_desiatov@apple.com>\n- Max Desiatov <max@desiatov.com>\n- Max Moiseev <moiseev@apple.com>\n- Maxim Zaks <maxim.zaks@gmail.com>\n- Moritz Lang <hi@slashmo.codes>\n- Nathan Harris <nathan@mordil.info>\n- Nethra Ravindran <nethra.ravindran@in.ibm.com>\n- Norio Nomura <norio.nomura@gmail.com>\n- Norman Maurer <norman_maurer@apple.com>\n- Ole Begemann <ole@oleb.net>\n- OleG <emptystamp@gmail.com>\n- Oleksandr Zhurba <69315809+mob-connection@users.noreply.github.com>\n- Paul Schmiedmayer <paul.schmiedmayer@tum.de>\n- Peter Adams <pp_adams@apple.com>\n- Peter Tolsma <pejato@umich.edu>\n- Petro Rovenskyy <petro.rovenskyy@gmail.com>\n- Philip Brown <122590765+asdf-bro@users.noreply.github.com>\n- Portia <portia-s@users.noreply.github.com>\n- Pushkar N Kulkarni <pushkar.nk@in.ibm.com>\n- Pushparaj Zala <pr92zala@gmail.com>\n- Richard Low <ral@apple.com>\n- Rick Newton-Rogers <rnewtonrogers@apple.com>\n- Romain Pouclet <rpouclet@apple.com>\n- Rukshani Athapathu <arukshani@users.noreply.github.com>\n- Rémi Doreau <remi.d45@gmail.com>\n- Saleem Abdulrasool <compnerd@compnerd.org>\n- Sebastian Thiebaud <770074+SebastianThiebaud@users.noreply.github.com>\n- Sebastian Vogt <sebastian1210@web.de>\n- Semen Zhydenko <simeon.zhidenko@gmail.com>\n- Sergej Jaskiewicz <jaskiewiczs@icloud.com>\n- Sergo Beruashvili <beruashvili@gmail.com>\n- Shaun Hubbard <shaunhubbard2013@icloud.com>\n- Shekhar Rajak <shekhar_rajak@apple.com>\n- Si Beaumont <beaumont@apple.com>\n- Siemen Sikkema <s.h.sikkema@gmail.com>\n- Simon Evans <si@si.org>\n- Stepan Ulyanin <sulyanin@apple.com>\n- Stuart Hinson <stuart.hinson@gmail.com>\n- Tanner <me@tanner.xyz>\n- Tiago Martinho <martinho@thoughtworks.com>\n- Tibor Bödecs <mail.tib@gmail.com>\n- Tim Condon <0xtimc@gmail.com>\n- Tim Kientzle <tkientzle@apple.com>\n- Timothée Peignier <timothee.peignier@icloud.com>\n- Tom Counsell <tamc@greenonblack.com>\n- Tomer Doron <tomerd@apple.com>\n- Tony Arnold <tony@thecocoabots.com>\n- Trevör <adtrevor@users.noreply.github.com>\n- Trevör Anne Denise <adtrevor@users.noreply.github.com>\n- Volodymyr Sapsai <vsapsai@users.noreply.github.com>\n- Will Lisac <will@lisac.org>\n- Wilson Ding <hello@wilsonding.com>\n- YR Chen <stevapple@icloud.com>\n- Yim Lee <yim_lee@apple.com>\n- akash-55 <61596874+akash-55@users.noreply.github.com>\n- buttaface <butta@fastem.com>\n- carolinacass <67160898+carolinacass@users.noreply.github.com>\n- dkz2 <132388278+dkz2@users.noreply.github.com>\n- fadi-botros <botros_fadi@yahoo.com>\n- jemmons <jemmons@users.noreply.github.com>\n- pokryfka <pokryfka@gmail.com>\n- ser <122270051+ser-0xff@users.noreply.github.com>\n- sun_ <sunlubo.sun@gmail.com>\n- taylorswift <kelvin13ma@gmail.com>\n- thomas-gill-0xff <115996764+thomas-gill-0xff@users.noreply.github.com>\n- toluRV <111301355+toluRV@users.noreply.github.com>\n- trungducc <gnurtduc@gmail.com>\n\n**Updating this list**\n\nPlease do not edit this file manually. It is generated using `./scripts/generate_contributors_list.sh`. If a name is misspelled or appearing multiple times: add an entry in `./.mailmap`\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/run-allocation-counter.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2019-2020 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\nbuild_opts=( -c release )\n\nfunction die() {\n    echo >&2 \"ERROR: $*\"\n    exit 1\n}\n\nfunction make_git_commit_all() {\n    git init > /dev/null\n    git checkout -b main > /dev/null\n    if [[ \"$(git config user.email)\" == \"\" ]]; then\n        git config --local user.email does@really-not.matter\n        git config --local user.name 'Does Not Matter'\n    fi\n    git add . > /dev/null\n    git commit -m 'everything' > /dev/null\n}\n\n# <extra_dependencies_file> <swiftpm_pkg_name> <targets...>\nfunction hooked_package_swift_start() {\n    local extra_dependencies_file=$1\n    local swiftpm_pkg_name=$2\n    shift 2\n\n    cat <<\"EOF\"\n// swift-tools-version:5.7\nimport PackageDescription\n\nlet package = Package(\n    name: \"allocation-counter-tests\",\n    platforms: [\n        .macOS(.v10_15),\n        .iOS(.v13),\n        .watchOS(.v6),\n        .tvOS(.v13),\n    ],\n    products: [\nEOF\n    for f in \"$@\"; do\n        local module\n        module=$(module_name_from_path \"$f\")\n        echo \".executable(name: \\\"$module\\\", targets: [\\\"bootstrap_$module\\\"]),\"\n    done\n    cat <<EOF\n    ],\n    dependencies: [\n        .package(path: \"HookedFunctions\"),\n        .package(path: \"AtomicCounter\"),\n        .package(path: \"$swiftpm_pkg_name\"),\nEOF\n    if [[ -n \"$extra_dependencies_file\" ]]; then\n        cat \"$extra_dependencies_file\"\n    fi\n    cat <<EOF\n    ],\n    targets: [\nEOF\n}\n\n# <target_name> <deps...>\nfunction hooked_package_swift_target() {\n    local target_name=\"$1\"\n    shift\n    local deps=\"\"\n    for dep in \"$@\"; do\n        deps=\"$deps .product(name: \\\"$dep\\\", package: \\\"swift-nio\\\"),\"\n    done\n    cat <<EOF\n            .target(name: \"Test_$target_name\", dependencies: [$deps \"AtomicCounter\"]),\n            .executableTarget(name: \"bootstrap_$target_name\",\n                    dependencies: [\"Test_$target_name\", \"HookedFunctions\"]),\nEOF\n}\n\nfunction hooked_package_swift_end() {\n    cat <<\"EOF\"\n    ]\n)\nEOF\n}\n\nfunction abs_path() {\n    if [[ \"${1:0:1}\" == \"/\" ]]; then\n        echo \"$1\"\n    else\n        echo \"$PWD/$1\"\n    fi\n}\n\nfunction dir_basename() {\n    test -d \"$1\"\n    basename \"$(cd \"$1\" && pwd)\"\n}\n\nfunction fake_package_swift() {\n    cat > Package.swift <<EOF\n// swift-tools-version:5.7\nimport PackageDescription\n\nlet package = Package(name: \"$1\")\nEOF\n}\n\n# <target> <template> <swiftpm_pkg_root> <swiftpm_pkg_name> <hooked_function_module> <bootstrap_module>\n# <extra_dependencies_file> <shared files...> -- <modules...> -- <test_files...>\nfunction build_package() {\n    local target=$1\n    local template=$2\n    local swiftpm_pkg_root=$3\n    local swiftpm_pkg_name=$4\n    local hooked_function_module=$5\n    local bootstrap_module=$6\n    local extra_dependencies_file=$7\n    shift 7\n\n    local shared_files=()\n    while [[ \"$1\" != \"--\" ]]; do\n        shared_files+=( \"$1\" )\n        shift\n    done\n    shift\n\n    local modules=()\n    while [[ \"$1\" != \"--\" ]]; do\n        modules+=( \"$1\" )\n        shift\n    done\n    shift\n\n    test -d \"$target\" || die \"target dir '$target' not a directory\"\n    test -d \"$template\" || die \"template dir '$template' not a directory\"\n    test -d \"$swiftpm_pkg_root\" || die \"root dir '$swiftpm_pkg_root' not a directory\"\n    test -n \"$hooked_function_module\" || die \"hooked function module empty\"\n    test -n \"$bootstrap_module\" || die \"bootstrap module empty\"\n\n    cp -R \"$template\"/* \"$target/\"\n    mv \"$target/$hooked_function_module\" \"$target/HookedFunctions\"\n    mv \"$target/Sources/$bootstrap_module\" \"$target/Sources/bootstrap\"\n\n    (\n    set -eu\n\n    cd \"$target\"\n\n    cd HookedFunctions\n    make_git_commit_all\n    cd ..\n\n    cd AtomicCounter\n    make_git_commit_all\n    cd ..\n\n    hooked_package_swift_start \"$extra_dependencies_file\" \"$swiftpm_pkg_root\" \"$@\" > Package.swift\n    for f in \"$@\"; do\n        local module\n        module=$(module_name_from_path \"$f\")\n        hooked_package_swift_target \"$module\" \"${modules[@]}\" >> Package.swift\n        mkdir \"Sources/bootstrap_$module\"\n        ln -s \"../bootstrap/main.c\" \"Sources/bootstrap_$module\"\n        mkdir \"Sources/Test_$module\"\n        cat > \"Sources/Test_$module/trampoline.swift\" <<EOF\n        @_cdecl(\"swift_main\")\n        func swift_main() {\n            run(identifier: \"$module\")\n        }\nEOF\n        ln -s \"$f\" \"Sources/Test_$module/file.swift\"\n        ln -s \"../../scaffolding.swift\" \"Sources/Test_$module/\"\n        for shared_file in \"${shared_files[@]+\"${shared_files[@]}\"}\"; do\n            name=$(basename \"$shared_file\")\n            ln -s \"$shared_file\" \"Sources/Test_$module/$name\"\n        done\n    done\n    hooked_package_swift_end >> Package.swift\n    )\n}\n\nfunction module_name_from_path() {\n    basename \"${1%.*}\" | tr \". \" \"__\"\n}\n\n# <pkg_root>\nfunction find_swiftpm_package_name() {\n    (\n    set -eu\n    cd \"$1\"\n    swift package dump-package | grep '^  \"name\"' | cut -d'\"' -f4\n    )\n}\n\ndo_hooking=true\npkg_root=\"$here/..\"\nshared_files=()\nmodules=()\nextra_dependencies_file=\"\"\ntmp_dir=\"/tmp\"\n\nwhile getopts \"ns:p:m:d:t:\" opt; do\n    case \"$opt\" in\n        n)\n            do_hooking=false\n            ;;\n        s)\n            shared_files+=( \"$(abs_path \"$OPTARG\")\" )\n            ;;\n        p)\n            pkg_root=$(abs_path \"$OPTARG\")\n            ;;\n        m)\n            modules+=( \"$OPTARG\" )\n            ;;\n        d)\n            extra_dependencies_file=\"$OPTARG\"\n            ;;\n        t)\n            tmp_dir=\"$OPTARG\"\n            ;;\n        \\?)\n            die \"unknown option $opt\"\n            ;;\n    esac\ndone\n\nshift $(( OPTIND - 1 ))\nif [[ $# -lt 1 ]]; then\n    die \"not enough files provided\"\nfi\n\nif [[ \"${#modules}\" == 0 ]]; then\n    die \"no modules specified, use '-m <MODULE>' for every module you plan to use\"\nfi\n\nif [[ ! -f \"$pkg_root/Package.swift\" ]]; then\n    die \"package root '$pkg_root' doesn't contain a Package.swift file, use -p\"\nfi\n\nfiles=()\nfor f in \"$@\"; do\n    files+=( \"$(abs_path \"$f\")\" )\ndone\n\ntest -d \"$pkg_root\" || die \"package root '$pkg_root' not a directory\"\nfor f in \"${files[@]}\"; do\n    test -f \"$f\" || die \"file '$f' not a file\"\ndone\n\nworking_dir=$(mktemp -d \"$tmp_dir/.nio_alloc_counter_tests_XXXXXX\")\necho \"Working directory: $working_dir\"\n\nselected_hooked_functions=\"HookedFunctionsDoHook\"\nselected_bootstrap=\"bootstrapDoHook\"\n\nif ! $do_hooking; then\n    selected_hooked_functions=HookedFunctionsDoNotHook\n    selected_bootstrap=bootstrapDoNotHook\nfi\n\nbuild_package \\\n    \"$working_dir\" \\\n    \"$here/template\" \\\n    \"$(realpath \"$pkg_root\")\" \\\n    \"$(find_swiftpm_package_name \"$pkg_root\")\" \\\n    \"$selected_hooked_functions\" \\\n    \"$selected_bootstrap\" \\\n    \"$extra_dependencies_file\" \\\n    \"${shared_files[@]+\"${shared_files[@]}\"}\" \\\n    -- \\\n    \"${modules[@]}\" \\\n    -- \\\n    \"${files[@]}\"\n(\nset -eu\ncd \"$working_dir\"\nswift build \"${build_opts[@]}\"\nbin_path=$(swift build \"${build_opts[@]}\" --show-bin-path)\nif [[ \"${NIO_ALLOC_COUNTER_TESTS_PARALLEL:-false}\" == \"true\" ]]; then\n    out_dir=$(mktemp -d)\n    trap 'rm -rf \"$out_dir\"' EXIT\n    for f in \"${files[@]}\"; do\n        module=$(module_name_from_path \"$f\")\n        (\n            rc=0\n            \"$bin_path/$module\" > \"$out_dir/$module\" || rc=$?\n            echo $rc > \"$out_dir/$module.exit\"\n        ) &\n    done\n    wait\n    all_ok=true\n    for f in \"${files[@]}\"; do\n        module=$(module_name_from_path \"$f\")\n        echo \"- $f\"\n        if [[ \"$(cat \"$out_dir/$module.exit\")\" == \"0\" ]]; then\n            cat \"$out_dir/$module\"\n        else\n            all_ok=false\n            echo \"FAILED: $f\" >&2\n            cat \"$out_dir/$module\"\n        fi\n    done\n    \"$all_ok\"\nelse\n    for f in \"${files[@]}\"; do\n        echo \"- $f\"\n        \"$bin_path/$(module_name_from_path \"$f\")\"\n    done\nfi\n)\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/AtomicCounter/Package.swift",
    "content": "// swift-tools-version:5.10\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"AtomicCounter\",\n    products: [\n        .library(name: \"AtomicCounter\", type: .dynamic, targets: [\"AtomicCounter\"])\n    ],\n    dependencies: [],\n    targets: [\n        .target(\n            name: \"AtomicCounter\",\n            dependencies: []\n        )\n    ]\n)\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/AtomicCounter/Sources/AtomicCounter/include/atomic-counter.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#ifndef ATOMIC_COUNTER\n#define ATOMIC_COUNTER\n\n#include <stdatomic.h>\n\nvoid inc_free_counter(void);\nvoid reset_free_counter(void);\nlong read_free_counter(void);\n\nvoid inc_malloc_counter(void);\nvoid reset_malloc_counter(void);\nlong read_malloc_counter(void);\n\nvoid add_malloc_bytes_counter(intptr_t v);\nvoid reset_malloc_bytes_counter(void);\nintptr_t read_malloc_bytes_counter(void);\n\ntypedef struct {\n    size_t count;\n    int *leaked;\n} LeakedFDs;\n\nvoid begin_tracking_fds(void);\nvoid track_open_fd(int fd);\nvoid track_closed_fd(int fd);\nLeakedFDs stop_tracking_fds(void);\n\n#endif\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/AtomicCounter/Sources/AtomicCounter/src/atomic-counter.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#include <atomic-counter.h>\n#include <assert.h>\n#include <pthread.h>\n#include <stdatomic.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define MAKE_COUNTER(name) /*\n*/ _Atomic long g_ ## name ## _counter = ATOMIC_VAR_INIT(0); /*\n*/ void inc_ ## name ## _counter(void) { /*\n*/    atomic_fetch_add_explicit(&g_ ## name ## _counter, 1, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ void add_ ## name ## _counter(intptr_t v) { /*\n*/    atomic_fetch_add_explicit(&g_ ## name ## _counter, v, memory_order_relaxed); /*\n*/ } /*\n*/ void reset_ ## name ## _counter(void) { /*\n*/     atomic_store_explicit(&g_ ## name ## _counter, 0, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ intptr_t read_ ## name ## _counter(void) { /*\n*/     return atomic_load_explicit(&g_ ## name ## _counter, memory_order_relaxed); /*\n*/ }\n\nMAKE_COUNTER(free)\nMAKE_COUNTER(malloc)\nMAKE_COUNTER(malloc_bytes)\n\n// This section covers tracking leaked FDs.\n//\n// We do this by recording which FD has been set in a queue. A queue is a bad data structure here,\n// but using a better one requires writing too much code, and the performance impact here is not\n// going to be too bad.\ntypedef struct {\n    size_t capacity;\n    size_t count;\n    int *allocatedFDs;\n} FDTracker;\n\nstatic _Bool FDTracker_search_fd(const FDTracker *tracker, int fd, size_t *foundIndex) {\n    if (tracker == NULL) { return false; }\n\n    for (size_t i = 0; i < tracker->count; i++) {\n        if (tracker->allocatedFDs[i] == fd) {\n            if (foundIndex != NULL) { \n                *foundIndex = i;\n            }\n            return true;\n        }\n    }\n\n    return false;\n}\n\nstatic void FDTracker_remove_at_index(FDTracker *tracker, size_t index) {\n    assert(tracker != NULL);\n    assert(index < tracker->count);\n\n    // Shuffle everything down by 1 from index onwards.\n    const size_t lastValidTargetIndex = tracker->count - 1;\n    for (size_t i = index; i < lastValidTargetIndex; i++) {\n        tracker->allocatedFDs[i] = tracker->allocatedFDs[i + 1];\n    }\n    tracker->count--;\n}\n\n_Atomic _Bool is_tracking = ATOMIC_VAR_INIT(false);\npthread_mutex_t tracker_lock = PTHREAD_MUTEX_INITIALIZER;\nFDTracker tracker = { 0 };\n\nvoid begin_tracking_fds(void) {\n    int rc = pthread_mutex_lock(&tracker_lock);\n    assert(rc == 0);\n\n    assert(tracker.capacity == 0);\n    assert(tracker.count == 0);\n    assert(tracker.allocatedFDs == NULL);\n\n    tracker.allocatedFDs = calloc(1024, sizeof(int));\n    tracker.capacity = 1024;\n\n    atomic_store_explicit(&is_tracking, true, memory_order_release);\n    rc = pthread_mutex_unlock(&tracker_lock);\n    assert(rc == 0);\n}\n\nvoid track_open_fd(int fd) {\n    bool should_track = atomic_load_explicit(&is_tracking, memory_order_acquire);\n    if (!should_track) { return; }\n\n    int rc = pthread_mutex_lock(&tracker_lock);\n    assert(rc == 0);\n\n    // We need to not be tracking this FD already, or there's a correctness error.\n    assert(!FDTracker_search_fd(&tracker, fd, NULL));\n\n    // We want to append to the queue.\n    if (tracker.capacity == tracker.count) {\n        // Wuh-oh, resize. We do this by doubling.\n        assert((tracker.capacity * sizeof(int)) < (SIZE_MAX / 2));\n        size_t newCapacity = tracker.capacity * 2;\n        int *new = realloc(tracker.allocatedFDs, newCapacity * sizeof(int));\n        assert(new != NULL);\n        tracker.allocatedFDs = new;\n        tracker.capacity = newCapacity;\n    }\n\n    tracker.allocatedFDs[tracker.count] = fd;\n    tracker.count++;\n\n    rc = pthread_mutex_unlock(&tracker_lock);\n    assert(rc == 0);\n}\n\nvoid track_closed_fd(int fd) {\n    bool should_track = atomic_load_explicit(&is_tracking, memory_order_acquire);\n    if (!should_track) { return; }\n\n    int rc = pthread_mutex_lock(&tracker_lock);\n    assert(rc == 0);\n\n    size_t index;\n    if (FDTracker_search_fd(&tracker, fd, &index)) {\n        // We're tracking this FD, let's remove it.\n        FDTracker_remove_at_index(&tracker, index);\n    }\n\n    rc = pthread_mutex_unlock(&tracker_lock);\n    assert(rc == 0);\n}\n\nLeakedFDs stop_tracking_fds(void) {\n    int rc = pthread_mutex_lock(&tracker_lock);\n    assert(rc == 0);\n\n    LeakedFDs result = {\n        .count = tracker.count,\n        .leaked = tracker.allocatedFDs\n    };\n\n    // Clear the tracker.\n    tracker.allocatedFDs = NULL;\n    tracker.capacity = 0;\n    tracker.count = 0;\n\n    atomic_store_explicit(&is_tracking, false, memory_order_release);\n    rc = pthread_mutex_unlock(&tracker_lock);\n    assert(rc == 0);\n\n    return result;\n}\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoHook/Package.swift",
    "content": "// swift-tools-version:5.10\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"HookedFunctions\",\n    products: [\n        .library(name: \"HookedFunctions\", type: .dynamic, targets: [\"HookedFunctions\"])\n    ],\n    dependencies: [\n        .package(path: \"../AtomicCounter\")\n    ],\n    targets: [\n        .target(name: \"HookedFunctions\", dependencies: [\"AtomicCounter\"])\n    ]\n)\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoHook/Sources/HookedFunctions/include/hooked-functions.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#ifndef HOOKED_FREE\n#define HOOKED_FREE\n\n#include <stdlib.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#if __APPLE__\n#  include <malloc/malloc.h>\n#endif\n\nvoid *replacement_malloc(size_t size);\nvoid replacement_free(void *ptr);\nvoid *replacement_calloc(size_t nmemb, size_t size);\nvoid *replacement_realloc(void *ptr, size_t size);\nvoid *replacement_reallocf(void *ptr, size_t size);\nvoid *replacement_valloc(size_t size);\nint replacement_posix_memalign(void **memptr, size_t alignment, size_t size);\nint replacement_socket(int domain, int type, int protocol);\nint replacement_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);\nint replacement_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);\nint replacement_close(int fildes);\n\n#if __APPLE__\nvoid *replacement_malloc_zone_malloc(malloc_zone_t *zone, size_t size);\nvoid *replacement_malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size);\nvoid *replacement_malloc_zone_valloc(malloc_zone_t *zone, size_t size);\nvoid *replacement_malloc_zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);\nvoid *replacement_malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size);\nvoid replacement_malloc_zone_free(malloc_zone_t *zone, void *ptr);\n#endif\n\n#endif\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoHook/Sources/HookedFunctions/src/hooked-functions-darwin.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#include <assert.h>\n#if __APPLE__\n\n#define _GNU_SOURCE\n#include <dlfcn.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <stdatomic.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <malloc/malloc.h>\n\n#include <atomic-counter.h>\n#include <hooked-functions.h>\n\n#define DYLD_INTERPOSE(_replacement,_replacee) \\\n   __attribute__((used)) static struct { const void *replacement; const void *replacee; } _interpose_##_replacee \\\n            __attribute__ ((section(\"__DATA,__interpose\"))) = { (const void *)(unsigned long)&_replacement, (const void *)(unsigned long)&_replacee };\n\n/* on Darwin calling the original function is super easy, just call it, done. */\n#define JUMP_INTO_LIBC_FUN(_fun, ...) /* \\\n*/ do { /* \\\n*/     return _fun(__VA_ARGS__); /* \\\n*/ } while(0)\n\nvoid replacement_free(void *ptr) {\n    if (ptr) {\n        inc_free_counter();\n        JUMP_INTO_LIBC_FUN(free, ptr);\n    }\n}\n\nvoid *replacement_malloc(size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t) size);\n\n    JUMP_INTO_LIBC_FUN(malloc, size);\n}\n\nvoid *replacement_realloc(void *ptr, size_t size) {\n    if (0 == size) {\n        replacement_free(ptr);\n        return NULL;\n    }\n    if (!ptr) {\n        return replacement_malloc(size);\n    }\n    inc_free_counter();\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t) size);\n\n    JUMP_INTO_LIBC_FUN(realloc, ptr, size);\n}\n\nvoid *replacement_calloc(size_t count, size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)(count * size));\n\n    JUMP_INTO_LIBC_FUN(calloc, count, size);\n}\n\nvoid *replacement_malloc_zone_malloc(malloc_zone_t *zone, size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)size);\n\n    JUMP_INTO_LIBC_FUN(malloc_zone_malloc, zone, size);\n}\n\nvoid *replacement_malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)(size * num_items));\n\n    JUMP_INTO_LIBC_FUN(malloc_zone_calloc, zone, num_items, size);\n}\n\nvoid *replacement_malloc_zone_valloc(malloc_zone_t *zone, size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)size);\n\n    JUMP_INTO_LIBC_FUN(malloc_zone_valloc, zone, size);\n}\n\nvoid *replacement_malloc_zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) {\n    if (0 == size) {\n        replacement_free(ptr);\n        return NULL;\n    }\n    if (!ptr) {\n        return replacement_malloc(size);\n    }\n    inc_free_counter();\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)size);\n\n    JUMP_INTO_LIBC_FUN(realloc, ptr, size);\n}\n\nvoid *replacement_malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)size);\n\n    JUMP_INTO_LIBC_FUN(malloc_zone_memalign, zone, alignment, size);\n}\n\nvoid replacement_malloc_zone_free(malloc_zone_t *zone, void *ptr) {\n    inc_free_counter();\n\n    JUMP_INTO_LIBC_FUN(malloc_zone_free, zone, ptr);\n}\n\nvoid *replacement_reallocf(void *ptr, size_t size) {\n    void *new_ptr = replacement_realloc(ptr, size);\n    if (!new_ptr) {\n        replacement_free(new_ptr);\n    }\n    return new_ptr;\n}\n\nvoid *replacement_valloc(size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)size);\n\n    JUMP_INTO_LIBC_FUN(valloc, size);\n}\n\nint replacement_posix_memalign(void **memptr, size_t alignment, size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t)size);\n\n    JUMP_INTO_LIBC_FUN(posix_memalign, memptr, alignment, size);\n}\n\nint replacement_socket(int domain, int type, int protocol) {\n    int fd = socket(domain, type, protocol);\n    if (fd < 0) {\n        return fd;\n    }\n\n    track_open_fd(fd);\n    return fd;\n}\n\nint replacement_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {\n    int fd = accept(socket, address, address_len);\n\n    if (fd < 0) {\n        return fd;\n    }\n\n    track_open_fd(fd);\n    return fd;\n}\n\nint replacement_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    // Should never be called.\n    assert(false);\n}\n\nint replacement_close(int fildes) {\n    track_closed_fd(fildes);\n    JUMP_INTO_LIBC_FUN(close, fildes);\n}\n\nDYLD_INTERPOSE(replacement_free, free)\nDYLD_INTERPOSE(replacement_malloc, malloc)\nDYLD_INTERPOSE(replacement_realloc, realloc)\nDYLD_INTERPOSE(replacement_calloc, calloc)\nDYLD_INTERPOSE(replacement_reallocf, reallocf)\nDYLD_INTERPOSE(replacement_valloc, valloc)\nDYLD_INTERPOSE(replacement_posix_memalign, posix_memalign)\nDYLD_INTERPOSE(replacement_malloc_zone_malloc, malloc_zone_malloc)\nDYLD_INTERPOSE(replacement_malloc_zone_calloc, malloc_zone_calloc)\nDYLD_INTERPOSE(replacement_malloc_zone_valloc, malloc_zone_valloc)\nDYLD_INTERPOSE(replacement_malloc_zone_realloc, malloc_zone_realloc)\nDYLD_INTERPOSE(replacement_malloc_zone_memalign, malloc_zone_memalign)\nDYLD_INTERPOSE(replacement_malloc_zone_free, malloc_zone_free)\nDYLD_INTERPOSE(replacement_socket, socket)\nDYLD_INTERPOSE(replacement_accept, accept)\nDYLD_INTERPOSE(replacement_close, close)\n#endif\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoHook/Sources/HookedFunctions/src/hooked-functions-unix.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#ifndef __APPLE__\n\n#define _GNU_SOURCE\n#include <dlfcn.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <stdatomic.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include <atomic-counter.h>\n#include <hooked-functions.h>\n\n/* a big block of memory that we'll use for recursive mallocs */\nstatic char g_recursive_malloc_mem[10 * 1024 * 1024] = {0};\n/* the index of the first free byte */\nstatic _Atomic ptrdiff_t g_recursive_malloc_next_free_ptr = ATOMIC_VAR_INIT(0);\n\n#define LIBC_SYMBOL(_fun) \"\" # _fun\n\n/* Some thread-local flags we use to check if we're recursively in a hooked function. */\nstatic __thread bool g_in_malloc = false;\nstatic __thread bool g_in_realloc = false;\nstatic __thread bool g_in_free = false;\nstatic __thread bool g_in_socket = false;\nstatic __thread bool g_in_accept = false;\nstatic __thread bool g_in_accept4 = false;\nstatic __thread bool g_in_close = false;\n\n/* The types of the variables holding the libc function pointers. */\ntypedef void *(*type_libc_malloc)(size_t);\ntypedef void *(*type_libc_realloc)(void *, size_t);\ntypedef void  (*type_libc_free)(void *);\ntypedef int   (*type_libc_socket)(int, int, int);\ntypedef int   (*type_libc_accept)(int, struct sockaddr*, socklen_t *);\ntypedef int   (*type_libc_accept4)(int, struct sockaddr *, socklen_t *, int);\ntypedef int   (*type_libc_close)(int);\n\n/* The (atomic) globals holding the pointer to the original libc implementation. */\n_Atomic type_libc_malloc g_libc_malloc;\n_Atomic type_libc_realloc g_libc_realloc;\n_Atomic type_libc_free g_libc_free;\n_Atomic type_libc_socket g_libc_socket;\n_Atomic type_libc_accept g_libc_accept;\n_Atomic type_libc_accept4 g_libc_accept4;\n_Atomic type_libc_close g_libc_close;\n\n// this is called if malloc is called whilst trying to resolve libc's realloc.\n// we just vend out pointers to a large block in the BSS (which we never free).\n// This block should be large enough because it's only used when malloc is\n// called from dlsym which should only happen once per thread.\nstatic void *recursive_malloc(size_t size_in) {\n    size_t size = size_in;\n    if ((size & 0xf) != 0) {\n        // make size 16 byte aligned\n        size = (size + 0xf) & (~(size_t)0xf);\n    }\n\n    ptrdiff_t next = atomic_fetch_add_explicit(&g_recursive_malloc_next_free_ptr,\n                                               size,\n                                               memory_order_relaxed);\n    if ((size_t)next >= sizeof(g_recursive_malloc_mem)) {\n        // we ran out of memory\n        return NULL;\n    }\n    return (void *)((intptr_t)g_recursive_malloc_mem + next);\n}\n\nstatic bool is_recursive_malloc_block(void *ptr) {\n    uintptr_t block_begin = (uintptr_t)g_recursive_malloc_mem;\n    uintptr_t block_end = block_begin + sizeof(g_recursive_malloc_mem);\n    uintptr_t user_ptr = (uintptr_t)ptr;\n\n    return user_ptr >= block_begin && user_ptr < block_end;\n}\n\n// this is called if realloc is called whilst trying to resolve libc's realloc.\nstatic void *recursive_realloc(void *ptr, size_t size) {\n    // not implemented yet...\n    abort();\n}\n\n// this is called if free is called whilst trying to resolve libc's free.\nstatic void recursive_free(void *ptr) {\n    // not implemented yet...\n    abort();\n}\n\n// this is called if socket is called whilst trying to resolve libc's socket.\nstatic int recursive_socket(int domain, int type, int protocol) {\n    // not possible\n    abort();\n}\n\n// this is called if accept is called whilst trying to resolve libc's accept.\nstatic int recursive_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {\n    // not possible\n    abort();\n}\n\n// this is called if accept4 is called whilst trying to resolve libc's accept4.\nstatic int recursive_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    // not possible\n    abort();\n}\n\n// this is called if close is called whilst trying to resolve libc's close.\nstatic int recursive_close(int fildes) {\n    // not possible\n    abort();\n}\n\n/* On Apple platforms getting to the original libc function from a hooked\n * function is easy.  On other UNIX systems this is slightly harder because we\n * have to look up the function with the dynamic linker.  Because that isn't\n * super performant we cache the lookup result in an (atomic) global.\n *\n * Calling into the libc function if we have already cached it is easy, we\n * (atomically) load it and call into it.  If have not yet cached it, we need to\n * resolve it which we do by using dlsym and then write it into the (atomic)\n * global.  There's only one slight problem: dlsym might call back into the\n * function we're just trying to resolve (dlsym does call malloc). In that case\n * we need to emulate that function (named recursive_*). But that's all then.\n */\n#define JUMP_INTO_LIBC_FUN(_fun, ...) /* \\\n*/ do { /* \\\n*/     /* Let's see if somebody else already resolved that function for us */ /* \\\n*/     type_libc_ ## _fun local_fun = atomic_load(&g_libc_ ## _fun); /* \\\n*/     if (!local_fun) { /* \\\n*/         /* No, we're the first ones to use this function. */ /* \\\n*/         if (!g_in_ ## _fun) { /* \\\n*/             g_in_ ## _fun = true; /* \\\n*/             /* If we're here, we're at least not recursively in ourselves. */ /* \\\n*/             /* That means we can use dlsym to resolve the libc function. */ /* \\\n*/             type_libc_ ## _fun desired = dlsym(RTLD_NEXT, LIBC_SYMBOL(_fun)); /* \\\n*/             if (atomic_compare_exchange_strong(&g_libc_ ## _fun, &local_fun, desired)) { /* \\\n*/                 /* If we're here, we won the race, so let's use our resolved function.  */ /* \\\n*/                 local_fun = desired; /* \\\n*/             } else { /* \\\n*/                 /* Lost the race, let's load the global again */ /* \\\n*/                 local_fun = atomic_load(&g_libc_ ## _fun); /* \\\n*/              } /* \\\n*/         } else { /* \\\n*/             /* Okay, we can't jump into libc here and need to use our own version. */ /* \\\n*/             return recursive_ ## _fun (__VA_ARGS__); /* \\\n*/         } /* \\\n*/     } /* \\\n*/     return local_fun(__VA_ARGS__); /* \\\n*/ } while(0)\n\nvoid replacement_free(void *ptr) {\n    if (ptr) {\n        inc_free_counter();\n        if (!is_recursive_malloc_block(ptr)) {\n            JUMP_INTO_LIBC_FUN(free, ptr);\n        }\n    }\n}\n\nvoid *replacement_malloc(size_t size) {\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t) size);\n\n    JUMP_INTO_LIBC_FUN(malloc, size);\n}\n\nvoid *replacement_realloc(void *ptr, size_t size) {\n    if (0 == size) {\n        replacement_free(ptr);\n        return NULL;\n    }\n    if (!ptr) {\n        return replacement_malloc(size);\n    }\n    inc_free_counter();\n    inc_malloc_counter();\n    add_malloc_bytes_counter((intptr_t) size);\n\n    JUMP_INTO_LIBC_FUN(realloc, ptr, size);\n}\n\nvoid *replacement_calloc(size_t count, size_t size) {\n    void *ptr = replacement_malloc(count * size);\n    memset(ptr, 0, count * size);\n    return ptr;\n}\n\nvoid *replacement_reallocf(void *ptr, size_t size) {\n    void *new_ptr = replacement_realloc(ptr, size);\n    if (!new_ptr) {\n        replacement_free(new_ptr);\n    }\n    return new_ptr;\n}\n\nvoid *replacement_valloc(size_t size) {\n    // not aligning correctly (should be PAGE_SIZE) but good enough\n    return replacement_malloc(size);\n}\n\nint replacement_posix_memalign(void **memptr, size_t alignment, size_t size) {\n    // not aligning correctly (should be `alignment`) but good enough\n    void *ptr = replacement_malloc(size);\n    if (ptr && memptr) {\n        *memptr = ptr;\n        return 0;\n    } else {\n        return 1;\n    }\n}\n\nstatic int socket_thunk(int domain, int type, int protocol) {\n    JUMP_INTO_LIBC_FUN(socket, domain, type, protocol);\n}\n\nint replacement_socket(int domain, int type, int protocol) {\n    int fd = socket_thunk(domain, type, protocol);\n    if (fd < 0) {\n        return fd;\n    }\n\n    track_open_fd(fd);\n    return fd;\n}\n\nstatic int accept_thunk(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {\n    JUMP_INTO_LIBC_FUN(accept, socket, address, address_len);\n}\n\nint replacement_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {\n    int fd = accept_thunk(socket, address, address_len);\n\n    if (fd < 0) {\n        return fd;\n    }\n\n    track_open_fd(fd);\n    return fd;\n}\n\nstatic int accept4_thunk(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    JUMP_INTO_LIBC_FUN(accept4, sockfd, addr, addrlen, flags);\n}\n\nint replacement_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    int fd = accept4_thunk(sockfd, addr, addrlen, flags);\n\n    if (fd < 0) {\n        return fd;\n    }\n\n    track_open_fd(fd);\n    return fd;\n}\n\nint replacement_close(int fildes) {\n    track_closed_fd(fildes);\n    JUMP_INTO_LIBC_FUN(close, fildes);\n}\n\n#endif\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoNotHook/Package.swift",
    "content": "// swift-tools-version:5.10\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"HookedFunctions\",\n    products: [\n        .library(name: \"HookedFunctions\", type: .dynamic, targets: [\"HookedFunctions\"])\n    ],\n    dependencies: [\n        .package(path: \"../AtomicCounter\")\n    ],\n    targets: [\n        .target(name: \"HookedFunctions\", dependencies: [\"AtomicCounter\"])\n    ]\n)\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoNotHook/Sources/HookedFunctions/include/hooked-functions.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#ifndef HOOKED_FREE\n#define HOOKED_FREE\n\n#endif\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/HookedFunctionsDoNotHook/Sources/HookedFunctions/src/hooked-functions.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/Sources/bootstrapDoHook/main.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#define _GNU_SOURCE\n#include <stdio.h>\n#include <dlfcn.h>\n#include <atomic-counter.h>\n#include <hooked-functions.h>\n#include <stdlib.h>\n\n#if !__APPLE__\nvoid free(void *ptr) {\n    replacement_free(ptr);\n}\nvoid *malloc(size_t size) {\n    return replacement_malloc(size);\n}\nvoid *calloc(size_t nmemb, size_t size) {\n    return replacement_calloc(nmemb, size);\n}\nvoid *realloc(void *ptr, size_t size) {\n    return replacement_realloc(ptr, size);\n}\nvoid *reallocf(void *ptr, size_t size) {\n    return replacement_reallocf(ptr, size);\n}\nvoid *valloc(size_t size) {\n    return replacement_valloc(size);\n}\nint posix_memalign(void **memptr, size_t alignment, size_t size) {\n    return replacement_posix_memalign(memptr, alignment, size);\n}\nint socket(int domain, int type, int protocol) {\n    return replacement_socket(domain, type, protocol);\n}\nint accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {\n    return replacement_accept(socket, address, address_len);\n}\nint accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    return replacement_accept4(sockfd, addr, addrlen, flags);\n}\nint close(int fildes) {\n    return replacement_close(fildes);\n}\n#endif\n\nvoid swift_main(void);\n\nint main() {\n    swift_main();\n}\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/Sources/bootstrapDoNotHook/main.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nvoid swift_main(void);\n\nint main() {\n    swift_main();\n}\n"
  },
  {
    "path": "IntegrationTests/allocation-counter-tests-framework/template/scaffolding.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport AtomicCounter\nimport Foundation\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\nimport Glibc\n#else\n#error(\"The integration test scaffolding was unable to identify your C library.\")\n#endif\n\nfunc waitForThreadsToQuiesce(shouldReachZero: Bool) {\n    func getUnfreed() -> Int {\n        AtomicCounter.read_malloc_counter() - AtomicCounter.read_free_counter()\n    }\n\n    var oldNumberOfUnfreed = getUnfreed()\n    var count = 0\n    repeat {\n        guard count < 100 else {\n            print(\"WARNING: Giving up, shouldReachZero=\\(shouldReachZero), unfreeds=\\(oldNumberOfUnfreed)\")\n            return\n        }\n        count += 1\n        // allocs/frees happen on multiple threads, allow some cool down time\n        usleep(shouldReachZero ? 50_000 : 200_000)\n        let newNumberOfUnfreed = getUnfreed()\n        if oldNumberOfUnfreed == newNumberOfUnfreed && (!shouldReachZero || newNumberOfUnfreed <= 0) {\n            // nothing happened in the last 100ms, let's assume everything's\n            // calmed down already.\n            if count > 5 || newNumberOfUnfreed != 0 {\n                print(\"DEBUG: After waiting \\(count) times, we quiesced to unfreeds=\\(newNumberOfUnfreed)\")\n            }\n            return\n        }\n        oldNumberOfUnfreed = newNumberOfUnfreed\n    } while true\n}\n\nstruct Measurement {\n    var totalAllocations: Int\n    var totalAllocatedBytes: Int\n    var remainingAllocations: Int\n    var leakedFDs: [CInt]\n}\n\nextension Array where Element == Measurement {\n    private func printIntegerMetric(\n        _ keyPath: KeyPath<Measurement, Int>,\n        description desc: String,\n        metricName k: String\n    ) {\n        let vs = self.map { $0[keyPath: keyPath] }\n        print(\"\\(desc).\\(k): \\(vs.min() ?? -1)\")\n    }\n\n    func printTotalAllocations(description: String) {\n        self.printIntegerMetric(\\.totalAllocations, description: description, metricName: \"total_allocations\")\n    }\n\n    func printTotalAllocatedBytes(description: String) {\n        self.printIntegerMetric(\\.totalAllocatedBytes, description: description, metricName: \"total_allocated_bytes\")\n    }\n\n    func printRemainingAllocations(description: String) {\n        self.printIntegerMetric(\\.remainingAllocations, description: description, metricName: \"remaining_allocations\")\n    }\n\n    func printLeakedFDs(description desc: String) {\n        let vs = self.map { $0.leakedFDs }.filter { !$0.isEmpty }\n        print(\"\\(desc).leaked_fds: \\(vs.first.map { $0.count } ?? 0)\")\n    }\n}\n\nfunc measureAll(trackFDs: Bool, _ fn: () -> Int) -> [Measurement] {\n    func measureOne(throwAway: Bool = false, trackFDs: Bool, _ fn: () -> Int) -> Measurement? {\n        AtomicCounter.reset_free_counter()\n        AtomicCounter.reset_malloc_counter()\n        AtomicCounter.reset_malloc_bytes_counter()\n\n        if trackFDs {\n            AtomicCounter.begin_tracking_fds()\n        }\n\n        #if canImport(Darwin)\n        autoreleasepool {\n            _ = fn()\n        }\n        #else\n        _ = fn()\n        #endif\n        waitForThreadsToQuiesce(shouldReachZero: !throwAway)\n        let frees = AtomicCounter.read_free_counter()\n        let mallocs = AtomicCounter.read_malloc_counter()\n        let mallocedBytes = AtomicCounter.read_malloc_bytes_counter()\n        var leakedFDs: [CInt] = []\n        if trackFDs {\n            let leaks = AtomicCounter.stop_tracking_fds()\n            defer {\n                free(leaks.leaked)\n            }\n            leakedFDs = Array(UnsafeBufferPointer(start: leaks.leaked, count: leaks.count))\n        }\n        if mallocs - frees < 0 {\n            print(\"WARNING: negative remaining allocation count, skipping.\")\n            return nil\n        }\n        return Measurement(\n            totalAllocations: mallocs,\n            totalAllocatedBytes: mallocedBytes,\n            remainingAllocations: mallocs - frees,\n            leakedFDs: leakedFDs\n        )\n    }\n\n    _ = measureOne(throwAway: true, trackFDs: trackFDs, fn)  // pre-heat and throw away\n\n    var measurements: [Measurement] = []\n    for _ in 0..<10 {\n        if let results = measureOne(trackFDs: trackFDs, fn) {\n            measurements.append(results)\n        }\n    }\n    return measurements\n}\n\nfunc measureAndPrint(desc: String, trackFDs: Bool, fn: () -> Int) {\n    let measurements = measureAll(trackFDs: trackFDs, fn)\n    measurements.printTotalAllocations(description: desc)\n    measurements.printRemainingAllocations(description: desc)\n    measurements.printTotalAllocatedBytes(description: desc)\n    measurements.printLeakedFDs(description: desc)\n\n    print(\"DEBUG: \\(measurements)\")\n}\n\npublic func measure(identifier: String, trackFDs: Bool = false, _ body: () -> Int) {\n    measureAndPrint(desc: identifier, trackFDs: trackFDs) {\n        body()\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc measureAll(trackFDs: Bool, _ fn: @escaping () async -> Int) -> [Measurement] {\n    func measureOne(throwAway: Bool = false, trackFDs: Bool, _ fn: @escaping () async -> Int) -> Measurement? {\n        func run(_ fn: @escaping () async -> Int) {\n            let group = DispatchGroup()\n            group.enter()\n            Task {\n                _ = await fn()\n                group.leave()\n            }\n            group.wait()\n        }\n\n        if trackFDs {\n            AtomicCounter.begin_tracking_fds()\n        }\n\n        AtomicCounter.reset_free_counter()\n        AtomicCounter.reset_malloc_counter()\n        AtomicCounter.reset_malloc_bytes_counter()\n\n        #if canImport(Darwin)\n        autoreleasepool {\n            run(fn)\n        }\n        #else\n        run(fn)\n        #endif\n        waitForThreadsToQuiesce(shouldReachZero: !throwAway)\n        let frees = AtomicCounter.read_free_counter()\n        let mallocs = AtomicCounter.read_malloc_counter()\n        let mallocedBytes = AtomicCounter.read_malloc_bytes_counter()\n        var leakedFDs: [CInt] = []\n        if trackFDs {\n            let leaks = AtomicCounter.stop_tracking_fds()\n            defer {\n                free(leaks.leaked)\n            }\n            leakedFDs = Array(UnsafeBufferPointer(start: leaks.leaked, count: leaks.count))\n        }\n        if mallocs - frees < 0 {\n            print(\"WARNING: negative remaining allocation count, skipping.\")\n            return nil\n        }\n        return Measurement(\n            totalAllocations: mallocs,\n            totalAllocatedBytes: mallocedBytes,\n            remainingAllocations: mallocs - frees,\n            leakedFDs: leakedFDs\n        )\n    }\n\n    _ = measureOne(throwAway: true, trackFDs: trackFDs, fn)  // pre-heat and throw away\n\n    var measurements: [Measurement] = []\n    for _ in 0..<10 {\n        if let results = measureOne(trackFDs: trackFDs, fn) {\n            measurements.append(results)\n        }\n    }\n    return measurements\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc measureAndPrint(desc: String, trackFDs: Bool, fn: @escaping () async -> Int) {\n    let measurements = measureAll(trackFDs: trackFDs, fn)\n    measurements.printTotalAllocations(description: desc)\n    measurements.printRemainingAllocations(description: desc)\n    measurements.printTotalAllocatedBytes(description: desc)\n    measurements.printLeakedFDs(description: desc)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic func measure(identifier: String, trackFDs: Bool = false, _ body: @escaping () async -> Int) {\n    measureAndPrint(desc: identifier, trackFDs: trackFDs, fn: body)\n}\n"
  },
  {
    "path": "IntegrationTests/plugin_echo.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nfunction plugin_echo_test_suite_begin() {\n    echo \"Running test suite '$1'\"\n}\n\nfunction plugin_echo_test_suite_end() {\n    true\n}\n\n# test_name\nfunction plugin_echo_test_begin() {\n    echo -n \"Running test '$1'... \"\n}\n\nfunction plugin_echo_test_skip() {\n    echo \"Skipping test '$1'\"\n}\n\nfunction plugin_echo_test_ok() {\n    echo \"OK (${1}s)\"\n}\n\nfunction plugin_echo_test_fail() {\n    echo \"FAILURE ($1)\"\n    echo \"--- OUTPUT BEGIN ---\"\n    cat \"$2\"\n    echo \"--- OUTPUT  END  ---\"\n}\n\nfunction plugin_echo_test_end() {\n    true\n}\n\nfunction plugin_echo_summary_ok() {\n    echo \"OK (ran $1 tests successfully)\"\n}\n\nfunction plugin_echo_summary_fail() {\n    echo \"FAILURE (oks: $1, failures: $2)\"\n}\n\nfunction plugin_echo_init() {\n    true\n}\n"
  },
  {
    "path": "IntegrationTests/plugin_junit_xml.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\njunit_testsuite_time=0\n\nfunction junit_output_write() {\n    extra_flags=\"\"\n    if [[ \"$1\" == \"-n\" ]]; then\n        extra_flags=\"-n\"\n        shift\n    fi\n    test -n \"$junit_xml_output\"\n    echo $extra_flags \"$*\" >> \"$junit_xml_output\"\n}\n\nfunction junit_output_cat() {\n    cat \"$@\" >> \"$junit_xml_output\"\n}\n\n# search, replace\nfunction junit_output_replace() {\n    test -n \"$junit_xml_output\"\n    case \"$(uname -s)\" in\n        Linux)\n            sed -i \"s/$1/$2/g\" \"$junit_xml_output\"\n            ;;\n        *)\n            sed -i \"\" \"s/$1/$2/g\" \"$junit_xml_output\"\n            ;;\n    esac\n}\n\nfunction plugin_junit_xml_test_suite_begin() {\n    junit_testsuite_time=0\n    junit_output_write \"<testsuite name='$1' hostname='$(hostname)' \" \\\n\"timestamp='$(date -u +\"%Y-%m-%dT%H:%M:%S\")' tests='XXX-TESTS-XXX' \" \\\n\"failures='XXX-FAILURES-XXX' time='XXX-TIME-XXX' errors='0' id='$(date +%s)'\" \\\n\" package='NIOIntegrationTests.$1'>\"\n}\n\nfunction plugin_junit_xml_test_suite_end() {\n    junit_repl_success_and_fail \"$1\" \"$2\"\n    junit_output_write \"</testsuite>\"\n}\n\n# test_name\nfunction plugin_junit_xml_test_begin() {\n    junit_output_write -n \"  <testcase classname='NIOIntegrationTests.$2' name='$1'\"\n}\n\nfunction plugin_junit_xml_test_skip() {\n    true\n}\n\nfunction plugin_junit_xml_test_ok() {\n    time_ms=$1\n    junit_output_write \" time='$time_ms'>\"\n    junit_testsuite_time=$((junit_testsuite_time + time_ms))\n}\n\nfunction plugin_junit_xml_test_fail() {\n    time_ms=$1\n    junit_output_write \" time='$time_ms'>\"\n    junit_output_write \"  <failure type='test_fail'>\"\n    junit_output_write \"    <system-out>\"\n    junit_output_write '      <![CDATA['\n    junit_output_cat \"$2\"\n    junit_output_write '      ]]>'\n    junit_output_write \"    </system-out>\"\n    junit_output_write \"  </failure>\"\n}\n\nfunction plugin_junit_xml_test_end() {\n    junit_output_write \"  </testcase>\"\n}\n\nfunction junit_repl_success_and_fail() {\n    junit_output_replace XXX-TESTS-XXX \"$(($1 + $2))\"\n    junit_output_replace XXX-FAILURES-XXX \"$2\"\n    junit_output_replace XXX-TIME-XXX \"$junit_testsuite_time\"\n}\n\nfunction plugin_junit_xml_summary_ok() {\n    junit_output_write \"</testsuites>\"\n}\n\nfunction plugin_junit_xml_summary_fail() {\n    junit_output_write \"</testsuites>\"\n}\n\nfunction plugin_junit_xml_init() {\n    junit_xml_output=\"\"\n    for f in \"$@\"; do\n        if [[ \"$junit_xml_output\" = \"PLACEHOLDER\" ]]; then\n            junit_xml_output=\"$f\"\n        fi\n        if [[ \"$f\" == \"--junit-xml\" && -z \"$junit_xml_output\" ]]; then\n            junit_xml_output=\"PLACEHOLDER\"\n        fi\n    done\n\n    if [[ -z \"$junit_xml_output\" || \"$junit_xml_output\" = \"PLACEHOLDER\" ]]; then\n        echo >&2 \"ERROR: you need to specify the output after the --junit-xml argument\"\n        false\n    fi\n    echo \"<testsuites>\" > \"$junit_xml_output\"\n}\n"
  },
  {
    "path": "IntegrationTests/run-single-test.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n(\n# this sub-shell is where the actual test is run\nset -eu\nset -x\nset -o pipefail\n\ntest=\"$1\"\n# shellcheck disable=SC2034 # Used by whatever we source transpile in\ntmp=\"$2\"\n# shellcheck disable=SC2034 # Used by whatever we source transpile in\nroot=\"$3\"\n# shellcheck disable=SC2034 # Used by whatever we source transpile in\ng_show_info=\"$4\"\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\n# shellcheck source=IntegrationTests/test_functions.sh\nsource \"$here/test_functions.sh\"\n# shellcheck source=/dev/null\nsource \"$test\"\nwait\n)\nexit_code=$?\nexit $exit_code\n"
  },
  {
    "path": "IntegrationTests/run-tests.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nshopt -s nullglob\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\ntmp=$(mktemp -d /tmp/.swift-nio-http1-server-sh-tests_XXXXXX)\n\n# start_time\nfunction time_diff_to_now() {\n    echo \"$(( $(date +%s) - $1 ))\"\n}\n\nfunction plugins_do() {\n    local method\n    method=\"$1\"\n    shift\n    for plugin in $plugins; do\n        cd \"$orig_cwd\"\n        \"plugin_${plugin}_${method}\" \"$@\"\n        cd - > /dev/null\n    done\n}\n\n# shellcheck source=IntegrationTests/plugin_echo.sh\nsource \"$here/plugin_echo.sh\"\n# shellcheck source=/dev/null\nsource \"$here/plugin_junit_xml.sh\"\n\nplugins=\"echo\"\nplugin_opts_ind=0\nif [[ \"${1-default}\" == \"--junit-xml\" ]]; then\n    plugins=\"echo junit_xml\"\n    plugin_opts_ind=2\nfi\n\nfunction usage() {\n    echo >&2 \"Usage: $0 [OPTIONS]\"\n    echo >&2\n    echo >&2 \"OPTIONS:\"\n    echo >&2 \"  -f FILTER: Only run tests matching FILTER (regex)\"\n}\n\norig_cwd=$(pwd)\ncd \"$here\"\n\nplugins_do init \"$@\"\nshift $plugin_opts_ind\n\nfilter=\".\"\nverbose=false\nshow_info=false\ndebug=false\nwhile getopts \"f:vid\" opt; do\n    case $opt in\n        f)\n            filter=\"$OPTARG\"\n            ;;\n        v)\n            verbose=true\n            ;;\n        i)\n            show_info=true\n            ;;\n        d)\n            debug=true\n            ;;\n        \\?)\n            usage\n            exit 1\n            ;;\n    esac\ndone\n\nfunction run_test() {\n    if $verbose; then\n        \"$@\" 2>&1 | tee -a \"$out\"\n        # we need to return the return value of the first command\n        return \"${PIPESTATUS[0]}\"\n    else\n        \"$@\" >> \"$out\" 2>&1\n    fi\n}\n\nexec 3>&1 4>&2 # copy stdout/err to fd 3/4 to we can output control messages\ncnt_ok=0\ncnt_fail=0\nfor f in tests_*; do\n    suite_ok=0\n    suite_fail=0\n    plugins_do test_suite_begin \"$f\"\n    start_suite=$(date +%s)\n    cd \"$f\"\n    for t in test_*.sh; do\n        if [[ ! \"$f/$t\" =~ $filter ]]; then\n            plugins_do test_skip \"$t\"\n            continue\n        fi\n        out=$(mktemp \"$tmp/test.out_XXXXXX\")\n        test_tmp=$(mktemp -d \"$tmp/test.tmp_XXXXXX\")\n        plugins_do test_begin \"$t\" \"$f\"\n        start=$(date +%s)\n        if run_test \"$here/run-single-test.sh\" \"$here/$f/$t\" \"$test_tmp\" \"$here/..\" \"$show_info\"; then\n            plugins_do test_ok \"$(time_diff_to_now \"$start\")\"\n            suite_ok=$((suite_ok+1))\n            if $verbose; then\n                cat \"$out\"\n            fi\n        else\n            plugins_do test_fail \"$(time_diff_to_now \"$start\")\" \"$out\"\n            suite_fail=$((suite_fail+1))\n        fi\n        if ! $debug; then\n            rm \"$out\"\n            rm -rf \"$test_tmp\"\n        fi\n        plugins_do test_end\n    done\n    cnt_ok=$((cnt_ok + suite_ok))\n    cnt_fail=$((cnt_fail + suite_fail))\n    cd ..\n    plugins_do test_suite_end \"$(time_diff_to_now \"$start_suite\")\" \"$suite_ok\" \"$suite_fail\"\ndone\n\nif ! $debug; then\n    rm -rf \"$tmp\"\nelse\n    echo >&2 \"debug mode, not deleting '$tmp'\"\nfi\n\n\n# report\nif [[ $cnt_fail -gt 0 ]]; then\n    # terminate leftovers (the whole process group)\n    trap '' TERM\n    kill 0 # ignore-unacceptable-language\n\n    plugins_do summary_fail \"$cnt_ok\" \"$cnt_fail\"\nelse\n    plugins_do summary_ok \"$cnt_ok\" \"$cnt_fail\"\nfi\n\nif [[ $cnt_fail -gt 0 ]]; then\n    exit 1\nelse\n    exit 0\nfi\n"
  },
  {
    "path": "IntegrationTests/test_functions.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\nfunction fail() {\n    echo >&2 \"FAILURE: $*\"\n    false\n}\n\nfunction assert_equal() {\n    if [[ \"$1\" != \"$2\" ]]; then\n        fail \"expected '$1', got '$2'${3+: }${3-}\"\n    fi\n}\n\nfunction assert_equal_files() {\n    if ! cmp -s \"$1\" \"$2\"; then\n        diff -u \"$1\" \"$2\" || true\n        echo\n        echo \"--- SNIP ($1, size=$(wc \"$1\"), SHA=$(shasum \"$1\")) ---\"\n        cat \"$1\"\n        echo \"--- SNAP ($1)---\"\n        echo \"--- SNIP ($2, size=$(wc \"$2\"), SHA=$(shasum \"$2\")) ---\"\n        cat \"$2\"\n        echo \"--- SNAP ($2) ---\"\n        fail \"file '$1' not equal to '$2'${3+: }${3-}\"\n    fi\n}\n\nfunction assert_less_than() {\n    if [[ ! \"$1\" -lt \"$2\" ]]; then\n        fail \"assertion '$1' < '$2' failed${3+: }${3-}\"\n    fi\n}\n\nfunction assert_less_than_or_equal() {\n    if [[ ! \"$1\" -le \"$2\" ]]; then\n        fail \"assertion '$1' <= '$2' failed${3+: }${3-}\"\n    fi\n}\n\nfunction assert_greater_than() {\n    if [[ ! \"$1\" -gt \"$2\" ]]; then\n        fail \"assertion '$1' > '$2' failed${3+: }${3-}\"\n    fi\n}\n\nfunction assert_greater_than_or_equal() {\n    if [[ ! \"$1\" -ge \"$2\" ]]; then\n        fail \"assertion '$1' >= '$2' failed${3+: }${3-}\"\n    fi\n}\n\nfunction assert_is_number() {\n    re='^[0-9]+$'\n    if ! [[ $1 =~ $re ]]; then\n       fail \"$1 is not a number${2+: }${2-}\"\n    fi\n}\n\ng_has_previously_infoed=false\n\nfunction info() {\n    # shellcheck disable=SC2154 # Defined by an include our by being source transpiled in\n    if $g_show_info; then\n        if ! $g_has_previously_infoed; then\n            echo >&3 || true # echo an extra newline so it looks better\n            g_has_previously_infoed=true\n        fi\n        echo >&3 \"info: $*\" || true\n    fi\n}\n\nfunction warn() {\n    echo >&4 \"warning: $*\"\n}\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/defines.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nfunction server_lsof() {\n    lsof -a -d 0-1024 -p \"$1\"\n}\n\nfunction get_number_of_open_fds_for_pid() {\n    server_lsof \"$1\" >&2\n    server_lsof \"$1\" | wc -l\n}\n\n# pid, expected_number_of_fds\nfunction assert_number_of_open_fds_for_pid_equals() {\n    local pid expected actual\n    pid=\"$1\"\n    expected=\"$2\"\n\n    for f in $(seq 50); do\n        sleep 0.2\n        actual=$(get_number_of_open_fds_for_pid \"$pid\")\n        echo \"try $f, actually having $actual open fds, expecting $expected\"\n        if [[ \"$expected\" == \"$actual\" ]]; then\n            break\n        fi\n    done\n    server_lsof \"$pid\"\n    assert_equal \"$expected\" \"$actual\" \"wrong number of open fds\"\n}\n\nfunction do_netstat() {\n    pf=\"$1\"\n    netstat_options=()\n    case \"$(uname -s)\" in\n        Linux)\n            netstat_options+=( \"-A\" \"$pf\" -p )\n            ;;\n        Darwin)\n            netstat_options+=( \"-f\" \"$pf\" -v )\n            ;;\n        *)\n            fail \"Unknown OS $(uname -s)\"\n            ;;\n    esac\n    netstat -an \"${netstat_options[@]}\"\n}\n\nfunction create_token() {\n    mktemp \"${tmp:?}/server_token_XXXXXX\"\n}\n\nfunction start_server() {\n    local extra_args=''\n    if [[ \"$1\" == \"--disable-half-closure\" ]]; then\n        extra_args=\"$1\"\n        shift\n    fi\n    local token=\"$1\"\n    local type=\"unix\"\n    local port=\"$tmp/port.sock\"\n    local tmp_server_pid\n    local curl_port=80\n\n    maybe_host=\"\"\n    maybe_nio_host=\"\"\n    if [[ \"${2:-uds}\" == \"tcp\" ]]; then\n        type=\"inet\"\n        port=\"0\"\n        maybe_host=\"localhost\"\n        maybe_nio_host=\"127.0.0.1\"\n    fi\n\n    mkdir \"$tmp/htdocs\"\n    swift build\n    # shellcheck disable=SC2086 # Disabled to properly pass the args\n    \"$(swift build --show-bin-path)/NIOHTTP1Server\" $extra_args $maybe_nio_host \"$port\" \"$tmp/htdocs\" &\n    tmp_server_pid=$!\n    case \"$type\" in\n    inet)\n        # TCP mode, need to wait until we found a port that we can curl\n        worked=false\n        for f in $(seq 20); do\n            server_lsof \"$tmp_server_pid\"\n            port=$(server_lsof \"$tmp_server_pid\" | grep -Eo 'TCP .*:[0-9]+ ' | grep -Eo '[0-9]{4,5} ' | tr -d ' ' || true)\n            curl_port=\"$port\"\n            if [[ -n \"$port\" ]] && curl --ipv4 \"http://$maybe_host:$curl_port/dynamic/pid\"; then\n                worked=true\n                break\n            else\n                server_lsof \"$tmp_server_pid\"\n                sleep 0.1 # wait for the socket to be bound\n            fi\n        done\n        \"$worked\" || fail \"Could not reach server 2s after lauching...\"\n        ;;\n    unix)\n        # Unix Domain Socket, wait for the file to appear\n        for f in $(seq 30); do if [[ -S \"$port\" ]]; then break; else sleep 0.1; fi; done\n        ;;\n    *)\n        fail \"Unknown server type '$type'\"\n        ;;\n    esac\n    echo \"port: $port\"\n    echo \"curl port: $curl_port\"\n    {\n        echo \"local token_port;   local token_htdocs;         local token_pid;\"\n        echo \"      token_port='$port'; token_htdocs='$tmp/htdocs'; token_pid='$!';\"\n        echo \"      token_type='$type'; token_server_ip='$maybe_nio_host'\"\n    } >> \"$token\"\n    tmp_server_pid=$(get_server_pid \"$token\")\n    echo \"local token_open_fds\" >> \"$token\"\n    echo \"token_open_fds='$(get_number_of_open_fds_for_pid \"$tmp_server_pid\")'\" >> \"$token\"\n    local curl_host=${maybe_host:-localhost}\n    do_curl \"$token\" \"http://$curl_host:$curl_port/dynamic/pid\"\n}\n\nfunction get_htdocs() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    # shellcheck disable=SC2154\n    echo \"${token_htdocs:?}\"\n}\n\nfunction get_socket() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    echo \"${token_port:?}\"\n}\n\nfunction stop_server() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    sleep 0.5 # just to make sure all the fds could be closed\n    if command -v lsof > /dev/null 2> /dev/null; then\n        do_netstat \"${token_type:?}\"\n        assert_number_of_open_fds_for_pid_equals \"${token_pid:?}\" \"${token_open_fds:?}\"\n    fi\n    # assert server is still running\n    kill -0 \"$token_pid\" # ignore-unacceptable-language\n    # tell server to shut down gracefully\n    kill \"$token_pid\" # ignore-unacceptable-language\n    for f in $(seq 20); do\n        if ! kill -0 \"$token_pid\" 2> /dev/null; then # ignore-unacceptable-language\n            break # good, dead\n        fi\n        # shellcheck disable=SC2009\n        ps auxw | grep \"$token_pid\" || true\n        sleep 0.1\n    done\n    if kill -0 \"$token_pid\" 2> /dev/null; then # ignore-unacceptable-language\n        fail \"server $token_pid still running\"\n    fi\n}\n\nfunction get_server_pid() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    echo \"$token_pid\"\n}\n\nfunction get_server_port() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    echo \"$token_port\"\n}\n\nfunction get_server_ip() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    # shellcheck disable=SC2154\n    echo \"$token_server_ip\"\n}\n\nfunction do_curl() {\n    # shellcheck source=/dev/null\n    source \"$1\"\n    shift\n    case \"$token_type\" in\n        inet)\n            curl -v --ipv4 \"$@\"\n            ;;\n        unix)\n            curl --unix-socket \"$token_port\" -v \"$@\"\n            ;;\n        *)\n            fail \"Unknown type '$token_type'\"\n            ;;\n    esac\n}\n\n_new_nc=false\nif nc -h 2>&1 | grep -- -N | grep -q EOF; then\n    # this is a new kind of 'nc' that doesn't automatically shut down\n    # the input socket after EOF. But we rely on that behaviour.\n    _new_nc=true\nfi\n\nfunction do_nc() {\n    if \"$_new_nc\"; then\n        nc -N \"$@\"\n    else\n        nc \"$@\"\n    fi\n}\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_01_get_file.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nhtdocs=$(get_htdocs \"$token\")\necho FOO BAR > \"$htdocs/some_file.txt\"\ntouch \"$htdocs/empty\"\nfor file in some_file.txt empty; do\n    for method in sendfile fileio; do\n        do_curl \"$token\" \"http://foobar.com/$method/$file\" > \"${tmp:?\"tmp variable not set\"}/out.txt\"\n        assert_equal_files \"$htdocs/$file\" \"$tmp/out.txt\"\n    done\ndone\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_02_get_random_bytes.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nhtdocs=$(get_htdocs \"$token\")\nbase=\"s/o/m/e/r/a/n/d/o/m/f/o/l/d/e/r\"\nmkdir -p \"$htdocs/$base\"\ndd if=/dev/urandom of=\"$htdocs/$base/random.bytes\" bs=$((1024 * 1024)) count=2\nfor method in sendfile fileio; do\n    do_curl \"$token\" \"http://foobar.com/$method/$base/random.bytes\" > \"${tmp:?\"tmp variable not set\"}/random.bytes\"\n    assert_equal_files \"$htdocs/$base/random.bytes\" \"$tmp/random.bytes\"\ndone\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_03_post_random_bytes.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\ndd if=/dev/urandom of=\"${tmp:?\"tmp variable not set\"}/random.bytes\" bs=$((64*1024)) count=1\ndo_curl \"$token\" --data-binary \"@$tmp/random.bytes\" \\\n    \"http://foobar.com/dynamic/echo\" > \"$tmp/random.bytes.out\"\ncmp \"$tmp/random.bytes\" \"$tmp/random.bytes.out\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_04_keep_alive_works.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nserver_pid=$(get_server_pid \"$token\")\necho -n \\\n    \"$server_pid$server_pid$server_pid$server_pid$server_pid$server_pid$server_pid$server_pid$server_pid$server_pid\" \\\n    > \"${tmp:?\"tmp variable not set\"}/out_expected\"\ndo_curl \"$token\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    \"http://foobar.com/dynamic/pid\" \\\n    > \"$tmp/out_actual\"\nassert_equal_files \"$tmp/out_expected\" \"$tmp/out_actual\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_05_repeated_reqs_work.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\ndo_curl \"$token\" \"http://foobar.com/dynamic/pid\" > \"${tmp:?\"tmp variable not set\"}/out\"\nfor _ in $(seq 100); do\n    do_curl \"$token\" \"http://foobar.com/dynamic/pid\" > \"$tmp/out2\"\n    assert_equal_files \"$tmp/out\" \"$tmp/out2\"\ndone\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_06_http_1.0.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\necho foo > \"${tmp:?\"tmp variable not set\"}/out_expected\"\ndo_curl \"$token\" --data-binary \"@$tmp/out_expected\" --http1.0 \\\n    \"http://foobar.com/dynamic/echo_balloon\" > \"$tmp/out_actual\"\nassert_equal_files \"$tmp/out_expected\" \"$tmp/out_actual\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_07_headers_work.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\ndo_curl \"$token\" -H \"foo: bar\" --http1.0 \\\n    \"http://foobar.com/dynamic/info\" >\"${tmp:?\"tmp variable not set\"}/out\"\nif ! grep -q 'foo: bar' \"$tmp/out\"; then\n    fail \"couldn't find header in response\"\nfi\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_08_survive_signals.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nhtdocs=$(get_htdocs \"$token\")\nserver_pid=$(get_server_pid \"$token\")\necho FOO BAR > \"$htdocs/some_file.txt\"\n\nfor _ in $(seq 20); do\n    # send some signals that are usually discarded\n    kill -CHLD \"$server_pid\" # ignore-unacceptable-language\n    kill -URG \"$server_pid\" # ignore-unacceptable-language\n    kill -CONT \"$server_pid\" # ignore-unacceptable-language\n    kill -WINCH \"$server_pid\" # ignore-unacceptable-language\n\n    do_curl \"$token\" \"http://foobar.com/fileio/some_file.txt\" > \"${tmp:?\"tmp variable not set\"}/out.txt\" &\n    curl_pid=$!\n    for _ in $(seq 20); do\n        kill -URG \"$server_pid\" # ignore-unacceptable-language\n    done\n    wait $curl_pid\n    cmp \"$htdocs/some_file.txt\" \"$tmp/out.txt\"\ndone\n\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_09_curl_happy_with_trailers.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nhtdocs=$(get_htdocs \"$token\")\nserver_pid=$(get_server_pid \"$token\")\nbackslash_r=$(echo -ne '\\r')\ncat > \"$htdocs/some_file.txt\" <<EOF\n$server_pid$backslash_r\n$server_pid$backslash_r\n$server_pid$backslash_r\n$server_pid$backslash_r\nEOF\ndo_curl \"$token\" \\\n    \"http://foobar.com/dynamic/trailers\" \\\n    \"http://foobar.com/dynamic/trailers\" \\\n    \"http://foobar.com/dynamic/trailers\" \\\n    \"http://foobar.com/dynamic/trailers\" \\\n    > \"${tmp:?\"tmp variable not set\"}/out.txt\"\nassert_equal_files \"$htdocs/some_file.txt\" \"${tmp}/out.txt\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_10_connection_drop_in_body_ok.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nserver_pid=$(get_server_pid \"$token\")\nsocket=$(get_socket \"$token\")\n\nkill -0 \"$server_pid\" # ignore-unacceptable-language\n(\n    echo -e 'POST /dynamic/echo HTTP/1.1\\r\\nContent-Length: 400000\\r\\n\\r\\nsome_bytes'\n    for f in $(seq 5); do\n        echo \"$f\"\n        sleep 0.1\n    done\n) | do_nc -U \"$socket\"\nsleep 0.1\nkill -0 \"$server_pid\" # ignore-unacceptable-language\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_11_res_body_streaming.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\n# shellcheck disable=SC2034\nserver_pid=$(get_server_pid \"$token\")\n# shellcheck disable=SC2034\nsocket=$(get_socket \"$token\")\n\ncat > \"${tmp:?\"tmp variable not set\"}/expected\" <<EOF\nline 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nEOF\n\n{ do_curl \"$token\" -N http://test/dynamic/continuous || true; } | head -7 > \"$tmp/actual\"\nassert_equal_files \"$tmp/expected\" \"$tmp/actual\"\n\nsleep 1 # need to have the next write fail\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_12_headers_too_large.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nhtdocs=$(get_htdocs \"$token\")\ntouch \"${tmp:?\"tmp variable not set\"}/empty\"\ncr=$(echo -e '\\r')\ncat > \"$tmp/headers_expected\" <<EOF\nHTTP/1.1 400 Bad Request$cr\nContent-Length: 0$cr\nConnection: close$cr\n$cr\nEOF\necho \"FOO BAR\" > \"$htdocs/some_file.txt\"\n# headers have acceptable size\ndo_curl \"$token\" -H \"$(dd if=/dev/zero bs=1000 count=80 2> /dev/null | tr '\\0' x): x\" \\\n    \"http://foobar.com/fileio/some_file.txt\" > \"$tmp/out\"\nassert_equal_files \"$htdocs/some_file.txt\" \"$tmp/out\"\n\n# headers too large\ndo_curl \"$token\" -H \"$(dd if=/dev/zero bs=1000 count=90 2> /dev/null | tr '\\0' x): x\" \\\n    -D \"$tmp/headers_actual\" \\\n    \"http://foobar.com/fileio/some_file.txt\" > \"$tmp/out\"\nassert_equal_files \"$tmp/empty\" \"$tmp/out\"\n\nif ! grep -q 'HTTP/1.1 400 Bad Request' \"$tmp/headers_actual\"; then\n    fail \"couldn't find status line in response\"\nfi\nif ! grep -q 'Content-Length: 0' \"$tmp/headers_actual\"; then\n    fail \"couldn't find content-length in response\"\nfi\nif ! grep -q 'Connection: close' \"$tmp/headers_actual\"; then\n    fail \"couldn't find connection: close in response\"\nfi\n\nlinecount=$(wc \"$tmp/headers_actual\")\nif [ \"$linecount\" -ne 4 ]; then\n    fail \"overlong response\"\nfi\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_13_http_pipelining.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\nserver_pid=$(get_server_pid \"$token\")\nsocket=$(get_socket \"$token\")\n\nkill -0 \"$server_pid\" # ignore-unacceptable-language\n\necho -e 'GET /dynamic/count-to-ten HTTP/1.1\\r\\n\\r\\nGET /dynamic/count-to-ten HTTP/1.1\\r\\n\\r\\n' | \\\n    do_nc -U \"$socket\" > \"${tmp:?\"tmp variable not set\"}/actual\"\nbackslash_r=$(echo -ne '\\r')\ncat > \"$tmp/expected\" <<EOF\nHTTP/1.1 200 OK$backslash_r\ntransfer-encoding: chunked$backslash_r\n$backslash_r\n1$backslash_r\n1$backslash_r\n1$backslash_r\n2$backslash_r\n1$backslash_r\n3$backslash_r\n1$backslash_r\n4$backslash_r\n1$backslash_r\n5$backslash_r\n1$backslash_r\n6$backslash_r\n1$backslash_r\n7$backslash_r\n1$backslash_r\n8$backslash_r\n1$backslash_r\n9$backslash_r\n2$backslash_r\n10$backslash_r\n0$backslash_r\n$backslash_r\nHTTP/1.1 200 OK$backslash_r\ntransfer-encoding: chunked$backslash_r\n$backslash_r\n1$backslash_r\n1$backslash_r\n1$backslash_r\n2$backslash_r\n1$backslash_r\n3$backslash_r\n1$backslash_r\n4$backslash_r\n1$backslash_r\n5$backslash_r\n1$backslash_r\n6$backslash_r\n1$backslash_r\n7$backslash_r\n1$backslash_r\n8$backslash_r\n1$backslash_r\n9$backslash_r\n2$backslash_r\n10$backslash_r\n0$backslash_r\n$backslash_r\nEOF\nassert_equal_files \"${tmp}/expected\" \"${tmp}/actual\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_14_strict_mode_assertion.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\nsocket=$(get_socket \"$token\")\necho -e 'GET / HTT\\r\\n\\r\\n' | do_nc -U \"$socket\" > \"${tmp:?\"tmp variable not set\"}/actual\"\n\nif ! grep -q 'HTTP/1.1 400 Bad Request' \"$tmp/actual\"; then\n    fail \"couldn't find status line in response\"\nfi\nif ! grep -q 'Content-Length: 0' \"$tmp/actual\"; then\n    fail \"couldn't find Content-Length in response\"\nfi\nif ! grep -q 'Connection: close' \"$tmp/actual\"; then\n    fail \"couldn't find Connection: close in response\"\nfi\n\nlinecount=$(wc \"$tmp/actual\")\nif [[ $linecount -ne 4 ]]; then\n    fail \"overlong response\"\nfi\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_15_post_in_chunked_encoding.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\ndd if=/dev/urandom of=\"${tmp:?\"tmp variable not set\"}/random.bytes\" bs=$((64*1024)) count=1\ndo_curl \"$token\" -X POST --header \"Transfer-Encoding: chunked\" \\\n    --data-binary \"@$tmp/random.bytes\" \\\n    \"http://foobar.com/dynamic/echo\" > \"$tmp/random.bytes.out\"\ncmp \"$tmp/random.bytes\" \"$tmp/random.bytes.out\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_16_tcp_client_ip.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\" tcp\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\necho -n '[IPv4]127.0.0.1' > \"${tmp:?\"tmp variable not set\"}/expected_ipv4\"\necho -n '[IPv6]::1' > \"$tmp/expected_ipv6\"\ndo_curl \"$token\" \"http://localhost:$(get_server_port \"$token\")/dynamic/client-ip\" > \"$tmp/actual\"\nif grep -q '\\[IPv4\\]127.0.0.1' \"$tmp/actual\"; then\n    true\nelif grep -q '\\[IPv6\\]::1' \"$tmp/actual\"; then\n    true\nelse\n    fail \"could not find client IP in $(cat \"$tmp/actual\")\"\nfi\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_17_serve_massive_sparse_file.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nhtdocs=$(get_htdocs \"$token\")\n# create a 3GB sparse file, this is above the 2,147,479,552 mentioned in the\n# BUGS section of Linux's sendfile(2) man page.\ndd if=/dev/zero of=\"$htdocs/lots_of_zeroes\" seek=$((3 * 1024)) bs=$((1024 * 1024)) count=1\ndo_curl \"$token\" \"http://foobar.com/fileio/lots_of_zeroes\" | shasum > \"${tmp:?\"tmp variable not set\"}/actual_sha\"\necho \"bf184d91c8f82092198e4d8e1d029e576dbec3bc  -\" > \"$tmp/expected_sha\"\nassert_equal_files \"$tmp/expected_sha\" \"$tmp/actual_sha\"\nsleep 3 # wait for all the fds to be closed\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_18_close_with_no_keepalive.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\nserver_pid=$(get_server_pid \"$token\")\nsocket=$(get_socket \"$token\")\n\nkill -0 \"$server_pid\" # ignore-unacceptable-language\n\necho -e 'GET /dynamic/count-to-ten HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n' | \\\n    do_nc -U \"$socket\" > \"${tmp:?\"tmp variable not set\"}/actual\"\nbackslash_r=$(echo -ne '\\r')\ncat > \"$tmp/expected\" <<EOF\nHTTP/1.1 200 OK$backslash_r\nConnection: close$backslash_r\ntransfer-encoding: chunked$backslash_r\n$backslash_r\n1$backslash_r\n1$backslash_r\n1$backslash_r\n2$backslash_r\n1$backslash_r\n3$backslash_r\n1$backslash_r\n4$backslash_r\n1$backslash_r\n5$backslash_r\n1$backslash_r\n6$backslash_r\n1$backslash_r\n7$backslash_r\n1$backslash_r\n8$backslash_r\n1$backslash_r\n9$backslash_r\n2$backslash_r\n10$backslash_r\n0$backslash_r\n$backslash_r\nEOF\nassert_equal_files \"$tmp/expected\" \"$tmp/actual\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_19_connection_drop_while_waiting_for_response_uds.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server --disable-half-closure \"$token\"\nserver_pid=$(get_server_pid \"$token\")\nsocket=$(get_socket \"$token\")\n\nkill -0 \"$server_pid\" # ignore-unacceptable-language\necho -e 'GET /dynamic/write-delay/10000 HTTP/1.1\\r\\n\\r\\n' | do_nc -w1 -U \"$socket\"\nsleep 0.2\n\n# note: the way this test would fail is to leak file descriptors (ie. have some\n# connections still open 0.2s after the request terminated). `stop_server`\n# checks for that, hence there aren't any explicit asserts in here.\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_20_connection_drop_while_waiting_for_response_tcp.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server --disable-half-closure \"$token\" tcp\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\nserver_pid=$(get_server_pid \"$token\")\nip=$(get_server_ip \"$token\")\nport=$(get_server_port \"$token\")\n\nkill -0 \"$server_pid\" # ignore-unacceptable-language\necho -e 'GET /dynamic/write-delay/10000 HTTP/1.1\\r\\n\\r\\n' | do_nc -w1 \"$ip\" \"$port\"\nsleep 0.2\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_21_connection_reset_tcp.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server --disable-half-closure \"$token\" tcp\n# shellcheck disable=SC2034\nhtdocs=$(get_htdocs \"$token\")\nserver_pid=$(get_server_pid \"$token\")\nip=$(get_server_ip \"$token\")\nport=$(get_server_port \"$token\")\n\nkill -0 \"$server_pid\" # ignore-unacceptable-language\n# try to simulate a TCP connection reset, works really well on Darwin but not on\n# Linux over loopback. On Linux however\n# `test_19_connection_drop_while_waiting_for_response_uds.sh` tests a very\n# similar situation.\nyes \"$( echo -e 'GET /dynamic/write-delay HTTP/1.1\\r\\n\\r\\n')\" | nc \"$ip\" \"$port\" > /dev/null & sleep 0.5; kill -9 $! # ignore-unacceptable-language\nsleep 0.2\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_22_http_1.0_keep_alive.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\ndo_curl \"$token\" -H 'connection: keep-alive' -v --http1.0 \\\n    \"http://foobar.com/dynamic/info\" > \"${tmp:?\"tmp variable not set\"}/out_actual\" 2>&1\ngrep -qi '< Connection: keep-alive' \"$tmp/out_actual\"\ngrep -qi '< HTTP/1.0 200 OK' \"$tmp/out_actual\"\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_23_repeated_reqs_with_half_closure.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\ntoken=$(create_token)\nstart_server \"$token\"\nsocket=$(get_socket \"$token\")\necho -ne 'HTTP/1.1 200 OK\\r\\ncontent-length: 13\\r\\n\\r\\nHello World\\r\\n' > \"${tmp:?\"tmp variable not set\"}/expected\"\nfor _ in $(seq 2000); do\n    echo -e 'GET / HTTP/1.1\\r\\n\\r\\n' | do_nc -w10 -U \"$socket\" > \"$tmp/actual\"\n    assert_equal_files \"$tmp/expected\" \"$tmp/actual\"\ndone\nstop_server \"$token\"\n"
  },
  {
    "path": "IntegrationTests/tests_01_http/test_24_http_over_stdio.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nswift build\necho -ne \"::: HELLO\\n::: WORLD\\n:::\\n\" > \"${tmp:?\"tmp variable not set\"}/file\"\nlines_in_file=\"$(wc -l < \"$tmp/file\"  | tr -d '\\t ')\"\nfunction echo_request_close() {\n    echo -e 'GET /fileio/file HTTP/1.1\\r\\nconnection: close\\r\\nhost: stdio\\r\\n\\r\\n'\n}\n\nfunction echo_request_keep_alive() {\n    echo -e 'GET /fileio/file HTTP/1.1\\r\\nconnection: keep-alive\\r\\nhost: stdio\\r\\n\\r\\n'\n}\n\necho_request_close | \"$(swift build --show-bin-path)/NIOHTTP1Server\" - \"$tmp\" | cat > \"$tmp/output\"\n\ntail -n \"$lines_in_file\" \"$tmp/output\" > \"$tmp/output-just-file\"\nassert_equal_files \"$tmp/file\" \"$tmp/output-just-file\"\n\nhow_many=100\n{\n    for _ in $(seq \"$(( how_many - 1 ))\" ); do\n        echo_request_keep_alive\n    done\n    echo_request_close\n} | \"$(swift build --show-bin-path)/NIOHTTP1Server\" - \"$tmp\" | grep ^::: > \"$tmp/multi-actual\"\n\nset +o pipefail # we know that 'yes' will fail with SIGPIPE\nyes \"$(cat \"$tmp/file\")\" | head -n $(( lines_in_file * how_many )) > \"$tmp/multi-expected\"\nassert_equal_files \"$tmp/multi-expected\" \"$tmp/multi-actual\"\n"
  },
  {
    "path": "IntegrationTests/tests_02_syscall_wrappers/defines.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nfunction make_package() {\n    if [[ ! -d \"${tmpdir:?\"tmpdir variable not set\"}/syscallwrapper/Sources/syscallwrapper/\" ]]; then\n        mkdir \"$tmpdir/syscallwrapper/Sources/syscallwrapper/\"\n        mv \"$tmpdir\"/syscallwrapper/Sources/*.swift \"$tmpdir/syscallwrapper/Sources/syscallwrapper/\"\n    fi\n\n    cat > \"$tmpdir/syscallwrapper/Package.swift\" <<\"EOF\"\n// swift-tools-version:6.0\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"syscallwrapper\",\n    dependencies: [],\n    targets: [\n        .target(\n            name: \"syscallwrapper\",\n            dependencies: [\"CNIOLinux\", \"CNIODarwin\", \"NIOCore\"]),\n        .target(\n            name: \"CNIOLinux\",\n            dependencies: [],\n            cSettings: [\n                .define(\"_GNU_SOURCE\")\n            ]),\n        .target(\n            name: \"CNIODarwin\",\n            dependencies: []),\n        // This target does nothing, it just makes imports work.\n        .target(\n            name: \"NIOCore\",\n            dependencies: []),\n    ]\n)\nEOF\n    cp \"${here:?\"here variable not set\"}/../../Tests/NIOPosixTests/SystemCallWrapperHelpers.swift\" \\\n        \"$here/../../Sources/NIOCore/BSDSocketAPI.swift\" \\\n        \"$here/../../Sources/NIOPosix/BSDSocketAPICommon.swift\" \\\n        \"$here/../../Sources/NIOPosix/BSDSocketAPIPosix.swift\" \\\n        \"$here/../../Sources/NIOPosix/System.swift\" \\\n        \"$here/../../Sources/NIOCore/IO.swift\" \\\n        \"$here/../../Sources/NIOCore/IPProtocol.swift\" \\\n        \"$here/../../Sources/NIOCore/NIOSendable.swift\" \\\n        \"$tmpdir/syscallwrapper/Sources/syscallwrapper\"\n    cp \"$here/../../Sources/NIOPosix/IO.swift\" \"$tmpdir/syscallwrapper/Sources/syscallwrapper/NIOPosixIO.swift\"\n    ln -s \"$here/../../Sources/CNIOLinux\" \"$tmpdir/syscallwrapper/Sources\"\n    ln -s \"$here/../../Sources/CNIODarwin\" \"$tmpdir/syscallwrapper/Sources\"\n    mkdir \"$tmpdir/syscallwrapper/Sources/NIOCore\"\n    touch \"$tmpdir/syscallwrapper/Sources/NIOCore/empty.swift\"\n    rm -rf \"$tmpdir/syscallwrapper/Sources/syscallwrapper/syscallwrapper.swift\"\n}\n"
  },
  {
    "path": "IntegrationTests/tests_02_syscall_wrappers/test_01_syscall_wrapper_fast.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nswift_binary=swift\n# shellcheck disable=SC2034 # Used in defines.sh\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nif [[ -n \"${SWIFT_EXEC-}\" ]]; then\n    swift_binary=\"$(dirname \"$SWIFT_EXEC\")/swift\"\nelif [[ \"$(uname -s)\" == \"Linux\" ]]; then\n    swift_binary=$(which swift)\nfi\n\ntmpdir=$(mktemp -d /tmp/.swift-nio-syscall-wrappers-sh-test_XXXXXX)\nmkdir \"$tmpdir/syscallwrapper\"\ncd \"$tmpdir/syscallwrapper\"\nswift package init --type=executable\n\nmain_path=\"$tmpdir/syscallwrapper/Sources/main.swift\"\nif [[ -d \"$tmpdir/syscallwrapper/Sources/syscallwrapper/\" ]]; then\n    main_path=\"$tmpdir/syscallwrapper/Sources/syscallwrapper/main.swift\"\nfi\n\ncat > \"$main_path\" <<EOF\n#if canImport(Darwin)\nimport Darwin\n#else\nimport Glibc\n#endif\npublic typealias IOVector = iovec\nrunStandalone()\nEOF\n\nmake_package\n\n\"$swift_binary\" run -c release -Xswiftc -DRUNNING_INTEGRATION_TESTS\n\nrm -rf \"$tmpdir\"\n"
  },
  {
    "path": "IntegrationTests/tests_02_syscall_wrappers/test_02_unacceptable_errnos.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nswift_binary=swift\n# shellcheck disable=SC2034 # Used in defines.sh\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nif [[ -n \"${SWIFT_EXEC-}\" ]]; then\n    swift_binary=\"$(dirname \"$SWIFT_EXEC\")/swift\"\nelif [[ \"$(uname -s)\" == \"Linux\" ]]; then\n    swift_binary=$(which swift)\nfi\n\ntmpdir=$(mktemp -d /tmp/.swift-nio-syscall-wrappers-sh-test_XXXXXX)\nmkdir \"$tmpdir/syscallwrapper\"\ncd \"$tmpdir/syscallwrapper\"\nswift package init --type=executable\n\nmain_path=\"$tmpdir/syscallwrapper/Sources/main.swift\"\nif [[ -d \"$tmpdir/syscallwrapper/Sources/syscallwrapper/\" ]]; then\n    main_path=\"$tmpdir/syscallwrapper/Sources/syscallwrapper/main.swift\"\nfi\n\ncat > \"$main_path\" <<EOF\n#if canImport(Darwin)\nimport Darwin\n#else\nimport Glibc\n#endif\npublic typealias IOVector = iovec\n\n\nvar fds: [Int32] = [-1, -1]\nlet pipeErr = pipe(&fds)\nif pipeErr != 0 {\n    // this program is expected to fail in correct operation\n    exit(0)\n}\nlet makeEBADFHappen =  CommandLine.arguments.dropFirst().first == .some(\"EBADF\")\nlet makeEFAULTHappen = CommandLine.arguments.dropFirst().first == .some(\"EFAULT\")\nvar whatevs: UInt8 = 123\n_ = try? withUnsafePointer(to: &whatevs) { ptr in\n    print(\"makeEBADFHappen? \\(makeEBADFHappen ? \"YES\" : \"NO\")\")\n    print(\"makeEFAULTHappen ? \\(makeEFAULTHappen ? \"YES\" : \"NO\")\")\n    _ = try Posix.write(descriptor: makeEBADFHappen ? -1 : fds[0],\n                        pointer: makeEFAULTHappen ? UnsafePointer<UInt8>(bitPattern: 0xdeadbee)! : ptr,\n                     size: 1)\n}\nexit(42)\nEOF\n\nmake_package\n\nfor mode in debug release; do\n    for error in EFAULT EBADF; do\n        temp_file=\"${tmp:?\"tmp variable not set\"}/stderr\"\n        if \"$swift_binary\" run -c \"$mode\" -Xswiftc -DRUNNING_INTEGRATION_TESTS \\\n            syscallwrapper \"$error\" 2> \"$temp_file\"; then\n\n            fail \"exited successfully but was supposed to fail\"\n        else\n            exit_code=$?\n            \n            # expecting irrecoverable error as process should be terminated through fatalError/precondition/assert\n            architecture=$(uname -m)\n            if [[ $architecture =~ ^(arm|aarch) ]]; then\n                assert_equal $exit_code $(( 128 + 5 )) # 5 == SIGTRAP aka trace trap, expected on ARM\n            elif [[ $architecture =~ ^(x86|i386) ]]; then\n                assert_equal $exit_code $(( 128 + 4 ))  # 4 == SIGILL aka illegal instruction, expected on x86\n            else\n                fail \"unknown CPU architecture for which we don't know the expected signal for a crash\"\n            fi\n            \n            if [[ \"$mode\" == \"debug\" ]]; then\n                grep -q unacceptable\\ errno \"$temp_file\"\n            fi\n        fi\n    done\ndone\n\nrm -rf \"$tmpdir\"\n"
  },
  {
    "path": "IntegrationTests/tests_02_syscall_wrappers/test_03_unacceptable_read_errnos.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nswift_binary=swift\n# shellcheck disable=SC2034 # Used in defines.sh\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nif [[ -n \"${SWIFT_EXEC-}\" ]]; then\n    swift_binary=\"$(dirname \"$SWIFT_EXEC\")/swift\"\nelif [[ \"$(uname -s)\" == \"Linux\" ]]; then\n    swift_binary=$(which swift)\nfi\n\ntmpdir=$(mktemp -d /tmp/.swift-nio-syscall-wrappers-sh-test_XXXXXX)\nmkdir \"$tmpdir/syscallwrapper\"\ncd \"$tmpdir/syscallwrapper\"\nswift package init --type=executable\n\nmain_path=\"$tmpdir/syscallwrapper/Sources/main.swift\"\nif [[ -d \"$tmpdir/syscallwrapper/Sources/syscallwrapper/\" ]]; then\n    main_path=\"$tmpdir/syscallwrapper/Sources/syscallwrapper/main.swift\"\nfi\n\ncat > \"$main_path\" <<EOF\n#if canImport(Darwin)\nimport Darwin\n#else\nimport Glibc\n#endif\npublic typealias IOVector = iovec\n\n\nvar fds: [Int32] = [-1, -1]\nlet pipeErr = pipe(&fds)\nif pipeErr != 0 {\n    // this program is expected to fail in correct operation\n    exit(0)\n}\nlet makeEBADFHappen =  CommandLine.arguments.dropFirst().first == .some(\"EBADF\")\nlet makeEFAULTHappen = CommandLine.arguments.dropFirst().first == .some(\"EFAULT\")\nlet makeEINVALHappen = CommandLine.arguments.dropFirst().first == .some(\"EINVAL\")\nvar whatevs: UInt8 = 123\n_ = try? withUnsafeMutablePointer(to: &whatevs) { ptr in\n    _ = try Posix.write(\n        descriptor: fds[0],\n        pointer: ptr,\n        size: 1\n    )\n    print(\"makeEBADFHappen? \\(makeEBADFHappen ? \"YES\" : \"NO\")\")\n    print(\"makeEFAULTHappen ? \\(makeEFAULTHappen ? \"YES\" : \"NO\")\")\n    print(\"makeEINVALHappen ? \\(makeEINVALHappen ? \"YES\" : \"NO\")\")\n\n    let pointer: UnsafeMutablePointer<UInt8>\n    if makeEFAULTHappen {\n        pointer = UnsafeMutablePointer<UInt8>(bitPattern: 0xdeadbee)!\n    } else if makeEINVALHappen {\n        pointer = UnsafeMutablePointer<UInt8>(bitPattern: -1)!\n    } else {\n        pointer = ptr\n    }\n    _ = try Posix.read(\n        descriptor: makeEBADFHappen ? -1 : fds[0],\n        pointer: pointer,\n        size: 1\n    )\n}\nexit(42)\nEOF\n\nmake_package\n\nfor mode in debug release; do\n    for error in EFAULT EBADF EINVAL; do\n        temp_file=\"${tmp:?\"tmp variable not set\"}/stderr\"\n        if \"$swift_binary\" run -c \"$mode\" -Xswiftc -DRUNNING_INTEGRATION_TESTS \\\n            syscallwrapper \"$error\" 2> \"$temp_file\"; then\n\n            fail \"exited successfully but was supposed to fail\"\n        else\n            exit_code=$?\n            \n            # expecting irrecoverable error as process should be terminated through fatalError/precondition/assert\n            architecture=$(uname -m)\n            if [[ $architecture =~ ^(arm|aarch) ]]; then\n                assert_equal $exit_code $(( 128 + 5 )) # 5 == SIGTRAP aka trace trap, expected on ARM\n            elif [[ $architecture =~ ^(x86|i386) ]]; then\n                assert_equal $exit_code $(( 128 + 4 ))  # 4 == SIGILL aka illegal instruction, expected on x86\n            else\n                fail \"unknown CPU architecture for which we don't know the expected signal for a crash\"\n            fi\n            \n            if [[ \"$mode\" == \"debug\" ]]; then\n                grep -q unacceptable\\ errno \"$temp_file\"\n            fi\n        fi\n    done\ndone\n\nrm -rf \"$tmpdir\"\n"
  },
  {
    "path": "IntegrationTests/tests_03_debug_binary_checks/defines.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\npushd \"$here/../..\" || exit\nswift build\n# shellcheck disable=SC2034 # Used by imports\nbin_path=$(swift build --show-bin-path)\npopd || exit\n"
  },
  {
    "path": "IntegrationTests/tests_03_debug_binary_checks/test_01_check_we_do_not_link_Foundation.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nfunction check_does_not_link() {\n    local library=\"$1\"\n    local binary=\"$2\"\n\n    case \"$(uname -s)\" in\n        Darwin)\n            otool -L \"$binary\" > \"${tmp:?\"tmp variable not set\"}/linked_libs\"\n            ;;\n        Linux)\n            ldd \"$binary\" > \"$tmp/linked_libs\"\n            ;;\n        *)\n            fail \"unsupported OS $(uname -s)\"\n            ;;\n    esac\n    echo -n > \"$tmp/expected\"\n    ! grep \"$library\" \"$tmp/linked_libs\" > \"$tmp/linked_checked_lib\"\n\n    assert_equal_files \"$tmp/expected\" \"$tmp/linked_checked_lib\"\n}\n\nfor binary in NIOEchoServer NIOEchoClient NIOChatServer NIOChatClient NIOHTTP1Server; do\n    check_does_not_link /Foundation \"${bin_path:?\"tmp variable not set\"}/$binary\" # Darwin (old)\n    check_does_not_link libFoundation \"$bin_path/$binary\" # Linux\n    check_does_not_link swiftFoundation \"$bin_path/$binary\" # Darwin (new)\ndone\n"
  },
  {
    "path": "IntegrationTests/tests_03_debug_binary_checks/test_02_expected_crashes_work.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\n\"${bin_path:?\"bin_path variable not set\"}/NIOCrashTester\" run-all\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/5.10.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 19,\n    \"1000000_asyncwriter\": 1000050,\n    \"1000_addHandlers\": 44050,\n    \"1000_addHandlers_sync\": 37050,\n    \"1000_addRemoveHandlers_handlercontext\": 8050,\n    \"1000_addRemoveHandlers_handlername\": 8050,\n    \"1000_addRemoveHandlers_handlertype\": 8050,\n    \"1000_autoReadGetAndSet\": 18050,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1050,\n    \"1000_copying_circularbuffer_to_array\": 1050,\n    \"1000_getHandlers\": 8050,\n    \"1000_getHandlers_sync\": 35,\n    \"1000_reqs_1_conn\": 26350,\n    \"1000_rst_connections\": 138050,\n    \"1000_tcpbootstraps\": 3050,\n    \"1000_tcpconnections\": 146050,\n    \"1000_udp_reqs\": 6050,\n    \"1000_udpbootstraps\": 2050,\n    \"1000_udpconnections\": 75050,\n    \"1_reqs_1000_conn\": 375050,\n    \"assume_isolated_scheduling_10000_executions\": 89,\n    \"bytebuffer_lots_of_rw\": 2050,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2050,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2050,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2050,\n    \"encode_1000_ws_frames_new_buffer\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5050,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5050,\n    \"execute_hop_10000_tasks\": 0,\n    \"flat_schedule_10000_tasks\": 100100,\n    \"flat_schedule_assume_isolated_10000_tasks\": 90100,\n    \"future_assume_isolated_lots_of_callbacks\": 68050,\n    \"future_erase_result\": 4050,\n    \"future_lots_of_callbacks\": 68050,\n    \"get_100000_headers_canonical_form\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 700050,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6050,\n    \"ping_pong_1000_reqs_1_conn\": 305,\n    \"read_10000_chunks_from_file\": 110050,\n    \"schedule_10000_tasks\": 40100,\n    \"schedule_and_run_10000_tasks\": 50050,\n    \"schedule_assume_isolated_10000_tasks\": 40100,\n    \"schedule_with_deadline_10000_tasks\": 40100,\n    \"schedule_with_deadline_assume_isolated_10000_tasks\": 40100,\n    \"scheduling_10000_executions\": 89,\n    \"submit_10000_tasks\": 20100,\n    \"submit_assume_isolated_10000_tasks\": 20100,\n    \"udp_1000_reqs_1_conn\": 6200,\n    \"udp_1_reqs_1000_conn\": 162050\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/5.8.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 20,\n    \"1000000_asyncwriter\": 1000015,\n    \"1000_addHandlers\": 43000,\n    \"1000_addHandlers_sync\": 36000,\n    \"1000_addRemoveHandlers_handlercontext\": 8032,\n    \"1000_addRemoveHandlers_handlername\": 8032,\n    \"1000_addRemoveHandlers_handlertype\": 8032,\n    \"1000_autoReadGetAndSet\": 18000,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1000,\n    \"1000_copying_circularbuffer_to_array\": 1000,\n    \"1000_getHandlers\": 8034,\n    \"1000_getHandlers_sync\": 34,\n    \"1000_reqs_1_conn\": 26372,\n    \"1000_rst_connections\": 147004,\n    \"1000_tcpbootstraps\": 4001,\n    \"1000_tcpconnections\": 154002,\n    \"1000_udp_reqs\": 6014,\n    \"1000_udpbootstraps\": 2000,\n    \"1000_udpconnections\": 75008,\n    \"1_reqs_1000_conn\": 398000,\n    \"bytebuffer_lots_of_rw\": 2005,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2000,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2003,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2003,\n    \"encode_1000_ws_frames_new_buffer\": 3000,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5000,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3000,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5000,\n    \"execute_hop_10000_tasks\": 0,\n    \"future_erase_result\": 4001,\n    \"future_lots_of_callbacks\": 53001,\n    \"get_100000_headers_canonical_form\": 700000,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 700000,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 700000,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 700000,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6000,\n    \"ping_pong_1000_reqs_1_conn\": 334,\n    \"read_10000_chunks_from_file\": 110009,\n    \"schedule_10000_tasks\": 40084,\n    \"schedule_and_run_10000_tasks\": 50010,\n    \"scheduling_10000_executions\": 89,\n    \"udp_1000_reqs_1_conn\": 6156,\n    \"udp_1_reqs_1000_conn\": 162000\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/6.0.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 18,\n    \"1000000_asyncwriter\": 1000050,\n    \"1000_addHandlers\": 46050,\n    \"1000_addHandlers_sync\": 39050,\n    \"1000_addRemoveHandlers_handlercontext\": 8050,\n    \"1000_addRemoveHandlers_handlername\": 8050,\n    \"1000_addRemoveHandlers_handlertype\": 8050,\n    \"1000_autoReadGetAndSet\": 18050,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1050,\n    \"1000_copying_circularbuffer_to_array\": 1050,\n    \"1000_getHandlers\": 8050,\n    \"1000_getHandlers_sync\": 37,\n    \"1000_reqs_1_conn\": 26350,\n    \"1000_rst_connections\": 138050,\n    \"1000_tcpbootstraps\": 3050,\n    \"1000_tcpconnections\": 146050,\n    \"1000_udp_reqs\": 6050,\n    \"1000_udpbootstraps\": 2050,\n    \"1000_udpconnections\": 75050,\n    \"1_reqs_1000_conn\": 375050,\n    \"assume_isolated_scheduling_10000_executions\": 88,\n    \"bytebuffer_lots_of_rw\": 2050,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2050,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2050,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2050,\n    \"encode_1000_ws_frames_new_buffer\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5050,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5050,\n    \"execute_hop_10000_tasks\": 0,\n    \"flat_schedule_10000_tasks\": 100100,\n    \"flat_schedule_assume_isolated_10000_tasks\": 90100,\n    \"future_assume_isolated_lots_of_callbacks\": 68050,\n    \"future_erase_result\": 4050,\n    \"future_lots_of_callbacks\": 68050,\n    \"get_100000_headers_canonical_form\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 700050,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6050,\n    \"ping_pong_1000_reqs_1_conn\": 305,\n    \"read_10000_chunks_from_file\": 110050,\n    \"schedule_10000_tasks\": 40100,\n    \"schedule_and_run_10000_tasks\": 50050,\n    \"schedule_assume_isolated_10000_tasks\": 40100,\n    \"schedule_with_deadline_10000_tasks\": 40100,\n    \"schedule_with_deadline_assume_isolated_10000_tasks\": 40100,\n    \"scheduling_10000_executions\": 88,\n    \"submit_10000_tasks\": 20100,\n    \"submit_assume_isolated_10000_tasks\": 20100,\n    \"udp_1000_reqs_1_conn\": 6200,\n    \"udp_1_reqs_1000_conn\": 162050\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/6.1.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 18,\n    \"1000000_asyncwriter\": 1000050,\n    \"1000_addHandlers\": 46050,\n    \"1000_addHandlers_sync\": 39050,\n    \"1000_addRemoveHandlers_handlercontext\": 8050,\n    \"1000_addRemoveHandlers_handlername\": 8050,\n    \"1000_addRemoveHandlers_handlertype\": 8050,\n    \"1000_autoReadGetAndSet\": 18050,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1050,\n    \"1000_copying_circularbuffer_to_array\": 1050,\n    \"1000_getHandlers\": 8050,\n    \"1000_getHandlers_sync\": 37,\n    \"1000_reqs_1_conn\": 26350,\n    \"1000_rst_connections\": 138050,\n    \"1000_tcpbootstraps\": 3050,\n    \"1000_tcpconnections\": 146050,\n    \"1000_udp_reqs\": 6050,\n    \"1000_udpbootstraps\": 2050,\n    \"1000_udpconnections\": 75050,\n    \"1_reqs_1000_conn\": 375050,\n    \"assume_isolated_scheduling_10000_executions\": 88,\n    \"bytebuffer_lots_of_rw\": 2050,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2050,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2050,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2050,\n    \"encode_1000_ws_frames_new_buffer\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5050,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5050,\n    \"execute_hop_10000_tasks\": 0,\n    \"flat_schedule_10000_tasks\": 100100,\n    \"flat_schedule_assume_isolated_10000_tasks\": 90100,\n    \"future_assume_isolated_lots_of_callbacks\": 68050,\n    \"future_erase_result\": 4050,\n    \"future_lots_of_callbacks\": 68050,\n    \"get_100000_headers_canonical_form\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 700050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 700050,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6050,\n    \"ping_pong_1000_reqs_1_conn\": 305,\n    \"read_10000_chunks_from_file\": 110050,\n    \"schedule_10000_tasks\": 40100,\n    \"schedule_and_run_10000_tasks\": 50050,\n    \"schedule_assume_isolated_10000_tasks\": 40100,\n    \"schedule_with_deadline_10000_tasks\": 40100,\n    \"schedule_with_deadline_assume_isolated_10000_tasks\": 40100,\n    \"scheduling_10000_executions\": 88,\n    \"submit_10000_tasks\": 20100,\n    \"submit_assume_isolated_10000_tasks\": 20100,\n    \"udp_1000_reqs_1_conn\": 6200,\n    \"udp_1_reqs_1000_conn\": 162050\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/6.2.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 18,\n    \"1000000_asyncwriter\": 1000050,\n    \"1000_addHandlers\": 46050,\n    \"1000_addHandlers_sync\": 39050,\n    \"1000_addRemoveHandlers_handlercontext\": 8050,\n    \"1000_addRemoveHandlers_handlername\": 8050,\n    \"1000_addRemoveHandlers_handlertype\": 8050,\n    \"1000_autoReadGetAndSet\": 18050,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1050,\n    \"1000_copying_circularbuffer_to_array\": 1050,\n    \"1000_getHandlers\": 8050,\n    \"1000_getHandlers_sync\": 37,\n    \"1000_reqs_1_conn\": 26350,\n    \"1000_rst_connections\": 138050,\n    \"1000_tcpbootstraps\": 3050,\n    \"1000_tcpconnections\": 146050,\n    \"1000_udp_reqs\": 6050,\n    \"1000_udpbootstraps\": 2050,\n    \"1000_udpconnections\": 75050,\n    \"1_reqs_1000_conn\": 375050,\n    \"assume_isolated_scheduling_10000_executions\": 88,\n    \"bytebuffer_lots_of_rw\": 2050,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2050,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2050,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2050,\n    \"encode_1000_ws_frames_new_buffer\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5050,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5050,\n    \"execute_hop_10000_tasks\": 0,\n    \"flat_schedule_10000_tasks\": 100100,\n    \"flat_schedule_assume_isolated_10000_tasks\": 80100,\n    \"future_assume_isolated_lots_of_callbacks\": 68050,\n    \"future_erase_result\": 4050,\n    \"future_lots_of_callbacks\": 68050,\n    \"get_100000_headers_canonical_form\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 500050,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6050,\n    \"ping_pong_1000_reqs_1_conn\": 305,\n    \"read_10000_chunks_from_file\": 110050,\n    \"schedule_10000_tasks\": 40100,\n    \"schedule_and_run_10000_tasks\": 50050,\n    \"schedule_assume_isolated_10000_tasks\": 40100,\n    \"schedule_with_deadline_10000_tasks\": 40100,\n    \"schedule_with_deadline_assume_isolated_10000_tasks\": 40100,\n    \"scheduling_10000_executions\": 88,\n    \"submit_10000_tasks\": 20100,\n    \"submit_assume_isolated_10000_tasks\": 20100,\n    \"udp_1000_reqs_1_conn\": 6200,\n    \"udp_1_reqs_1000_conn\": 162050\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/nightly-main.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 21,\n    \"1000000_asyncwriter\": 1000050,\n    \"1000_addHandlers\": 46050,\n    \"1000_addHandlers_sync\": 39050,\n    \"1000_addRemoveHandlers_handlercontext\": 8050,\n    \"1000_addRemoveHandlers_handlername\": 8050,\n    \"1000_addRemoveHandlers_handlertype\": 8050,\n    \"1000_autoReadGetAndSet\": 18050,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1050,\n    \"1000_copying_circularbuffer_to_array\": 1050,\n    \"1000_getHandlers\": 8050,\n    \"1000_getHandlers_sync\": 37,\n    \"1000_reqs_1_conn\": 26350,\n    \"1000_rst_connections\": 136050,\n    \"1000_tcpbootstraps\": 3050,\n    \"1000_tcpconnections\": 144050,\n    \"1000_udp_reqs\": 6050,\n    \"1000_udpbootstraps\": 2050,\n    \"1000_udpconnections\": 74050,\n    \"1_reqs_1000_conn\": 372050,\n    \"assume_isolated_scheduling_10000_executions\": 88,\n    \"bytebuffer_lots_of_rw\": 2050,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2050,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2050,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2050,\n    \"encode_1000_ws_frames_new_buffer\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5050,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5050,\n    \"execute_hop_10000_tasks\": 0,\n    \"flat_schedule_10000_tasks\": 100100,\n    \"flat_schedule_assume_isolated_10000_tasks\": 80100,\n    \"future_assume_isolated_lots_of_callbacks\": 68050,\n    \"future_erase_result\": 4050,\n    \"future_lots_of_callbacks\": 68050,\n    \"get_100000_headers_canonical_form\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 500050,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6050,\n    \"ping_pong_1000_reqs_1_conn\": 302,\n    \"read_10000_chunks_from_file\": 110050,\n    \"schedule_10000_tasks\": 40100,\n    \"schedule_and_run_10000_tasks\": 50050,\n    \"schedule_assume_isolated_10000_tasks\": 40100,\n    \"schedule_with_deadline_10000_tasks\": 40100,\n    \"schedule_with_deadline_assume_isolated_10000_tasks\": 40100,\n    \"scheduling_10000_executions\": 88,\n    \"submit_10000_tasks\": 20100,\n    \"submit_assume_isolated_10000_tasks\": 20100,\n    \"udp_1000_reqs_1_conn\": 6200,\n    \"udp_1_reqs_1000_conn\": 160050\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/Thresholds/nightly-next.json",
    "content": "{\n    \"10000000_asyncsequenceproducer\": 21,\n    \"1000000_asyncwriter\": 1000050,\n    \"1000_addHandlers\": 46050,\n    \"1000_addHandlers_sync\": 39050,\n    \"1000_addRemoveHandlers_handlercontext\": 8050,\n    \"1000_addRemoveHandlers_handlername\": 8050,\n    \"1000_addRemoveHandlers_handlertype\": 8050,\n    \"1000_autoReadGetAndSet\": 18050,\n    \"1000_autoReadGetAndSet_sync\": 0,\n    \"1000_copying_bytebufferview_to_array\": 1050,\n    \"1000_copying_circularbuffer_to_array\": 1050,\n    \"1000_getHandlers\": 8050,\n    \"1000_getHandlers_sync\": 37,\n    \"1000_reqs_1_conn\": 26350,\n    \"1000_rst_connections\": 138050,\n    \"1000_tcpbootstraps\": 3050,\n    \"1000_tcpconnections\": 146050,\n    \"1000_udp_reqs\": 6050,\n    \"1000_udpbootstraps\": 2050,\n    \"1000_udpconnections\": 75050,\n    \"1_reqs_1000_conn\": 375050,\n    \"assume_isolated_scheduling_10000_executions\": 88,\n    \"bytebuffer_lots_of_rw\": 2050,\n    \"creating_10000_headers\": 0,\n    \"decode_1000_ws_frames\": 2050,\n    \"encode_1000_ws_frames_holding_buffer\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_mask\": 2050,\n    \"encode_1000_ws_frames_holding_buffer_with_space\": 3,\n    \"encode_1000_ws_frames_holding_buffer_with_space_with_mask\": 2050,\n    \"encode_1000_ws_frames_new_buffer\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_mask\": 5050,\n    \"encode_1000_ws_frames_new_buffer_with_space\": 3050,\n    \"encode_1000_ws_frames_new_buffer_with_space_with_mask\": 5050,\n    \"execute_hop_10000_tasks\": 0,\n    \"flat_schedule_10000_tasks\": 100100,\n    \"flat_schedule_assume_isolated_10000_tasks\": 80100,\n    \"future_assume_isolated_lots_of_callbacks\": 68050,\n    \"future_erase_result\": 4050,\n    \"future_lots_of_callbacks\": 68050,\n    \"get_100000_headers_canonical_form\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_long_string\": 500050,\n    \"get_100000_headers_canonical_form_trimming_whitespace_from_short_string\": 500050,\n    \"modifying_1000_circular_buffer_elements\": 0,\n    \"modifying_byte_buffer_view\": 6050,\n    \"ping_pong_1000_reqs_1_conn\": 305,\n    \"read_10000_chunks_from_file\": 110050,\n    \"schedule_10000_tasks\": 40100,\n    \"schedule_and_run_10000_tasks\": 50050,\n    \"schedule_assume_isolated_10000_tasks\": 40100,\n    \"schedule_with_deadline_10000_tasks\": 40100,\n    \"schedule_with_deadline_assume_isolated_10000_tasks\": 40100,\n    \"scheduling_10000_executions\": 88,\n    \"submit_10000_tasks\": 20100,\n    \"submit_assume_isolated_10000_tasks\": 20100,\n    \"udp_1000_reqs_1_conn\": 6200,\n    \"udp_1_reqs_1000_conn\": 162050\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/defines.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_allocation_counts.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nset -eu\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\ntest -n \"${SWIFT_VERSION:-}\" || fatal \"SWIFT_VERSION unset\"\n\nall_tests=()\nfor file in \"$here/test_01_resources/\"test_*.swift; do\n    test_name=$(basename \"$file\")\n    test_name=${test_name#test_*}\n    test_name=${test_name%*.swift}\n    all_tests+=( \"$test_name\" )\ndone\n\n\"$here/test_01_resources/run-nio-alloc-counter-tests.sh\" -t \"$tmp\" > \"$tmp/output\"\n\nobserved_allocations=\"{\"\nfor test in \"${all_tests[@]}\"; do\n    while read -r test_case; do\n        test_case=${test_case#test_*}\n        total_allocations=$(grep \"^test_$test_case.total_allocations:\" \"$tmp/output\" | cut -d: -f2 | sed 's/ //g')\n        observed_allocations=\"${observed_allocations}\n    \\\"${test_case}\\\": ${total_allocations},\"\n    done < <(grep \"^test_${test}[^\\W]*.total_allocations:\" \"$tmp/output\" | cut -d: -f1 | cut -d. -f1 | sort | uniq)\ndone\nobserved_allocations=\"${observed_allocations}\n}\"\ninfo \"observed allocations:\n${observed_allocations}\"\n\nfor test in \"${all_tests[@]}\"; do\n    cat \"$tmp/output\"  # helps debugging\n\n    while read -r test_case; do\n        test_case=${test_case#test_*}\n        total_allocations=$(grep \"^test_$test_case.total_allocations:\" \"$tmp/output\" | cut -d: -f2 | sed 's/ //g')\n        not_freed_allocations=$(grep \"^test_$test_case.remaining_allocations:\" \"$tmp/output\" | cut -d: -f2 | sed 's/ //g')\n        leaked_fds=$(grep \"^test_$test_case.leaked_fds:\" \"$tmp/output\" | cut -d: -f2 | sed 's/ //g')\n        max_allowed_env_name=\"MAX_ALLOCS_ALLOWED_$test_case\"\n        max_allowed=$(jq '.'\\\"\"$test_case\"\\\" \"$here/Thresholds/$SWIFT_VERSION.json\")\n        \n        assert_is_number \"$max_allowed\" \"Malformed or nonexistent ${SWIFT_VERSION}.json thresholds file\"\n\n        info \"$test_case: allocations not freed: $not_freed_allocations\"\n        info \"$test_case: total number of mallocs: $total_allocations\"\n        info \"$test_case: leaked fds: $leaked_fds\"\n\n        assert_less_than \"$not_freed_allocations\" 5 \"Allocations not freed are greater than expected\"     # allow some slack\n        assert_greater_than \"$not_freed_allocations\" -5 \"Allocations not freed are less than expected\" # allow some slack\n        assert_less_than \"$leaked_fds\" 1 \"There are leaked file descriptors\" # No slack allowed here though\n        if [[ -z \"${!max_allowed_env_name+x}\" ]] && [ -z \"${max_allowed}\" ]; then\n            if [[ -z \"${!max_allowed_env_name+x}\" ]]; then\n                warn \"no reference number of allocations set (set to \\$$max_allowed_env_name)\"\n                warn \"to set current number either:\"\n                warn \"    export $max_allowed_env_name=$total_allocations\"\n                warn \"    or set them in the Swift version specific threshold json\"\n            fi\n        else\n            if [ -z \"${max_allowed}\" ]; then\n                max_allowed=${!max_allowed_env_name}\n            fi\n            assert_less_than_or_equal \"$total_allocations\" \"$max_allowed\" \"Total allocations exceed the max allowed\"\n            assert_greater_than \"$total_allocations\" \"$(( max_allowed - 1000))\" \"Total allocations are less than expected\"\n        fi\n    done < <(grep \"^test_${test}[^\\W]*.total_allocations:\" \"$tmp/output\" | cut -d: -f1 | cut -d. -f1 | sort | uniq)\ndone\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/README.md",
    "content": "# Allocation Counting Test\n\nThis briefly describes how the allocation counting test works.\n\n## How does it work?\n\nThis is possibly the simplest implementation that counts memory allocations (`malloc` and friends) and frees (mostly `free`). It just maintains two atomic variables which count the number of mallocs and the number of frees respectively. We run a simple HTTP1 example -- 1000 requests and responses generated by a simple SwiftNIO based client and server -- and then evaluate the number of mallocs and frees. The difference `mallocs - frees` should be pretty much 0 and the number of `mallocs` should remain stable (or decrease) across commits. We can't establish a perfect baseline as the exact number of allocations depends on your operating system, libc and Swift version.\n\n### How are the functions hooked?\n\nUsually in UNIX it's enough to just define a function, for example\n\n```C\nvoid free(void *ptr) { ... }\n```\n\nin the main binary and all modules will use this `free` function instead of the real one from the `libc`. For Linux, this is exactly what we're doing, the `bootstrap` binary defines such a `free` function in its `main.c`. On Darwin (macOS/iOS/...) however that is not the case and you need to use [dyld's interpose feature](https://books.google.co.uk/books?id=K8vUkpOXhN4C&lpg=PA73&ots=OMjhRWWwUu&dq=dyld%20interpose&pg=PA73#v=onepage&q=dyld%20interpose&f=false). The odd thing is that dyld's interposing _only_ works if it's in a `.dylib` and not from a binary's main executable. Therefore we need to build a slightly strange SwiftPM package:\n\n- `bootstrap`: The main executable's main module (written in C) so we can hook the `free` function on Linux.\n- `BootstrapSwift`: A SwiftPM module (written in Swift) called in from `bootstrap` which implements the actual SwiftNIO benchmark (and therefore depends on the `NIO` module).\n- `HookedFunctions`: A separate SwiftPM package that builds a shared library (`.so` on Linux, `.dylib` on Darwin) which contains the `replacement_malloc`, `replacement_free`, etc functions which just increment an atomic integers representing the number of operations. On Darwin, we use `DYLD_INTERPOSE` in this module, interposing libc functions with our `replacement_` functions. This needs to be a separate SwiftPM package as otherwise its code would just live inside of the `bootstrap` executable and the dyld interposing feature wouldn't work.\n- `AtomicCounter`: SwiftPM package (written in C) that implements the atomic counters. It needs to be a separate package as both `BoostrapSwift` (to read the allocation counter) as well as `HookedFree` (to increment the allocation counter) depend on it.\n\n## What benchmark is run?\n\nWe run a single TCP connection over which 1000 HTTP requests are made by a client written in NIO, responded to by a server also written in NIO. We re-run the benchmark 10 times and return the lowest number of allocations that has been made.\n\n## Why do I have to set a baseline?\n\nBy default this test should always succeed as it doesn't actually compare the number of allocations to a certain number. The reason is that this number varies ever so slightly between operating systems and Swift versions. At the time of writing on macOS we got roughly 326k allocations and on Linux 322k allocations for 1000 HTTP requests & responses. To set a baseline simply run\n\n```bash\nexport MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=327000\n```\n\nor similar to set the maximum number of allocations allowed. If the benchmark exceeds these allocations the test will fail.\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/run-nio-alloc-counter-tests.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\ntmp_dir=\"/tmp\"\n\nwhile getopts \"t:\" opt; do\n    case \"$opt\" in\n        t)\n            tmp_dir=\"$OPTARG\"\n            ;;\n        *)\n            exit 1\n            ;;\n    esac\ndone\n\nshift $((OPTIND-1))\n\ntests_to_run=(\"$here\"/test_*.swift)\n\nif [[ $# -gt 0 ]]; then\n    tests_to_run=(\"$@\")\nfi\n\n\"$here/../../allocation-counter-tests-framework/run-allocation-counter.sh\" \\\n    -p \"$here/../../..\" \\\n    -m NIOCore -m NIOEmbedded -m NIOPosix -m NIOHTTP1 -m NIOWebSocket \\\n    -s \"$here/shared.swift\" \\\n    -t \"$tmp_dir\" \\\n    \"${tests_to_run[@]}\"\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/shared.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\n\nlet localhostPickPort = try! SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0)\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\n\nfinal class RepeatedRequests: ChannelInboundHandler {\n    typealias InboundIn = HTTPClientResponsePart\n    typealias OutboundOut = HTTPClientRequestPart\n\n    private let numberOfRequests: Int\n    private var remainingNumberOfRequests: Int\n    private let isDonePromise: EventLoopPromise<Int>\n    static var requestHead: HTTPRequestHead {\n        var head = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/allocation-test-1\")\n        head.headers.add(name: \"Host\", value: \"foo-\\(ObjectIdentifier(self)).com\")\n        return head\n    }\n\n    init(numberOfRequests: Int, eventLoop: EventLoop) {\n        self.remainingNumberOfRequests = numberOfRequests\n        self.numberOfRequests = numberOfRequests\n        self.isDonePromise = eventLoop.makePromise()\n    }\n\n    func wait() throws -> Int {\n        let reqs = try self.isDonePromise.futureResult.wait()\n        precondition(reqs == self.numberOfRequests)\n        return reqs\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        context.channel.close(promise: nil)\n        self.isDonePromise.fail(error)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let respPart = self.unwrapInboundIn(data)\n        if case .end(nil) = respPart {\n            if self.remainingNumberOfRequests <= 0 {\n                context.channel.close().map { self.numberOfRequests - self.remainingNumberOfRequests }.cascade(\n                    to: self.isDonePromise\n                )\n            } else {\n                self.remainingNumberOfRequests -= 1\n                context.write(self.wrapOutboundOut(.head(RepeatedRequests.requestHead)), promise: nil)\n                context.writeAndFlush(self.wrapOutboundOut(.end(nil)), promise: nil)\n            }\n        }\n    }\n}\n\nprivate final class SimpleHTTPServer: ChannelInboundHandler {\n    typealias InboundIn = HTTPServerRequestPart\n    typealias OutboundOut = HTTPServerResponsePart\n\n    private let bodyLength = 100\n    private let numberOfAdditionalHeaders = 3\n\n    private var responseHead: HTTPResponseHead {\n        var head = HTTPResponseHead(version: .http1_1, status: .ok)\n        head.headers.add(name: \"Content-Length\", value: \"\\(self.bodyLength)\")\n        for i in 0..<self.numberOfAdditionalHeaders {\n            head.headers.add(name: \"X-Random-Extra-Header\", value: \"\\(i)\")\n        }\n        return head\n    }\n\n    private func responseBody(allocator: ByteBufferAllocator) -> ByteBuffer {\n        var buffer = allocator.buffer(capacity: self.bodyLength)\n        for i in 0..<self.bodyLength {\n            buffer.writeInteger(UInt8(i % Int(UInt8.max)))\n        }\n        return buffer\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        (context.channel as? SocketOptionProvider)?.setSoLinger(linger(l_onoff: 1, l_linger: 0))\n            .whenFailure({ error in fatalError(\"Failed to set linger \\(error)\") })\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        if case .head(let req) = self.unwrapInboundIn(data), req.uri == \"/allocation-test-1\" {\n            context.write(self.wrapOutboundOut(.head(self.responseHead)), promise: nil)\n            context.write(\n                self.wrapOutboundOut(.body(.byteBuffer(self.responseBody(allocator: context.channel.allocator)))),\n                promise: nil\n            )\n            context.writeAndFlush(self.wrapOutboundOut(.end(nil)), promise: nil)\n        }\n    }\n}\n\nfunc doRequests(group: EventLoopGroup, number numberOfRequests: Int) throws -> Int {\n    let serverChannel = try ServerBootstrap(group: group)\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .childChannelInitializer { channel in\n            channel.pipeline.configureHTTPServerPipeline(\n                withPipeliningAssistance: true,\n                withErrorHandling: false\n            ).flatMap {\n                channel.pipeline.addHandler(SimpleHTTPServer())\n            }\n        }.bind(to: localhostPickPort).wait()\n\n    defer {\n        try! serverChannel.close().wait()\n    }\n\n    let repeatedRequestsHandler = RepeatedRequests(numberOfRequests: numberOfRequests, eventLoop: group.next())\n\n    let clientChannel = try ClientBootstrap(group: group)\n        .channelInitializer { channel in\n            channel.pipeline.addHTTPClientHandlers().flatMap {\n                channel.pipeline.addHandler(repeatedRequestsHandler)\n            }\n        }\n        .connect(to: serverChannel.localAddress!)\n        .wait()\n\n    clientChannel.write(NIOAny(HTTPClientRequestPart.head(RepeatedRequests.requestHead)), promise: nil)\n    try clientChannel.writeAndFlush(NIOAny(HTTPClientRequestPart.end(nil))).wait()\n    let result = try repeatedRequestsHandler.wait()\n    try clientChannel.closeFuture.wait()\n    return result\n}\n\nfunc withAutoReleasePool<T>(_ execute: () throws -> T) rethrows -> T {\n    #if os(Linux)\n    return try execute()\n    #else\n    return try autoreleasepool {\n        try execute()\n    }\n    #endif\n}\n\n// MARK: UDP Shared\n\n/// Repeatedly send, echo and receive a number of UDP requests.\n/// Based on the UDPEchoClient/Server example.\nenum UDPShared {\n    private final class EchoHandler: ChannelInboundHandler {\n        public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n        public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n        public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            // As we are not really interested getting notified on success or failure we just pass nil as promise to\n            // reduce allocations.\n            context.write(data, promise: nil)\n        }\n\n        public func channelReadComplete(context: ChannelHandlerContext) {\n            // As we are not really interested getting notified on success or failure we just pass nil as promise to\n            // reduce allocations.\n            context.flush()\n        }\n\n        public func errorCaught(context: ChannelHandlerContext, error: Error) {\n            // Errors should never happen.\n            fatalError(\"EchoHandler received errorCaught\")\n        }\n    }\n\n    private final class EchoHandlerClient: ChannelInboundHandler {\n        public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n        public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n        private var repetitionsRemaining: Int\n\n        private let remoteAddress: SocketAddress\n\n        init(remoteAddress: SocketAddress, numberOfRepetitions: Int) {\n            self.remoteAddress = remoteAddress\n            self.repetitionsRemaining = numberOfRepetitions\n        }\n\n        public func channelActive(context: ChannelHandlerContext) {\n            // Channel is available. It's time to send the message to the server to initialize the ping-pong sequence.\n            self.sendSomeDataIfDesiredOrClose(context: context)\n        }\n\n        private func sendSomeDataIfDesiredOrClose(context: ChannelHandlerContext) {\n            if repetitionsRemaining > 0 {\n                repetitionsRemaining -= 1\n\n                // Set the transmission data.\n                let line = \"Something to send there and back again.\"\n                let buffer = context.channel.allocator.buffer(string: line)\n\n                // Forward the data.\n                let envolope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buffer)\n\n                context.writeAndFlush(self.wrapOutboundOut(envolope), promise: nil)\n            } else {\n                // We're all done - hurrah!\n                context.close(promise: nil)\n            }\n        }\n\n        public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            // Got back a response - maybe send some more.\n            self.sendSomeDataIfDesiredOrClose(context: context)\n        }\n\n        public func errorCaught(context: ChannelHandlerContext, error: Error) {\n            // Errors should never happen.\n            fatalError(\"EchoHandlerClient received errorCaught\")\n        }\n    }\n\n    static func doUDPRequests(group: EventLoopGroup, number numberOfRequests: Int) throws -> Int {\n        let serverChannel = try DatagramBootstrap(group: group)\n            // Set the handlers that are applied to the bound channel\n            .channelInitializer { channel in\n                channel.pipeline.addHandler(EchoHandler())\n            }\n            .bind(to: localhostPickPort).wait()\n\n        defer {\n            try! serverChannel.close().wait()\n        }\n\n        let remoteAddress = serverChannel.localAddress!\n\n        let clientChannel = try DatagramBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.pipeline.addHandler(\n                    EchoHandlerClient(\n                        remoteAddress: remoteAddress,\n                        numberOfRepetitions: numberOfRequests\n                    )\n                )\n            }\n            .bind(to: localhostPickPort).wait()\n\n        // Will be closed after all the work is done and replies received.\n        try clientChannel.closeFuture.wait()\n        return numberOfRequests\n    }\n\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_10000000_asyncsequenceproducer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate typealias SequenceProducer = NIOAsyncSequenceProducer<\n    Int, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, Delegate\n>\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate final class Delegate: NIOAsyncSequenceProducerDelegate, @unchecked Sendable {\n    private let elements = Array(repeating: 1, count: 1000)\n\n    var source: SequenceProducer.Source!\n\n    func produceMore() {\n        _ = self.source.yield(contentsOf: self.elements)\n    }\n\n    func didTerminate() {}\n}\n\nfunc run(identifier: String) {\n    guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) else {\n        return\n    }\n    measure(identifier: identifier) {\n        let delegate = Delegate()\n        let producer = SequenceProducer.makeSequence(\n            backPressureStrategy: .init(lowWatermark: 100, highWatermark: 500),\n            delegate: delegate\n        )\n        let sequence = producer.sequence\n        delegate.source = producer.source\n\n        var counter = 0\n        for await i in sequence {\n            counter += i\n\n            if counter == 10_000_000 {\n                return counter\n            }\n        }\n\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000000_asyncwriter.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate struct Delegate: NIOAsyncWriterSinkDelegate, Sendable {\n    typealias Element = Int\n\n    func didYield(contentsOf sequence: Deque<Int>) {}\n\n    func didTerminate(error: Error?) {}\n}\n\nfunc run(identifier: String) {\n    guard #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) else {\n        return\n    }\n    measure(identifier: identifier) {\n        let delegate = Delegate()\n        let newWriter = NIOAsyncWriter<Int, Delegate>.makeWriter(isWritable: true, delegate: delegate)\n        let writer = newWriter.writer\n\n        for i in 0..<1_000_000 {\n            try! await writer.yield(i)\n        }\n\n        return 1_000_000\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_addHandlers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nprivate final class SimpleHandler: ChannelInboundHandler {\n    typealias InboundIn = NIOAny\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let iterations = 1000\n        for _ in 0..<iterations {\n            let channel = EmbeddedChannel()\n            defer {\n                _ = try! channel.finish()\n            }\n            try! channel.pipeline.addHandlers([\n                SimpleHandler(),\n                SimpleHandler(),\n            ]).wait()\n        }\n        return iterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_addHandlers_sync.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nprivate final class SimpleHandler: ChannelInboundHandler {\n    typealias InboundIn = NIOAny\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let iterations = 1000\n        for _ in 0..<iterations {\n            let channel = EmbeddedChannel()\n            defer {\n                _ = try! channel.finish()\n            }\n            try! channel.pipeline.syncOperations.addHandlers([\n                SimpleHandler(),\n                SimpleHandler(),\n            ])\n        }\n        return iterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_addRemoveHandlers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nprivate final class RemovableHandler: ChannelInboundHandler, RemovableChannelHandler {\n    typealias InboundIn = NIOAny\n\n    static let name: String = \"RemovableHandler\"\n\n    var context: ChannelHandlerContext?\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        self.context = context\n    }\n\n    func handlerRemoved(context: ChannelHandlerContext) {\n        self.context = nil\n    }\n}\n\n@inline(__always)\nprivate func addRemoveBench(\n    iterations: Int,\n    _ removalOperation: (Channel, RemovableHandler) -> EventLoopFuture<Void>\n) -> Int {\n    let channel = EmbeddedChannel()\n    defer {\n        _ = try! channel.finish()\n    }\n\n    for _ in 0..<iterations {\n        let handler = RemovableHandler()\n        try! channel.pipeline.syncOperations.addHandler(handler, name: RemovableHandler.name)\n        try! removalOperation(channel, handler).wait()\n    }\n\n    return iterations\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier + \"_handlertype\") {\n        addRemoveBench(iterations: 1000) { channel, handler in\n            channel.pipeline.removeHandler(handler)\n        }\n    }\n\n    measure(identifier: identifier + \"_handlername\") {\n        addRemoveBench(iterations: 1000) { channel, _ in\n            channel.pipeline.removeHandler(name: RemovableHandler.name)\n        }\n    }\n\n    measure(identifier: identifier + \"_handlercontext\") {\n        addRemoveBench(iterations: 1000) { channel, handler in\n            channel.pipeline.removeHandler(context: handler.context!)\n        }\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_autoReadGetAndSet.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        try! group.syncShutdownGracefully()\n    }\n\n    let server = try! ServerBootstrap(group: group)\n        .bind(host: \"127.0.0.1\", port: 0)\n        .wait()\n    defer {\n        try! server.close().wait()\n    }\n\n    measure(identifier: identifier) {\n        let iterations = 1000\n\n        for _ in 0..<iterations {\n            let autoReadOption = try! server.getOption(.autoRead).wait()\n            try! server.setOption(.autoRead, value: !autoReadOption).wait()\n        }\n\n        return iterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_autoReadGetAndSet_sync.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    MultiThreadedEventLoopGroup.withCurrentThreadAsEventLoop { loop in\n        ServerBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).map { server in\n            measure(identifier: identifier) {\n                let iterations = 1000\n\n                let syncOptions = server.syncOptions!\n\n                for _ in 0..<iterations {\n                    let autoReadOption = try! syncOptions.getOption(.autoRead)\n                    try! syncOptions.setOption(.autoRead, value: !autoReadOption)\n                }\n\n                return iterations\n            }\n        }.always { _ in\n            loop.shutdownGracefully { _ in }\n        }\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_copying_bytebufferview_to_array.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\nfunc run(identifier: String) {\n    let data = ByteBuffer(repeating: 0xfe, count: 1024).readableBytesView\n\n    measure(identifier: identifier) {\n        var count = 0\n\n        for _ in 0..<1_000 {\n            let copy = Array(data)\n            count &+= copy.count\n        }\n\n        return count\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_copying_circularbuffer_to_array.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\nfunc run(identifier: String) {\n    let data = CircularBuffer(repeating: UInt8(0xfe), count: 1024)\n\n    measure(identifier: identifier) {\n        var count = 0\n\n        for _ in 0..<1_000 {\n            let copy = Array(data)\n            count &+= copy.count\n        }\n\n        return count\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_getHandlers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nprivate final class SimpleHandler: ChannelInboundHandler {\n    typealias InboundIn = NIOAny\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let iterations = 1000\n        let channel = EmbeddedChannel()\n        defer {\n            _ = try! channel.finish()\n        }\n        try! channel.pipeline.syncOperations.addHandler(SimpleHandler())\n\n        for _ in 0..<iterations {\n            _ = try! channel.pipeline.handler(type: SimpleHandler.self).wait()\n        }\n        return iterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_getHandlers_sync.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nprivate final class SimpleHandler: ChannelInboundHandler {\n    typealias InboundIn = NIOAny\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let iterations = 1000\n        let channel = EmbeddedChannel()\n        defer {\n            _ = try! channel.finish()\n        }\n        try! channel.pipeline.syncOperations.addHandler(SimpleHandler())\n\n        for _ in 0..<iterations {\n            _ = try! channel.pipeline.syncOperations.handler(type: SimpleHandler.self)\n        }\n        return iterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_reqs_1_conn.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let numberDone = try! doRequests(group: group, number: 1000)\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_rst_connections.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class CloseAfterTimeoutHandler: ChannelInboundHandler {\n    typealias InboundIn = ByteBuffer\n\n    func channelActive(context: ChannelHandlerContext) {\n        context.fireChannelActive()\n        context.eventLoop.scheduleTask(in: .milliseconds(1)) {\n            context.close(promise: nil)\n        }\n    }\n}\n\nfunc run(identifier: String) {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        try! group.syncShutdownGracefully()\n    }\n\n    let serverConnection = try! ServerBootstrap(group: group)\n        .bind(host: \"localhost\", port: 0)\n        .wait()\n\n    let serverAddress = serverConnection.localAddress!\n    let clientBootstrap = ClientBootstrap(group: group)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHandler(CloseAfterTimeoutHandler())\n            }\n        }\n\n    measure(identifier: identifier, trackFDs: true) {\n        let iterations = 1000\n        for _ in 0..<iterations {\n            let conn = clientBootstrap.connect(to: serverAddress)\n\n            let _: Void? = try? conn.flatMap { channel in\n                (channel as! SocketOptionProvider).setSoLinger(linger(l_onoff: 1, l_linger: 0)).flatMap {\n                    channel.closeFuture\n                }\n            }.wait()\n        }\n        return iterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_tcpbootstraps.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class DoNothingHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let numberOfIterations = 1000\n        let doNothingHandler = DoNothingHandler()\n        for _ in 0..<numberOfIterations {\n            _ = ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHTTPClientHandlers().flatMap {\n                        channel.pipeline.addHandler(doNothingHandler)\n                    }\n                }\n        }\n        return numberOfIterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_tcpconnections.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class ReceiveAndCloseHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let byteBuffer = Self.unwrapInboundIn(data)\n        precondition(byteBuffer.readableBytes == 1)\n        context.channel.close(promise: nil)\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        fatalError(\"unexpected \\(error)\")\n    }\n}\n\nprivate final class LingerSettingHandler: ChannelInboundHandler {\n    typealias InboundIn = ByteBuffer\n    typealias OutboundOut = ByteBuffer\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        (context.channel as? SocketOptionProvider)?.setSoLinger(linger(l_onoff: 1, l_linger: 0))\n            .whenFailure({ error in fatalError(\"Failed to set linger \\(error)\") })\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        fatalError(\"unexpected \\(error)\")\n    }\n}\n\nfunc run(identifier: String) {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        try! group.syncShutdownGracefully()\n    }\n\n    let serverChannel = try! ServerBootstrap(group: group)\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .childChannelInitializer { channel in\n            channel.pipeline.addHandler(ReceiveAndCloseHandler())\n        }.bind(host: \"127.0.0.1\", port: 0).wait()\n    defer {\n        try! serverChannel.close().wait()\n    }\n\n    let clientHandler = LingerSettingHandler()\n    let clientBootstrap = ClientBootstrap(group: group).channelInitializer { channel in\n        channel.pipeline.addHandler(clientHandler)\n    }\n\n    measure(identifier: identifier) {\n        let numberOfIterations = 1000\n        let serverAddress = serverChannel.localAddress!\n        let buffer = ByteBuffer(integer: 1, as: UInt8.self)\n        let el = group.next()\n\n        for _ in 0..<numberOfIterations {\n            try! el.flatSubmit {\n                clientBootstrap.connect(to: serverAddress).flatMap { (clientChannel) -> EventLoopFuture<Void> in\n                    writeWaitAndClose(clientChannel: clientChannel, buffer: buffer)\n                        .flatMap { clientChannel.closeFuture }\n                }\n            }.wait()\n        }\n        return numberOfIterations\n    }\n}\n\nprivate func writeWaitAndClose(clientChannel: Channel, buffer: ByteBuffer) -> EventLoopFuture<Void> {\n    // Send a byte to make sure everything is really open.\n    clientChannel.writeAndFlush(buffer).flatMap {\n        clientChannel.closeFuture\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_udp_reqs.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class ServerEchoHandler: ChannelInboundHandler {\n    public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.write(data, promise: nil)\n    }\n\n    // Flush it out. This can make use of gathering writes if multiple buffers are pending\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        context.flush()\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        fatalError()\n    }\n}\n\nprivate final class ClientHandler: ChannelInboundHandler {\n    public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n    private let remoteAddress: SocketAddress\n\n    init(remoteAddress: SocketAddress) {\n        self.remoteAddress = remoteAddress\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        // If we still have iterations to do send some more data.\n        if self.iterationsOutstanding > 0 {\n            self.iterationsOutstanding -= 1\n            sendBytes(clientChannel: context.channel)\n        } else {\n            self.whenDone!.succeed(())\n        }\n    }\n\n    // Flush it out. This can make use of gathering writes if multiple buffers are pending\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        context.flush()\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        fatalError()\n    }\n\n    var iterationsOutstanding = 0\n    var whenDone: EventLoopPromise<Void>? = nil\n\n    private func sendBytes(clientChannel: Channel) {\n        var buffer = clientChannel.allocator.buffer(capacity: 1)\n        buffer.writeInteger(3, as: UInt8.self)\n        // Send the data with ECN\n        let metadata = AddressedEnvelope<ByteBuffer>.Metadata(ecnState: .transportCapableFlag1)\n        let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buffer, metadata: metadata)\n        clientChannel.writeAndFlush(Self.wrapOutboundOut(envelope), promise: nil)\n    }\n\n    func sendBytesAndWaitForReply(clientChannel: Channel) -> Int {\n        let numberOfIterations = 1000\n\n        // Setup for iteration.\n        self.iterationsOutstanding = numberOfIterations\n        self.whenDone = clientChannel.eventLoop.makePromise()\n        // Kick start\n        sendBytes(clientChannel: clientChannel)\n        // Wait for completion.\n        try! self.whenDone!.futureResult.wait()\n        return numberOfIterations\n    }\n}\n\nfunc run(identifier: String) {\n    let serverChannel = try! DatagramBootstrap(group: group)\n        .channelOption(.explicitCongestionNotification, value: true)\n        // Set the handlers that are applied to the bound channel\n        .channelInitializer { channel in\n            channel.pipeline.addHandler(ServerEchoHandler())\n        }\n        .bind(to: localhostPickPort).wait()\n    defer {\n        try! serverChannel.close().wait()\n    }\n\n    let remoteAddress = serverChannel.localAddress!\n    let clientHandler = ClientHandler(remoteAddress: remoteAddress)\n\n    let clientChannel = try! DatagramBootstrap(group: group)\n        .channelOption(.explicitCongestionNotification, value: true)\n        .channelInitializer { channel in\n            channel.pipeline.addHandler(clientHandler)\n        }\n        .bind(to: localhostPickPort).wait()\n    defer {\n        try! clientChannel.close().wait()\n    }\n\n    measure(identifier: identifier) {\n        clientHandler.sendBytesAndWaitForReply(clientChannel: clientChannel)\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_udpbootstraps.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class DoNothingHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let numberOfIterations = 1000\n        for _ in 0..<numberOfIterations {\n            _ = DatagramBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHandler(DoNothingHandler())\n                }\n        }\n        return numberOfIterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1000_udpconnections.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate final class CountReadsHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n\n    private var readsRemaining: Int\n    private let completed: EventLoopPromise<Void>\n\n    var completionFuture: EventLoopFuture<Void> {\n        self.completed.futureResult\n    }\n\n    init(numberOfReadsExpected: Int, completionPromise: EventLoopPromise<Void>) {\n        self.readsRemaining = numberOfReadsExpected\n        self.completed = completionPromise\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.readsRemaining -= 1\n        if self.readsRemaining <= 0 {\n            self.completed.succeed(())\n        }\n    }\n}\n\nfunc run(identifier: String) {\n    let numberOfIterations = 1000\n\n    let serverHandler = CountReadsHandler(\n        numberOfReadsExpected: numberOfIterations,\n        completionPromise: group.next().makePromise()\n    )\n    let serverChannel = try! DatagramBootstrap(group: group)\n        // Set the handlers that are applied to the bound channel\n        .channelInitializer { channel in\n            channel.pipeline.addHandler(serverHandler)\n        }\n        .bind(to: localhostPickPort).wait()\n    defer {\n        try! serverChannel.close().wait()\n    }\n\n    let remoteAddress = serverChannel.localAddress!\n\n    let clientBootstrap = DatagramBootstrap(group: group)\n\n    measure(identifier: identifier) {\n        let buffer = ByteBuffer(integer: 1, as: UInt8.self)\n        for _ in 0..<numberOfIterations {\n            try! clientBootstrap.bind(to: localhostPickPort).flatMap { clientChannel -> EventLoopFuture<Void> in\n                // Send a byte to make sure everything is really open.\n                let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buffer)\n                return clientChannel.writeAndFlush(envelope).flatMap {\n                    clientChannel.close()\n                }\n            }.wait()\n        }\n        try! serverHandler.completionFuture.wait()\n        return numberOfIterations\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_1_reqs_1000_conn.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        var numberDone = 1\n        for _ in 0..<1000 {\n            let newDones = try! doRequests(group: group, number: 1)\n            precondition(newDones == 1)\n            numberDone += newDones\n        }\n        return numberDone\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_assume_isolated_scheduling_10000_executions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let dg = DispatchGroup()\n\n        try! loop.submit {\n            for _ in 0..<10_000 {\n                dg.enter()\n                loop.assumeIsolated().execute { dg.leave() }\n            }\n        }.wait()\n        dg.wait()\n        try! group.syncShutdownGracefully()\n        return 10_000\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_bytebuffer_lots_of_rw.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let dispatchData = (\"A\" as StaticString).withUTF8Buffer { ptr in\n            DispatchData(bytes: UnsafeRawBufferPointer(ptr))\n        }\n        var buffer = ByteBufferAllocator().buffer(capacity: 7 * 1000)\n        let foundationData = \"A\".data(using: .utf8)!\n        let substring = Substring(\"A\")\n        @inline(never)\n        func doWrites(buffer: inout ByteBuffer, dispatchData: DispatchData, substring: Substring) {\n            // these ones are zero allocations\n            // buffer.writeBytes(foundationData) // see SR-7542\n            buffer.writeBytes([0x41])\n            buffer.writeBytes(\"A\".utf8)\n            buffer.writeString(\"A\")\n            buffer.writeStaticString(\"A\")\n            buffer.writeInteger(0x41, as: UInt8.self)\n\n            // those down here should be one allocation each (on Linux)\n            buffer.writeBytes(dispatchData)  // see https://bugs.swift.org/browse/SR-9597\n\n            // these here are one allocation on all platforms\n            buffer.writeSubstring(substring)\n        }\n        @inline(never)\n        func doReads(buffer: inout ByteBuffer) {\n            // these ones are zero allocations\n            let val = buffer.readInteger(as: UInt8.self)\n            precondition(0x41 == val, \"\\(val!)\")\n            var slice = buffer.readSlice(length: 1)\n            let sliceVal = slice!.readInteger(as: UInt8.self)\n            precondition(0x41 == sliceVal, \"\\(sliceVal!)\")\n            buffer.withUnsafeReadableBytes { ptr in\n                precondition(ptr[0] == 0x41)\n            }\n\n            // those down here should be one allocation each\n            let arr = buffer.readBytes(length: 1)\n            precondition([0x41] == arr!, \"\\(arr!)\")\n            let str = buffer.readString(length: 1)\n            precondition(\"A\" == str, \"\\(str!)\")\n        }\n        for _ in 0..<1000 {\n            doWrites(buffer: &buffer, dispatchData: dispatchData, substring: substring)\n            doReads(buffer: &buffer)\n        }\n        return buffer.readableBytes\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_creating_10000_headers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOHTTP1\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        var count = 0\n\n        for _ in 0..<10_000 {\n            let baseHeaders: [(String, String)] = [(\"Host\", \"example.com\"), (\"Content-Length\", \"4\")]\n            count += HTTPHeaders(baseHeaders).count\n        }\n\n        return count\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_decode_1000_ws_frames.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\n\nclass UnboxingChannelHandler: ChannelInboundHandler {\n    typealias InboundIn = WebSocketFrame\n    typealias InboundOut = WebSocketFrame\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let data = Self.unwrapInboundIn(data)\n        context.fireChannelRead(Self.wrapInboundOut(data))\n    }\n}\n\nfunc run(identifier: String) {\n    let channel = EmbeddedChannel()\n    try! channel.pipeline.addHandler(ByteToMessageHandler(WebSocketFrameDecoder())).wait()\n    try! channel.pipeline.addHandler(UnboxingChannelHandler()).wait()\n    let data = ByteBuffer(bytes: [0x81, 0x00])  // empty websocket\n\n    measure(identifier: identifier) {\n        for _ in 0..<1000 {\n            try! channel.writeInbound(data)\n            let _: WebSocketFrame? = try! channel.readInbound()\n        }\n        return 1000\n    }\n\n    _ = try! channel.finish()\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_encode_1000_ws_frames.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\n\nfunc doSendFramesHoldingBuffer(\n    channel: EmbeddedChannel,\n    number numberOfFrameSends: Int,\n    data originalData: [UInt8],\n    spareBytesAtFront: Int,\n    mask: WebSocketMaskingKey? = nil\n) throws -> Int {\n    var data = channel.allocator.buffer(capacity: originalData.count + spareBytesAtFront)\n    data.moveWriterIndex(forwardBy: spareBytesAtFront)\n    data.moveReaderIndex(forwardBy: spareBytesAtFront)\n    data.writeBytes(originalData)\n\n    let frame = WebSocketFrame(opcode: .binary, maskKey: mask, data: data, extensionData: nil)\n\n    // We're interested in counting allocations, so this test reads the data from the EmbeddedChannel\n    // to force the data out of memory.\n    for _ in 0..<numberOfFrameSends {\n        channel.writeAndFlush(frame, promise: nil)\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n    }\n\n    return numberOfFrameSends\n}\n\nfunc doSendFramesNewBuffer(\n    channel: EmbeddedChannel,\n    number numberOfFrameSends: Int,\n    data originalData: [UInt8],\n    spareBytesAtFront: Int,\n    mask: WebSocketMaskingKey? = nil\n) throws -> Int {\n    for _ in 0..<numberOfFrameSends {\n        // We need a new allocation every time to drop the original data ref.\n        var data = channel.allocator.buffer(capacity: originalData.count + spareBytesAtFront)\n        data.moveWriterIndex(forwardBy: spareBytesAtFront)\n        data.moveReaderIndex(forwardBy: spareBytesAtFront)\n        data.writeBytes(originalData)\n        let frame = WebSocketFrame(opcode: .binary, maskKey: mask, data: data, extensionData: nil)\n\n        // We're interested in counting allocations, so this test reads the data from the EmbeddedChannel\n        // to force the data out of memory.\n        channel.writeAndFlush(frame, promise: nil)\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n    }\n\n    return numberOfFrameSends\n}\n\nfunc run(identifier: String) {\n    let maskKey: WebSocketMaskingKey = [1, 2, 3, 4]\n    let channel = EmbeddedChannel()\n    try! channel.pipeline.addHandler(WebSocketFrameEncoder()).wait()\n    let data = Array(repeating: UInt8(0), count: 1024)\n\n    measure(identifier: identifier + \"_holding_buffer\") {\n        let numberDone = try! doSendFramesHoldingBuffer(\n            channel: channel,\n            number: 1000,\n            data: data,\n            spareBytesAtFront: 0\n        )\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_holding_buffer_with_space\") {\n        let numberDone = try! doSendFramesHoldingBuffer(\n            channel: channel,\n            number: 1000,\n            data: data,\n            spareBytesAtFront: 8\n        )\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_holding_buffer_with_mask\") {\n        let numberDone = try! doSendFramesHoldingBuffer(\n            channel: channel,\n            number: 1000,\n            data: data,\n            spareBytesAtFront: 0,\n            mask: maskKey\n        )\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_holding_buffer_with_space_with_mask\") {\n        let numberDone = try! doSendFramesHoldingBuffer(\n            channel: channel,\n            number: 1000,\n            data: data,\n            spareBytesAtFront: 8,\n            mask: maskKey\n        )\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_new_buffer\") {\n        let numberDone = try! doSendFramesNewBuffer(channel: channel, number: 1000, data: data, spareBytesAtFront: 0)\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_new_buffer_with_space\") {\n        let numberDone = try! doSendFramesNewBuffer(channel: channel, number: 1000, data: data, spareBytesAtFront: 8)\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_new_buffer_with_mask\") {\n        let numberDone = try! doSendFramesNewBuffer(\n            channel: channel,\n            number: 1000,\n            data: data,\n            spareBytesAtFront: 0,\n            mask: maskKey\n        )\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    measure(identifier: identifier + \"_new_buffer_with_space_with_mask\") {\n        let numberDone = try! doSendFramesNewBuffer(\n            channel: channel,\n            number: 1000,\n            data: data,\n            spareBytesAtFront: 8,\n            mask: maskKey\n        )\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n\n    _ = try! channel.finish()\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_execute_hop_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    let loop = group.next()\n    let dg = DispatchGroup()\n\n    measure(identifier: identifier) {\n        for _ in 0..<10000 {\n            dg.enter()\n            loop.execute { dg.leave() }\n        }\n        dg.wait()\n        return 10_000\n    }\n\n    try! group.syncShutdownGracefully()\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_flat_schedule_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            let deadline = NIODeadline.now() + .hours(1)\n\n            for _ in 0..<10000 {\n                loop.flatScheduleTask(deadline: deadline) {\n                    counter &+= 1\n                    return loop.makeSucceededFuture(counter)\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_flat_schedule_assume_isolated_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            let deadline = NIODeadline.now() + .hours(1)\n\n            for _ in 0..<10000 {\n                loop.assumeIsolated().flatScheduleTask(deadline: deadline) {\n                    counter &+= 1\n                    return loop.makeSucceededFuture(counter)\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_future_assume_isolated_lots_of_callbacks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\n// This test is an equivalent of test_future_lots_of_callbacks.swift. It should\n// have the same allocations as that test, and any difference is a bug.\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        struct MyError: Error {}\n        @inline(never)\n        func doThenAndFriends(loop: EventLoop) {\n            let p = loop.makePromise(of: Int.self)\n            let f = p.futureResult.assumeIsolated().flatMap { (r: Int) -> EventLoopFuture<Int> in\n                // This call allocates a new Future, and\n                // so does flatMap(), so this is two Futures.\n                loop.makeSucceededFuture(r + 1)\n            }.flatMapThrowing { (r: Int) -> Int in\n                // flatMapThrowing allocates a new Future, and calls `flatMap`\n                // which also allocates, so this is two.\n                r + 2\n            }.map { (r: Int) -> Int in\n                // map allocates a new future, and calls `flatMap` which\n                // also allocates, so this is two.\n                r + 2\n            }.flatMapThrowing { (r: Int) -> Int in\n                // flatMapThrowing allocates a future on the error path and\n                // calls `flatMap`, which also allocates, so this is two.\n                throw MyError()\n            }.flatMapError { (err: Error) -> EventLoopFuture<Int?> in\n                // This call allocates a new Future, and so does flatMapError,\n                // so this is two Futures.\n                loop.makeFailedFuture(err)\n            }.flatMapErrorThrowing { (err: Error) -> Int? in\n                // flatMapError allocates a new Future, and calls flatMapError,\n                // so this is two Futures\n                throw err\n            }.recover { (err: Error) -> Int? in\n                // recover allocates a future, and calls flatMapError, so\n                // this is two Futures.\n                nil\n            }.unwrap { () -> Int in\n                // unwrap calls map, with an extra closure, so this is three.\n                1\n            }.always { (Int) -> Void in\n                // This is a do-nothing call, but it can't be optimised out.\n                // always calls whenComplete but adds a new closure, so it allocates\n                // two times.\n                _ = 1 + 1\n            }.flatMapResult { (Int) -> Result<Int?, Error> in\n                // flatMapResult allocates a new future and creates a _whenComplete closure,\n                // so this is two.\n                .success(5)\n            }\n            .unwrap(orReplace: 5)  // Same as unwrap above, this is three.\n\n            // Add some when*.\n            f.whenSuccess {\n                // whenSuccess should be just one.\n                _ = $0 + 1\n            }\n            f.whenFailure { _ in\n                // whenFailure should also be just one.\n                fatalError()\n            }\n            f.whenComplete {\n                // whenComplete should also be just one.\n                switch $0 {\n                case .success:\n                    ()\n                case .failure:\n                    fatalError()\n                }\n            }\n\n            p.assumeIsolated().succeed(0)\n\n            // Wait also allocates a lock.\n            _ = try! f.nonisolated().wait()\n        }\n        @inline(never)\n        func doAnd(loop: EventLoop) {\n            // This isn't relevant to this test, but we keep it here to keep the numbers lining up.\n            let p1 = loop.makePromise(of: Int.self)\n            let p2 = loop.makePromise(of: Int.self)\n            let p3 = loop.makePromise(of: Int.self)\n\n            // Each call to and() allocates a Future. The calls to\n            // and(result:) allocate two.\n\n            let f = p1.futureResult\n                .and(p2.futureResult)\n                .and(p3.futureResult)\n                .and(value: 1)\n                .and(value: 1)\n\n            p1.succeed(1)\n            p2.succeed(1)\n            p3.succeed(1)\n            _ = try! f.wait()\n        }\n\n        let el = EmbeddedEventLoop()\n        for _ in 0..<1000 {\n            doThenAndFriends(loop: el)\n            doAnd(loop: el)\n        }\n        return 1000\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_future_erase_result.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        @inline(never)\n        func doEraseResult(loop: EventLoop) {\n            // In an ideal implementation the only allocation is this promise.\n            let p = loop.makePromise(of: Int.self)\n            let f = p.futureResult.map { (r: Int) -> Void in\n                // This closure is a value-to-no-value erase that closes over nothing.\n                // Ideally this would not allocate.\n                return\n            }.map { (_: Void) -> Void in\n                // This closure is a nothing-to-nothing map, basically a \"completed\" observer. This should\n                // also not allocate, but it has a separate code path to the above.\n            }\n            p.succeed(0)\n        }\n\n        let el = EmbeddedEventLoop()\n        for _ in 0..<1000 {\n            doEraseResult(loop: el)\n        }\n        return 1000\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_future_lots_of_callbacks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        struct MyError: Error {}\n        @inline(never)\n        func doThenAndFriends(loop: EventLoop) {\n            let p = loop.makePromise(of: Int.self)\n            let f = p.futureResult.flatMap { (r: Int) -> EventLoopFuture<Int> in\n                // This call allocates a new Future, and\n                // so does flatMap(), so this is two Futures.\n                loop.makeSucceededFuture(r + 1)\n            }.flatMapThrowing { (r: Int) -> Int in\n                // flatMapThrowing allocates a new Future, and calls `flatMap`\n                // which also allocates, so this is two.\n                r + 2\n            }.map { (r: Int) -> Int in\n                // map allocates a new future, and calls `flatMap` which\n                // also allocates, so this is two.\n                r + 2\n            }.flatMapThrowing { (r: Int) -> Int in\n                // flatMapThrowing allocates a future on the error path and\n                // calls `flatMap`, which also allocates, so this is two.\n                throw MyError()\n            }.flatMapError { (err: Error) -> EventLoopFuture<Int?> in\n                // This call allocates a new Future, and so does flatMapError,\n                // so this is two Futures.\n                loop.makeFailedFuture(err)\n            }.flatMapErrorThrowing { (err: Error) -> Int? in\n                // flatMapError allocates a new Future, and calls flatMapError,\n                // so this is two Futures\n                throw err\n            }.recover { (err: Error) -> Int? in\n                // recover allocates a future, and calls flatMapError, so\n                // this is two Futures.\n                nil\n            }.unwrap { () -> Int in\n                // unwrap calls map, with an extra closure, so this is three.\n                1\n            }.always { (Int) -> Void in\n                // This is a do-nothing call, but it can't be optimised out.\n                // always calls whenComplete but adds a new closure, so it allocates\n                // two times.\n                _ = 1 + 1\n            }.flatMapResult { (Int) -> Result<Int?, Error> in\n                // flatMapResult allocates a new future and creates a _whenComplete closure,\n                // so this is two.\n                .success(5)\n            }\n            .unwrap(orReplace: 5)  // Same as unwrap above, this is three.\n\n            // Add some when*.\n            f.whenSuccess {\n                // whenSuccess should be just one.\n                _ = $0 + 1\n            }\n            f.whenFailure { _ in\n                // whenFailure should also be just one.\n                fatalError()\n            }\n            f.whenComplete {\n                // whenComplete should also be just one.\n                switch $0 {\n                case .success:\n                    ()\n                case .failure:\n                    fatalError()\n                }\n            }\n\n            p.succeed(0)\n\n            // Wait also allocates a lock.\n            _ = try! f.wait()\n        }\n        @inline(never)\n        func doAnd(loop: EventLoop) {\n            let p1 = loop.makePromise(of: Int.self)\n            let p2 = loop.makePromise(of: Int.self)\n            let p3 = loop.makePromise(of: Int.self)\n\n            // Each call to and() allocates a Future. The calls to\n            // and(result:) allocate two.\n\n            let f = p1.futureResult\n                .and(p2.futureResult)\n                .and(p3.futureResult)\n                .and(value: 1)\n                .and(value: 1)\n\n            p1.succeed(1)\n            p2.succeed(1)\n            p3.succeed(1)\n            _ = try! f.wait()\n        }\n        let el = EmbeddedEventLoop()\n        for _ in 0..<1000 {\n            doThenAndFriends(loop: el)\n            doAnd(loop: el)\n        }\n        return 1000\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_get_100000_headers_canonical_form.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOHTTP1\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let headers: HTTPHeaders = [\"key\": \"no,trimming\"]\n        var count = 0\n        for _ in 0..<100_000 {\n            count &+= headers[canonicalForm: \"key\"].count\n        }\n        return count\n    }\n\n    measure(identifier: identifier + \"_trimming_whitespace\") {\n        let headers: HTTPHeaders = [\"key\": \"         some   ,   trimming     \"]\n        var count = 0\n        for _ in 0..<100_000 {\n            count &+= headers[canonicalForm: \"key\"].count\n        }\n        return count\n    }\n\n    measure(identifier: identifier + \"_trimming_whitespace_from_short_string\") {\n        // first components has length > 15 with whitespace and <= 15 without.\n        let headers: HTTPHeaders = [\"key\": \"   smallString   ,whenStripped\"]\n        var count = 0\n        for _ in 0..<100_000 {\n            count &+= headers[canonicalForm: \"key\"].count\n        }\n        return count\n    }\n\n    measure(identifier: identifier + \"_trimming_whitespace_from_long_string\") {\n        let headers: HTTPHeaders = [\"key\": \" moreThan15CharactersWithAndWithoutWhitespace ,anotherValue\"]\n        var count = 0\n        for _ in 0..<100_000 {\n            count &+= headers[canonicalForm: \"key\"].count\n        }\n        return count\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_modifying_1000_circular_buffer_elements.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nfunc run(identifier: String) {\n    var buffer = CircularBuffer<[Int]>(initialCapacity: 100)\n    for _ in 0..<100 {\n        buffer.append([])\n    }\n\n    measure(identifier: identifier) {\n        for idx in 0..<1000 {\n            let index = buffer.index(buffer.startIndex, offsetBy: idx % 100)\n            buffer.modify(index) { value in\n                value.append(idx)\n            }\n        }\n        return buffer.last!.last!\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_modifying_byte_buffer_view.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\nfunc run(identifier: String) {\n    let allocator = ByteBufferAllocator()\n    let data = Array(repeating: UInt8(0), count: 1024)\n\n    measure(identifier: identifier) {\n        var count = 0\n\n        for _ in 0..<1_000 {\n            var buffer = allocator.buffer(capacity: data.count)\n            buffer.writeBytes(data)\n\n            var view = ByteBufferView(buffer)\n\n            // Unfortunately this CoWs: https://bugs.swift.org/browse/SR-11675\n            view[0] = 42\n            view.replaceSubrange(0..<4, with: [0x0, 0x1, 0x2, 0x3])\n\n            var modified = ByteBuffer(view)\n            modified.setBytes([0xa, 0xb, 0xc], at: modified.readerIndex)\n            count &+= modified.readableBytes\n        }\n\n        return count\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_ping_pong_1000_reqs_1_conn.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate struct PingPongFailure: Error, CustomStringConvertible {\n    public var description: String\n\n    init(problem: String) {\n        self.description = problem\n    }\n}\n\nprivate final class PongDecoder: ByteToMessageDecoder {\n    typealias InboundOut = UInt8\n\n    public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) -> DecodingState {\n        if let ping = buffer.readInteger(as: UInt8.self) {\n            context.fireChannelRead(Self.wrapInboundOut(ping))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n\n    public func decodeLast(\n        context: ChannelHandlerContext,\n        buffer: inout ByteBuffer,\n        seenEOF: Bool\n    ) throws -> DecodingState {\n        .needMoreData\n    }\n}\n\nprivate final class PingHandler: ChannelInboundHandler {\n    typealias InboundIn = ByteBuffer\n    typealias OutboundOut = ByteBuffer\n\n    private var pingBuffer: ByteBuffer!\n    private let numberOfRequests: Int\n    private var remainingNumberOfRequests: Int\n    private let allDone: EventLoopPromise<Void>\n    public static let pingCode: UInt8 = 0xbe\n\n    public init(numberOfRequests: Int, eventLoop: EventLoop) {\n        self.numberOfRequests = numberOfRequests\n        self.remainingNumberOfRequests = numberOfRequests\n        self.allDone = eventLoop.makePromise()\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        (context.channel as? SocketOptionProvider)?.setSoLinger(linger(l_onoff: 1, l_linger: 0))\n            .whenFailure({ error in fatalError(\"Failed to set linger \\(error)\") })\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n        self.pingBuffer = context.channel.allocator.buffer(capacity: 1)\n        self.pingBuffer.writeInteger(PingHandler.pingCode)\n\n        context.writeAndFlush(Self.wrapOutboundOut(self.pingBuffer), promise: nil)\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var buf = self.unwrapInboundIn(data)\n        if buf.readableBytes == 1 && buf.readInteger(as: UInt8.self) == PongHandler.pongCode {\n            if self.remainingNumberOfRequests > 0 {\n                self.remainingNumberOfRequests -= 1\n                context.writeAndFlush(Self.wrapOutboundOut(self.pingBuffer), promise: nil)\n            } else {\n                context.close(promise: self.allDone)\n            }\n        } else {\n            context.close(promise: nil)\n            self.allDone.fail(PingPongFailure(problem: \"wrong buffer received: \\(buf.debugDescription)\"))\n        }\n    }\n\n    public func wait() throws {\n        try self.allDone.futureResult.wait()\n    }\n}\n\nprivate final class PongHandler: ChannelInboundHandler {\n    typealias InboundIn = UInt8\n    typealias OutboundOut = ByteBuffer\n\n    private var pongBuffer: ByteBuffer!\n    public static let pongCode: UInt8 = 0xef\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self.pongBuffer = context.channel.allocator.buffer(capacity: 1)\n        self.pongBuffer.writeInteger(PongHandler.pongCode)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let data = Self.unwrapInboundIn(data)\n        if data == PingHandler.pingCode {\n            context.writeAndFlush(NIOAny(self.pongBuffer), promise: nil)\n        } else {\n            context.close(promise: nil)\n        }\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        context.close(promise: nil)\n    }\n}\n\nfunc doPingPongRequests(group: EventLoopGroup, number numberOfRequests: Int) throws -> Int {\n    let serverChannel = try ServerBootstrap(group: group)\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .childChannelOption(.recvAllocator, value: FixedSizeRecvByteBufferAllocator(capacity: 4))\n        .childChannelInitializer { channel in\n            channel.pipeline.addHandler(ByteToMessageHandler(PongDecoder())).flatMap {\n                channel.pipeline.addHandler(PongHandler())\n            }\n        }.bind(host: \"127.0.0.1\", port: 0).wait()\n\n    defer {\n        try! serverChannel.close().wait()\n    }\n\n    let pingHandler = PingHandler(numberOfRequests: numberOfRequests, eventLoop: group.next())\n    _ = try ClientBootstrap(group: group)\n        .channelInitializer { channel in\n            channel.pipeline.addHandler(pingHandler)\n        }\n        .channelOption(.recvAllocator, value: FixedSizeRecvByteBufferAllocator(capacity: 4))\n        .connect(to: serverChannel.localAddress!)\n        .wait()\n\n    try pingHandler.wait()\n    return numberOfRequests\n}\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let numberDone = try! doPingPongRequests(group: group, number: 1000)\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_read_10000_chunks_from_file.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport Foundation\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        try! group.syncShutdownGracefully()\n    }\n    let loop = group.next()\n    let threadPool = NIOThreadPool(numberOfThreads: 1)\n    threadPool.start()\n    defer {\n        try! threadPool.syncShutdownGracefully()\n    }\n    let fileIO = NonBlockingFileIO(threadPool: threadPool)\n\n    let numberOfChunks = 10_000\n\n    let allocator = ByteBufferAllocator()\n    var fileBuffer = allocator.buffer(capacity: numberOfChunks)\n    fileBuffer.writeString(String(repeating: \"X\", count: numberOfChunks))\n    let path = NSTemporaryDirectory() + \"/\\(UUID())\"\n    let fileHandle = try! NIOFileHandle(\n        path: path,\n        mode: [.write, .read],\n        flags: .allowFileCreation(posixMode: 0o600)\n    )\n    defer {\n        unlink(path)\n    }\n    try! fileIO.write(\n        fileHandle: fileHandle,\n        buffer: fileBuffer,\n        eventLoop: loop\n    ).wait()\n\n    let numberOfBytes = NIOAtomic<Int>.makeAtomic(value: 0)\n    measure(identifier: identifier) {\n        numberOfBytes.store(0)\n        try! fileIO.readChunked(\n            fileHandle: fileHandle,\n            fromOffset: 0,\n            byteCount: numberOfChunks,\n            chunkSize: 1,\n            allocator: allocator,\n            eventLoop: loop\n        ) { buffer in\n            numberOfBytes.add(buffer.readableBytes)\n            return loop.makeSucceededFuture(())\n        }.wait()\n        precondition(numberOfBytes.load() == numberOfChunks, \"\\(numberOfBytes.load()), \\(numberOfChunks)\")\n        return numberOfBytes.load()\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_schedule_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            for _ in 0..<10000 {\n                loop.scheduleTask(in: .hours(1)) {\n                    counter &+= 1\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_schedule_and_run_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    let loop = group.next()\n    let dg = DispatchGroup()\n\n    measure(identifier: identifier) {\n        var counter = 0\n\n        try! loop.submit {\n            for _ in 0..<10000 {\n                dg.enter()\n\n                loop.scheduleTask(in: .nanoseconds(0)) {\n                    counter &+= 1\n                    dg.leave()\n                }\n            }\n        }.wait()\n        dg.wait()\n\n        return counter\n    }\n\n    try! group.syncShutdownGracefully()\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_schedule_assume_isolated_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            for _ in 0..<10000 {\n                loop.assumeIsolated().scheduleTask(in: .hours(1)) {\n                    counter &+= 1\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_schedule_with_deadline_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            let deadline = NIODeadline.now() + .hours(1)\n\n            for _ in 0..<10000 {\n                loop.scheduleTask(deadline: deadline) {\n                    counter &+= 1\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_schedule_with_deadline_assume_isolated_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            let deadline = NIODeadline.now() + .hours(1)\n\n            for _ in 0..<10000 {\n                loop.assumeIsolated().scheduleTask(deadline: deadline) {\n                    counter &+= 1\n                    return counter\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_scheduling_10000_executions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let dg = DispatchGroup()\n\n        try! loop.submit {\n            for _ in 0..<10_000 {\n                dg.enter()\n                loop.execute { dg.leave() }\n            }\n        }.wait()\n        dg.wait()\n        try! group.syncShutdownGracefully()\n        return 10_000\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_submit_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            for _ in 0..<10000 {\n                _ = loop.submit {\n                    counter &+= 1\n                    return counter\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_submit_assume_isolated_10000_tasks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        let counter = try! loop.submit { () -> Int in\n            var counter: Int = 0\n\n            for _ in 0..<10000 {\n                _ = loop.assumeIsolated().submit {\n                    counter &+= 1\n                    return counter\n                }\n            }\n\n            return counter\n        }.wait()\n\n        try! group.syncShutdownGracefully()\n        return counter\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_udp_1000_reqs_1_conn.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        let numberDone = try! UDPShared.doUDPRequests(group: group, number: 1000)\n        precondition(numberDone == 1000)\n        return numberDone\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_04_performance/test_01_resources/test_udp_1_reqs_1000_conn.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOPosix\n\nfunc run(identifier: String) {\n    measure(identifier: identifier) {\n        var numberDone = 1\n        for _ in 0..<1000 {\n            let newDones = try! UDPShared.doUDPRequests(group: group, number: 1)\n            precondition(newDones == 1)\n            numberDone += newDones\n        }\n        return numberDone\n    }\n}\n"
  },
  {
    "path": "IntegrationTests/tests_05_assertions/defines.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nfunction make_package() {\n    cat > \"${tmpdir:?\"tmpdir variable not set\"}/syscallwrapper/Package.swift\" <<\"EOF\"\n// swift-tools-version:5.7\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"syscallwrapper\",\n    dependencies: [],\n    targets: [\n        .target(\n            name: \"syscallwrapper\",\n            dependencies: [\"CNIOLinux\", \"CNIODarwin\", \"NIOCore\"]),\n        .target(\n            name: \"CNIOLinux\",\n            dependencies: [],\n            cSettings: [\n                .define(\"_GNU_SOURCE\")\n            ]),\n        .target(\n            name: \"CNIODarwin\",\n            dependencies: []),\n        // This target does nothing, it just makes imports work.\n        .target(\n            name: \"NIOCore\",\n            dependencies: []),\n    ]\n)\nEOF\n    cp \"${here:?\"here variable not set\"}/../../Tests/NIOTests/SystemCallWrapperHelpers.swift\" \\\n        \"$here/../../Sources/NIOPosix/System.swift\" \\\n        \"$here/../../Sources/NIOPosix/IO.swift\" \\\n        \"$tmpdir/syscallwrapper/Sources/syscallwrapper\"\n    ln -s \"$here/../../Sources/CNIOLinux\" \"$tmpdir/syscallwrapper/Sources\"\n    ln -s \"$here/../../Sources/CNIODarwin\" \"$tmpdir/syscallwrapper/Sources\"\n    mkdir \"$tmpdir/syscallwrapper/Sources/NIOCore\"\n    touch \"$tmpdir/syscallwrapper/Sources/NIOCore/empty.swift\"\n}\n"
  },
  {
    "path": "IntegrationTests/tests_05_assertions/test_01_syscall_wrapper_fast.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\n# shellcheck source=IntegrationTests/tests_01_http/defines.sh\nsource defines.sh\n\nswift_binary=swiftc\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nif [[ -n \"${SWIFT_EXEC-}\" ]]; then\n    swift_binary=\"$(dirname \"$SWIFT_EXEC\")/swiftc\"\nelif [[ \"$(uname -s)\" == \"Linux\" ]]; then\n    swift_binary=$(which swiftc)\nfi\n\ncp \"$here/../../Sources/NIOConcurrencyHelpers/\"{lock,NIOLock}.swift \"${tmp:?\"tmp variable not set\"}\"\ncat > \"$tmp/main.swift\" <<\"EOF\"\nlet l = NIOLock()\nl.lock()\nl.lock()\nEOF\n\n\"$swift_binary\" -o \"$tmp/test\" \"$tmp/main.swift\" \"$tmp/\"{lock,NIOLock}.swift\nif \"$tmp/test\"; then\n    fail \"should have crashed\"\nelse\n    exit_code=$?\n    \n    # expecting irrecoverable error as process should be terminated through fatalError/precondition/assert\n    architecture=$(uname -m)\n    if [[ $architecture =~ ^(arm|aarch) ]]; then\n        assert_equal $exit_code $(( 128 + 5 )) # 5 == SIGTRAP aka trace trap, expected on ARM\n    elif [[ $architecture =~ ^(x86|i386) ]]; then\n        assert_equal $exit_code $(( 128 + 4 ))  # 4 == SIGILL aka illegal instruction, expected on x86\n    else\n        fail \"unknown CPU architecture for which we don't know the expected signal for a crash\"\n    fi\nfi\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NOTICE.txt",
    "content": "\n                            The SwiftNIO Project\n                            ====================\n\nPlease visit the SwiftNIO web site for more information:\n\n  * https://github.com/apple/swift-nio\n\nCopyright 2017, 2018 The SwiftNIO Project\n\nThe SwiftNIO Project licenses this file to you under the Apache License,\nversion 2.0 (the \"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at:\n\n  https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\nWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\nLicense for the specific language governing permissions and limitations\nunder the License.\n\nAlso, please refer to each LICENSE.<component>.txt file, which is located in\nthe 'license' directory of the distribution file, for the license terms of the\ncomponents that this product depends on.\n\n-------------------------------------------------------------------------------\n\nThis product is heavily influenced by Netty.\n\n  * LICENSE (Apache License 2.0):\n    * https://github.com/netty/netty/blob/4.1/LICENSE.txt\n  * HOMEPAGE:\n    * https://netty.io\n\n---\n\nThis product contains NodeJS's llhttp.\n\n  * LICENSE (MIT):\n    * https://github.com/nodejs/llhttp/blob/1e1c5b43326494e97cf8244ff57475eb72a1b62c/LICENSE-MIT\n  * HOMEPAGE:\n    * https://github.com/nodejs/llhttp\n\n---\n\nThis product contains \"cpp_magic.h\" from Thomas Nixon & Jonathan Heathcote's uSHET\n\n  * LICENSE (MIT):\n    * https://github.com/18sg/uSHET/blob/c09e0acafd86720efe42dc15c63e0cc228244c32/lib/cpp_magic.h\n  * HOMEPAGE:\n    * https://github.com/18sg/uSHET\n\n---\n\nThis product contains \"sha1.c\" and \"sha1.h\" from FreeBSD (Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project)\n\n  * LICENSE (BSD-3):\n    * https://opensource.org/licenses/BSD-3-Clause\n  * HOMEPAGE:\n    * https://github.com/freebsd/freebsd-src\n\n---\n\nThis product contains a derivation of Fabian Fett's 'Base64.swift'.\n\n  * LICENSE (Apache License 2.0):\n    * https://github.com/swift-extras/swift-extras-base64/blob/b8af49699d59ad065b801715a5009619100245ca/LICENSE\n  * HOMEPAGE:\n    * https://github.com/fabianfett/swift-base64-kit\n\n---\n\nThis product contains a derivation of \"XCTest+AsyncAwait.swift\" & \"StructuredConcurrencyHelpers\" from AsyncHTTPClient.\n\n  * LICENSE (Apache License 2.0):\n    * https://www.apache.org/licenses/LICENSE-2.0\n  * HOMEPAGE:\n    * https://github.com/swift-server/async-http-client\n\n---\n\nThis product contains a derivation of \"_TinyArray.swift\" from SwiftCertificates.\n\n  * LICENSE (Apache License 2.0):\n    * https://www.apache.org/licenses/LICENSE-2.0\n  * HOMEPAGE:\n    * https://github.com/apple/swift-certificates\n\n---\n\nThis product contains a derivation of the mocking infrastructure from Swift System.\n\n  * LICENSE (Apache License 2.0):\n    * https://www.apache.org/licenses/LICENSE-2.0\n  * HOMEPAGE:\n    * https://github.com/apple/swift-system\n\n---\n\nThis product contains a derivation of \"TokenBucket.swift\" from Swift Package Manager.\n\n  * LICENSE (Apache License 2.0):\n    * https://www.apache.org/licenses/LICENSE-2.0\n  * HOMEPAGE:\n    * https://github.com/swiftlang/swift-package-manager\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:6.0\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport PackageDescription\n\nlet swiftAtomics: PackageDescription.Target.Dependency = .product(name: \"Atomics\", package: \"swift-atomics\")\nlet swiftCollections: PackageDescription.Target.Dependency = .product(name: \"DequeModule\", package: \"swift-collections\")\nlet swiftSystem: PackageDescription.Target.Dependency = .product(name: \"SystemPackage\", package: \"swift-system\")\n\n// These platforms require a dependency on `NIOPosix` from `NIOHTTP1` to maintain backward\n// compatibility with previous NIO versions.\nlet historicalNIOPosixDependencyRequired: [Platform] = [.macOS, .iOS, .tvOS, .watchOS, .linux, .android]\n\nlet swiftSettings: [SwiftSetting] = [\n    // The Language Steering Group has promised that they won't break the APIs that currently exist under\n    // this \"experimental\" feature flag without two subsequent releases. We assume they will respect that\n    // promise, so we enable this here. For more, see:\n    // https://forums.swift.org/t/experimental-support-for-lifetime-dependencies-in-swift-6-2-and-beyond/78638\n    .enableExperimentalFeature(\"Lifetimes\")\n]\n\n// This doesn't work when cross-compiling: the privacy manifest will be included in the Bundle and\n// Foundation will be linked. This is, however, strictly better than unconditionally adding the\n// resource.\n#if canImport(Darwin)\nlet includePrivacyManifest = true\n#else\nlet includePrivacyManifest = false\n#endif\n\nlet package = Package(\n    name: \"swift-nio\",\n    products: [\n        .library(name: \"NIOCore\", targets: [\"NIOCore\"]),\n        .library(name: \"NIO\", targets: [\"NIO\"]),\n        .library(name: \"NIOEmbedded\", targets: [\"NIOEmbedded\"]),\n        .library(name: \"NIOPosix\", targets: [\"NIOPosix\"]),\n        .library(name: \"_NIOConcurrency\", targets: [\"_NIOConcurrency\"]),\n        .library(name: \"NIOTLS\", targets: [\"NIOTLS\"]),\n        .library(name: \"NIOHTTP1\", targets: [\"NIOHTTP1\"]),\n        .library(name: \"NIOConcurrencyHelpers\", targets: [\"NIOConcurrencyHelpers\"]),\n        .library(name: \"NIOFoundationCompat\", targets: [\"NIOFoundationCompat\"]),\n        .library(name: \"NIOWebSocket\", targets: [\"NIOWebSocket\"]),\n        .library(name: \"NIOTestUtils\", targets: [\"NIOTestUtils\"]),\n        .library(name: \"_NIOFileSystem\", targets: [\"_NIOFileSystem\", \"NIOFileSystem\"]),\n        .library(name: \"_NIOFileSystemFoundationCompat\", targets: [\"_NIOFileSystemFoundationCompat\"]),\n    ],\n    targets: [\n        // MARK: - Targets\n\n        .target(\n            name: \"NIOCore\",\n            dependencies: [\n                \"NIOConcurrencyHelpers\",\n                \"_NIOBase64\",\n                \"CNIOOpenBSD\",\n                \"CNIODarwin\",\n                \"CNIOLinux\",\n                \"CNIOWindows\",\n                \"CNIOWASI\",\n                \"_NIODataStructures\",\n                swiftCollections,\n                swiftAtomics,\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"_NIODataStructures\",\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"_NIOBase64\",\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOEmbedded\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOConcurrencyHelpers\",\n                \"_NIODataStructures\",\n                swiftAtomics,\n                swiftCollections,\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOPosix\",\n            dependencies: [\n                \"CNIOOpenBSD\",\n                \"CNIOLinux\",\n                \"CNIODarwin\",\n                \"CNIOWindows\",\n                \"NIOConcurrencyHelpers\",\n                \"NIOCore\",\n                \"_NIODataStructures\",\n                \"CNIOPosix\",\n                swiftAtomics,\n            ],\n            exclude: includePrivacyManifest ? [] : [\"PrivacyInfo.xcprivacy\"],\n            resources: includePrivacyManifest ? [.copy(\"PrivacyInfo.xcprivacy\")] : [],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIO\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOPosix\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"_NIOConcurrency\",\n            dependencies: [\n                .target(name: \"NIO\", condition: .when(platforms: historicalNIOPosixDependencyRequired)),\n                \"NIOCore\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOFoundationCompat\",\n            dependencies: [\n                .target(name: \"NIO\", condition: .when(platforms: historicalNIOPosixDependencyRequired)),\n                \"NIOCore\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"CNIOAtomics\",\n            dependencies: [],\n            cSettings: [\n                .define(\"_GNU_SOURCE\")\n            ]\n        ),\n        .target(\n            name: \"CNIOPosix\",\n            dependencies: [],\n            cSettings: [\n                .define(\"_GNU_SOURCE\")\n            ]\n        ),\n        .target(\n            name: \"CNIOSHA1\",\n            dependencies: []\n        ),\n        .target(\n            name: \"CNIOOpenBSD\",\n            dependencies: []\n        ),\n        .target(\n            name: \"CNIOLinux\",\n            dependencies: [],\n            cSettings: [\n                .define(\"_GNU_SOURCE\")\n            ]\n        ),\n        .target(\n            name: \"CNIODarwin\",\n            dependencies: [],\n            cSettings: [\n                .define(\"__APPLE_USE_RFC_3542\")\n            ]\n        ),\n        .target(\n            name: \"CNIOWindows\",\n            dependencies: []\n        ),\n        .target(\n            name: \"CNIOWASI\",\n            dependencies: []\n        ),\n        .target(\n            name: \"NIOConcurrencyHelpers\",\n            dependencies: [\n                \"CNIOAtomics\"\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOHTTP1\",\n            dependencies: [\n                .target(name: \"NIO\", condition: .when(platforms: historicalNIOPosixDependencyRequired)),\n                \"NIOCore\",\n                \"NIOConcurrencyHelpers\",\n                \"CNIOLLHTTP\",\n                swiftCollections,\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOWebSocket\",\n            dependencies: [\n                .target(name: \"NIO\", condition: .when(platforms: historicalNIOPosixDependencyRequired)),\n                \"NIOCore\",\n                \"NIOHTTP1\",\n                \"CNIOSHA1\",\n                \"_NIOBase64\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"CNIOLLHTTP\",\n            cSettings: [\n                .define(\"_GNU_SOURCE\"),\n                .define(\"LLHTTP_STRICT_MODE\"),\n            ]\n        ),\n        .target(\n            name: \"NIOTLS\",\n            dependencies: [\n                .target(name: \"NIO\", condition: .when(platforms: historicalNIOPosixDependencyRequired)),\n                \"NIOCore\",\n                swiftCollections,\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOTestUtils\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOHTTP1\",\n                swiftAtomics,\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOFS\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOPosix\",\n                \"CNIOLinux\",\n                \"CNIODarwin\",\n                swiftAtomics,\n                swiftCollections,\n                swiftSystem,\n            ],\n            path: \"Sources/NIOFS\",\n            exclude: includePrivacyManifest ? [] : [\"PrivacyInfo.xcprivacy\"],\n            resources: includePrivacyManifest ? [.copy(\"PrivacyInfo.xcprivacy\")] : [],\n            swiftSettings: swiftSettings + [\n                .define(\"ENABLE_MOCKING\", .when(configuration: .debug))\n            ]\n        ),\n        .target(\n            name: \"NIOFSFoundationCompat\",\n            dependencies: [\n                \"NIOFS\",\n                \"NIOFoundationCompat\",\n            ],\n            path: \"Sources/NIOFSFoundationCompat\",\n            swiftSettings: swiftSettings\n        ),\n\n        .target(\n            name: \"_NIOFileSystem\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOPosix\",\n                \"CNIOLinux\",\n                \"CNIODarwin\",\n                swiftAtomics,\n                swiftCollections,\n                swiftSystem,\n            ],\n            path: \"Sources/_NIOFileSystem\",\n            exclude: includePrivacyManifest ? [] : [\"PrivacyInfo.xcprivacy\"],\n            resources: includePrivacyManifest ? [.copy(\"PrivacyInfo.xcprivacy\")] : [],\n            swiftSettings: swiftSettings + [\n                .define(\"ENABLE_MOCKING\", .when(configuration: .debug))\n            ]\n        ),\n        .target(\n            name: \"_NIOFileSystemFoundationCompat\",\n            dependencies: [\n                \"_NIOFileSystem\",\n                \"NIOFoundationCompat\",\n            ],\n            path: \"Sources/_NIOFileSystemFoundationCompat\",\n            swiftSettings: swiftSettings\n        ),\n        .target(\n            name: \"NIOFileSystem\",\n            dependencies: [\"_NIOFileSystem\"],\n            swiftSettings: swiftSettings\n        ),\n\n        // MARK: - Examples\n\n        .executableTarget(\n            name: \"NIOTCPEchoServer\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOTCPEchoClient\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOEchoServer\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOConcurrencyHelpers\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOEchoClient\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOConcurrencyHelpers\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOHTTP1Server\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOHTTP1\",\n                \"NIOConcurrencyHelpers\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOHTTP1Client\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOHTTP1\",\n                \"NIOConcurrencyHelpers\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOChatServer\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOConcurrencyHelpers\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOChatClient\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOConcurrencyHelpers\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOWebSocketServer\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOHTTP1\",\n                \"NIOWebSocket\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOWebSocketClient\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOHTTP1\",\n                \"NIOWebSocket\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOMulticastChat\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOUDPEchoServer\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOUDPEchoClient\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n            ],\n            exclude: [\"README.md\"],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOAsyncAwaitDemo\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOHTTP1\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n\n        // MARK: - Tests\n\n        .executableTarget(\n            name: \"NIOPerformanceTester\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOHTTP1\",\n                \"NIOFoundationCompat\",\n                \"NIOWebSocket\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .executableTarget(\n            name: \"NIOCrashTester\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOHTTP1\",\n                \"NIOWebSocket\",\n                \"NIOFoundationCompat\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOCoreTests\",\n            dependencies: [\n                \"NIOConcurrencyHelpers\",\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOFoundationCompat\",\n                \"NIOTestUtils\",\n                swiftAtomics,\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOEmbeddedTests\",\n            dependencies: [\n                \"NIOConcurrencyHelpers\",\n                \"NIOCore\",\n                \"NIOEmbedded\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOPosixTests\",\n            dependencies: [\n                \"NIOPosix\",\n                \"NIOCore\",\n                \"NIOFoundationCompat\",\n                \"NIOTestUtils\",\n                \"NIOConcurrencyHelpers\",\n                \"NIOEmbedded\",\n                \"CNIOOpenBSD\",\n                \"CNIOLinux\",\n                \"CNIODarwin\",\n                \"NIOTLS\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOConcurrencyHelpersTests\",\n            dependencies: [\n                \"NIOConcurrencyHelpers\",\n                \"NIOCore\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIODataStructuresTests\",\n            dependencies: [\"_NIODataStructures\"],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOBase64Tests\",\n            dependencies: [\"_NIOBase64\"],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOHTTP1Tests\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOPosix\",\n                \"NIOHTTP1\",\n                \"NIOFoundationCompat\",\n                \"NIOTestUtils\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOTLSTests\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOTLS\",\n                \"NIOFoundationCompat\",\n                \"NIOTestUtils\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOWebSocketTests\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOWebSocket\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOTestUtilsTests\",\n            dependencies: [\n                \"NIOTestUtils\",\n                \"NIOCore\",\n                \"NIOEmbedded\",\n                \"NIOPosix\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOFoundationCompatTests\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOFoundationCompat\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOTests\",\n            dependencies: [\"NIO\"],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOSingletonsTests\",\n            dependencies: [\"NIOCore\", \"NIOPosix\"],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOFSTests\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOFS\",\n                swiftAtomics,\n                swiftCollections,\n                swiftSystem,\n            ],\n            swiftSettings: swiftSettings + [\n                .define(\"ENABLE_MOCKING\", .when(configuration: .debug))\n            ]\n        ),\n        .testTarget(\n            name: \"NIOFSIntegrationTests\",\n            dependencies: [\n                \"NIOCore\",\n                \"NIOPosix\",\n                \"NIOFS\",\n                \"NIOFoundationCompat\",\n            ],\n            exclude: [\n                // Contains known files and directory structures used\n                // for the integration tests. Exclude the whole tree from\n                // the build.\n                \"Test Data\"\n            ],\n            swiftSettings: swiftSettings\n        ),\n        .testTarget(\n            name: \"NIOFSFoundationCompatTests\",\n            dependencies: [\n                \"NIOFS\",\n                \"NIOFSFoundationCompat\",\n            ],\n            swiftSettings: swiftSettings\n        ),\n    ]\n)\n\nif Context.environment[\"SWIFTCI_USE_LOCAL_DEPS\"] == nil {\n    package.dependencies += [\n        .package(url: \"https://github.com/apple/swift-atomics.git\", from: \"1.1.0\"),\n        .package(url: \"https://github.com/apple/swift-collections.git\", from: \"1.1.0\"),\n        .package(url: \"https://github.com/apple/swift-system.git\", from: \"1.4.0\"),\n    ]\n} else {\n    package.dependencies += [\n        .package(path: \"../swift-atomics\"),\n        .package(path: \"../swift-collections\"),\n        .package(path: \"../swift-system\"),\n    ]\n}\n\n// ---    STANDARD CROSS-REPO SETTINGS DO NOT EDIT   --- //\nfor target in package.targets {\n    switch target.type {\n    case .regular, .test, .executable:\n        var settings = target.swiftSettings ?? []\n        // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md\n        settings.append(.enableUpcomingFeature(\"MemberImportVisibility\"))\n        target.swiftSettings = settings\n    case .macro, .plugin, .system, .binary:\n        ()  // not applicable\n    @unknown default:\n        ()  // we don't know what to do here, do nothing\n    }\n}\n// --- END: STANDARD CROSS-REPO SETTINGS DO NOT EDIT --- //\n"
  },
  {
    "path": "README.md",
    "content": "[![sswg:graduated|104x20](https://img.shields.io/badge/sswg-graduated-green.svg)](https://github.com/swift-server/sswg/blob/main/process/incubation.md#graduated-level)\n\n# SwiftNIO\n\nSwiftNIO is a cross-platform asynchronous event-driven network application framework\nfor rapid development of maintainable high performance protocol servers & clients.\n\nIt's like [Netty](https://netty.io), but written for Swift.\n\n### Repository organization\n\nThe SwiftNIO project is split across multiple repositories:\n\nRepository | NIO 2\n--- | ---\n[https://github.com/apple/swift-nio][repo-nio] <br> SwiftNIO core | `from: \"2.0.0\"`\n[https://github.com/apple/swift-nio-ssl][repo-nio-ssl] <br> TLS (SSL) support | `from: \"2.0.0\"`\n[https://github.com/apple/swift-nio-http2][repo-nio-http2]<br> HTTP/2 support | `from: \"1.0.0\"`\n[https://github.com/apple/swift-nio-extras][repo-nio-extras] <br>useful additions around SwiftNIO | `from: \"1.0.0\"`\n[https://github.com/apple/swift-nio-transport-services][repo-nio-transport-services] <br> first-class support for macOS, iOS, tvOS, and watchOS | `from: \"1.0.0\"`\n[https://github.com/apple/swift-nio-ssh][repo-nio-ssh] <br> SSH support | `.upToNextMinor(from: \"0.2.0\")`\n\nWithin this repository we have a number of products that provide different functionality. This package contains the following products:\n\n- `NIO`. This is an umbrella module exporting `NIOCore`, `NIOEmbedded` and `NIOPosix`.\n- `NIOCore`. This provides the core abstractions and types for using SwiftNIO (see [\"Conceptual Overview\"](#conceptual-overview) for more details). Most NIO extension projects that provide things like new [`EventLoop`s][el] and [`Channel`s][c] or new protocol implementations should only need to depend on `NIOCore`.\n- `NIOPosix`. This provides the primary [`EventLoopGroup`], [`EventLoop`][el], and [`Channel`s][c] for use on POSIX-based systems. This is our high performance core I/O layer. In general, this should only be imported by projects that plan to do some actual I/O, such as high-level protocol implementations or applications.\n- `NIOEmbedded`. This provides [`EmbeddedChannel`][ec] and [`EmbeddedEventLoop`][eel], implementations of the `NIOCore` abstractions that provide fine-grained control over their execution. These are most often used for testing, but can also be used to drive protocol implementations in a way that is decoupled from networking altogether.\n- `NIOConcurrencyHelpers`. This provides a few low-level concurrency primitives that are used by NIO implementations, such as locks and atomics.\n- `NIOFoundationCompat`. This extends a number of NIO types for better interoperation with Foundation data types. If you are working with Foundation data types such as `Data`, you should import this.\n- `NIOTLS`. This provides a few common abstraction types for working with multiple TLS implementations. Note that this doesn't provide TLS itself: please investigate [swift-nio-ssl][repo-nio-ssl] and [swift-nio-transport-services][repo-nio-transport-services] for concrete implementations.\n- `NIOHTTP1`. This provides a low-level HTTP/1.1 protocol implementation.\n- `NIOWebSocket`. This provides a low-level WebSocket protocol implementation.\n- `NIOTestUtils`. This provides a number of helpers for testing projects that use SwiftNIO.\n- `_NIOFileSystem`. This provides `async` APIs for interacting with the file system.\n\n### Protocol Implementations\n\nBelow you can find a list of a few protocol implementations that are done with SwiftNIO. This is a non-exhaustive list of protocols that are either part of the SwiftNIO project or are accepted into the [SSWG](https://swift.org/server)'s incubation process. All of the libraries listed below do all of their I/O in a non-blocking fashion using SwiftNIO.\n\n#### Low-level protocol implementations\n\nLow-level protocol implementations are often a collection of [`ChannelHandler`][ch]s that implement a protocol but still require the user to have a good understanding of SwiftNIO. Often, low-level protocol implementations will then be wrapped in high-level libraries with a nicer, more user-friendly API.\n\nProtocol | Client<br />(Sends requests) | Server<br />(Responds to requests) | Repository | Module | Comment\n--- |  --- | --- | --- | --- | ---\nHTTP/1 | ✅| ✅ | [apple/swift-nio](https://github.com/apple/swift-nio) | [`NIOHTTP1`][nioh1] | official NIO project\nHTTP/2 | ✅| ✅ | [apple/swift-nio-http2](https://github.com/apple/swift-nio-http2) | [`NIOHTTP2`][nioh2] | official NIO project\nWebSocket | ✅| ✅ | [apple/swift-nio](https://github.com/apple/swift-nio) | [`NIOWebSocket`][niows] | official NIO project\nTLS | ✅ | ✅ | [apple/swift-nio-ssl](https://github.com/apple/swift-nio-ssl) | [`NIOSSL`][niossl] | official NIO project\nSSH | ✅ | ✅ | [apple/swift-nio-ssh][repo-nio-ssh] | [`NIOSSH`][niossh] | official NIO project\n\n\n#### High-level implementations\n\nHigh-level implementations are usually libraries that come with an API that doesn't expose SwiftNIO's [`ChannelPipeline`][cp] and can therefore be used with very little (or no) SwiftNIO-specific knowledge. The implementations listed below do still do all of their I/O in SwiftNIO and integrate really well with the SwiftNIO ecosystem.\n\nProtocol | Client<br />(Sends requests) | Server<br />(Responds to requests) | Repository | Module | Comment\n--- |  --- | --- | --- | --- | ---\nHTTP | ✅| ❌ | [swift-server/async-http-client](https://github.com/swift-server/async-http-client) | `AsyncHTTPClient` | SSWG community project\ngRPC | ✅| ✅ | [grpc/grpc-swift](https://github.com/grpc/grpc-swift) | `GRPC` | also offers a low-level API; SSWG community project\nAPNS | ✅ | ❌ | [swift-server-community/APNSwift](https://github.com/swift-server-community/APNSwift) | `APNSwift` | SSWG community project\nPostgreSQL | ✅ | ❌ | [vapor/postgres-nio](https://github.com/vapor/postgres-nio) | `PostgresNIO` | SSWG community project\nRedis | ✅ | ❌ | [swift-server/RediStack](https://github.com/swift-server/RediStack) | `RediStack` | SSWG community project\n\n### Supported Versions\n\n### SwiftNIO 2\n\nThis is the current version of SwiftNIO and will be supported for the foreseeable future.\n\n### Swift Versions\n\nWe commit to support the most recently released Swift version and the last two minor releases before that unless this is impossible to do in one codebase.\nIn addition checks are run against the latest beta release (if any) as well as the nightly Swift builds and the intent is that these should pass.\n\nThe minimum Swift version supported by SwiftNIO releases are detailed below:\n\nSwiftNIO            | Minimum Swift Version\n--------------------|----------------------\n`2.0.0 ..< 2.30.0`  | 5.0\n`2.30.0 ..< 2.40.0` | 5.2\n`2.40.0 ..< 2.43.0` | 5.4\n`2.43.0 ..< 2.51.0` | 5.5.2\n`2.51.0 ..< 2.60.0` | 5.6\n`2.60.0 ..< 2.65.0` | 5.7\n`2.65.0 ..< 2.76.0` | 5.8\n`2.76.0 ..< 2.83.0` | 5.9\n`2.83.0 ..< 2.87.0` | 5.10\n`2.87.0 ...       ` | 6.0\n\n### SwiftNIO 1\nSwiftNIO 1 is considered end of life - it is strongly recommended that you move to a newer version.  The Core NIO team does not actively work on this version.  No new features will be added to this version but PRs which fix bugs or security vulnerabilities will be accepted until the end of May 2022.\n\nIf you have a SwiftNIO 1 application or library that you would like to migrate to SwiftNIO 2, please check out the [migration guide](docs/migration-guide-NIO1-to-NIO2.md) we prepared for you.\n\nThe latest released SwiftNIO 1 version supports Swift 4.0, 4.1, 4.2, and 5.0.\n\n### Supported Platforms\n\nSwiftNIO aims to support all of the platforms where Swift is supported. Currently, it is developed and tested on macOS and Linux, and is known to support the following operating system versions:\n\n* Ubuntu 18.04+\n* macOS 10.9+, iOS 7+; (macOS 10.14+, iOS 12+, tvOS 12+ or watchOS 6+ with [swift-nio-transport-services][repo-nio-transport-services])\n\nSwiftNIO has experimental support on OpenBSD for all SwiftNIO libraries _except_ for `_NIOFileSystem`, which is not yet supported. You can use all other SwiftNIO libraries on OpenBSD by adding them as dependencies in `Package.swift`.\n\n### Compatibility\n\nSwiftNIO follows [SemVer 2.0.0](https://semver.org/#semantic-versioning-200) with a separate document declaring [SwiftNIO's Public API](docs/public-api.md).\n\nWhat this means for you is that you should depend on SwiftNIO with a version range that covers everything from the minimum SwiftNIO version you require up to the next major version.\nIn SwiftPM that can be easily done specifying for example `from: \"2.0.0\"` meaning that you support SwiftNIO in every version starting from 2.0.0 up to (excluding) 3.0.0.\nSemVer and SwiftNIO's Public API guarantees should result in a working program without having to worry about testing every single version for compatibility.\n\n\n## Conceptual Overview\n\nSwiftNIO is fundamentally a low-level tool for building high-performance networking applications in Swift. It particularly targets those use-cases where using a \"thread-per-connection\" model of concurrency is inefficient or untenable. This is a common limitation when building servers that use a large number of relatively low-utilization connections, such as HTTP servers.\n\nTo achieve its goals, SwiftNIO extensively uses \"non-blocking I/O\": hence the name! Non-blocking I/O differs from the more common blocking I/O model because the application does not wait for data to be sent to or received from the network: instead, SwiftNIO asks for the kernel to notify it when I/O operations can be performed without waiting.\n\nSwiftNIO does not aim to provide high-level solutions like, for example, web frameworks do. Instead, SwiftNIO is focused on providing the low-level building blocks for these higher-level applications. When it comes to building a web application, most users will not want to use SwiftNIO directly: instead, they'll want to use one of the many great web frameworks available in the Swift ecosystem. Those web frameworks, however, may choose to use SwiftNIO under the covers to provide their networking support.\n\nThe following sections will describe the low-level tools that SwiftNIO provides, and provide a quick overview of how to work with them. If you feel comfortable with these concepts, then you can skip right ahead to the other sections of this README.\n\n### Basic Architecture\n\nThe basic building blocks of SwiftNIO are the following 8 types of objects:\n\n- [`EventLoopGroup`][elg], a protocol, provided by `NIOCore`.\n- [`EventLoop`][el], a protocol, provided by `NIOCore`.\n- [`Channel`][c], a protocol, provided by `NIOCore`.\n- [`ChannelHandler`][ch], a protocol, provided by `NIOCore`.\n- `Bootstrap`, several related structures, provided by `NIOCore`.\n- [`ByteBuffer`][bb], a struct, provided by `NIOCore`.\n- [`EventLoopFuture`][elf], a generic class, provided by `NIOCore`.\n- [`EventLoopPromise`][elp], a generic struct, provided by `NIOCore`.\n\nAll SwiftNIO applications are ultimately constructed of these various components.\n\n#### EventLoops and EventLoopGroups\n\nThe basic I/O primitive of SwiftNIO is the event loop. The event loop is an object that waits for events (usually I/O related events, such as \"data received\") to happen and then fires some kind of callback when they do. In almost all SwiftNIO applications there will be relatively few event loops: usually only one or two per CPU core the application wants to use. Generally speaking, event loops run for the entire lifetime of your application, spinning in an endless loop dispatching events.\n\nEvent loops are gathered together into event loop *groups*. These groups provide a mechanism to distribute work around the event loops. For example, when listening for inbound connections the listening socket will be registered on one event loop. However, we don't want all connections that are accepted on that listening socket to be registered with the same event loop, as that would potentially overload one event loop while leaving the others empty. For that reason, the event loop group provides the ability to spread load across multiple event loops.\n\nIn SwiftNIO today there is one [`EventLoopGroup`][elg] implementation, and two [`EventLoop`][el] implementations. For production applications there is the [`MultiThreadedEventLoopGroup`][mtelg], an [`EventLoopGroup`][elg] that creates a number of threads (using the POSIX [`pthreads`][pthreads] library) and places one `SelectableEventLoop` on each one. The `SelectableEventLoop` is an event loop that uses a selector (either [`kqueue`][kqueue] or [`epoll`][epoll] depending on the target system) to manage I/O events from file descriptors and to dispatch work. These [`EventLoop`s][el] and [`EventLoopGroup`s][elg] are provided by the `NIOPosix` module. Additionally, there is the [`EmbeddedEventLoop`][eel], which is a dummy event loop that is used primarily for testing purposes, provided by the `NIOEmbedded` module.\n\n[`EventLoop`][el]s have a number of important properties. Most vitally, they are the way all work gets done in SwiftNIO applications. In order to ensure thread-safety, any work that wants to be done on almost any of the other objects in SwiftNIO must be dispatched via an [`EventLoop`][el]. [`EventLoop`][el] objects own almost all the other objects in a SwiftNIO application, and understanding their execution model is critical for building high-performance SwiftNIO applications.\n\n#### Channels, Channel Handlers, Channel Pipelines, and Channel Contexts\n\nWhile [`EventLoop`][el]s are critical to the way SwiftNIO works, most users will not interact with them substantially beyond asking them to create [`EventLoopPromise`][elp]s and to schedule work. The parts of a SwiftNIO application most users will spend the most time interacting with are [`Channel`][c]s and [`ChannelHandler`][ch]s.\n\nAlmost every file descriptor that a user interacts with in a SwiftNIO program is associated with a single [`Channel`][c]. The [`Channel`][c] owns this file descriptor, and is responsible for managing its lifetime. It is also responsible for processing inbound and outbound events on that file descriptor: whenever the event loop has an event that corresponds to a file descriptor, it will notify the [`Channel`][c] that owns that file descriptor.\n\n[`Channel`][c]s by themselves, however, are not useful. After all, it is a rare application that doesn't want to do anything with the data it sends or receives on a socket! So the other important part of the [`Channel`][c] is the [`ChannelPipeline`][cp].\n\nA [`ChannelPipeline`][cp] is a sequence of objects, called [`ChannelHandler`][ch]s, that process events on a [`Channel`][c]. The [`ChannelHandler`][ch]s process these events one after another, in order, mutating and transforming events as they go. This can be thought of as a data processing pipeline; hence the name [`ChannelPipeline`][cp].\n\nAll [`ChannelHandler`][ch]s are either Inbound or Outbound handlers, or both. Inbound handlers process \"inbound\" events: events like reading data from a socket, reading socket close, or other kinds of events initiated by remote peers. Outbound handlers process \"outbound\" events, such as writes, connection attempts, and local socket closes.\n\nEach handler processes the events in order. For example, read events are passed from the front of the pipeline to the back, one handler at a time, while write events are passed from the back of the pipeline to the front. Each handler may, at any time, generate either inbound or outbound events that will be sent to the next handler in whichever direction is appropriate. This allows handlers to split up reads, coalesce writes, delay connection attempts, and generally perform arbitrary transformations of events.\n\nIn general, [`ChannelHandler`][ch]s are designed to be highly re-usable components. This means they tend to be designed to be as small as possible, performing one specific data transformation. This allows handlers to be composed together in novel and flexible ways, which helps with code reuse and encapsulation.\n\n[`ChannelHandler`][ch]s are able to keep track of where they are in a [`ChannelPipeline`][cp] by using a [`ChannelHandlerContext`][chc]. These objects contain references to the previous and next channel handler in the pipeline, ensuring that it is always possible for a [`ChannelHandler`][ch] to emit events while it remains in a pipeline.\n\nSwiftNIO ships with many [`ChannelHandler`][ch]s built in that provide useful functionality, such as HTTP parsing. In addition, high-performance applications will want to provide as much of their logic as possible in [`ChannelHandler`][ch]s, as it helps avoid problems with context switching.\n\nAdditionally, SwiftNIO ships with a few [`Channel`][c] implementations. In particular, it ships with `ServerSocketChannel`, a [`Channel`][c] for sockets that accept inbound connections; `SocketChannel`, a [`Channel`][c] for TCP connections; and `DatagramChannel`, a [`Channel`][c] for UDP sockets. All of these are provided by the `NIOPosix` module. It also provides [`EmbeddedChannel`][ec], a [`Channel`][c] primarily used for testing, provided by the `NIOEmbedded` module.\n\n##### A Note on Blocking\n\nOne of the important notes about [`ChannelPipeline`][cp]s is that they are thread-safe. This is very important for writing SwiftNIO applications, as it allows you to write much simpler [`ChannelHandler`][ch]s in the knowledge that they will not require synchronization.\n\nHowever, this is achieved by dispatching all code on the [`ChannelPipeline`][cp] on the same thread as the [`EventLoop`][el]. This means that, as a general rule, [`ChannelHandler`][ch]s **must not** call blocking code without dispatching it to a background thread. If a [`ChannelHandler`][ch] blocks for any reason, all [`Channel`][c]s attached to the parent [`EventLoop`][el] will be unable to progress until the blocking call completes.\n\nThis is a common concern while writing SwiftNIO applications. If it is useful to write code in a blocking style, it is highly recommended that you dispatch work to a different thread when you're done with it in your pipeline.\n\n#### Bootstrap\n\nWhile it is possible to configure and register [`Channel`][c]s with [`EventLoop`][el]s directly, it is generally more useful to have a higher-level abstraction to handle this work.\n\nFor this reason, SwiftNIO ships a number of `Bootstrap` objects whose purpose is to streamline the creation of channels. Some `Bootstrap` objects also provide other functionality, such as support for Happy Eyeballs for making TCP connection attempts.\n\nCurrently SwiftNIO ships with three `Bootstrap` objects in the `NIOPosix` module: [`ServerBootstrap`][sbootstrap], for bootstrapping listening channels; [`ClientBootstrap`][cbootstrap], for bootstrapping client TCP channels; and [`DatagramBootstrap`][dbootstrap] for bootstrapping UDP channels.\n\n#### ByteBuffer\n\nThe majority of the work in a SwiftNIO application involves shuffling buffers of bytes around. At the very least, data is sent and received to and from the network in the form of buffers of bytes. For this reason it's very important to have a high-performance data structure that is optimized for the kind of work SwiftNIO applications perform.\n\nFor this reason, SwiftNIO provides [`ByteBuffer`][bb], a fast copy-on-write byte buffer that forms a key building block of most SwiftNIO applications. This type is provided by the `NIOCore` module.\n\n[`ByteBuffer`][bb] provides a number of useful features, and in addition provides a number of hooks to use it in an \"unsafe\" mode. This turns off bounds checking for improved performance, at the cost of potentially opening your application up to memory correctness problems.\n\nIn general, it is highly recommended that you use the [`ByteBuffer`][bb] in its safe mode at all times.\n\nFor more details on the API of [`ByteBuffer`][bb], please see our API documentation, linked below.\n\n#### Promises and Futures\n\nOne major difference between writing concurrent code and writing synchronous code is that not all actions will complete immediately. For example, when you write data on a channel, it is possible that the event loop will not be able to immediately flush that write out to the network. For this reason, SwiftNIO provides [`EventLoopPromise<T>`][elp] and [`EventLoopFuture<T>`][elf] to manage operations that complete *asynchronously*. These types are provided by the `NIOCore` module.\n\nAn [`EventLoopFuture<T>`][elf] is essentially a container for the return value of a function that will be populated *at some time in the future*. Each [`EventLoopFuture<T>`][elf] has a corresponding [`EventLoopPromise<T>`][elp], which is the object that the result will be put into. When the promise is succeeded, the future will be fulfilled.\n\nIf you had to poll the future to detect when it completed that would be quite inefficient, so [`EventLoopFuture<T>`][elf] is designed to have managed callbacks. Essentially, you can chain callbacks off the future that will be executed when a result is available. The [`EventLoopFuture<T>`][elf] will even carefully arrange the scheduling to ensure that these callbacks always execute on the event loop that initially created the promise, which helps ensure that you don't need too much synchronization around [`EventLoopFuture<T>`][elf] callbacks.\n\nAnother important topic for consideration is the difference between how the promise passed to `close` works as opposed to `closeFuture` on a [`Channel`][c]. For example, the promise passed into `close` will succeed after the [`Channel`][c] is closed down but before the [`ChannelPipeline`][cp] is completely cleared out. This will allow you to take action on the [`ChannelPipeline`][cp] before it is completely cleared out, if needed. If it is desired to wait for the [`Channel`][c] to close down and the [`ChannelPipeline`][cp] to be cleared out without any further action, then the better option would be to wait for the `closeFuture` to succeed.\n\nThere are several functions for applying callbacks to [`EventLoopFuture<T>`][elf], depending on how and when you want them to execute. Details of these functions is left to the API documentation.\n\n### Design Philosophy\n\nSwiftNIO is designed to be a powerful tool for building networked applications and frameworks, but it is not intended to be the perfect solution for all levels of abstraction. SwiftNIO is tightly focused on providing the basic I/O primitives and protocol implementations at low levels of abstraction, leaving more expressive but slower abstractions to the wider community to build. The intention is that SwiftNIO will be a building block for server-side applications, not necessarily the framework those applications will use directly.\n\nApplications that need extremely high performance from their networking stack may choose to use SwiftNIO directly in order to reduce the overhead of their abstractions. These applications should be able to maintain extremely high performance with relatively little maintenance cost. SwiftNIO also focuses on providing useful abstractions for this use-case, such that extremely high performance network servers can be built directly.\n\nThe core SwiftNIO repository will contain a few extremely important protocol implementations, such as HTTP, directly in tree. However, we believe that most protocol implementations should be decoupled from the release cycle of the underlying networking stack, as the release cadence is likely to be very different (either much faster or much slower). For this reason, we actively encourage the community to develop and maintain their protocol implementations out-of-tree. Indeed, some first-party SwiftNIO protocol implementations, including our TLS and HTTP/2 bindings, are developed out-of-tree!\n\n## Documentation\n\n - [API documentation](https://swiftpackageindex.com/apple/swift-nio/documentation/nio)\n\n## Example Usage\n\nThere are currently several example projects that demonstrate how to use SwiftNIO.\n\n- **chat client** https://github.com/apple/swift-nio/tree/main/Sources/NIOChatClient\n- **chat server** https://github.com/apple/swift-nio/tree/main/Sources/NIOChatServer\n- **echo client** https://github.com/apple/swift-nio/tree/main/Sources/NIOEchoClient\n- **echo server** https://github.com/apple/swift-nio/tree/main/Sources/NIOEchoServer\n- **UDP echo client** https://github.com/apple/swift-nio/tree/main/Sources/NIOUDPEchoClient\n- **UDP echo server** https://github.com/apple/swift-nio/tree/main/Sources/NIOUDPEchoServer\n- **HTTP client** https://github.com/apple/swift-nio/tree/main/Sources/NIOHTTP1Client\n- **HTTP server** https://github.com/apple/swift-nio/tree/main/Sources/NIOHTTP1Server\n- **WebSocket client** https://github.com/apple/swift-nio/tree/main/Sources/NIOWebSocketClient\n- **WebSocket server** https://github.com/apple/swift-nio/tree/main/Sources/NIOWebSocketServer\n\nTo build & run them, run following command, replace TARGET_NAME with the folder name under `./Sources`\n\n```bash\nswift run TARGET_NAME\n```\n\nFor example, to run NIOHTTP1Server, run following command:\n\n```bash\nswift run NIOHTTP1Server\n```\n\n## Getting Started\n\nSwiftNIO primarily uses [SwiftPM](https://swift.org/package-manager/) as its build tool, so we recommend using that as well. If you want to depend on SwiftNIO in your own project, it's as simple as adding a `dependencies` clause to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/apple/swift-nio.git\", from: \"2.0.0\")\n]\n```\n\nand then adding the appropriate SwiftNIO module(s) to your target dependencies.\nThe syntax for adding target dependencies differs slightly between Swift\nversions. For example, if you want to depend on the `NIOCore`, `NIOPosix` and\n`NIOHTTP1` modules, specify the following dependencies:\n\n#### Swift 5.4 and newer (`swift-tools-version:5.4`)\n\n    dependencies: [.product(name: \"NIOCore\", package: \"swift-nio\"),\n                   .product(name: \"NIOPosix\", package: \"swift-nio\"),\n                   .product(name: \"NIOHTTP1\", package: \"swift-nio\")]\n\n### Using Xcode Package support\n\nIf your project is set up as an Xcode project and you're using Xcode 11+, you can add SwiftNIO as a dependency to your\nXcode project by clicking File -> Swift Packages -> Add Package Dependency. In the upcoming dialog, please enter\n`https://github.com/apple/swift-nio.git` and click Next twice. Finally, select the targets you are planning to use (for\nexample `NIOCore`, `NIOHTTP1`, and `NIOFoundationCompat`) and click finish. Now will be able to `import NIOCore` (as well as all\nthe other targets you have selected) in your project.\n\nTo work on SwiftNIO itself, or to investigate some of the demonstration applications, you can clone the repository directly and use SwiftPM to help build it. For example, you can run the following commands to compile and run the example echo server:\n\n```bash\nswift build\nswift test\nswift run NIOEchoServer\n```\n\nTo verify that it is working, you can use another shell to attempt to connect to it:\n\n```bash\necho \"Hello SwiftNIO\" | nc localhost 9999\n```\n\nIf all goes well, you'll see the message echoed back to you.\n\nTo work on SwiftNIO in Xcode, you can just open the `Package.swift`\nfile in Xcode and use Xcode's support for SwiftPM Packages.\n\n## Developing SwiftNIO\n\n*Note*: This section is only relevant if you would like to develop SwiftNIO yourself. You can ignore the information here if you just want to use SwiftNIO as a SwiftPM package.\n\nFor the most part, SwiftNIO development is as straightforward as any other SwiftPM project. With that said, we do have a few processes that are worth understanding before you contribute. For details, please see `CONTRIBUTING.md` in this repository.\n\n### Prerequisites\n\nSwiftNIO's `main` branch is the development branch for the next releases of SwiftNIO 2, it's Swift 5-only.\n\nTo be able to compile and run SwiftNIO and the integration tests, you need to\nhave a few prerequisites installed on your system.\n\n#### macOS\n\n- Xcode 11.4 or newer, Xcode 12 recommended.\n\n### Linux\n\n- Swift 5.7 or newer from [swift.org/download](https://swift.org/download/#releases). We always recommend to use the latest released version.\n- netcat (for integration tests only)\n- lsof (for integration tests only)\n- shasum (for integration tests only)\n\n#### Ubuntu 18.04\n\n```\n# install swift tarball from https://swift.org/downloads\napt-get install -y git curl libatomic1 libxml2 netcat-openbsd lsof perl\n```\n\n\n### Fedora 28+\n\n```\ndnf install swift-lang /usr/bin/nc /usr/bin/lsof /usr/bin/shasum\n```\n\n[ch]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/channelhandler\n[c]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/channel\n[chc]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/channelhandlercontext\n[ec]: https://swiftpackageindex.com/apple/swift-nio/documentation/nioembedded/embeddedchannel\n[el]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/eventloop\n[eel]: https://swiftpackageindex.com/apple/swift-nio/documentation/nioembedded/embeddedeventloop\n[elg]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/eventloopgroup\n[bb]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/bytebuffer\n[elf]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/eventloopfuture\n[elp]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/eventlooppromise\n[cp]: https://swiftpackageindex.com/apple/swift-nio/documentation/niocore/channelpipeline\n[sbootstrap]: https://swiftpackageindex.com/apple/swift-nio/documentation/nioposix/serverbootstrap\n[cbootstrap]: https://swiftpackageindex.com/apple/swift-nio/documentation/nioposix/clientbootstrap\n[dbootstrap]: https://swiftpackageindex.com/apple/swift-nio/documentation/nioposix/datagrambootstrap\n[mtelg]: https://swiftpackageindex.com/apple/swift-nio/documentation/nioposix/multithreadedeventloopgroup\n[nioh1]: https://swiftpackageindex.com/apple/swift-nio/documentation/niohttp1\n[nioh2]: https://swiftpackageindex.com/apple/swift-nio-http2/documentation/niohttp2\n[niows]: https://swiftpackageindex.com/apple/swift-nio/documentation/niowebsocket\n[niossl]: https://swiftpackageindex.com/apple/swift-nio-ssl/documentation/niossl\n[niossh]: https://swiftpackageindex.com/apple/swift-nio-ssh/documentation/niossh\n[pthreads]: https://en.wikipedia.org/wiki/POSIX_Threads\n[kqueue]: https://en.wikipedia.org/wiki/Kqueue\n[epoll]: https://en.wikipedia.org/wiki/Epoll\n[repo-nio]: https://github.com/apple/swift-nio\n[repo-nio-extras]: https://github.com/apple/swift-nio-extras\n[repo-nio-http2]: https://github.com/apple/swift-nio-http2\n[repo-nio-ssl]: https://github.com/apple/swift-nio-ssl\n[repo-nio-transport-services]: https://github.com/apple/swift-nio-transport-services\n[repo-nio-ssh]: https://github.com/apple/swift-nio-ssh\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security\n\nThis document specifies the security process for the SwiftNIO project.\n\n## Versions\n\nThe SwiftNIO core team will address security vulnerabilities in all SwiftNIO 2.x\nversions. Since support for some Swift versions was dropped during the lifetime of\nSwiftNIO 2, patch releases will be created for the last supported SwiftNIO versions\nthat supported older Swift versions.\nIf a hypothetical security vulnerability was introduced in 2.10.0, then SwiftNIO core\nteam would create the following patch releases:\n\n* NIO 2.29. + plus next patch release to address the issue for projects that support\n  Swift 5.0 and 5.1\n* NIO 2.39. + plus next patch release to address the issue for projects that support\n  Swift 5.2 and 5.3\n* NIO 2.42. + plus next patch release to address the issue for projects that support\n  Swift 5.4 and later\n* NIO 2.50. + plus next patch release to address the issue for projects that support\n  Swift 5.5.2 and later\n* NIO 2.59. + plus next patch release to address the issue for projects that support\n  Swift 5.6 and later\n* mainline + plus next patch release to address the issue for projects that support\n  Swift 5.7 and later\n\nSwiftNIO 1.x is considered end of life and will not receive any security patches.\n\n## Disclosures\n\nIf you believe that you have discovered a security or privacy vulnerability in our open source software, please report it to us using the GitHub private vulnerability feature. Reports should include specific product and software version(s) that you believe are affected; a technical description of the behavior that you observed and the behavior that you expected; the steps required to reproduce the issue; and a proof of concept or exploit.\n\nThe project team will do their best to acknowledge receiving all security reports within 7 days of submission. This initial acknowledgment is neither acceptance nor rejection of your report. The project team may come back to you with further questions or invite you to collaborate while working through the details of your report.\n\nKeep these additional guidelines in mind when submitting your report:\n\n* Reports concerning known, publicly disclosed CVEs can be submitted as normal issues to this project.\n* Output from automated security scans or fuzzers MUST include additional context demonstrating the vulnerability with a proof of concept or working exploit.\n* Application crashes due to malformed inputs are typically not treated as security vulnerabilities, unless they are shown to also impact other processes on the system.\n\n\nWhile we welcome reports for open source software projects, they are not eligible for Apple Security Bounties.\n"
  },
  {
    "path": "Snippets/NIOFileSystemTour.swift",
    "content": "// snippet.hide\n\nimport NIOCore\nimport _NIOFileSystem\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfunc main() async throws {\n    // snippet.show\n\n    // NIOFileSystem provides access to the local file system via the FileSystem\n    // type which is available as a global shared instance.\n    let fileSystem = FileSystem.shared\n\n    // Files can be inspected by using 'info':\n    if let info = try await fileSystem.info(forFileAt: \"/Users/hal9000/demise-of-dave.txt\") {\n        print(\"demise-of-dave.txt has type '\\(info.type)'\")\n    } else {\n        print(\"demise-of-dave.txt doesn't exist\")\n    }\n\n    // Let's find out what's in that file.\n    do {\n        // Reading a whole file requires a limit. If the file is larger than the limit\n        // then an error is thrown. This avoids accidentally consuming too much memory\n        // if the file is larger than expected.\n        let plan = try await ByteBuffer(\n            contentsOf: \"/Users/hal9000/demise-of-dave.txt\",\n            maximumSizeAllowed: .mebibytes(1)\n        )\n        print(\"Plan for Dave's demise:\", String(decoding: plan.readableBytesView, as: UTF8.self))\n    } catch let error as FileSystemError where error.code == .notFound {\n        // All errors thrown by the module have type FileSystemError (or\n        // Swift.CancellationError). It looks like the file doesn't exist. Let's\n        // create it now.\n        //\n        // The code above for reading the file is shorthand for opening the file in\n        // read-only mode and then reading its contents. The FileSystemProtocol\n        // has a few different 'withFileHandle' methods for opening a file in different\n        // modes. Let's open a file for writing, creating it at the same time.\n        try await fileSystem.withFileHandle(\n            forWritingAt: \"/Users/hal9000/demise-of-dave.txt\",\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let plan = ByteBuffer(string: \"TODO...\")\n            try await file.write(contentsOf: plan.readableBytesView, toAbsoluteOffset: 0)\n        }\n    }\n\n    // Directories can be opened like regular files but they cannot be read from or\n    // written to. However, their contents can be listed:\n    let path: FilePath? = try await fileSystem.withDirectoryHandle(atPath: \"/Users/hal9000/Music\") { directory in\n        for try await entry in directory.listContents() {\n            if entry.name == \"daisy.mp3\" {\n                // Found it!\n                return entry.path\n            }\n        }\n        // No luck.\n        return nil\n    }\n\n    if let path = path {\n        print(\"Found file at '\\(path)'\")\n    }\n\n    // The file system can also be used to perform the following operations on files\n    // and directories:\n    // - copy,\n    // - remove,\n    // - rename, and\n    // - replace.\n    //\n    // Here's an example of copying a directory:\n    try await fileSystem.copyItem(at: \"/Users/hal9000/Music\", to: \"/Volumes/Tardis/Music\")\n\n    // Symbolic links can also be created (and read with 'destinationOfSymbolicLink(at:)').\n    try await fileSystem.createSymbolicLink(at: \"/Users/hal9000/Backup\", withDestination: \"/Volumes/Tardis\")\n\n    // Opening a symbolic link opens its destination so in most cases there's no\n    // need to read the destination of a symbolic link:\n    try await fileSystem.withDirectoryHandle(atPath: \"/Users/hal9000/Backup\") { directory in\n        // Beyond listing the contents of a directory, the directory handle provides a\n        // number of other functions, many of which are also available on regular file\n        // handles.\n        //\n        // This includes getting information about a file, such as its permissions, last access time,\n        // and last modification time:\n        let info = try await directory.info()\n        print(\"The directory has permissions '\\(info.permissions)'\")\n\n        // Where supported, the extended attributes of a file can also be accessed, read, and modified:\n        for attribute in try await directory.attributeNames() {\n            let value = try await directory.valueForAttribute(attribute)\n            print(\"Extended attribute '\\(attribute)' has value '\\(value)'\")\n        }\n\n        // Once this closure returns the file system will close the directory handle freeing\n        // any resources required to access it such as file descriptors. Handles can also be opened\n        // with the 'openFile' and 'openDirectory' APIs but that places the onus you to close the\n        // handle at an appropriate time to avoid leaking resources.\n    }\n    // snippet.end\n}\n"
  },
  {
    "path": "Sources/CNIOAtomics/include/CNIOAtomics.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#include <stdbool.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define DECLARE_ATOMIC_OPERATIONS(type, name)                                                                                         \\\n  struct catmc_atomic_ ## name;                                                                                                       \\\n                                                                                                                                      \\\n  struct catmc_atomic_ ## name * _Nonnull catmc_atomic_ ## name ## _create(type value);                                               \\\n  void catmc_atomic_ ## name ## _destroy(struct catmc_atomic_ ## name * _Nonnull);                                                    \\\n  bool catmc_atomic_ ## name ## _compare_and_exchange(struct catmc_atomic_ ## name * _Nonnull, type expected, type desired);          \\\n  type catmc_atomic_ ## name ## _add(struct catmc_atomic_ ## name * _Nonnull, type value);                                            \\\n  type catmc_atomic_ ## name ## _sub(struct catmc_atomic_ ## name * _Nonnull, type value);                                            \\\n  type catmc_atomic_ ## name ## _exchange(struct catmc_atomic_ ## name * _Nonnull, type value);                                       \\\n  type catmc_atomic_ ## name ## _load(struct catmc_atomic_ ## name * _Nonnull);                                                       \\\n  void catmc_atomic_ ## name ## _store(struct catmc_atomic_ ## name * _Nonnull, type value);                                          \\\n                                                                                                                                      \\\n  struct catmc_nio_atomic_ ## name {                                                                                                  \\\n    _Atomic type value;                                                                                                               \\\n  };                                                                                                                                  \\\n                                                                                                                                      \\\n  void catmc_nio_atomic_ ## name ## _create_with_existing_storage(struct catmc_nio_atomic_ ## name * _Nonnull, type value);           \\\n  bool catmc_nio_atomic_ ## name ## _compare_and_exchange(struct catmc_nio_atomic_ ## name * _Nonnull, type expected, type desired);  \\\n  type catmc_nio_atomic_ ## name ## _add(struct catmc_nio_atomic_ ## name * _Nonnull, type value);                                    \\\n  type catmc_nio_atomic_ ## name ## _sub(struct catmc_nio_atomic_ ## name * _Nonnull, type value);                                    \\\n  type catmc_nio_atomic_ ## name ## _exchange(struct catmc_nio_atomic_ ## name * _Nonnull, type value);                               \\\n  type catmc_nio_atomic_ ## name ## _load(struct catmc_nio_atomic_ ## name * _Nonnull);                                               \\\n  void catmc_nio_atomic_ ## name ## _store(struct catmc_nio_atomic_ ## name * _Nonnull, type value);                                  \\\n\n#ifdef __cplusplus\nDECLARE_ATOMIC_OPERATIONS(bool, _Bool)\n#else\nDECLARE_ATOMIC_OPERATIONS(_Bool, _Bool)\n#endif\nDECLARE_ATOMIC_OPERATIONS(char, char)\nDECLARE_ATOMIC_OPERATIONS(short, short)\nDECLARE_ATOMIC_OPERATIONS(int, int)\nDECLARE_ATOMIC_OPERATIONS(long, long)\nDECLARE_ATOMIC_OPERATIONS(long long, long_long)\n\nDECLARE_ATOMIC_OPERATIONS(signed char, signed_char)\nDECLARE_ATOMIC_OPERATIONS(signed short, signed_short)\nDECLARE_ATOMIC_OPERATIONS(signed int, signed_int)\nDECLARE_ATOMIC_OPERATIONS(signed long, signed_long)\nDECLARE_ATOMIC_OPERATIONS(signed long long, signed_long_long)\n\nDECLARE_ATOMIC_OPERATIONS(unsigned char, unsigned_char)\nDECLARE_ATOMIC_OPERATIONS(unsigned short, unsigned_short)\nDECLARE_ATOMIC_OPERATIONS(unsigned int, unsigned_int)\nDECLARE_ATOMIC_OPERATIONS(unsigned long, unsigned_long)\nDECLARE_ATOMIC_OPERATIONS(unsigned long long, unsigned_long_long)\n\nDECLARE_ATOMIC_OPERATIONS(int_least8_t, int_least8_t)\nDECLARE_ATOMIC_OPERATIONS(uint_least8_t, uint_least8_t)\n\nDECLARE_ATOMIC_OPERATIONS(int_least16_t, int_least16_t)\nDECLARE_ATOMIC_OPERATIONS(uint_least16_t, uint_least16_t)\n\nDECLARE_ATOMIC_OPERATIONS(int_least32_t, int_least32_t)\nDECLARE_ATOMIC_OPERATIONS(uint_least32_t, uint_least32_t)\n\nDECLARE_ATOMIC_OPERATIONS(int_least64_t, int_least64_t)\nDECLARE_ATOMIC_OPERATIONS(uint_least64_t, uint_least64_t)\n\nDECLARE_ATOMIC_OPERATIONS(intptr_t, intptr_t)\nDECLARE_ATOMIC_OPERATIONS(uintptr_t, uintptr_t)\n\n#undef DECLARE_ATOMIC_OPERATIONS\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "Sources/CNIOAtomics/src/c-atomics.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#include <stdlib.h>\n#include <stdatomic.h>\n#include <stdbool.h>\n#include <inttypes.h>\n#include <stdio.h>\n\n#include \"../include/CNIOAtomics.h\"\n#include \"cpp_magic.h\"\n\n#define MAKE(type) /*\n*/ struct catmc_atomic_##type { /*\n*/     _Atomic type value; /*\n*/ }; /*\n*/ /*\n*/ struct catmc_atomic_##type *catmc_atomic_##type##_create(type value) { /*\n*/     struct catmc_atomic_##type *wrapper = malloc(sizeof(*wrapper)); /*\n*/     atomic_init(&wrapper->value, value); /*\n*/     return wrapper; /*\n*/ } /*\n*/ /*\n*/ void catmc_atomic_##type##_destroy(struct catmc_atomic_##type *wrapper) { /*\n*/     free(wrapper); /*\n*/ } /*\n*/ /*\n*/ bool catmc_atomic_##type##_compare_and_exchange(struct catmc_atomic_##type *wrapper, type expected, type desired) { /*\n*/     type expected_copy = expected; /*\n*/     return atomic_compare_exchange_strong(&wrapper->value, &expected_copy, desired); /*\n*/ } /*\n*/ /*\n*/ type catmc_atomic_##type##_add(struct catmc_atomic_##type *wrapper, type value) { /*\n*/     return atomic_fetch_add_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ type catmc_atomic_##type##_sub(struct catmc_atomic_##type *wrapper, type value) { /*\n*/     return atomic_fetch_sub_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ type catmc_atomic_##type##_exchange(struct catmc_atomic_##type *wrapper, type value) { /*\n*/     return atomic_exchange_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ type catmc_atomic_##type##_load(struct catmc_atomic_##type *wrapper) { /*\n*/     return atomic_load_explicit(&wrapper->value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ void catmc_atomic_##type##_store(struct catmc_atomic_##type *wrapper, type value) { /*\n*/     atomic_store_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ }\n\ntypedef signed char signed_char;\ntypedef signed short signed_short;\ntypedef signed int signed_int;\ntypedef signed long signed_long;\ntypedef signed long long signed_long_long;\ntypedef unsigned char unsigned_char;\ntypedef unsigned short unsigned_short;\ntypedef unsigned int unsigned_int;\ntypedef unsigned long unsigned_long;\ntypedef unsigned long long unsigned_long_long;\ntypedef long long long_long;\n\nMAP(MAKE,EMPTY,\n         bool,\n\t\t          char,          short,          int,          long,          long_long,\n\t\t   signed_char,   signed_short,   signed_int,   signed_long,   signed_long_long,\n\t\t unsigned_char, unsigned_short, unsigned_int, unsigned_long, unsigned_long_long,\n\t\t int_least8_t, uint_least8_t,\n\t\t int_least16_t, uint_least16_t,\n\t\t int_least32_t, uint_least32_t,\n\t\t int_least64_t, uint_least64_t,\n\t\t intptr_t, uintptr_t\n\t\t)\n"
  },
  {
    "path": "Sources/CNIOAtomics/src/c-nioatomics.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#include <stdlib.h>\n#include <stdatomic.h>\n#include <stdbool.h>\n#include <inttypes.h>\n#include <stdio.h>\n\n#include \"../include/CNIOAtomics.h\"\n#include \"cpp_magic.h\"\n\n#define MAKE(type) /*\n*/ void catmc_nio_atomic_##type##_create_with_existing_storage(struct catmc_nio_atomic_##type *storage, type value) { /*\n*/     atomic_init(&storage->value, value); /*\n*/ } /*\n*/ /*\n*/ bool catmc_nio_atomic_##type##_compare_and_exchange(struct catmc_nio_atomic_##type *wrapper, type expected, type desired) { /*\n*/     type expected_copy = expected; /*\n*/     return atomic_compare_exchange_strong(&wrapper->value, &expected_copy, desired); /*\n*/ } /*\n*/ /*\n*/ type catmc_nio_atomic_##type##_add(struct catmc_nio_atomic_##type *wrapper, type value) { /*\n*/     return atomic_fetch_add_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ type catmc_nio_atomic_##type##_sub(struct catmc_nio_atomic_##type *wrapper, type value) { /*\n*/     return atomic_fetch_sub_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ type catmc_nio_atomic_##type##_exchange(struct catmc_nio_atomic_##type *wrapper, type value) { /*\n*/     return atomic_exchange_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ type catmc_nio_atomic_##type##_load(struct catmc_nio_atomic_##type *wrapper) { /*\n*/     return atomic_load_explicit(&wrapper->value, memory_order_relaxed); /*\n*/ } /*\n*/ /*\n*/ void catmc_nio_atomic_##type##_store(struct catmc_nio_atomic_##type *wrapper, type value) { /*\n*/     atomic_store_explicit(&wrapper->value, value, memory_order_relaxed); /*\n*/ }\n\ntypedef signed char signed_char;\ntypedef signed short signed_short;\ntypedef signed int signed_int;\ntypedef signed long signed_long;\ntypedef signed long long signed_long_long;\ntypedef unsigned char unsigned_char;\ntypedef unsigned short unsigned_short;\ntypedef unsigned int unsigned_int;\ntypedef unsigned long unsigned_long;\ntypedef unsigned long long unsigned_long_long;\ntypedef long long long_long;\n\nMAP(MAKE,EMPTY,\n         bool,\n\t\t          char,          short,          int,          long,          long_long,\n\t\t   signed_char,   signed_short,   signed_int,   signed_long,   signed_long_long,\n\t\t unsigned_char, unsigned_short, unsigned_int, unsigned_long, unsigned_long_long,\n\t\t int_least8_t, uint_least8_t,\n\t\t int_least16_t, uint_least16_t,\n\t\t int_least32_t, uint_least32_t,\n\t\t int_least64_t, uint_least64_t,\n\t\t intptr_t, uintptr_t\n\t\t)\n"
  },
  {
    "path": "Sources/CNIOAtomics/src/cpp_magic.h",
    "content": "//\n// this is https://github.com/18sg/uSHET/blob/c09e0acafd86720efe42dc15c63e0cc228244c32/lib/cpp_magic.h\n// LICENSE: MIT\n//\n//\n\n/**\n * This header file contains a library of advanced C Pre-Processor (CPP) macros\n * which implement various useful functions, such as iteration, in the\n * pre-processor.\n *\n * Though the file name (quite validly) labels this as magic, there should be\n * enough documentation in the comments for a reader only casually familiar\n * with the CPP to be able to understand how everything works.\n *\n * The majority of the magic tricks used in this file are based on those\n * described by pfultz2 in his \"Cloak\" library:\n *\n *    https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms\n *\n * Major differences are a greater level of detailed explanation in this\n * implementation and also a refusal to include any macros which require a O(N)\n * macro definitions to handle O(N) arguments (with the exception of DEFERn).\n */\n\n#ifndef CPP_MAGIC_H\n#define CPP_MAGIC_H\n\n/**\n * Force the pre-processor to expand the macro a large number of times. Usage:\n *\n *   EVAL(expression)\n *\n * This is useful when you have a macro which evaluates to a valid macro\n * expression which is not subsequently expanded in the same pass. A contrived,\n * but easy to understand, example of such a macro follows. Note that though\n * this example is contrived, this behaviour is abused to implement bounded\n * recursion in macros such as FOR.\n *\n *   #define A(x) x+1\n *   #define EMPTY\n *   #define NOT_QUITE_RIGHT(x) A EMPTY (x)\n *   NOT_QUITE_RIGHT(999)\n *\n * Here's what happens inside the C preprocessor:\n *\n * 1. It sees a macro \"NOT_QUITE_RIGHT\" and performs a single macro expansion\n *    pass on its arguments. Since the argument is \"999\" and this isn't a macro,\n *    this is a boring step resulting in no change.\n * 2. The NOT_QUITE_RIGHT macro is substituted for its definition giving \"A\n *    EMPTY() (x)\".\n * 3. The expander moves from left-to-right trying to expand the macro:\n *    The first token, A, cannot be expanded since there are no brackets\n *    immediately following it. The second token EMPTY(), however, can be\n *    expanded (recursively in this manner) and is replaced with \"\".\n * 4. Expansion continues from the start of the substituted test (which in this\n *    case is just empty), and sees \"(999)\" but since no macro name is present,\n *    nothing is done. This results in a final expansion of \"A (999)\".\n *\n * Unfortunately, this doesn't quite meet expectations since you may expect that\n * \"A (999)\" would have been expanded into \"999+1\". Unfortunately this requires\n * a second expansion pass but luckily we can force the macro processor to make\n * more passes by abusing the first step of macro expansion: the preprocessor\n * expands arguments in their own pass. If we define a macro which does nothing\n * except produce its arguments e.g.:\n *\n *   #define PASS_THROUGH(...) __VA_ARGS__\n *\n * We can now do \"PASS_THROUGH(NOT_QUITE_RIGHT(999))\" causing \"NOT_QUITE_RIGHT\" to be\n * expanded to \"A (999)\", as described above, when the arguments are expanded.\n * Now when the body of PASS_THROUGH is expanded, \"A (999)\" gets expanded to\n * \"999+1\".\n *\n * The EVAL defined below is essentially equivalent to a large nesting of\n * \"PASS_THROUGH(PASS_THROUGH(PASS_THROUGH(...\" which results in the\n * preprocessor making a large number of expansion passes over the given\n * expression.\n */\n#define EVAL(...) EVAL1024(__VA_ARGS__)\n#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))\n#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))\n#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))\n#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))\n#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))\n#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))\n#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))\n#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))\n#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))\n#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))\n#define EVAL1(...) __VA_ARGS__\n\n\n/**\n * Macros which expand to common values\n */\n#define PASS(...) __VA_ARGS__\n#define EMPTY()\n#define COMMA() ,\n#define PLUS() +\n#define ZERO() 0\n#define ONE() 1\n\n/**\n * Causes a function-style macro to require an additional pass to be expanded.\n *\n * This is useful, for example, when trying to implement recursion since the\n * recursive step must not be expanded in a single pass as the pre-processor\n * will catch it and prevent it.\n *\n * Usage:\n *\n *   DEFER1(IN_NEXT_PASS)(args, to, the, macro)\n *\n * How it works:\n *\n * 1. When DEFER1 is expanded, first its arguments are expanded which are\n *    simply IN_NEXT_PASS. Since this is a function-style macro and it has no\n *    arguments, nothing will happen.\n * 2. The body of DEFER1 will now be expanded resulting in EMPTY() being\n *    deleted. This results in \"IN_NEXT_PASS (args, to, the macro)\". Note that\n *    since the macro expander has already passed IN_NEXT_PASS by the time it\n *    expands EMPTY() and so it won't spot that the brackets which remain can be\n *    applied to IN_NEXT_PASS.\n * 3. At this point the macro expansion completes. If one more pass is made,\n *    IN_NEXT_PASS(args, to, the, macro) will be expanded as desired.\n */\n#define DEFER1(id) id EMPTY()\n\n/**\n * As with DEFER1 except here n additional passes are required for DEFERn.\n *\n * The mechanism is analogous.\n *\n * Note that there doesn't appear to be a way of combining DEFERn macros in\n * order to achieve exponentially increasing defers e.g. as is done by EVAL.\n */\n#define DEFER2(id) id EMPTY EMPTY()()\n#define DEFER3(id) id EMPTY EMPTY EMPTY()()()\n#define DEFER4(id) id EMPTY EMPTY EMPTY EMPTY()()()()\n#define DEFER5(id) id EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()\n#define DEFER6(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()\n#define DEFER7(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()\n#define DEFER8(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()()\n\n\n/**\n * Indirection around the standard ## concatenation operator. This simply\n * ensures that the arguments are expanded (once) before concatenation.\n */\n#define CAT(a, ...) a ## __VA_ARGS__\n#define CAT3(a, b, ...) a ## b ## __VA_ARGS__\n\n\n/**\n * Get the first argument and ignore the rest.\n */\n#define FIRST(a, ...) a\n\n/**\n * Get the second argument and ignore the rest.\n */\n#define SECOND(a, b, ...) b\n\n/**\n * Expects a single input (not containing commas). Returns 1 if the input is\n * PROBE() and otherwise returns 0.\n *\n * This can be useful as the basis of a NOT function.\n *\n * This macro abuses the fact that PROBE() contains a comma while other valid\n * inputs must not.\n */\n#define IS_PROBE(...) SECOND(__VA_ARGS__, 0)\n#define PROBE() ~, 1\n\n\n/**\n * Logical negation. 0 is defined as false and everything else as true.\n *\n * When 0, _NOT_0 will be found which evaluates to the PROBE. When 1 (or any other\n * value) is given, an appropriately named macro won't be found and the\n * concatenated string will be produced. IS_PROBE then simply checks to see if\n * the PROBE was returned, cleanly converting the argument into a 1 or 0.\n */\n#define NOT(x) IS_PROBE(CAT(_NOT_, x))\n#define _NOT_0 PROBE()\n\n/**\n * Macro version of C's famous \"cast to bool\" operator (i.e. !!) which takes\n * anything and casts it to 0 if it is 0 and 1 otherwise.\n */\n#define BOOLIFY(x) NOT(NOT(x))\n\n/**\n * Logical OR. Simply performs a lookup.\n */\n#define OR(a,b) CAT3(_OR_, a, b)\n#define _OR_00 0\n#define _OR_01 1\n#define _OR_10 1\n#define _OR_11 1\n\n/**\n * Logical AND. Simply performs a lookup.\n */\n#define AND(a,b) CAT3(_AND_, a, b)\n#define _AND_00 0\n#define _AND_01 0\n#define _AND_10 0\n#define _AND_11 1\n\n\n/**\n * Macro if statement. Usage:\n *\n *   IF(c)(expansion when true)\n *\n * Here's how:\n *\n * 1. The preprocessor expands the arguments to _IF casting the condition to '0'\n *    or '1'.\n * 2. The casted condition is concatencated with _IF_ giving _IF_0 or _IF_1.\n * 3. The _IF_0 and _IF_1 macros either returns the argument or doesn't (e.g.\n *    they implement the \"choice selection\" part of the macro).\n * 4. Note that the \"true\" clause is in the extra set of brackets; thus these\n *    become the arguments to _IF_0 or _IF_1 and thus a selection is made!\n */\n#define IF(c) _IF(BOOLIFY(c))\n#define _IF(c) CAT(_IF_,c)\n#define _IF_0(...)\n#define _IF_1(...) __VA_ARGS__\n\n/**\n * Macro if/else statement. Usage:\n *\n *   IF_ELSE(c)( \\\n *     expansion when true, \\\n *     expansion when false \\\n *   )\n *\n * The mechanism is analogous to IF.\n */\n#define IF_ELSE(c) _IF_ELSE(BOOLIFY(c))\n#define _IF_ELSE(c) CAT(_IF_ELSE_,c)\n#define _IF_ELSE_0(t,f) f\n#define _IF_ELSE_1(t,f) t\n\n\n/**\n * Macro which checks if it has any arguments. Returns '0' if there are no\n * arguments, '1' otherwise.\n *\n * Limitation: HAS_ARGS(,1,2,3) returns 0 -- this check essentially only checks\n * that the first argument exists.\n *\n * This macro works as follows:\n *\n * 1. _END_OF_ARGUMENTS_ is concatenated with the first argument.\n * 2. If the first argument is not present then only \"_END_OF_ARGUMENTS_\" will\n *    remain, otherwise \"_END_OF_ARGUMENTS something_here\" will remain. This\n *    remaining argument can start with parentheses.\n * 3. In the former case, the _END_OF_ARGUMENTS_(0) macro expands to a\n *    0 when it is expanded. In the latter, a non-zero result remains. If the\n *    first argument started with parentheses these will mostly not contain\n *    only a single 0, but e.g a C cast or some arithmetic operation that will\n *    cause the BOOLIFY in _END_OF_ARGUMENTS_ to be one.\n * 4. BOOLIFY is used to force non-zero results into 1 giving the clean 0 or 1\n *    output required.\n */\n#define HAS_ARGS(...) BOOLIFY(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)(0))\n#define _END_OF_ARGUMENTS_(...) BOOLIFY(FIRST(__VA_ARGS__))\n\n\n/**\n * Macro map/list comprehension. Usage:\n *\n *   MAP(op, sep, ...)\n *\n * Produces a 'sep()'-separated list of the result of op(arg) for each arg.\n *\n * Example Usage:\n *\n *   #define MAKE_HAPPY(x) happy_##x\n *   #define COMMA() ,\n *   MAP(MAKE_HAPPY, COMMA, 1,2,3)\n *\n * Which expands to:\n *\n *    happy_1 , happy_2 , happy_3\n *\n * How it works:\n *\n * 1. The MAP macro simply maps the inner MAP_INNER function in an EVAL which\n *    forces it to be expanded a large number of times, thus enabling many steps\n *    of iteration (see step 6).\n * 2. The MAP_INNER macro is substituted for its body.\n * 3. In the body, op(cur_val) is substituted giving the value for this\n *    iteration.\n * 4. The IF macro expands according to whether further iterations are required.\n *    This expansion either produces _IF_0 or _IF_1.\n * 5. Since the IF is followed by a set of brackets containing the \"if true\"\n *    clause, these become the argument to _IF_0 or _IF_1. At this point, the\n *    macro in the brackets will be expanded giving the separator followed by\n *    _MAP_INNER EMPTY()()(op, sep, __VA_ARGS__).\n * 5. If the IF was not taken, the above will simply be discarded and everything\n *    stops. If the IF is taken, The expression is then processed a second time\n *    yielding \"_MAP_INNER()(op, sep, __VA_ARGS__)\". Note that this call looks\n *    very similar to the  essentially the same as the original call except the\n *    first argument has been dropped.\n * 6. At this point expansion of MAP_INNER will terminate. However, since we can\n *    force more rounds of expansion using EVAL1. In the argument-expansion pass\n *    of the EVAL1, _MAP_INNER() is expanded to MAP_INNER which is then expanded\n *    using the arguments which follow it as in step 2-5. This is followed by a\n *    second expansion pass as the substitution of EVAL1() is expanded executing\n *    2-5 a second time. This results in up to two iterations occurring. Using\n *    many nested EVAL1 macros, i.e. the very-deeply-nested EVAL macro, will in\n *    this manner produce further iterations, hence the outer MAP macro doing\n *    this for us.\n *\n * Important tricks used:\n *\n * * If we directly produce \"MAP_INNER\" in an expansion of MAP_INNER, a special\n *   case in the preprocessor will prevent it being expanded in the future, even\n *   if we EVAL.  As a result, the MAP_INNER macro carefully only expands to\n *   something containing \"_MAP_INNER()\" which requires a further expansion step\n *   to invoke MAP_INNER and thus implementing the recursion.\n * * To prevent _MAP_INNER being expanded within the macro we must first defer its\n *   expansion during its initial pass as an argument to _IF_0 or _IF_1. We must\n *   then defer its expansion a second time as part of the body of the _IF_0. As\n *   a result hence the DEFER2.\n * * _MAP_INNER seemingly gets away with producing itself because it actually only\n *   produces MAP_INNER. It just happens that when _MAP_INNER() is expanded in\n *   this case it is followed by some arguments which get consumed by MAP_INNER\n *   and produce a _MAP_INNER.  As such, the macro expander never marks\n *   _MAP_INNER as expanding to itself and thus it will still be expanded in\n *   future productions of itself.\n */\n#define MAP(...) \\\n   IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_INNER(__VA_ARGS__)))\n#define MAP_INNER(op,sep,cur_val, ...) \\\n  op(cur_val) \\\n  IF(HAS_ARGS(__VA_ARGS__))( \\\n    sep() DEFER2(_MAP_INNER)()(op, sep, ##__VA_ARGS__) \\\n  )\n#define _MAP_INNER() MAP_INNER\n\n\n/**\n * This is a variant of the MAP macro which also includes as an argument to the\n * operation a valid C variable name which is different for each iteration.\n *\n * Usage:\n *   MAP_WITH_ID(op, sep, ...)\n *\n * Where op is a macro op(val, id) which takes a list value and an ID. This ID\n * will simply be a unary number using the digit \"I\", that is, I, II, III, IIII,\n * and so on.\n *\n * Example:\n *\n *   #define MAKE_STATIC_VAR(type, name) static type name;\n *   MAP_WITH_ID(MAKE_STATIC_VAR, EMPTY, int, int, int, bool, char)\n *\n * Which expands to:\n *\n *   static int I; static int II; static int III; static bool IIII; static char IIIII;\n *\n * The mechanism is analogous to the MAP macro.\n */\n#define MAP_WITH_ID(op,sep,...) \\\n  IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_WITH_ID_INNER(op,sep,I, ##__VA_ARGS__)))\n#define MAP_WITH_ID_INNER(op,sep,id,cur_val, ...) \\\n  op(cur_val,id) \\\n  IF(HAS_ARGS(__VA_ARGS__))( \\\n    sep() DEFER2(_MAP_WITH_ID_INNER)()(op, sep, CAT(id,I), ##__VA_ARGS__) \\\n  )\n#define _MAP_WITH_ID_INNER() MAP_WITH_ID_INNER\n\n\n/**\n * This is a variant of the MAP macro which iterates over pairs rather than\n * singletons.\n *\n * Usage:\n *   MAP_PAIRS(op, sep, ...)\n *\n * Where op is a macro op(val_1, val_2) which takes two list values.\n *\n * Example:\n *\n *   #define MAKE_STATIC_VAR(type, name) static type name;\n *   MAP_PAIRS(MAKE_STATIC_VAR, EMPTY, char, my_char, int, my_int)\n *\n * Which expands to:\n *\n *   static char my_char; static int my_int;\n *\n * The mechanism is analogous to the MAP macro.\n */\n#define MAP_PAIRS(op,sep,...) \\\n  IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_PAIRS_INNER(op,sep,__VA_ARGS__)))\n#define MAP_PAIRS_INNER(op,sep,cur_val_1, cur_val_2, ...) \\\n  op(cur_val_1,cur_val_2) \\\n  IF(HAS_ARGS(__VA_ARGS__))( \\\n    sep() DEFER2(_MAP_PAIRS_INNER)()(op, sep, __VA_ARGS__) \\\n  )\n#define _MAP_PAIRS_INNER() MAP_PAIRS_INNER\n\n/**\n * This is a variant of the MAP macro which iterates over a two-element sliding\n * window.\n *\n * Usage:\n *   MAP_SLIDE(op, last_op, sep, ...)\n *\n * Where op is a macro op(val_1, val_2) which takes the two list values\n * currently in the window. last_op is a macro taking a single value which is\n * called for the last argument.\n *\n * Example:\n *\n *   #define SIMON_SAYS_OP(simon, next) IF(NOT(simon()))(next)\n *   #define SIMON_SAYS_LAST_OP(val) last_but_not_least_##val\n *   #define SIMON_SAYS() 0\n *\n *   MAP_SLIDE(SIMON_SAYS_OP, SIMON_SAYS_LAST_OP, EMPTY, wiggle, SIMON_SAYS, dance, move, SIMON_SAYS, boogie, stop)\n *\n * Which expands to:\n *\n *   dance boogie last_but_not_least_stop\n *\n * The mechanism is analogous to the MAP macro.\n */\n#define MAP_SLIDE(op,last_op,sep,...) \\\n  IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_SLIDE_INNER(op,last_op,sep,__VA_ARGS__)))\n#define MAP_SLIDE_INNER(op,last_op,sep,cur_val, ...) \\\n  IF(HAS_ARGS(__VA_ARGS__))(op(cur_val,FIRST(__VA_ARGS__))) \\\n  IF(NOT(HAS_ARGS(__VA_ARGS__)))(last_op(cur_val)) \\\n  IF(HAS_ARGS(__VA_ARGS__))( \\\n    sep() DEFER2(_MAP_SLIDE_INNER)()(op, last_op, sep, __VA_ARGS__) \\\n  )\n#define _MAP_SLIDE_INNER() MAP_SLIDE_INNER\n\n\n/**\n * Strip any excess commas from a set of arguments.\n */\n#define REMOVE_TRAILING_COMMAS(...) \\\n\tMAP(PASS, COMMA, __VA_ARGS__)\n\n\n#endif\n"
  },
  {
    "path": "Sources/CNIODarwin/include/CNIODarwin.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#ifndef C_NIO_DARWIN_H\n#define C_NIO_DARWIN_H\n\n#ifdef __APPLE__\n#include <sys/socket.h>\n#include <sys/vsock.h>\n#include <sys/ioctl.h>\n#include <time.h>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fts.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Darwin platforms do not have a sendmmsg implementation available to them. This C module\n// provides a shim that implements sendmmsg on top of sendmsg. It also provides a shim for\n// recvmmsg, but does not actually implement that shim, instantly throwing errors if called.\n//\n// On Linux sendmmsg will error immediately in many cases if it knows any of the messages\n// cannot be sent. This is not something we can easily achieve from userspace on Darwin,\n// so instead if we encounter an error on any message but the first we will return \"short\".\n\ntypedef struct {\n    struct msghdr msg_hdr;\n    unsigned int msg_len;\n} CNIODarwin_mmsghdr;\n\nextern const int CNIODarwin_IPTOS_ECN_NOTECT;\nextern const int CNIODarwin_IPTOS_ECN_MASK;\nextern const int CNIODarwin_IPTOS_ECN_ECT0;\nextern const int CNIODarwin_IPTOS_ECN_ECT1;\nextern const int CNIODarwin_IPTOS_ECN_CE;\nextern const int CNIODarwin_IPV6_RECVPKTINFO;\nextern const int CNIODarwin_IPV6_PKTINFO;\n\nint CNIODarwin_sendmmsg(int sockfd, CNIODarwin_mmsghdr *msgvec, unsigned int vlen, int flags);\nint CNIODarwin_recvmmsg(int sockfd, CNIODarwin_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);\n\n// cmsghdr handling\nstruct cmsghdr *CNIODarwin_CMSG_FIRSTHDR(const struct msghdr *);\nstruct cmsghdr *CNIODarwin_CMSG_NXTHDR(const struct msghdr *, const struct cmsghdr *);\nconst void *CNIODarwin_CMSG_DATA(const struct cmsghdr *);\nvoid *CNIODarwin_CMSG_DATA_MUTABLE(struct cmsghdr *);\nsize_t CNIODarwin_CMSG_LEN(size_t);\nsize_t CNIODarwin_CMSG_SPACE(size_t);\n\nextern const unsigned long CNIODarwin_IOCTL_VM_SOCKETS_GET_LOCAL_CID;\n\nconst char* CNIODarwin_dirent_dname(struct dirent* ent);\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n\n#endif  // __APPLE__\n#endif  // C_NIO_DARWIN_H\n"
  },
  {
    "path": "Sources/CNIODarwin/shim.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#ifdef __APPLE__\n#include <CNIODarwin.h>\n#include <err.h>\n#include <sysexits.h>\n#include <stdlib.h>\n#include <limits.h>\n#include <errno.h>\n#include <assert.h>\n#include <netinet/ip.h>\n#include <netinet/in.h>\n#include \"dirent.h\"\n\nint CNIODarwin_sendmmsg(int sockfd, CNIODarwin_mmsghdr *msgvec, unsigned int vlen, int flags) {\n    // Some quick error checking. If vlen can't fit into int, we bail.\n    if ((vlen > INT_MAX) || (msgvec == NULL)) {\n        errno = EINVAL;\n        return -1;\n    }\n\n    for (unsigned int i = 0; i < vlen; i++) {\n        ssize_t sendAmount = sendmsg(sockfd, &(msgvec[i].msg_hdr), flags);\n        if (sendAmount < 0 && i == 0) {\n            // Error on the first send, return the error.\n            return -1;\n        }\n\n        if (sendAmount < 0) {\n            // Error on a later send, return short.\n            return i;\n        }\n\n        // Send succeeded, save off the bytes written.\n        msgvec[i].msg_len = (unsigned int)sendAmount;\n    }\n\n    // If we dropped out, we sent everything.\n    return vlen;\n}\n\nint CNIODarwin_recvmmsg(int sockfd, CNIODarwin_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {\n    errx(EX_SOFTWARE, \"recvmmsg shim not implemented on Darwin platforms\\n\");\n}\n\nstruct cmsghdr *CNIODarwin_CMSG_FIRSTHDR(const struct msghdr *mhdr) {\n    assert(mhdr != NULL);\n    return CMSG_FIRSTHDR(mhdr);\n}\n\nstruct cmsghdr *CNIODarwin_CMSG_NXTHDR(const struct msghdr *mhdr, const struct cmsghdr *cmsg) {\n    assert(mhdr != NULL);\n    assert(cmsg != NULL);   // Not required by Darwin but Linux needs this so we should match.\n    return CMSG_NXTHDR(mhdr, cmsg);\n}\n\nconst void *CNIODarwin_CMSG_DATA(const struct cmsghdr *cmsg) {\n    assert(cmsg != NULL);\n    return CMSG_DATA(cmsg);\n}\n\nvoid *CNIODarwin_CMSG_DATA_MUTABLE(struct cmsghdr *cmsg) {\n    assert(cmsg != NULL);\n    return CMSG_DATA(cmsg);\n}\n\nsize_t CNIODarwin_CMSG_LEN(size_t payloadSizeBytes) {\n    return CMSG_LEN(payloadSizeBytes);\n}\n\nsize_t CNIODarwin_CMSG_SPACE(size_t payloadSizeBytes) {\n    return CMSG_SPACE(payloadSizeBytes);\n}\n\nconst int CNIODarwin_IPTOS_ECN_NOTECT = IPTOS_ECN_NOTECT;\nconst int CNIODarwin_IPTOS_ECN_MASK = IPTOS_ECN_MASK;\nconst int CNIODarwin_IPTOS_ECN_ECT0 = IPTOS_ECN_ECT0;\nconst int CNIODarwin_IPTOS_ECN_ECT1 = IPTOS_ECN_ECT1;\nconst int CNIODarwin_IPTOS_ECN_CE = IPTOS_ECN_CE;\nconst int CNIODarwin_IPV6_RECVPKTINFO = IPV6_RECVPKTINFO;\nconst int CNIODarwin_IPV6_PKTINFO = IPV6_PKTINFO;\n\nconst unsigned long CNIODarwin_IOCTL_VM_SOCKETS_GET_LOCAL_CID = IOCTL_VM_SOCKETS_GET_LOCAL_CID;\n\nconst char* CNIODarwin_dirent_dname(struct dirent* ent) {\n    return ent->d_name;\n}\n\n#endif  // __APPLE__\n"
  },
  {
    "path": "Sources/CNIOLLHTTP/LICENSE",
    "content": "This software is licensed under the MIT License.\n\nCopyright Fedor Indutny, 2018.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the\nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\nNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Sources/CNIOLLHTTP/c_nio_api.c",
    "content": "/* Additional changes for SwiftNIO:\n    - prefixed all symbols by 'c_nio_'\n*/\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"include/c_nio_llhttp.h\"\n\n#define CALLBACK_MAYBE(PARSER, NAME)                                          \\\n  do {                                                                        \\\n    const llhttp_settings_t* settings;                                        \\\n    settings = (const llhttp_settings_t*) (PARSER)->settings;                 \\\n    if (settings == NULL || settings->NAME == NULL) {                         \\\n      err = 0;                                                                \\\n      break;                                                                  \\\n    }                                                                         \\\n    err = settings->NAME((PARSER));                                           \\\n  } while (0)\n\n#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN)                         \\\n  do {                                                                        \\\n    const llhttp_settings_t* settings;                                        \\\n    settings = (const llhttp_settings_t*) (PARSER)->settings;                 \\\n    if (settings == NULL || settings->NAME == NULL) {                         \\\n      err = 0;                                                                \\\n      break;                                                                  \\\n    }                                                                         \\\n    err = settings->NAME((PARSER), (START), (LEN));                           \\\n    if (err == -1) {                                                          \\\n      err = HPE_USER;                                                         \\\n      c_nio_llhttp_set_error_reason((PARSER), \"Span callback error in \" #NAME);     \\\n    }                                                                         \\\n  } while (0)\n\nvoid c_nio_llhttp_init(llhttp_t* parser, llhttp_type_t type,\n                 const llhttp_settings_t* settings) {\n  c_nio_llhttp__internal_init(parser);\n\n  parser->type = type;\n  parser->settings = (void*) settings;\n}\n\n\n#if defined(__wasm__)\n\nextern int wasm_on_message_begin(llhttp_t * p);\nextern int wasm_on_url(llhttp_t* p, const char* at, size_t length);\nextern int wasm_on_status(llhttp_t* p, const char* at, size_t length);\nextern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);\nextern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);\nextern int wasm_on_headers_complete(llhttp_t * p, int status_code,\n                                    uint8_t upgrade, int should_keep_alive);\nextern int wasm_on_body(llhttp_t* p, const char* at, size_t length);\nextern int wasm_on_message_complete(llhttp_t * p);\n\nstatic int wasm_on_headers_complete_wrap(llhttp_t* p) {\n  return wasm_on_headers_complete(p, p->status_code, p->upgrade,\n                                  c_nio_llhttp_should_keep_alive(p));\n}\n\nconst llhttp_settings_t wasm_settings = {\n  .on_message_begin = wasm_on_message_begin,\n  .on_url = wasm_on_url,\n  .on_status = wasm_on_status,\n  .on_header_field = wasm_on_header_field,\n  .on_header_value = wasm_on_header_value,\n  .on_headers_complete = wasm_on_headers_complete_wrap,\n  .on_body = wasm_on_body,\n  .on_message_complete = wasm_on_message_complete,\n};\n\n\nllhttp_t* llhttp_alloc(llhttp_type_t type) {\n  llhttp_t* parser = malloc(sizeof(llhttp_t));\n  c_nio_llhttp_init(parser, type, &wasm_settings);\n  return parser;\n}\n\nvoid llhttp_free(llhttp_t* parser) {\n  free(parser);\n}\n\n#endif  // defined(__wasm__)\n\n/* Some getters required to get stuff from the parser */\n\nuint8_t c_nio_llhttp_get_type(llhttp_t* parser) {\n  return parser->type;\n}\n\nuint8_t c_nio_llhttp_get_http_major(llhttp_t* parser) {\n  return parser->http_major;\n}\n\nuint8_t c_nio_llhttp_get_http_minor(llhttp_t* parser) {\n  return parser->http_minor;\n}\n\nuint8_t c_nio_llhttp_get_method(llhttp_t* parser) {\n  return parser->method;\n}\n\nint c_nio_llhttp_get_status_code(llhttp_t* parser) {\n  return parser->status_code;\n}\n\nuint8_t c_nio_llhttp_get_upgrade(llhttp_t* parser) {\n  return parser->upgrade;\n}\n\n\nvoid c_nio_llhttp_reset(llhttp_t* parser) {\n  llhttp_type_t type = parser->type;\n  const llhttp_settings_t* settings = parser->settings;\n  void* data = parser->data;\n  uint16_t lenient_flags = parser->lenient_flags;\n\n  c_nio_llhttp__internal_init(parser);\n\n  parser->type = type;\n  parser->settings = (void*) settings;\n  parser->data = data;\n  parser->lenient_flags = lenient_flags;\n}\n\n\nllhttp_errno_t c_nio_llhttp_execute(llhttp_t* parser, const char* data, size_t len) {\n  return c_nio_llhttp__internal_execute(parser, data, data + len);\n}\n\n\nvoid c_nio_llhttp_settings_init(llhttp_settings_t* settings) {\n  memset(settings, 0, sizeof(*settings));\n}\n\n\nllhttp_errno_t c_nio_llhttp_finish(llhttp_t* parser) {\n  int err;\n\n  /* We're in an error state. Don't bother doing anything. */\n  if (parser->error != 0) {\n    return 0;\n  }\n\n  switch (parser->finish) {\n    case HTTP_FINISH_SAFE_WITH_CB:\n      CALLBACK_MAYBE(parser, on_message_complete);\n      if (err != HPE_OK) return err;\n\n    /* FALLTHROUGH */\n    case HTTP_FINISH_SAFE:\n      return HPE_OK;\n    case HTTP_FINISH_UNSAFE:\n      parser->reason = \"Invalid EOF state\";\n      return HPE_INVALID_EOF_STATE;\n    default:\n      abort();\n  }\n}\n\n\nvoid c_nio_llhttp_pause(llhttp_t* parser) {\n  if (parser->error != HPE_OK) {\n    return;\n  }\n\n  parser->error = HPE_PAUSED;\n  parser->reason = \"Paused\";\n}\n\n\nvoid c_nio_llhttp_resume(llhttp_t* parser) {\n  if (parser->error != HPE_PAUSED) {\n    return;\n  }\n\n  parser->error = 0;\n}\n\n\nvoid c_nio_llhttp_resume_after_upgrade(llhttp_t* parser) {\n  if (parser->error != HPE_PAUSED_UPGRADE) {\n    return;\n  }\n\n  parser->error = 0;\n}\n\n\nllhttp_errno_t c_nio_llhttp_get_errno(const llhttp_t* parser) {\n  return parser->error;\n}\n\n\nconst char* c_nio_llhttp_get_error_reason(const llhttp_t* parser) {\n  return parser->reason;\n}\n\n\nvoid c_nio_llhttp_set_error_reason(llhttp_t* parser, const char* reason) {\n  parser->reason = reason;\n}\n\n\nconst char* c_nio_llhttp_get_error_pos(const llhttp_t* parser) {\n  return parser->error_pos;\n}\n\n\nconst char* c_nio_llhttp_errno_name(llhttp_errno_t err) {\n#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return \"HPE_\" #NAME;\n  switch (err) {\n    HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)\n    default: abort();\n  }\n#undef HTTP_ERRNO_GEN\n}\n\n\nconst char* c_nio_llhttp_method_name(llhttp_method_t method) {\n#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;\n  switch (method) {\n    HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)\n    default: abort();\n  }\n#undef HTTP_METHOD_GEN\n}\n\nconst char* c_nio_llhttp_status_name(llhttp_status_t status) {\n#define HTTP_STATUS_GEN(NUM, NAME, STRING) case HTTP_STATUS_##NAME: return #STRING;\n  switch (status) {\n    HTTP_STATUS_MAP(HTTP_STATUS_GEN)\n    default: abort();\n  }\n#undef HTTP_STATUS_GEN\n}\n\n\nvoid c_nio_llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_HEADERS;\n  } else {\n    parser->lenient_flags &= ~LENIENT_HEADERS;\n  }\n}\n\n\nvoid c_nio_llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;\n  } else {\n    parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH;\n  }\n}\n\n\nvoid c_nio_llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_KEEP_ALIVE;\n  } else {\n    parser->lenient_flags &= ~LENIENT_KEEP_ALIVE;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_TRANSFER_ENCODING;\n  } else {\n    parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_version(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_VERSION;\n  } else {\n    parser->lenient_flags &= ~LENIENT_VERSION;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_DATA_AFTER_CLOSE;\n  } else {\n    parser->lenient_flags &= ~LENIENT_DATA_AFTER_CLOSE;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR;\n  } else {\n    parser->lenient_flags &= ~LENIENT_OPTIONAL_LF_AFTER_CR;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;\n  } else {\n    parser->lenient_flags &= ~LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF;\n  } else {\n    parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF;\n  }\n}\n\nvoid c_nio_llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) {\n  if (enabled) {\n    parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE;\n  } else {\n    parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE;\n  }\n}\n\n/* Callbacks */\n\n\nint c_nio_llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_message_begin);\n  return err;\n}\n\n\nint c_nio_llhttp__on_protocol(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_protocol, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_protocol_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_protocol_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_url_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_status_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_method(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_method_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_version(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_version_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_header_field_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_header_value_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_headers_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_message_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_chunk_header);\n  return err;\n}\n\n\nint c_nio_llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_chunk_extension_name_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p);\n  return err;\n}\n\n\nint c_nio_llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_chunk_extension_value_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_chunk_complete);\n  return err;\n}\n\n\nint c_nio_llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) {\n  int err;\n  CALLBACK_MAYBE(s, on_reset);\n  return err;\n}\n\n\n/* Private */\n\n\nvoid c_nio_llhttp__debug(llhttp_t* s, const char* p, const char* endp,\n                   const char* msg) {\n  if (p == endp) {\n    fprintf(stderr, \"p=%p type=%d flags=%02x next=null debug=%s\\n\", s, s->type,\n            s->flags, msg);\n  } else {\n    fprintf(stderr, \"p=%p type=%d flags=%02x next=%02x   debug=%s\\n\", s,\n            s->type, s->flags, *p, msg);\n  }\n}\n"
  },
  {
    "path": "Sources/CNIOLLHTTP/c_nio_http.c",
    "content": "/* Additional changes for SwiftNIO:\n    - prefixed all symbols by 'c_nio_'\n*/\n#include <stdio.h>\n#ifndef LLHTTP__TEST\n# include \"include/c_nio_llhttp.h\"\n#else\n# define llhttp_t llparse_t\n#endif  /* */\n\nint c_nio_llhttp_message_needs_eof(const llhttp_t* parser);\nint c_nio_llhttp_should_keep_alive(const llhttp_t* parser);\n\nint c_nio_llhttp__before_headers_complete(llhttp_t* parser, const char* p,\n                                    const char* endp) {\n  /* Set this here so that on_headers_complete() callbacks can see it */\n  if ((parser->flags & F_UPGRADE) &&\n      (parser->flags & F_CONNECTION_UPGRADE)) {\n    /* For responses, \"Upgrade: foo\" and \"Connection: upgrade\" are\n     * mandatory only when it is a 101 Switching Protocols response,\n     * otherwise it is purely informational, to announce support.\n     */\n    parser->upgrade =\n        (parser->type == HTTP_REQUEST || parser->status_code == 101);\n  } else {\n    parser->upgrade = (parser->method == HTTP_CONNECT);\n  }\n  return 0;\n}\n\n\n/* Return values:\n * 0 - No body, `restart`, message_complete\n * 1 - CONNECT request, `restart`, message_complete, and pause\n * 2 - chunk_size_start\n * 3 - body_identity\n * 4 - body_identity_eof\n * 5 - invalid transfer-encoding for request\n */\nint c_nio_llhttp__after_headers_complete(llhttp_t* parser, const char* p,\n                                   const char* endp) {\n  int hasBody;\n\n  hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;\n  if (\n      (parser->upgrade && (parser->method == HTTP_CONNECT ||\n                          (parser->flags & F_SKIPBODY) || !hasBody)) ||\n      /* See RFC 2616 section 4.4 - 1xx e.g. Continue */\n      (parser->type == HTTP_RESPONSE && parser->status_code == 101)\n  ) {\n    /* Exit, the rest of the message is in a different protocol. */\n    return 1;\n  }\n\n  if (parser->type == HTTP_RESPONSE && parser->status_code == 100) {\n    /* No body, restart as the message is complete */\n    return 0;\n  }\n\n  /* See RFC 2616 section 4.4 */\n  if (\n    parser->flags & F_SKIPBODY ||         /* response to a HEAD request */\n    (\n      parser->type == HTTP_RESPONSE && (\n        parser->status_code == 102 ||     /* Processing */\n        parser->status_code == 103 ||     /* Early Hints */\n        parser->status_code == 204 ||     /* No Content */\n        parser->status_code == 304        /* Not Modified */\n      )\n    )\n  ) {\n    return 0;\n  } else if (parser->flags & F_CHUNKED) {\n    /* chunked encoding - ignore Content-Length header, prepare for a chunk */\n    return 2;\n  } else if (parser->flags & F_TRANSFER_ENCODING) {\n    if (parser->type == HTTP_REQUEST &&\n        (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 &&\n        (parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) {\n      /* RFC 7230 3.3.3 */\n\n      /* If a Transfer-Encoding header field\n       * is present in a request and the chunked transfer coding is not\n       * the final encoding, the message body length cannot be determined\n       * reliably; the server MUST respond with the 400 (Bad Request)\n       * status code and then close the connection.\n       */\n      return 5;\n    } else {\n      /* RFC 7230 3.3.3 */\n\n      /* If a Transfer-Encoding header field is present in a response and\n       * the chunked transfer coding is not the final encoding, the\n       * message body length is determined by reading the connection until\n       * it is closed by the server.\n       */\n      return 4;\n    }\n  } else {\n    if (!(parser->flags & F_CONTENT_LENGTH)) {\n      if (!c_nio_llhttp_message_needs_eof(parser)) {\n        /* Assume content-length 0 - read the next */\n        return 0;\n      } else {\n        /* Read body until EOF */\n        return 4;\n      }\n    } else if (parser->content_length == 0) {\n      /* Content-Length header given but zero: Content-Length: 0\\r\\n */\n      return 0;\n    } else {\n      /* Content-Length header given and non-zero */\n      return 3;\n    }\n  }\n}\n\n\nint c_nio_llhttp__after_message_complete(llhttp_t* parser, const char* p,\n                                   const char* endp) {\n  int should_keep_alive;\n\n  should_keep_alive = c_nio_llhttp_should_keep_alive(parser);\n  parser->finish = HTTP_FINISH_SAFE;\n  parser->flags = 0;\n\n  /* NOTE: this is ignored in loose parsing mode */\n  return should_keep_alive;\n}\n\n\nint c_nio_llhttp_message_needs_eof(const llhttp_t* parser) {\n  if (parser->type == HTTP_REQUEST) {\n    return 0;\n  }\n\n  /* See RFC 2616 section 4.4 */\n  if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */\n      parser->status_code == 204 ||     /* No Content */\n      parser->status_code == 304 ||     /* Not Modified */\n      (parser->flags & F_SKIPBODY)) {     /* response to a HEAD request */\n    return 0;\n  }\n\n  /* RFC 7230 3.3.3, see `c_nio_llhttp__after_headers_complete` */\n  if ((parser->flags & F_TRANSFER_ENCODING) &&\n      (parser->flags & F_CHUNKED) == 0) {\n    return 1;\n  }\n\n  if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {\n    return 0;\n  }\n\n  return 1;\n}\n\n\nint c_nio_llhttp_should_keep_alive(const llhttp_t* parser) {\n  if (parser->http_major > 0 && parser->http_minor > 0) {\n    /* HTTP/1.1 */\n    if (parser->flags & F_CONNECTION_CLOSE) {\n      return 0;\n    }\n  } else {\n    /* HTTP/1.0 or earlier */\n    if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {\n      return 0;\n    }\n  }\n\n  return !c_nio_llhttp_message_needs_eof(parser);\n}\n"
  },
  {
    "path": "Sources/CNIOLLHTTP/c_nio_llhttp.c",
    "content": "/* Additional changes for SwiftNIO:\n    - prefixed all symbols by 'c_nio_'\n*/\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#ifdef __SSE4_2__\n #ifdef _MSC_VER\n  #include <nmmintrin.h>\n #else  /* !_MSC_VER */\n  #include <x86intrin.h>\n #endif  /* _MSC_VER */\n#endif  /* __SSE4_2__ */\n\n#ifdef __ARM_NEON__\n #include <arm_neon.h>\n#endif  /* __ARM_NEON__ */\n\n#ifdef __wasm__\n #include <wasm_simd128.h>\n#endif  /* __wasm__ */\n\n#ifdef _MSC_VER\n #define ALIGN(n) _declspec(align(n))\n #define UNREACHABLE __assume(0)\n#else  /* !_MSC_VER */\n #define ALIGN(n) __attribute__((aligned(n)))\n #define UNREACHABLE __builtin_unreachable()\n#endif  /* _MSC_VER */\n\n#include \"include/c_nio_llhttp.h\"\n\ntypedef int (*c_nio_llhttp__internal__span_cb)(\n             c_nio_llhttp__internal_t*, const char*, const char*);\n\nstatic const unsigned char llparse_blob0[] = {\n  'o', 'n'\n};\nstatic const unsigned char llparse_blob1[] = {\n  'e', 'c', 't', 'i', 'o', 'n'\n};\nstatic const unsigned char llparse_blob2[] = {\n  'l', 'o', 's', 'e'\n};\nstatic const unsigned char llparse_blob3[] = {\n  'e', 'e', 'p', '-', 'a', 'l', 'i', 'v', 'e'\n};\nstatic const unsigned char llparse_blob4[] = {\n  'p', 'g', 'r', 'a', 'd', 'e'\n};\nstatic const unsigned char llparse_blob5[] = {\n  'c', 'h', 'u', 'n', 'k', 'e', 'd'\n};\n#ifdef __SSE4_2__\nstatic const unsigned char ALIGN(16) llparse_blob6[] = {\n  0x9, 0x9, ' ', '~', 0x80, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,\n  0x0, 0x0, 0x0, 0x0, 0x0\n};\n#endif  /* __SSE4_2__ */\n#ifdef __SSE4_2__\nstatic const unsigned char ALIGN(16) llparse_blob7[] = {\n  '!', '!', '#', '\\'', '*', '+', '-', '.', '0', '9', 'A',\n  'Z', '^', 'z', '|', '|'\n};\n#endif  /* __SSE4_2__ */\n#ifdef __SSE4_2__\nstatic const unsigned char ALIGN(16) llparse_blob8[] = {\n  '~', '~', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n  0x0, 0x0, 0x0, 0x0, 0x0\n};\n#endif  /* __SSE4_2__ */\nstatic const unsigned char llparse_blob9[] = {\n  'e', 'n', 't', '-', 'l', 'e', 'n', 'g', 't', 'h'\n};\nstatic const unsigned char llparse_blob10[] = {\n  'r', 'o', 'x', 'y', '-', 'c', 'o', 'n', 'n', 'e', 'c',\n  't', 'i', 'o', 'n'\n};\nstatic const unsigned char llparse_blob11[] = {\n  'r', 'a', 'n', 's', 'f', 'e', 'r', '-', 'e', 'n', 'c',\n  'o', 'd', 'i', 'n', 'g'\n};\nstatic const unsigned char llparse_blob12[] = {\n  'p', 'g', 'r', 'a', 'd', 'e'\n};\nstatic const unsigned char llparse_blob13[] = {\n  'T', 'T', 'P'\n};\nstatic const unsigned char llparse_blob14[] = {\n  0xd, 0xa, 0xd, 0xa, 'S', 'M', 0xd, 0xa, 0xd, 0xa\n};\nstatic const unsigned char llparse_blob15[] = {\n  'C', 'E'\n};\nstatic const unsigned char llparse_blob16[] = {\n  'T', 'S', 'P'\n};\nstatic const unsigned char llparse_blob17[] = {\n  'N', 'O', 'U', 'N', 'C', 'E'\n};\nstatic const unsigned char llparse_blob18[] = {\n  'I', 'N', 'D'\n};\nstatic const unsigned char llparse_blob19[] = {\n  'E', 'C', 'K', 'O', 'U', 'T'\n};\nstatic const unsigned char llparse_blob20[] = {\n  'N', 'E', 'C', 'T'\n};\nstatic const unsigned char llparse_blob21[] = {\n  'E', 'T', 'E'\n};\nstatic const unsigned char llparse_blob22[] = {\n  'C', 'R', 'I', 'B', 'E'\n};\nstatic const unsigned char llparse_blob23[] = {\n  'L', 'U', 'S', 'H'\n};\nstatic const unsigned char llparse_blob24[] = {\n  'E', 'T'\n};\nstatic const unsigned char llparse_blob25[] = {\n  'P', 'A', 'R', 'A', 'M', 'E', 'T', 'E', 'R'\n};\nstatic const unsigned char llparse_blob26[] = {\n  'E', 'A', 'D'\n};\nstatic const unsigned char llparse_blob27[] = {\n  'N', 'K'\n};\nstatic const unsigned char llparse_blob28[] = {\n  'C', 'K'\n};\nstatic const unsigned char llparse_blob29[] = {\n  'S', 'E', 'A', 'R', 'C', 'H'\n};\nstatic const unsigned char llparse_blob30[] = {\n  'R', 'G', 'E'\n};\nstatic const unsigned char llparse_blob31[] = {\n  'C', 'T', 'I', 'V', 'I', 'T', 'Y'\n};\nstatic const unsigned char llparse_blob32[] = {\n  'L', 'E', 'N', 'D', 'A', 'R'\n};\nstatic const unsigned char llparse_blob33[] = {\n  'V', 'E'\n};\nstatic const unsigned char llparse_blob34[] = {\n  'O', 'T', 'I', 'F', 'Y'\n};\nstatic const unsigned char llparse_blob35[] = {\n  'P', 'T', 'I', 'O', 'N', 'S'\n};\nstatic const unsigned char llparse_blob36[] = {\n  'C', 'H'\n};\nstatic const unsigned char llparse_blob37[] = {\n  'S', 'E'\n};\nstatic const unsigned char llparse_blob38[] = {\n  'A', 'Y'\n};\nstatic const unsigned char llparse_blob39[] = {\n  'S', 'T'\n};\nstatic const unsigned char llparse_blob40[] = {\n  'I', 'N', 'D'\n};\nstatic const unsigned char llparse_blob41[] = {\n  'A', 'T', 'C', 'H'\n};\nstatic const unsigned char llparse_blob42[] = {\n  'G', 'E'\n};\nstatic const unsigned char llparse_blob43[] = {\n  'U', 'E', 'R', 'Y'\n};\nstatic const unsigned char llparse_blob44[] = {\n  'I', 'N', 'D'\n};\nstatic const unsigned char llparse_blob45[] = {\n  'O', 'R', 'D'\n};\nstatic const unsigned char llparse_blob46[] = {\n  'I', 'R', 'E', 'C', 'T'\n};\nstatic const unsigned char llparse_blob47[] = {\n  'O', 'R', 'T'\n};\nstatic const unsigned char llparse_blob48[] = {\n  'R', 'C', 'H'\n};\nstatic const unsigned char llparse_blob49[] = {\n  'P', 'A', 'R', 'A', 'M', 'E', 'T', 'E', 'R'\n};\nstatic const unsigned char llparse_blob50[] = {\n  'U', 'R', 'C', 'E'\n};\nstatic const unsigned char llparse_blob51[] = {\n  'B', 'S', 'C', 'R', 'I', 'B', 'E'\n};\nstatic const unsigned char llparse_blob52[] = {\n  'A', 'R', 'D', 'O', 'W', 'N'\n};\nstatic const unsigned char llparse_blob53[] = {\n  'A', 'C', 'E'\n};\nstatic const unsigned char llparse_blob54[] = {\n  'I', 'N', 'D'\n};\nstatic const unsigned char llparse_blob55[] = {\n  'N', 'K'\n};\nstatic const unsigned char llparse_blob56[] = {\n  'C', 'K'\n};\nstatic const unsigned char llparse_blob57[] = {\n  'U', 'B', 'S', 'C', 'R', 'I', 'B', 'E'\n};\nstatic const unsigned char llparse_blob58[] = {\n  'T', 'T', 'P'\n};\nstatic const unsigned char llparse_blob59[] = {\n  'C', 'E'\n};\nstatic const unsigned char llparse_blob60[] = {\n  'T', 'S', 'P'\n};\nstatic const unsigned char llparse_blob61[] = {\n  'A', 'D'\n};\nstatic const unsigned char llparse_blob62[] = {\n  'T', 'P', '/'\n};\n\nenum llparse_match_status_e {\n  kMatchComplete,\n  kMatchPause,\n  kMatchMismatch\n};\ntypedef enum llparse_match_status_e llparse_match_status_t;\n\nstruct llparse_match_s {\n  llparse_match_status_t status;\n  const unsigned char* current;\n};\ntypedef struct llparse_match_s llparse_match_t;\n\nstatic llparse_match_t llparse__match_sequence_to_lower(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp,\n    const unsigned char* seq, uint32_t seq_len) {\n  uint32_t index;\n  llparse_match_t res;\n\n  index = s->_index;\n  for (; p != endp; p++) {\n    unsigned char current;\n\n    current = ((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p));\n    if (current == seq[index]) {\n      if (++index == seq_len) {\n        res.status = kMatchComplete;\n        goto reset;\n      }\n    } else {\n      res.status = kMatchMismatch;\n      goto reset;\n    }\n  }\n  s->_index = index;\n  res.status = kMatchPause;\n  res.current = p;\n  return res;\nreset:\n  s->_index = 0;\n  res.current = p;\n  return res;\n}\n\nstatic llparse_match_t llparse__match_sequence_to_lower_unsafe(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp,\n    const unsigned char* seq, uint32_t seq_len) {\n  uint32_t index;\n  llparse_match_t res;\n\n  index = s->_index;\n  for (; p != endp; p++) {\n    unsigned char current;\n\n    current = ((*p) | 0x20);\n    if (current == seq[index]) {\n      if (++index == seq_len) {\n        res.status = kMatchComplete;\n        goto reset;\n      }\n    } else {\n      res.status = kMatchMismatch;\n      goto reset;\n    }\n  }\n  s->_index = index;\n  res.status = kMatchPause;\n  res.current = p;\n  return res;\nreset:\n  s->_index = 0;\n  res.current = p;\n  return res;\n}\n\nstatic llparse_match_t llparse__match_sequence_id(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp,\n    const unsigned char* seq, uint32_t seq_len) {\n  uint32_t index;\n  llparse_match_t res;\n\n  index = s->_index;\n  for (; p != endp; p++) {\n    unsigned char current;\n\n    current = *p;\n    if (current == seq[index]) {\n      if (++index == seq_len) {\n        res.status = kMatchComplete;\n        goto reset;\n      }\n    } else {\n      res.status = kMatchMismatch;\n      goto reset;\n    }\n  }\n  s->_index = index;\n  res.status = kMatchPause;\n  res.current = p;\n  return res;\nreset:\n  s->_index = 0;\n  res.current = p;\n  return res;\n}\n\nenum llparse_state_e {\n  s_error,\n  s_n_llhttp__internal__n_closed,\n  s_n_llhttp__internal__n_invoke_llhttp__after_message_complete,\n  s_n_llhttp__internal__n_pause_1,\n  s_n_llhttp__internal__n_invoke_is_equal_upgrade,\n  s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2,\n  s_n_llhttp__internal__n_chunk_data_almost_done_1,\n  s_n_llhttp__internal__n_chunk_data_almost_done,\n  s_n_llhttp__internal__n_consume_content_length,\n  s_n_llhttp__internal__n_span_start_llhttp__on_body,\n  s_n_llhttp__internal__n_invoke_is_equal_content_length,\n  s_n_llhttp__internal__n_chunk_size_almost_done,\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_9,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2,\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_10,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1,\n  s_n_llhttp__internal__n_chunk_extension_quoted_value_done,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2,\n  s_n_llhttp__internal__n_error_30,\n  s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair,\n  s_n_llhttp__internal__n_error_31,\n  s_n_llhttp__internal__n_chunk_extension_quoted_value,\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3,\n  s_n_llhttp__internal__n_error_33,\n  s_n_llhttp__internal__n_chunk_extension_value,\n  s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value,\n  s_n_llhttp__internal__n_error_34,\n  s_n_llhttp__internal__n_chunk_extension_name,\n  s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name,\n  s_n_llhttp__internal__n_chunk_extensions,\n  s_n_llhttp__internal__n_chunk_size_otherwise,\n  s_n_llhttp__internal__n_chunk_size,\n  s_n_llhttp__internal__n_chunk_size_digit,\n  s_n_llhttp__internal__n_invoke_update_content_length_1,\n  s_n_llhttp__internal__n_consume_content_length_1,\n  s_n_llhttp__internal__n_span_start_llhttp__on_body_1,\n  s_n_llhttp__internal__n_eof,\n  s_n_llhttp__internal__n_span_start_llhttp__on_body_2,\n  s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete,\n  s_n_llhttp__internal__n_error_5,\n  s_n_llhttp__internal__n_headers_almost_done,\n  s_n_llhttp__internal__n_header_field_colon_discard_ws,\n  s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete,\n  s_n_llhttp__internal__n_span_start_llhttp__on_header_value,\n  s_n_llhttp__internal__n_header_value_discard_lws,\n  s_n_llhttp__internal__n_header_value_discard_ws_almost_done,\n  s_n_llhttp__internal__n_header_value_lws,\n  s_n_llhttp__internal__n_header_value_almost_done,\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_17,\n  s_n_llhttp__internal__n_header_value_lenient,\n  s_n_llhttp__internal__n_error_54,\n  s_n_llhttp__internal__n_header_value_otherwise,\n  s_n_llhttp__internal__n_header_value_connection_token,\n  s_n_llhttp__internal__n_header_value_connection_ws,\n  s_n_llhttp__internal__n_header_value_connection_1,\n  s_n_llhttp__internal__n_header_value_connection_2,\n  s_n_llhttp__internal__n_header_value_connection_3,\n  s_n_llhttp__internal__n_header_value_connection,\n  s_n_llhttp__internal__n_error_56,\n  s_n_llhttp__internal__n_error_57,\n  s_n_llhttp__internal__n_header_value_content_length_ws,\n  s_n_llhttp__internal__n_header_value_content_length,\n  s_n_llhttp__internal__n_error_59,\n  s_n_llhttp__internal__n_error_58,\n  s_n_llhttp__internal__n_header_value_te_token_ows,\n  s_n_llhttp__internal__n_header_value,\n  s_n_llhttp__internal__n_header_value_te_token,\n  s_n_llhttp__internal__n_header_value_te_chunked_last,\n  s_n_llhttp__internal__n_header_value_te_chunked,\n  s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1,\n  s_n_llhttp__internal__n_header_value_discard_ws,\n  s_n_llhttp__internal__n_invoke_load_header_state,\n  s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete,\n  s_n_llhttp__internal__n_header_field_general_otherwise,\n  s_n_llhttp__internal__n_header_field_general,\n  s_n_llhttp__internal__n_header_field_colon,\n  s_n_llhttp__internal__n_header_field_3,\n  s_n_llhttp__internal__n_header_field_4,\n  s_n_llhttp__internal__n_header_field_2,\n  s_n_llhttp__internal__n_header_field_1,\n  s_n_llhttp__internal__n_header_field_5,\n  s_n_llhttp__internal__n_header_field_6,\n  s_n_llhttp__internal__n_header_field_7,\n  s_n_llhttp__internal__n_header_field,\n  s_n_llhttp__internal__n_span_start_llhttp__on_header_field,\n  s_n_llhttp__internal__n_header_field_start,\n  s_n_llhttp__internal__n_headers_start,\n  s_n_llhttp__internal__n_url_to_http_09,\n  s_n_llhttp__internal__n_url_skip_to_http09,\n  s_n_llhttp__internal__n_url_skip_lf_to_http09_1,\n  s_n_llhttp__internal__n_url_skip_lf_to_http09,\n  s_n_llhttp__internal__n_req_pri_upgrade,\n  s_n_llhttp__internal__n_req_http_complete_crlf,\n  s_n_llhttp__internal__n_req_http_complete,\n  s_n_llhttp__internal__n_invoke_load_method_1,\n  s_n_llhttp__internal__n_invoke_llhttp__on_version_complete,\n  s_n_llhttp__internal__n_error_67,\n  s_n_llhttp__internal__n_error_74,\n  s_n_llhttp__internal__n_req_http_minor,\n  s_n_llhttp__internal__n_error_75,\n  s_n_llhttp__internal__n_req_http_dot,\n  s_n_llhttp__internal__n_error_76,\n  s_n_llhttp__internal__n_req_http_major,\n  s_n_llhttp__internal__n_span_start_llhttp__on_version,\n  s_n_llhttp__internal__n_req_after_protocol,\n  s_n_llhttp__internal__n_invoke_load_method,\n  s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete,\n  s_n_llhttp__internal__n_error_82,\n  s_n_llhttp__internal__n_req_after_http_start_1,\n  s_n_llhttp__internal__n_invoke_load_method_2,\n  s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_1,\n  s_n_llhttp__internal__n_req_after_http_start_2,\n  s_n_llhttp__internal__n_invoke_load_method_3,\n  s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_2,\n  s_n_llhttp__internal__n_req_after_http_start_3,\n  s_n_llhttp__internal__n_req_after_http_start,\n  s_n_llhttp__internal__n_span_start_llhttp__on_protocol,\n  s_n_llhttp__internal__n_req_http_start,\n  s_n_llhttp__internal__n_url_to_http,\n  s_n_llhttp__internal__n_url_skip_to_http,\n  s_n_llhttp__internal__n_url_fragment,\n  s_n_llhttp__internal__n_span_end_stub_query_3,\n  s_n_llhttp__internal__n_url_query,\n  s_n_llhttp__internal__n_url_query_or_fragment,\n  s_n_llhttp__internal__n_url_path,\n  s_n_llhttp__internal__n_span_start_stub_path_2,\n  s_n_llhttp__internal__n_span_start_stub_path,\n  s_n_llhttp__internal__n_span_start_stub_path_1,\n  s_n_llhttp__internal__n_url_server_with_at,\n  s_n_llhttp__internal__n_url_server,\n  s_n_llhttp__internal__n_url_schema_delim_1,\n  s_n_llhttp__internal__n_url_schema_delim,\n  s_n_llhttp__internal__n_span_end_stub_schema,\n  s_n_llhttp__internal__n_url_schema,\n  s_n_llhttp__internal__n_url_start,\n  s_n_llhttp__internal__n_span_start_llhttp__on_url_1,\n  s_n_llhttp__internal__n_url_entry_normal,\n  s_n_llhttp__internal__n_span_start_llhttp__on_url,\n  s_n_llhttp__internal__n_url_entry_connect,\n  s_n_llhttp__internal__n_req_spaces_before_url,\n  s_n_llhttp__internal__n_req_first_space_before_url,\n  s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1,\n  s_n_llhttp__internal__n_after_start_req_2,\n  s_n_llhttp__internal__n_after_start_req_3,\n  s_n_llhttp__internal__n_after_start_req_1,\n  s_n_llhttp__internal__n_after_start_req_4,\n  s_n_llhttp__internal__n_after_start_req_6,\n  s_n_llhttp__internal__n_after_start_req_8,\n  s_n_llhttp__internal__n_after_start_req_9,\n  s_n_llhttp__internal__n_after_start_req_7,\n  s_n_llhttp__internal__n_after_start_req_5,\n  s_n_llhttp__internal__n_after_start_req_12,\n  s_n_llhttp__internal__n_after_start_req_13,\n  s_n_llhttp__internal__n_after_start_req_11,\n  s_n_llhttp__internal__n_after_start_req_10,\n  s_n_llhttp__internal__n_after_start_req_14,\n  s_n_llhttp__internal__n_after_start_req_17,\n  s_n_llhttp__internal__n_after_start_req_16,\n  s_n_llhttp__internal__n_after_start_req_15,\n  s_n_llhttp__internal__n_after_start_req_18,\n  s_n_llhttp__internal__n_after_start_req_20,\n  s_n_llhttp__internal__n_after_start_req_21,\n  s_n_llhttp__internal__n_after_start_req_19,\n  s_n_llhttp__internal__n_after_start_req_23,\n  s_n_llhttp__internal__n_after_start_req_24,\n  s_n_llhttp__internal__n_after_start_req_26,\n  s_n_llhttp__internal__n_after_start_req_28,\n  s_n_llhttp__internal__n_after_start_req_29,\n  s_n_llhttp__internal__n_after_start_req_27,\n  s_n_llhttp__internal__n_after_start_req_25,\n  s_n_llhttp__internal__n_after_start_req_30,\n  s_n_llhttp__internal__n_after_start_req_22,\n  s_n_llhttp__internal__n_after_start_req_31,\n  s_n_llhttp__internal__n_after_start_req_32,\n  s_n_llhttp__internal__n_after_start_req_35,\n  s_n_llhttp__internal__n_after_start_req_36,\n  s_n_llhttp__internal__n_after_start_req_34,\n  s_n_llhttp__internal__n_after_start_req_37,\n  s_n_llhttp__internal__n_after_start_req_38,\n  s_n_llhttp__internal__n_after_start_req_42,\n  s_n_llhttp__internal__n_after_start_req_43,\n  s_n_llhttp__internal__n_after_start_req_41,\n  s_n_llhttp__internal__n_after_start_req_40,\n  s_n_llhttp__internal__n_after_start_req_39,\n  s_n_llhttp__internal__n_after_start_req_45,\n  s_n_llhttp__internal__n_after_start_req_44,\n  s_n_llhttp__internal__n_after_start_req_33,\n  s_n_llhttp__internal__n_after_start_req_46,\n  s_n_llhttp__internal__n_after_start_req_49,\n  s_n_llhttp__internal__n_after_start_req_50,\n  s_n_llhttp__internal__n_after_start_req_51,\n  s_n_llhttp__internal__n_after_start_req_52,\n  s_n_llhttp__internal__n_after_start_req_48,\n  s_n_llhttp__internal__n_after_start_req_47,\n  s_n_llhttp__internal__n_after_start_req_55,\n  s_n_llhttp__internal__n_after_start_req_57,\n  s_n_llhttp__internal__n_after_start_req_58,\n  s_n_llhttp__internal__n_after_start_req_56,\n  s_n_llhttp__internal__n_after_start_req_54,\n  s_n_llhttp__internal__n_after_start_req_59,\n  s_n_llhttp__internal__n_after_start_req_60,\n  s_n_llhttp__internal__n_after_start_req_53,\n  s_n_llhttp__internal__n_after_start_req_62,\n  s_n_llhttp__internal__n_after_start_req_63,\n  s_n_llhttp__internal__n_after_start_req_61,\n  s_n_llhttp__internal__n_after_start_req_66,\n  s_n_llhttp__internal__n_after_start_req_68,\n  s_n_llhttp__internal__n_after_start_req_69,\n  s_n_llhttp__internal__n_after_start_req_67,\n  s_n_llhttp__internal__n_after_start_req_70,\n  s_n_llhttp__internal__n_after_start_req_65,\n  s_n_llhttp__internal__n_after_start_req_64,\n  s_n_llhttp__internal__n_after_start_req,\n  s_n_llhttp__internal__n_span_start_llhttp__on_method_1,\n  s_n_llhttp__internal__n_res_line_almost_done,\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_30,\n  s_n_llhttp__internal__n_res_status,\n  s_n_llhttp__internal__n_span_start_llhttp__on_status,\n  s_n_llhttp__internal__n_res_status_code_otherwise,\n  s_n_llhttp__internal__n_res_status_code_digit_3,\n  s_n_llhttp__internal__n_res_status_code_digit_2,\n  s_n_llhttp__internal__n_res_status_code_digit_1,\n  s_n_llhttp__internal__n_res_after_version,\n  s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1,\n  s_n_llhttp__internal__n_error_93,\n  s_n_llhttp__internal__n_error_107,\n  s_n_llhttp__internal__n_res_http_minor,\n  s_n_llhttp__internal__n_error_108,\n  s_n_llhttp__internal__n_res_http_dot,\n  s_n_llhttp__internal__n_error_109,\n  s_n_llhttp__internal__n_res_http_major,\n  s_n_llhttp__internal__n_span_start_llhttp__on_version_1,\n  s_n_llhttp__internal__n_res_after_protocol,\n  s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_3,\n  s_n_llhttp__internal__n_error_115,\n  s_n_llhttp__internal__n_res_after_start_1,\n  s_n_llhttp__internal__n_res_after_start_2,\n  s_n_llhttp__internal__n_res_after_start_3,\n  s_n_llhttp__internal__n_res_after_start,\n  s_n_llhttp__internal__n_span_start_llhttp__on_protocol_1,\n  s_n_llhttp__internal__n_invoke_llhttp__on_method_complete,\n  s_n_llhttp__internal__n_req_or_res_method_2,\n  s_n_llhttp__internal__n_invoke_update_type_1,\n  s_n_llhttp__internal__n_req_or_res_method_3,\n  s_n_llhttp__internal__n_req_or_res_method_1,\n  s_n_llhttp__internal__n_req_or_res_method,\n  s_n_llhttp__internal__n_span_start_llhttp__on_method,\n  s_n_llhttp__internal__n_start_req_or_res,\n  s_n_llhttp__internal__n_invoke_load_type,\n  s_n_llhttp__internal__n_invoke_update_finish,\n  s_n_llhttp__internal__n_start,\n};\ntypedef enum llparse_state_e llparse_state_t;\n\nint c_nio_llhttp__on_method(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_url(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_protocol(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_version(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_header_field(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_header_value(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_body(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_chunk_extension_name(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_chunk_extension_value(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_status(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_load_initial_message_completed(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->initial_message_completed;\n}\n\nint c_nio_llhttp__on_reset(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_update_finish(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->finish = 2;\n  return 0;\n}\n\nint c_nio_llhttp__on_message_begin(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_load_type(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->type;\n}\n\nint c_nio_llhttp__internal__c_store_method(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  state->method = match;\n  return 0;\n}\n\nint c_nio_llhttp__on_method_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_is_equal_method(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->method == 5;\n}\n\nint c_nio_llhttp__internal__c_update_http_major(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->http_major = 0;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_http_minor(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->http_minor = 9;\n  return 0;\n}\n\nint c_nio_llhttp__on_url_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_test_lenient_flags(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 1) == 1;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_1(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 256) == 256;\n}\n\nint c_nio_llhttp__internal__c_test_flags(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->flags & 128) == 128;\n}\n\nint c_nio_llhttp__on_chunk_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_message_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_is_equal_upgrade(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->upgrade == 1;\n}\n\nint c_nio_llhttp__after_message_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_update_content_length(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->content_length = 0;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_initial_message_completed(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->initial_message_completed = 1;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_finish_1(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->finish = 0;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_2(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 4) == 4;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_3(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 32) == 32;\n}\n\nint c_nio_llhttp__before_headers_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_headers_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__after_headers_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_mul_add_content_length(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  /* Multiplication overflow */\n  if (state->content_length > 0xffffffffffffffffULL / 16) {\n    return 1;\n  }\n  \n  state->content_length *= 16;\n  \n  /* Addition overflow */\n  if (match >= 0) {\n    if (state->content_length > 0xffffffffffffffffULL - match) {\n      return 1;\n    }\n  } else {\n    if (state->content_length < 0ULL - match) {\n      return 1;\n    }\n  }\n  state->content_length += match;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_4(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 512) == 512;\n}\n\nint c_nio_llhttp__on_chunk_header(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_is_equal_content_length(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->content_length == 0;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_7(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 128) == 128;\n}\n\nint c_nio_llhttp__internal__c_or_flags(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 128;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_8(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 64) == 64;\n}\n\nint c_nio_llhttp__on_chunk_extension_name_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__on_chunk_extension_value_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_update_finish_3(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->finish = 1;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_or_flags_1(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 64;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_upgrade(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->upgrade = 1;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_store_header_state(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  state->header_state = match;\n  return 0;\n}\n\nint c_nio_llhttp__on_header_field_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_load_header_state(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->header_state;\n}\n\nint c_nio_llhttp__internal__c_test_flags_4(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->flags & 512) == 512;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_22(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 2) == 2;\n}\n\nint c_nio_llhttp__internal__c_or_flags_5(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 1;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_header_state(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->header_state = 1;\n  return 0;\n}\n\nint c_nio_llhttp__on_header_value_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_or_flags_6(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 2;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_or_flags_7(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 4;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_or_flags_8(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 8;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_header_state_3(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->header_state = 6;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_header_state_1(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->header_state = 0;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_header_state_6(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->header_state = 5;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_header_state_7(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->header_state = 7;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_test_flags_2(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->flags & 32) == 32;\n}\n\nint c_nio_llhttp__internal__c_mul_add_content_length_1(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  /* Multiplication overflow */\n  if (state->content_length > 0xffffffffffffffffULL / 10) {\n    return 1;\n  }\n  \n  state->content_length *= 10;\n  \n  /* Addition overflow */\n  if (match >= 0) {\n    if (state->content_length > 0xffffffffffffffffULL - match) {\n      return 1;\n    }\n  } else {\n    if (state->content_length < 0ULL - match) {\n      return 1;\n    }\n  }\n  state->content_length += match;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_or_flags_17(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 32;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_test_flags_3(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->flags & 8) == 8;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_20(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 8) == 8;\n}\n\nint c_nio_llhttp__internal__c_or_flags_18(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 512;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_and_flags(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags &= -9;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_header_state_8(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->header_state = 8;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_or_flags_20(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->flags |= 16;\n  return 0;\n}\n\nint c_nio_llhttp__on_protocol_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_load_method(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->method;\n}\n\nint c_nio_llhttp__internal__c_store_http_major(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  state->http_major = match;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_store_http_minor(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  state->http_minor = match;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_test_lenient_flags_24(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return (state->lenient_flags & 16) == 16;\n}\n\nint c_nio_llhttp__on_version_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_load_http_major(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->http_major;\n}\n\nint c_nio_llhttp__internal__c_load_http_minor(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  return state->http_minor;\n}\n\nint c_nio_llhttp__internal__c_update_status_code(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->status_code = 0;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_mul_add_status_code(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp,\n    int match) {\n  /* Multiplication overflow */\n  if (state->status_code > 0xffff / 10) {\n    return 1;\n  }\n  \n  state->status_code *= 10;\n  \n  /* Addition overflow */\n  if (match >= 0) {\n    if (state->status_code > 0xffff - match) {\n      return 1;\n    }\n  } else {\n    if (state->status_code < 0 - match) {\n      return 1;\n    }\n  }\n  state->status_code += match;\n  return 0;\n}\n\nint c_nio_llhttp__on_status_complete(\n    c_nio_llhttp__internal_t* s, const unsigned char* p,\n    const unsigned char* endp);\n\nint c_nio_llhttp__internal__c_update_type(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->type = 1;\n  return 0;\n}\n\nint c_nio_llhttp__internal__c_update_type_1(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  state->type = 2;\n  return 0;\n}\n\nint c_nio_llhttp__internal_init(c_nio_llhttp__internal_t* state) {\n  memset(state, 0, sizeof(*state));\n  state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_start;\n  return 0;\n}\n\nstatic llparse_state_t c_nio_llhttp__internal__run(\n    c_nio_llhttp__internal_t* state,\n    const unsigned char* p,\n    const unsigned char* endp) {\n  int match;\n  switch ((llparse_state_t) (intptr_t) state->_current) {\n    case s_n_llhttp__internal__n_closed:\n    s_n_llhttp__internal__n_closed: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_closed;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_closed;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_closed;\n        }\n        default: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__after_message_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: {\n      switch (c_nio_llhttp__after_message_complete(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_invoke_update_content_length;\n        default:\n          goto s_n_llhttp__internal__n_invoke_update_finish_1;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_pause_1:\n    s_n_llhttp__internal__n_pause_1: {\n      state->error = 0x16;\n      state->reason = \"Pause on CONNECT/Upgrade\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_message_complete;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_is_equal_upgrade:\n    s_n_llhttp__internal__n_invoke_is_equal_upgrade: {\n      switch (c_nio_llhttp__internal__c_is_equal_upgrade(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_llhttp__after_message_complete;\n        default:\n          goto s_n_llhttp__internal__n_pause_1;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2:\n    s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2: {\n      switch (c_nio_llhttp__on_message_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_is_equal_upgrade;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_13;\n        default:\n          goto s_n_llhttp__internal__n_error_38;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_data_almost_done_1:\n    s_n_llhttp__internal__n_chunk_data_almost_done_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_data_almost_done_1;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_7;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_data_almost_done:\n    s_n_llhttp__internal__n_chunk_data_almost_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_data_almost_done;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_6;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_data_almost_done_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_7;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_consume_content_length:\n    s_n_llhttp__internal__n_consume_content_length: {\n      size_t avail;\n      uint64_t need;\n      \n      avail = endp - p;\n      need = state->content_length;\n      if (avail >= need) {\n        p += need;\n        state->content_length = 0;\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_body;\n      }\n      \n      state->content_length -= avail;\n      return s_n_llhttp__internal__n_consume_content_length;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_body:\n    s_n_llhttp__internal__n_span_start_llhttp__on_body: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_body;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_body;\n      goto s_n_llhttp__internal__n_consume_content_length;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_is_equal_content_length:\n    s_n_llhttp__internal__n_invoke_is_equal_content_length: {\n      switch (c_nio_llhttp__internal__c_is_equal_content_length(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_body;\n        default:\n          goto s_n_llhttp__internal__n_invoke_or_flags;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_size_almost_done:\n    s_n_llhttp__internal__n_chunk_size_almost_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_size_almost_done;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_header;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_8;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_test_lenient_flags_9:\n    s_n_llhttp__internal__n_invoke_test_lenient_flags_9: {\n      switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_chunk_size_almost_done;\n        default:\n          goto s_n_llhttp__internal__n_error_20;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete: {\n      switch (c_nio_llhttp__on_chunk_extension_name_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_9;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_5;\n        default:\n          goto s_n_llhttp__internal__n_error_19;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1: {\n      switch (c_nio_llhttp__on_chunk_extension_name_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_chunk_size_almost_done;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_6;\n        default:\n          goto s_n_llhttp__internal__n_error_21;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2: {\n      switch (c_nio_llhttp__on_chunk_extension_name_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_chunk_extensions;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_7;\n        default:\n          goto s_n_llhttp__internal__n_error_22;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_test_lenient_flags_10:\n    s_n_llhttp__internal__n_invoke_test_lenient_flags_10: {\n      switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_chunk_size_almost_done;\n        default:\n          goto s_n_llhttp__internal__n_error_25;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete: {\n      switch (c_nio_llhttp__on_chunk_extension_value_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_10;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_8;\n        default:\n          goto s_n_llhttp__internal__n_error_24;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1: {\n      switch (c_nio_llhttp__on_chunk_extension_value_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_chunk_size_almost_done;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_9;\n        default:\n          goto s_n_llhttp__internal__n_error_26;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_extension_quoted_value_done:\n    s_n_llhttp__internal__n_chunk_extension_quoted_value_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_extension_quoted_value_done;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_11;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_size_almost_done;\n        }\n        case ';': {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extensions;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_29;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2: {\n      switch (c_nio_llhttp__on_chunk_extension_value_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_chunk_extension_quoted_value_done;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_10;\n        default:\n          goto s_n_llhttp__internal__n_error_27;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_30:\n    s_n_llhttp__internal__n_error_30: {\n      state->error = 0x2;\n      state->reason = \"Invalid quoted-pair in chunk extensions quoted value\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair:\n    s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extension_quoted_value;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_31:\n    s_n_llhttp__internal__n_error_31: {\n      state->error = 0x2;\n      state->reason = \"Invalid character in chunk extensions quoted value\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_extension_quoted_value:\n    s_n_llhttp__internal__n_chunk_extension_quoted_value: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_extension_quoted_value;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extension_quoted_value;\n        }\n        case 2: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_2;\n        }\n        case 3: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_4;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3:\n    s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3: {\n      switch (c_nio_llhttp__on_chunk_extension_value_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_chunk_extensions;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_11;\n        default:\n          goto s_n_llhttp__internal__n_error_32;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_33:\n    s_n_llhttp__internal__n_error_33: {\n      state->error = 0x2;\n      state->reason = \"Invalid character in chunk extensions value\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_extension_value:\n    s_n_llhttp__internal__n_chunk_extension_value: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 3, 4, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3, 3, 0,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 5, 0, 0, 0, 0,\n        0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 0, 3, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_extension_value;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_1;\n        }\n        case 3: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extension_value;\n        }\n        case 4: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extension_quoted_value;\n        }\n        case 5: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_5;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_6;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value:\n    s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_chunk_extension_value;\n      goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_3;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_34:\n    s_n_llhttp__internal__n_error_34: {\n      state->error = 0x2;\n      state->reason = \"Invalid character in chunk extensions name\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_extension_name:\n    s_n_llhttp__internal__n_chunk_extension_name: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3, 3, 0,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 4, 0, 5, 0, 0,\n        0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 0, 3, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_extension_name;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_1;\n        }\n        case 3: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extension_name;\n        }\n        case 4: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_2;\n        }\n        case 5: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_4;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name:\n    s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_chunk_extension_name;\n      goto s_n_llhttp__internal__n_chunk_extension_name;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_extensions:\n    s_n_llhttp__internal__n_chunk_extensions: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_extensions;\n      }\n      switch (*p) {\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_error_17;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_error_18;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_size_otherwise:\n    s_n_llhttp__internal__n_chunk_size_otherwise: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_size_otherwise;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_4;\n        }\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_5;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_size_almost_done;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_4;\n        }\n        case ';': {\n          p++;\n          goto s_n_llhttp__internal__n_chunk_extensions;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_35;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_size:\n    s_n_llhttp__internal__n_chunk_size: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_size;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'A': {\n          p++;\n          match = 10;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'B': {\n          p++;\n          match = 11;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'C': {\n          p++;\n          match = 12;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'D': {\n          p++;\n          match = 13;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'E': {\n          p++;\n          match = 14;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'F': {\n          p++;\n          match = 15;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'a': {\n          p++;\n          match = 10;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'b': {\n          p++;\n          match = 11;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'c': {\n          p++;\n          match = 12;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'd': {\n          p++;\n          match = 13;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'e': {\n          p++;\n          match = 14;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'f': {\n          p++;\n          match = 15;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_chunk_size_otherwise;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_chunk_size_digit:\n    s_n_llhttp__internal__n_chunk_size_digit: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_chunk_size_digit;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'A': {\n          p++;\n          match = 10;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'B': {\n          p++;\n          match = 11;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'C': {\n          p++;\n          match = 12;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'D': {\n          p++;\n          match = 13;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'E': {\n          p++;\n          match = 14;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'F': {\n          p++;\n          match = 15;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'a': {\n          p++;\n          match = 10;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'b': {\n          p++;\n          match = 11;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'c': {\n          p++;\n          match = 12;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'd': {\n          p++;\n          match = 13;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'e': {\n          p++;\n          match = 14;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        case 'f': {\n          p++;\n          match = 15;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_37;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_update_content_length_1:\n    s_n_llhttp__internal__n_invoke_update_content_length_1: {\n      switch (c_nio_llhttp__internal__c_update_content_length(state, p, endp)) {\n        default:\n          goto s_n_llhttp__internal__n_chunk_size_digit;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_consume_content_length_1:\n    s_n_llhttp__internal__n_consume_content_length_1: {\n      size_t avail;\n      uint64_t need;\n      \n      avail = endp - p;\n      need = state->content_length;\n      if (avail >= need) {\n        p += need;\n        state->content_length = 0;\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_body_1;\n      }\n      \n      state->content_length -= avail;\n      return s_n_llhttp__internal__n_consume_content_length_1;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_body_1:\n    s_n_llhttp__internal__n_span_start_llhttp__on_body_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_body_1;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_body;\n      goto s_n_llhttp__internal__n_consume_content_length_1;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_eof:\n    s_n_llhttp__internal__n_eof: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_eof;\n      }\n      p++;\n      goto s_n_llhttp__internal__n_eof;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_body_2:\n    s_n_llhttp__internal__n_span_start_llhttp__on_body_2: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_body_2;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_body;\n      goto s_n_llhttp__internal__n_eof;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete: {\n      switch (c_nio_llhttp__after_headers_complete(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_1;\n        case 2:\n          goto s_n_llhttp__internal__n_invoke_update_content_length_1;\n        case 3:\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_body_1;\n        case 4:\n          goto s_n_llhttp__internal__n_invoke_update_finish_3;\n        case 5:\n          goto s_n_llhttp__internal__n_error_39;\n        default:\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_5:\n    s_n_llhttp__internal__n_error_5: {\n      state->error = 0xa;\n      state->reason = \"Invalid header field char\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_headers_almost_done:\n    s_n_llhttp__internal__n_headers_almost_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_headers_almost_done;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_flags_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_12;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_colon_discard_ws:\n    s_n_llhttp__internal__n_header_field_colon_discard_ws: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_colon_discard_ws;\n      }\n      switch (*p) {\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_colon_discard_ws;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_field_colon;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete: {\n      switch (c_nio_llhttp__on_header_value_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_header_field_start;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_18;\n        default:\n          goto s_n_llhttp__internal__n_error_48;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_header_value:\n    s_n_llhttp__internal__n_span_start_llhttp__on_header_value: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_header_value;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_header_value;\n      goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_discard_lws:\n    s_n_llhttp__internal__n_header_value_discard_lws: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_discard_lws;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_15;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_15;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_load_header_state_1;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_discard_ws_almost_done:\n    s_n_llhttp__internal__n_header_value_discard_ws_almost_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_discard_ws_almost_done;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_discard_lws;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_16;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_lws:\n    s_n_llhttp__internal__n_header_value_lws: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_lws;\n      }\n      switch (*p) {\n        case 9: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_18;\n        }\n        case ' ': {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_18;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_load_header_state_5;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_almost_done:\n    s_n_llhttp__internal__n_header_value_almost_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_almost_done;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_lws;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_53;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_test_lenient_flags_17:\n    s_n_llhttp__internal__n_invoke_test_lenient_flags_17: {\n      switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_header_value_almost_done;\n        default:\n          goto s_n_llhttp__internal__n_error_51;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_lenient:\n    s_n_llhttp__internal__n_header_value_lenient: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_lenient;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_4;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_5;\n        }\n        default: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_lenient;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_54:\n    s_n_llhttp__internal__n_error_54: {\n      state->error = 0xa;\n      state->reason = \"Invalid header value char\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_otherwise:\n    s_n_llhttp__internal__n_header_value_otherwise: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_otherwise;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_1;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_19;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_connection_token:\n    s_n_llhttp__internal__n_header_value_connection_token: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_connection_token;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection_token;\n        }\n        case 2: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_value_otherwise;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_connection_ws:\n    s_n_llhttp__internal__n_header_value_connection_ws: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_connection_ws;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_header_value_otherwise;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_header_value_otherwise;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection_ws;\n        }\n        case ',': {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_load_header_state_6;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_5;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_connection_1:\n    s_n_llhttp__internal__n_header_value_connection_1: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_connection_1;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob2, 4);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_update_header_state_3;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_value_connection_1;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_header_value_connection_token;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_connection_2:\n    s_n_llhttp__internal__n_header_value_connection_2: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_connection_2;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob3, 9);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_update_header_state_6;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_value_connection_2;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_header_value_connection_token;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_connection_3:\n    s_n_llhttp__internal__n_header_value_connection_3: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_connection_3;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob4, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_update_header_state_7;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_value_connection_3;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_header_value_connection_token;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_connection:\n    s_n_llhttp__internal__n_header_value_connection: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_connection;\n      }\n      switch (((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p))) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection;\n        }\n        case 'c': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection_1;\n        }\n        case 'k': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection_2;\n        }\n        case 'u': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_connection_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_value_connection_token;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_56:\n    s_n_llhttp__internal__n_error_56: {\n      state->error = 0xb;\n      state->reason = \"Content-Length overflow\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_57:\n    s_n_llhttp__internal__n_error_57: {\n      state->error = 0xb;\n      state->reason = \"Invalid character in Content-Length\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_content_length_ws:\n    s_n_llhttp__internal__n_header_value_content_length_ws: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_content_length_ws;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_invoke_or_flags_17;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_invoke_or_flags_17;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_content_length_ws;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_7;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_content_length:\n    s_n_llhttp__internal__n_header_value_content_length: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_content_length;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_value_content_length_ws;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_59:\n    s_n_llhttp__internal__n_error_59: {\n      state->error = 0xf;\n      state->reason = \"Invalid `Transfer-Encoding` header value\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_58:\n    s_n_llhttp__internal__n_error_58: {\n      state->error = 0xf;\n      state->reason = \"Invalid `Transfer-Encoding` header value\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_te_token_ows:\n    s_n_llhttp__internal__n_header_value_te_token_ows: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_te_token_ows;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_te_token_ows;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_te_token_ows;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_value_te_chunked;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value:\n    s_n_llhttp__internal__n_header_value: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value;\n      }\n      #ifdef __SSE4_2__\n      if (endp - p >= 16) {\n        __m128i ranges;\n        __m128i input;\n        int match_len;\n      \n        /* Load input */\n        input = _mm_loadu_si128((__m128i const*) p);\n        ranges = _mm_loadu_si128((__m128i const*) llparse_blob6);\n      \n        /* Find first character that does not match `ranges` */\n        match_len = _mm_cmpestri(ranges, 6,\n            input, 16,\n            _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |\n              _SIDD_NEGATIVE_POLARITY);\n      \n        if (match_len != 0) {\n          p += match_len;\n          goto s_n_llhttp__internal__n_header_value;\n        }\n        goto s_n_llhttp__internal__n_header_value_otherwise;\n      }\n      #endif  /* __SSE4_2__ */\n      #ifdef __ARM_NEON__\n      while (endp - p >= 16) {\n        uint8x16_t input;\n        uint8x16_t single;\n        uint8x16_t mask;\n        uint8x8_t narrow;\n        uint64_t match_mask;\n        int match_len;\n      \n        /* Load input */\n        input = vld1q_u8(p);\n        /* Find first character that does not match `ranges` */\n        single = vceqq_u8(input, vdupq_n_u8(0x9));\n        mask = single;\n        single = vandq_u16(\n          vcgeq_u8(input, vdupq_n_u8(' ')),\n          vcleq_u8(input, vdupq_n_u8('~'))\n        );\n        mask = vorrq_u16(mask, single);\n        single = vandq_u16(\n          vcgeq_u8(input, vdupq_n_u8(0x80)),\n          vcleq_u8(input, vdupq_n_u8(0xff))\n        );\n        mask = vorrq_u16(mask, single);\n        narrow = vshrn_n_u16(mask, 4);\n        match_mask = ~vget_lane_u64(vreinterpret_u64_u8(narrow), 0);\n        match_len = __builtin_ctzll(match_mask) >> 2;\n        if (match_len != 16) {\n          p += match_len;\n          goto s_n_llhttp__internal__n_header_value_otherwise;\n        }\n        p += 16;\n      }\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value;\n      }\n      #endif  /* __ARM_NEON__ */\n      #ifdef __wasm_simd128__\n      while (endp - p >= 16) {\n        v128_t input;\n        v128_t mask;\n        v128_t single;\n        int match_len;\n      \n        /* Load input */\n        input = wasm_v128_load(p);\n        /* Find first character that does not match `ranges` */\n        single = wasm_i8x16_eq(input, wasm_u8x16_const_splat(0x9));\n        mask = single;\n        single = wasm_v128_and(\n          wasm_i8x16_ge(input, wasm_u8x16_const_splat(' ')),\n          wasm_i8x16_le(input, wasm_u8x16_const_splat('~'))\n        );\n        mask = wasm_v128_or(mask, single);\n        single = wasm_v128_and(\n          wasm_i8x16_ge(input, wasm_u8x16_const_splat(0x80)),\n          wasm_i8x16_le(input, wasm_u8x16_const_splat(0xff))\n        );\n        mask = wasm_v128_or(mask, single);\n        match_len = __builtin_ctz(\n          ~wasm_i8x16_bitmask(mask)\n        );\n        if (match_len != 16) {\n          p += match_len;\n          goto s_n_llhttp__internal__n_header_value_otherwise;\n        }\n        p += 16;\n      }\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value;\n      }\n      #endif  /* __wasm_simd128__ */\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_value_otherwise;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_te_token:\n    s_n_llhttp__internal__n_header_value_te_token: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_te_token;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_te_token;\n        }\n        case 2: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_te_token_ows;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_9;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_te_chunked_last:\n    s_n_llhttp__internal__n_header_value_te_chunked_last: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_te_chunked_last;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_8;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_8;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_te_chunked_last;\n        }\n        case ',': {\n          goto s_n_llhttp__internal__n_invoke_load_type_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_value_te_token;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_te_chunked:\n    s_n_llhttp__internal__n_header_value_te_chunked: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_te_chunked;\n      }\n      match_seq = llparse__match_sequence_to_lower_unsafe(state, p, endp, llparse_blob5, 7);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_te_chunked_last;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_value_te_chunked;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_header_value_te_token;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1:\n    s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_header_value;\n      goto s_n_llhttp__internal__n_invoke_load_header_state_3;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_value_discard_ws:\n    s_n_llhttp__internal__n_header_value_discard_ws: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_value_discard_ws;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_discard_ws;\n        }\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_14;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_discard_ws_almost_done;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_header_value_discard_ws;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_load_header_state:\n    s_n_llhttp__internal__n_invoke_load_header_state: {\n      switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n        case 2:\n          goto s_n_llhttp__internal__n_invoke_test_flags_4;\n        case 3:\n          goto s_n_llhttp__internal__n_invoke_test_flags_5;\n        default:\n          goto s_n_llhttp__internal__n_header_value_discard_ws;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete: {\n      switch (c_nio_llhttp__on_header_field_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_load_header_state;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_19;\n        default:\n          goto s_n_llhttp__internal__n_error_45;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_general_otherwise:\n    s_n_llhttp__internal__n_header_field_general_otherwise: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_general_otherwise;\n      }\n      switch (*p) {\n        case ':': {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_62;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_general:\n    s_n_llhttp__internal__n_header_field_general: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,\n        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_general;\n      }\n      #ifdef __SSE4_2__\n      if (endp - p >= 16) {\n        __m128i ranges;\n        __m128i input;\n        int match_len;\n      \n        /* Load input */\n        input = _mm_loadu_si128((__m128i const*) p);\n        ranges = _mm_loadu_si128((__m128i const*) llparse_blob7);\n      \n        /* Find first character that does not match `ranges` */\n        match_len = _mm_cmpestri(ranges, 16,\n            input, 16,\n            _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |\n              _SIDD_NEGATIVE_POLARITY);\n      \n        if (match_len != 0) {\n          p += match_len;\n          goto s_n_llhttp__internal__n_header_field_general;\n        }\n        ranges = _mm_loadu_si128((__m128i const*) llparse_blob8);\n      \n        /* Find first character that does not match `ranges` */\n        match_len = _mm_cmpestri(ranges, 2,\n            input, 16,\n            _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |\n              _SIDD_NEGATIVE_POLARITY);\n      \n        if (match_len != 0) {\n          p += match_len;\n          goto s_n_llhttp__internal__n_header_field_general;\n        }\n        goto s_n_llhttp__internal__n_header_field_general_otherwise;\n      }\n      #endif  /* __SSE4_2__ */\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_general;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_field_general_otherwise;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_colon:\n    s_n_llhttp__internal__n_header_field_colon: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_colon;\n      }\n      switch (*p) {\n        case ' ': {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_13;\n        }\n        case ':': {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_10;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_3:\n    s_n_llhttp__internal__n_header_field_3: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_3;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob1, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_header_state;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_field_3;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_4:\n    s_n_llhttp__internal__n_header_field_4: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_4;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob9, 10);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_header_state;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_field_4;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_2:\n    s_n_llhttp__internal__n_header_field_2: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_2;\n      }\n      switch (((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p))) {\n        case 'n': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_3;\n        }\n        case 't': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_4;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_1:\n    s_n_llhttp__internal__n_header_field_1: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_1;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob0, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_2;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_field_1;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_5:\n    s_n_llhttp__internal__n_header_field_5: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_5;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob10, 15);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_header_state;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_field_5;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_6:\n    s_n_llhttp__internal__n_header_field_6: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_6;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob11, 16);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_store_header_state;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_field_6;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_7:\n    s_n_llhttp__internal__n_header_field_7: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_7;\n      }\n      match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob12, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_store_header_state;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_header_field_7;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field:\n    s_n_llhttp__internal__n_header_field: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field;\n      }\n      switch (((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p))) {\n        case 'c': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_1;\n        }\n        case 'p': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_5;\n        }\n        case 't': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_6;\n        }\n        case 'u': {\n          p++;\n          goto s_n_llhttp__internal__n_header_field_7;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_header_state_11;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_header_field:\n    s_n_llhttp__internal__n_span_start_llhttp__on_header_field: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_header_field;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_header_field;\n      goto s_n_llhttp__internal__n_header_field;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_header_field_start:\n    s_n_llhttp__internal__n_header_field_start: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_header_field_start;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_headers_almost_done;\n        }\n        case ':': {\n          goto s_n_llhttp__internal__n_error_44;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_header_field;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_headers_start:\n    s_n_llhttp__internal__n_headers_start: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_headers_start;\n      }\n      switch (*p) {\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_header_field_start;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_to_http_09:\n    s_n_llhttp__internal__n_url_to_http_09: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_to_http_09;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_http_major;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_skip_to_http09:\n    s_n_llhttp__internal__n_url_skip_to_http09: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_skip_to_http09;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        default: {\n          p++;\n          goto s_n_llhttp__internal__n_url_to_http_09;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_skip_lf_to_http09_1:\n    s_n_llhttp__internal__n_url_skip_lf_to_http09_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_skip_lf_to_http09_1;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_url_to_http_09;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_63;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_skip_lf_to_http09:\n    s_n_llhttp__internal__n_url_skip_lf_to_http09: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_skip_lf_to_http09;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_url_skip_lf_to_http09_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_63;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_pri_upgrade:\n    s_n_llhttp__internal__n_req_pri_upgrade: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_pri_upgrade;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob14, 10);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_error_72;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_req_pri_upgrade;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_73;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_http_complete_crlf:\n    s_n_llhttp__internal__n_req_http_complete_crlf: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_http_complete_crlf;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_headers_start;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_26;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_http_complete:\n    s_n_llhttp__internal__n_req_http_complete: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_http_complete;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_25;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_req_http_complete_crlf;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_71;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_load_method_1:\n    s_n_llhttp__internal__n_invoke_load_method_1: {\n      switch (c_nio_llhttp__internal__c_load_method(state, p, endp)) {\n        case 34:\n          goto s_n_llhttp__internal__n_req_pri_upgrade;\n        default:\n          goto s_n_llhttp__internal__n_req_http_complete;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_version_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_version_complete: {\n      switch (c_nio_llhttp__on_version_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_load_method_1;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_21;\n        default:\n          goto s_n_llhttp__internal__n_error_68;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_67:\n    s_n_llhttp__internal__n_error_67: {\n      state->error = 0x9;\n      state->reason = \"Invalid HTTP version\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_74:\n    s_n_llhttp__internal__n_error_74: {\n      state->error = 0x9;\n      state->reason = \"Invalid minor version\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_http_minor:\n    s_n_llhttp__internal__n_req_http_minor: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_http_minor;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_version_2;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_75:\n    s_n_llhttp__internal__n_error_75: {\n      state->error = 0x9;\n      state->reason = \"Expected dot\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_http_dot:\n    s_n_llhttp__internal__n_req_http_dot: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_http_dot;\n      }\n      switch (*p) {\n        case '.': {\n          p++;\n          goto s_n_llhttp__internal__n_req_http_minor;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_version_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_76:\n    s_n_llhttp__internal__n_error_76: {\n      state->error = 0x9;\n      state->reason = \"Invalid major version\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_http_major:\n    s_n_llhttp__internal__n_req_http_major: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_http_major;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_store_http_major;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_version_4;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_version:\n    s_n_llhttp__internal__n_span_start_llhttp__on_version: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_version;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_version;\n      goto s_n_llhttp__internal__n_req_http_major;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_after_protocol:\n    s_n_llhttp__internal__n_req_after_protocol: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_after_protocol;\n      }\n      switch (*p) {\n        case '/': {\n          p++;\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_version;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_77;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_load_method:\n    s_n_llhttp__internal__n_invoke_load_method: {\n      switch (c_nio_llhttp__internal__c_load_method(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 1:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 2:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 3:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 4:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 5:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 6:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 7:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 8:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 9:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 10:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 11:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 12:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 13:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 14:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 15:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 16:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 17:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 18:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 19:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 20:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 21:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 22:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 23:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 24:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 25:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 26:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 27:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 28:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 29:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 30:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 31:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 32:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 33:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 34:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 46:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        default:\n          goto s_n_llhttp__internal__n_error_66;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete: {\n      switch (c_nio_llhttp__on_protocol_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_load_method;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_22;\n        default:\n          goto s_n_llhttp__internal__n_error_65;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_82:\n    s_n_llhttp__internal__n_error_82: {\n      state->error = 0x8;\n      state->reason = \"Expected HTTP/, RTSP/ or ICE/\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_after_http_start_1:\n    s_n_llhttp__internal__n_req_after_http_start_1: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_after_http_start_1;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob13, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_req_after_http_start_1;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_load_method_2:\n    s_n_llhttp__internal__n_invoke_load_method_2: {\n      switch (c_nio_llhttp__internal__c_load_method(state, p, endp)) {\n        case 33:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        default:\n          goto s_n_llhttp__internal__n_error_79;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_1:\n    s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_1: {\n      switch (c_nio_llhttp__on_protocol_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_load_method_2;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_23;\n        default:\n          goto s_n_llhttp__internal__n_error_78;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_after_http_start_2:\n    s_n_llhttp__internal__n_req_after_http_start_2: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_after_http_start_2;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob15, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_req_after_http_start_2;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_load_method_3:\n    s_n_llhttp__internal__n_invoke_load_method_3: {\n      switch (c_nio_llhttp__internal__c_load_method(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 3:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 6:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 35:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 36:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 37:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 38:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 39:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 40:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 41:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 42:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 43:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 44:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        case 45:\n          goto s_n_llhttp__internal__n_req_after_protocol;\n        default:\n          goto s_n_llhttp__internal__n_error_81;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_2:\n    s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_2: {\n      switch (c_nio_llhttp__on_protocol_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_invoke_load_method_3;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_24;\n        default:\n          goto s_n_llhttp__internal__n_error_80;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_after_http_start_3:\n    s_n_llhttp__internal__n_req_after_http_start_3: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_after_http_start_3;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob16, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_2;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_req_after_http_start_3;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_after_http_start:\n    s_n_llhttp__internal__n_req_after_http_start: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_after_http_start;\n      }\n      switch (*p) {\n        case 'H': {\n          p++;\n          goto s_n_llhttp__internal__n_req_after_http_start_1;\n        }\n        case 'I': {\n          p++;\n          goto s_n_llhttp__internal__n_req_after_http_start_2;\n        }\n        case 'R': {\n          p++;\n          goto s_n_llhttp__internal__n_req_after_http_start_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_3;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_protocol:\n    s_n_llhttp__internal__n_span_start_llhttp__on_protocol: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_protocol;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_protocol;\n      goto s_n_llhttp__internal__n_req_after_http_start;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_http_start:\n    s_n_llhttp__internal__n_req_http_start: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_http_start;\n      }\n      switch (*p) {\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_req_http_start;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_protocol;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_to_http:\n    s_n_llhttp__internal__n_url_to_http: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_to_http;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_url_complete_1;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_skip_to_http:\n    s_n_llhttp__internal__n_url_skip_to_http: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_skip_to_http;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        default: {\n          p++;\n          goto s_n_llhttp__internal__n_url_to_http;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_fragment:\n    s_n_llhttp__internal__n_url_fragment: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_fragment;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_6;\n        }\n        case 3: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_7;\n        }\n        case 4: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_8;\n        }\n        case 5: {\n          p++;\n          goto s_n_llhttp__internal__n_url_fragment;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_83;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_end_stub_query_3:\n    s_n_llhttp__internal__n_span_end_stub_query_3: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_end_stub_query_3;\n      }\n      p++;\n      goto s_n_llhttp__internal__n_url_fragment;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_query:\n    s_n_llhttp__internal__n_url_query: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        4, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_query;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_9;\n        }\n        case 3: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_10;\n        }\n        case 4: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_11;\n        }\n        case 5: {\n          p++;\n          goto s_n_llhttp__internal__n_url_query;\n        }\n        case 6: {\n          goto s_n_llhttp__internal__n_span_end_stub_query_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_84;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_query_or_fragment:\n    s_n_llhttp__internal__n_url_query_or_fragment: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_query_or_fragment;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 10: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_3;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_4;\n        }\n        case ' ': {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_5;\n        }\n        case '#': {\n          p++;\n          goto s_n_llhttp__internal__n_url_fragment;\n        }\n        case '?': {\n          p++;\n          goto s_n_llhttp__internal__n_url_query;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_85;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_path:\n    s_n_llhttp__internal__n_url_path: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,\n        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_path;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          p++;\n          goto s_n_llhttp__internal__n_url_path;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_url_query_or_fragment;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_stub_path_2:\n    s_n_llhttp__internal__n_span_start_stub_path_2: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_stub_path_2;\n      }\n      p++;\n      goto s_n_llhttp__internal__n_url_path;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_stub_path:\n    s_n_llhttp__internal__n_span_start_stub_path: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_stub_path;\n      }\n      p++;\n      goto s_n_llhttp__internal__n_url_path;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_stub_path_1:\n    s_n_llhttp__internal__n_span_start_stub_path_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_stub_path_1;\n      }\n      p++;\n      goto s_n_llhttp__internal__n_url_path;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_server_with_at:\n    s_n_llhttp__internal__n_url_server_with_at: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        4, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 7,\n        8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5,\n        0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_server_with_at;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_12;\n        }\n        case 3: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_13;\n        }\n        case 4: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_14;\n        }\n        case 5: {\n          p++;\n          goto s_n_llhttp__internal__n_url_server;\n        }\n        case 6: {\n          goto s_n_llhttp__internal__n_span_start_stub_path_1;\n        }\n        case 7: {\n          p++;\n          goto s_n_llhttp__internal__n_url_query;\n        }\n        case 8: {\n          p++;\n          goto s_n_llhttp__internal__n_error_86;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_87;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_server:\n    s_n_llhttp__internal__n_url_server: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        4, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 7,\n        8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5,\n        0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_server;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url;\n        }\n        case 3: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_1;\n        }\n        case 4: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_url_2;\n        }\n        case 5: {\n          p++;\n          goto s_n_llhttp__internal__n_url_server;\n        }\n        case 6: {\n          goto s_n_llhttp__internal__n_span_start_stub_path;\n        }\n        case 7: {\n          p++;\n          goto s_n_llhttp__internal__n_url_query;\n        }\n        case 8: {\n          p++;\n          goto s_n_llhttp__internal__n_url_server_with_at;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_88;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_schema_delim_1:\n    s_n_llhttp__internal__n_url_schema_delim_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_schema_delim_1;\n      }\n      switch (*p) {\n        case '/': {\n          p++;\n          goto s_n_llhttp__internal__n_url_server;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_89;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_schema_delim:\n    s_n_llhttp__internal__n_url_schema_delim: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_schema_delim;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case '/': {\n          p++;\n          goto s_n_llhttp__internal__n_url_schema_delim_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_89;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_end_stub_schema:\n    s_n_llhttp__internal__n_span_end_stub_schema: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_end_stub_schema;\n      }\n      p++;\n      goto s_n_llhttp__internal__n_url_schema_delim;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_schema:\n    s_n_llhttp__internal__n_url_schema: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,\n        0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,\n        0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_schema;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_end_stub_schema;\n        }\n        case 3: {\n          p++;\n          goto s_n_llhttp__internal__n_url_schema;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_90;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_start:\n    s_n_llhttp__internal__n_url_start: {\n      static uint8_t lookup_table[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,\n        0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n      };\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_start;\n      }\n      switch (lookup_table[(uint8_t) *p]) {\n        case 1: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 2: {\n          goto s_n_llhttp__internal__n_span_start_stub_path_2;\n        }\n        case 3: {\n          goto s_n_llhttp__internal__n_url_schema;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_91;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_url_1:\n    s_n_llhttp__internal__n_span_start_llhttp__on_url_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_url_1;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_url;\n      goto s_n_llhttp__internal__n_url_start;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_entry_normal:\n    s_n_llhttp__internal__n_url_entry_normal: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_entry_normal;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_url_1;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_url:\n    s_n_llhttp__internal__n_span_start_llhttp__on_url: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_url;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_url;\n      goto s_n_llhttp__internal__n_url_server;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_url_entry_connect:\n    s_n_llhttp__internal__n_url_entry_connect: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_url_entry_connect;\n      }\n      switch (*p) {\n        case 9: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        case 12: {\n          p++;\n          goto s_n_llhttp__internal__n_error_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_url;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_spaces_before_url:\n    s_n_llhttp__internal__n_req_spaces_before_url: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_spaces_before_url;\n      }\n      switch (*p) {\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_req_spaces_before_url;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_is_equal_method;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_first_space_before_url:\n    s_n_llhttp__internal__n_req_first_space_before_url: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_first_space_before_url;\n      }\n      switch (*p) {\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_req_spaces_before_url;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_92;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1:\n    s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1: {\n      switch (c_nio_llhttp__on_method_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_req_first_space_before_url;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_29;\n        default:\n          goto s_n_llhttp__internal__n_error_111;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_2:\n    s_n_llhttp__internal__n_after_start_req_2: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_2;\n      }\n      switch (*p) {\n        case 'L': {\n          p++;\n          match = 19;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_3:\n    s_n_llhttp__internal__n_after_start_req_3: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_3;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob17, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 36;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_3;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_1:\n    s_n_llhttp__internal__n_after_start_req_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_1;\n      }\n      switch (*p) {\n        case 'C': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_2;\n        }\n        case 'N': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_4:\n    s_n_llhttp__internal__n_after_start_req_4: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_4;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob18, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 16;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_4;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_6:\n    s_n_llhttp__internal__n_after_start_req_6: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_6;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob19, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 22;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_6;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_8:\n    s_n_llhttp__internal__n_after_start_req_8: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_8;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob20, 4);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_8;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_9:\n    s_n_llhttp__internal__n_after_start_req_9: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_9;\n      }\n      switch (*p) {\n        case 'Y': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_7:\n    s_n_llhttp__internal__n_after_start_req_7: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_7;\n      }\n      switch (*p) {\n        case 'N': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_8;\n        }\n        case 'P': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_9;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_5:\n    s_n_llhttp__internal__n_after_start_req_5: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_5;\n      }\n      switch (*p) {\n        case 'H': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_6;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_7;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_12:\n    s_n_llhttp__internal__n_after_start_req_12: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_12;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob21, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_12;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_13:\n    s_n_llhttp__internal__n_after_start_req_13: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_13;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob22, 5);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 35;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_13;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_11:\n    s_n_llhttp__internal__n_after_start_req_11: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_11;\n      }\n      switch (*p) {\n        case 'L': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_12;\n        }\n        case 'S': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_13;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_10:\n    s_n_llhttp__internal__n_after_start_req_10: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_10;\n      }\n      switch (*p) {\n        case 'E': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_11;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_14:\n    s_n_llhttp__internal__n_after_start_req_14: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_14;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob23, 4);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 45;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_14;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_17:\n    s_n_llhttp__internal__n_after_start_req_17: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_17;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob25, 9);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 41;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_17;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_16:\n    s_n_llhttp__internal__n_after_start_req_16: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_16;\n      }\n      switch (*p) {\n        case '_': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_17;\n        }\n        default: {\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_15:\n    s_n_llhttp__internal__n_after_start_req_15: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_15;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob24, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_16;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_15;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_18:\n    s_n_llhttp__internal__n_after_start_req_18: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_18;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob26, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_18;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_20:\n    s_n_llhttp__internal__n_after_start_req_20: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_20;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob27, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 31;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_20;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_21:\n    s_n_llhttp__internal__n_after_start_req_21: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_21;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob28, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_21;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_19:\n    s_n_llhttp__internal__n_after_start_req_19: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_19;\n      }\n      switch (*p) {\n        case 'I': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_20;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_21;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_23:\n    s_n_llhttp__internal__n_after_start_req_23: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_23;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob29, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 24;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_23;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_24:\n    s_n_llhttp__internal__n_after_start_req_24: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_24;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob30, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 23;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_24;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_26:\n    s_n_llhttp__internal__n_after_start_req_26: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_26;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob31, 7);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 21;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_26;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_28:\n    s_n_llhttp__internal__n_after_start_req_28: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_28;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob32, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 30;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_28;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_29:\n    s_n_llhttp__internal__n_after_start_req_29: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_29;\n      }\n      switch (*p) {\n        case 'L': {\n          p++;\n          match = 10;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_27:\n    s_n_llhttp__internal__n_after_start_req_27: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_27;\n      }\n      switch (*p) {\n        case 'A': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_28;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_29;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_25:\n    s_n_llhttp__internal__n_after_start_req_25: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_25;\n      }\n      switch (*p) {\n        case 'A': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_26;\n        }\n        case 'C': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_27;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_30:\n    s_n_llhttp__internal__n_after_start_req_30: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_30;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob33, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 11;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_30;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_22:\n    s_n_llhttp__internal__n_after_start_req_22: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_22;\n      }\n      switch (*p) {\n        case '-': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_23;\n        }\n        case 'E': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_24;\n        }\n        case 'K': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_25;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_30;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_31:\n    s_n_llhttp__internal__n_after_start_req_31: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_31;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob34, 5);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 25;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_31;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_32:\n    s_n_llhttp__internal__n_after_start_req_32: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_32;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob35, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_32;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_35:\n    s_n_llhttp__internal__n_after_start_req_35: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_35;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob36, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 28;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_35;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_36:\n    s_n_llhttp__internal__n_after_start_req_36: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_36;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob37, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 39;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_36;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_34:\n    s_n_llhttp__internal__n_after_start_req_34: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_34;\n      }\n      switch (*p) {\n        case 'T': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_35;\n        }\n        case 'U': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_36;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_37:\n    s_n_llhttp__internal__n_after_start_req_37: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_37;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob38, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 38;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_37;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_38:\n    s_n_llhttp__internal__n_after_start_req_38: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_38;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob39, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_38;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_42:\n    s_n_llhttp__internal__n_after_start_req_42: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_42;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob40, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 12;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_42;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_43:\n    s_n_llhttp__internal__n_after_start_req_43: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_43;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob41, 4);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 13;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_43;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_41:\n    s_n_llhttp__internal__n_after_start_req_41: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_41;\n      }\n      switch (*p) {\n        case 'F': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_42;\n        }\n        case 'P': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_43;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_40:\n    s_n_llhttp__internal__n_after_start_req_40: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_40;\n      }\n      switch (*p) {\n        case 'P': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_41;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_39:\n    s_n_llhttp__internal__n_after_start_req_39: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_39;\n      }\n      switch (*p) {\n        case 'I': {\n          p++;\n          match = 34;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_40;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_45:\n    s_n_llhttp__internal__n_after_start_req_45: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_45;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob42, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 29;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_45;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_44:\n    s_n_llhttp__internal__n_after_start_req_44: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_44;\n      }\n      switch (*p) {\n        case 'R': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_45;\n        }\n        case 'T': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_33:\n    s_n_llhttp__internal__n_after_start_req_33: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_33;\n      }\n      switch (*p) {\n        case 'A': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_34;\n        }\n        case 'L': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_37;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_38;\n        }\n        case 'R': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_39;\n        }\n        case 'U': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_44;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_46:\n    s_n_llhttp__internal__n_after_start_req_46: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_46;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob43, 4);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 46;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_46;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_49:\n    s_n_llhttp__internal__n_after_start_req_49: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_49;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob44, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 17;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_49;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_50:\n    s_n_llhttp__internal__n_after_start_req_50: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_50;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob45, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 44;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_50;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_51:\n    s_n_llhttp__internal__n_after_start_req_51: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_51;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob46, 5);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 43;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_51;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_52:\n    s_n_llhttp__internal__n_after_start_req_52: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_52;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob47, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 20;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_52;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_48:\n    s_n_llhttp__internal__n_after_start_req_48: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_48;\n      }\n      switch (*p) {\n        case 'B': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_49;\n        }\n        case 'C': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_50;\n        }\n        case 'D': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_51;\n        }\n        case 'P': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_52;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_47:\n    s_n_llhttp__internal__n_after_start_req_47: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_47;\n      }\n      switch (*p) {\n        case 'E': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_48;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_55:\n    s_n_llhttp__internal__n_after_start_req_55: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_55;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob48, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 14;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_55;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_57:\n    s_n_llhttp__internal__n_after_start_req_57: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_57;\n      }\n      switch (*p) {\n        case 'P': {\n          p++;\n          match = 37;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_58:\n    s_n_llhttp__internal__n_after_start_req_58: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_58;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob49, 9);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 42;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_58;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_56:\n    s_n_llhttp__internal__n_after_start_req_56: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_56;\n      }\n      switch (*p) {\n        case 'U': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_57;\n        }\n        case '_': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_58;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_54:\n    s_n_llhttp__internal__n_after_start_req_54: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_54;\n      }\n      switch (*p) {\n        case 'A': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_55;\n        }\n        case 'T': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_56;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_59:\n    s_n_llhttp__internal__n_after_start_req_59: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_59;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob50, 4);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 33;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_59;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_60:\n    s_n_llhttp__internal__n_after_start_req_60: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_60;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob51, 7);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 26;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_60;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_53:\n    s_n_llhttp__internal__n_after_start_req_53: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_53;\n      }\n      switch (*p) {\n        case 'E': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_54;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_59;\n        }\n        case 'U': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_60;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_62:\n    s_n_llhttp__internal__n_after_start_req_62: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_62;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob52, 6);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 40;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_62;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_63:\n    s_n_llhttp__internal__n_after_start_req_63: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_63;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob53, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_63;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_61:\n    s_n_llhttp__internal__n_after_start_req_61: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_61;\n      }\n      switch (*p) {\n        case 'E': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_62;\n        }\n        case 'R': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_63;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_66:\n    s_n_llhttp__internal__n_after_start_req_66: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_66;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob54, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 18;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_66;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_68:\n    s_n_llhttp__internal__n_after_start_req_68: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_68;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob55, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 32;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_68;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_69:\n    s_n_llhttp__internal__n_after_start_req_69: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_69;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob56, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 15;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_69;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_67:\n    s_n_llhttp__internal__n_after_start_req_67: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_67;\n      }\n      switch (*p) {\n        case 'I': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_68;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_69;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_70:\n    s_n_llhttp__internal__n_after_start_req_70: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_70;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob57, 8);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 27;\n          goto s_n_llhttp__internal__n_invoke_store_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_after_start_req_70;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_65:\n    s_n_llhttp__internal__n_after_start_req_65: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_65;\n      }\n      switch (*p) {\n        case 'B': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_66;\n        }\n        case 'L': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_67;\n        }\n        case 'S': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_70;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req_64:\n    s_n_llhttp__internal__n_after_start_req_64: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req_64;\n      }\n      switch (*p) {\n        case 'N': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_65;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_after_start_req:\n    s_n_llhttp__internal__n_after_start_req: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_after_start_req;\n      }\n      switch (*p) {\n        case 'A': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_1;\n        }\n        case 'B': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_4;\n        }\n        case 'C': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_5;\n        }\n        case 'D': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_10;\n        }\n        case 'F': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_14;\n        }\n        case 'G': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_15;\n        }\n        case 'H': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_18;\n        }\n        case 'L': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_19;\n        }\n        case 'M': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_22;\n        }\n        case 'N': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_31;\n        }\n        case 'O': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_32;\n        }\n        case 'P': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_33;\n        }\n        case 'Q': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_46;\n        }\n        case 'R': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_47;\n        }\n        case 'S': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_53;\n        }\n        case 'T': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_61;\n        }\n        case 'U': {\n          p++;\n          goto s_n_llhttp__internal__n_after_start_req_64;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_112;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_method_1:\n    s_n_llhttp__internal__n_span_start_llhttp__on_method_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_method_1;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_method;\n      goto s_n_llhttp__internal__n_after_start_req;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_line_almost_done:\n    s_n_llhttp__internal__n_res_line_almost_done: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_line_almost_done;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_29;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_test_lenient_flags_30:\n    s_n_llhttp__internal__n_invoke_test_lenient_flags_30: {\n      switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete;\n        default:\n          goto s_n_llhttp__internal__n_error_98;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_status:\n    s_n_llhttp__internal__n_res_status: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_status;\n      }\n      switch (*p) {\n        case 10: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_status;\n        }\n        case 13: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_status_1;\n        }\n        default: {\n          p++;\n          goto s_n_llhttp__internal__n_res_status;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_status:\n    s_n_llhttp__internal__n_span_start_llhttp__on_status: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_status;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_status;\n      goto s_n_llhttp__internal__n_res_status;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_status_code_otherwise:\n    s_n_llhttp__internal__n_res_status_code_otherwise: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_status_code_otherwise;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_test_lenient_flags_28;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_res_line_almost_done;\n        }\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_status;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_99;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_status_code_digit_3:\n    s_n_llhttp__internal__n_res_status_code_digit_3: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_status_code_digit_3;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_101;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_status_code_digit_2:\n    s_n_llhttp__internal__n_res_status_code_digit_2: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_status_code_digit_2;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_103;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_status_code_digit_1:\n    s_n_llhttp__internal__n_res_status_code_digit_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_status_code_digit_1;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_mul_add_status_code;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_105;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_after_version:\n    s_n_llhttp__internal__n_res_after_version: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_after_version;\n      }\n      switch (*p) {\n        case ' ': {\n          p++;\n          goto s_n_llhttp__internal__n_invoke_update_status_code;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_106;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1:\n    s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1: {\n      switch (c_nio_llhttp__on_version_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_res_after_version;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_28;\n        default:\n          goto s_n_llhttp__internal__n_error_94;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_93:\n    s_n_llhttp__internal__n_error_93: {\n      state->error = 0x9;\n      state->reason = \"Invalid HTTP version\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_107:\n    s_n_llhttp__internal__n_error_107: {\n      state->error = 0x9;\n      state->reason = \"Invalid minor version\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_http_minor:\n    s_n_llhttp__internal__n_res_http_minor: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_http_minor;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_store_http_minor_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_version_7;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_108:\n    s_n_llhttp__internal__n_error_108: {\n      state->error = 0x9;\n      state->reason = \"Expected dot\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_http_dot:\n    s_n_llhttp__internal__n_res_http_dot: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_http_dot;\n      }\n      switch (*p) {\n        case '.': {\n          p++;\n          goto s_n_llhttp__internal__n_res_http_minor;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_version_8;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_109:\n    s_n_llhttp__internal__n_error_109: {\n      state->error = 0x9;\n      state->reason = \"Invalid major version\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_http_major:\n    s_n_llhttp__internal__n_res_http_major: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_http_major;\n      }\n      switch (*p) {\n        case '0': {\n          p++;\n          match = 0;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '1': {\n          p++;\n          match = 1;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '2': {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '3': {\n          p++;\n          match = 3;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '4': {\n          p++;\n          match = 4;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '5': {\n          p++;\n          match = 5;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '6': {\n          p++;\n          match = 6;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '7': {\n          p++;\n          match = 7;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '8': {\n          p++;\n          match = 8;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        case '9': {\n          p++;\n          match = 9;\n          goto s_n_llhttp__internal__n_invoke_store_http_major_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_version_9;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_version_1:\n    s_n_llhttp__internal__n_span_start_llhttp__on_version_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_version_1;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_version;\n      goto s_n_llhttp__internal__n_res_http_major;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_after_protocol:\n    s_n_llhttp__internal__n_res_after_protocol: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_after_protocol;\n      }\n      switch (*p) {\n        case '/': {\n          p++;\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_version_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_114;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_3:\n    s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_3: {\n      switch (c_nio_llhttp__on_protocol_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_res_after_protocol;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_30;\n        default:\n          goto s_n_llhttp__internal__n_error_113;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_error_115:\n    s_n_llhttp__internal__n_error_115: {\n      state->error = 0x8;\n      state->reason = \"Expected HTTP/, RTSP/ or ICE/\";\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_error;\n      return s_error;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_after_start_1:\n    s_n_llhttp__internal__n_res_after_start_1: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_after_start_1;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob58, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_4;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_res_after_start_1;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_5;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_after_start_2:\n    s_n_llhttp__internal__n_res_after_start_2: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_after_start_2;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob59, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_4;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_res_after_start_2;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_5;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_after_start_3:\n    s_n_llhttp__internal__n_res_after_start_3: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_after_start_3;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob60, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_4;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_res_after_start_3;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_5;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_res_after_start:\n    s_n_llhttp__internal__n_res_after_start: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_res_after_start;\n      }\n      switch (*p) {\n        case 'H': {\n          p++;\n          goto s_n_llhttp__internal__n_res_after_start_1;\n        }\n        case 'I': {\n          p++;\n          goto s_n_llhttp__internal__n_res_after_start_2;\n        }\n        case 'R': {\n          p++;\n          goto s_n_llhttp__internal__n_res_after_start_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_protocol_5;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_protocol_1:\n    s_n_llhttp__internal__n_span_start_llhttp__on_protocol_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_protocol_1;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_protocol;\n      goto s_n_llhttp__internal__n_res_after_start;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_llhttp__on_method_complete:\n    s_n_llhttp__internal__n_invoke_llhttp__on_method_complete: {\n      switch (c_nio_llhttp__on_method_complete(state, p, endp)) {\n        case 0:\n          goto s_n_llhttp__internal__n_req_first_space_before_url;\n        case 21:\n          goto s_n_llhttp__internal__n_pause_26;\n        default:\n          goto s_n_llhttp__internal__n_error_1;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_or_res_method_2:\n    s_n_llhttp__internal__n_req_or_res_method_2: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_or_res_method_2;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob61, 2);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          match = 2;\n          goto s_n_llhttp__internal__n_invoke_store_method;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_req_or_res_method_2;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_110;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_update_type_1:\n    s_n_llhttp__internal__n_invoke_update_type_1: {\n      switch (c_nio_llhttp__internal__c_update_type_1(state, p, endp)) {\n        default:\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_version_1;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_or_res_method_3:\n    s_n_llhttp__internal__n_req_or_res_method_3: {\n      llparse_match_t match_seq;\n      \n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_or_res_method_3;\n      }\n      match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob62, 3);\n      p = match_seq.current;\n      switch (match_seq.status) {\n        case kMatchComplete: {\n          p++;\n          goto s_n_llhttp__internal__n_span_end_llhttp__on_method_1;\n        }\n        case kMatchPause: {\n          return s_n_llhttp__internal__n_req_or_res_method_3;\n        }\n        case kMatchMismatch: {\n          goto s_n_llhttp__internal__n_error_110;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_or_res_method_1:\n    s_n_llhttp__internal__n_req_or_res_method_1: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_or_res_method_1;\n      }\n      switch (*p) {\n        case 'E': {\n          p++;\n          goto s_n_llhttp__internal__n_req_or_res_method_2;\n        }\n        case 'T': {\n          p++;\n          goto s_n_llhttp__internal__n_req_or_res_method_3;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_110;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_req_or_res_method:\n    s_n_llhttp__internal__n_req_or_res_method: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_req_or_res_method;\n      }\n      switch (*p) {\n        case 'H': {\n          p++;\n          goto s_n_llhttp__internal__n_req_or_res_method_1;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_error_110;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_span_start_llhttp__on_method:\n    s_n_llhttp__internal__n_span_start_llhttp__on_method: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_span_start_llhttp__on_method;\n      }\n      state->_span_pos0 = (void*) p;\n      state->_span_cb0 = c_nio_llhttp__on_method;\n      goto s_n_llhttp__internal__n_req_or_res_method;\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_start_req_or_res:\n    s_n_llhttp__internal__n_start_req_or_res: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_start_req_or_res;\n      }\n      switch (*p) {\n        case 'H': {\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_method;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_update_type_2;\n        }\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_load_type:\n    s_n_llhttp__internal__n_invoke_load_type: {\n      switch (c_nio_llhttp__internal__c_load_type(state, p, endp)) {\n        case 1:\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_method_1;\n        case 2:\n          goto s_n_llhttp__internal__n_span_start_llhttp__on_protocol_1;\n        default:\n          goto s_n_llhttp__internal__n_start_req_or_res;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_invoke_update_finish:\n    s_n_llhttp__internal__n_invoke_update_finish: {\n      switch (c_nio_llhttp__internal__c_update_finish(state, p, endp)) {\n        default:\n          goto s_n_llhttp__internal__n_invoke_llhttp__on_message_begin;\n      }\n      UNREACHABLE;\n    }\n    case s_n_llhttp__internal__n_start:\n    s_n_llhttp__internal__n_start: {\n      if (p == endp) {\n        return s_n_llhttp__internal__n_start;\n      }\n      switch (*p) {\n        case 10: {\n          p++;\n          goto s_n_llhttp__internal__n_start;\n        }\n        case 13: {\n          p++;\n          goto s_n_llhttp__internal__n_start;\n        }\n        default: {\n          goto s_n_llhttp__internal__n_invoke_load_initial_message_completed;\n        }\n      }\n      UNREACHABLE;\n    }\n    default:\n      UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_2: {\n    state->error = 0x7;\n    state->reason = \"Invalid characters in url\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_finish_2: {\n    switch (c_nio_llhttp__internal__c_update_finish_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_start;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_initial_message_completed: {\n    switch (c_nio_llhttp__internal__c_update_initial_message_completed(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_finish_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_content_length: {\n    switch (c_nio_llhttp__internal__c_update_content_length(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_initial_message_completed;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_8: {\n    state->error = 0x5;\n    state->reason = \"Data after `Connection: close`\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_3: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_3(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_closed;\n      default:\n        goto s_n_llhttp__internal__n_error_8;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_2: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_2(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_update_initial_message_completed;\n      default:\n        goto s_n_llhttp__internal__n_closed;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_finish_1: {\n    switch (c_nio_llhttp__internal__c_update_finish_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_13: {\n    state->error = 0x15;\n    state->reason = \"on_message_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_is_equal_upgrade;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_38: {\n    state->error = 0x12;\n    state->reason = \"`on_message_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_15: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_40: {\n    state->error = 0x14;\n    state->reason = \"`on_chunk_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_1: {\n    switch (c_nio_llhttp__on_chunk_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_15;\n      default:\n        goto s_n_llhttp__internal__n_error_40;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_2: {\n    state->error = 0x15;\n    state->reason = \"on_message_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_pause_1;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_9: {\n    state->error = 0x12;\n    state->reason = \"`on_message_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_1: {\n    switch (c_nio_llhttp__on_message_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_pause_1;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_2;\n      default:\n        goto s_n_llhttp__internal__n_error_9;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_36: {\n    state->error = 0xc;\n    state->reason = \"Chunk size overflow\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_10: {\n    state->error = 0xc;\n    state->reason = \"Invalid character in chunk size\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_4: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_4(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_chunk_size_otherwise;\n      default:\n        goto s_n_llhttp__internal__n_error_10;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_3: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_update_content_length_1;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_14: {\n    state->error = 0x14;\n    state->reason = \"`on_chunk_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete: {\n    switch (c_nio_llhttp__on_chunk_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_update_content_length_1;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_3;\n      default:\n        goto s_n_llhttp__internal__n_error_14;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_13: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after chunk data\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_6: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete;\n      default:\n        goto s_n_llhttp__internal__n_error_13;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_15: {\n    state->error = 0x2;\n    state->reason = \"Expected LF after chunk data\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_7: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_7(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete;\n      default:\n        goto s_n_llhttp__internal__n_error_15;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_body: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_body(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_data_almost_done;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_chunk_data_almost_done;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags: {\n    switch (c_nio_llhttp__internal__c_or_flags(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_field_start;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_4: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_header pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_is_equal_content_length;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_12: {\n    state->error = 0x13;\n    state->reason = \"`on_chunk_header` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_header: {\n    switch (c_nio_llhttp__on_chunk_header(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_is_equal_content_length;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_4;\n      default:\n        goto s_n_llhttp__internal__n_error_12;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_16: {\n    state->error = 0x2;\n    state->reason = \"Expected LF after chunk size\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_8: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_8(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_header;\n      default:\n        goto s_n_llhttp__internal__n_error_16;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_11: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after chunk size\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_5: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_chunk_size_almost_done;\n      default:\n        goto s_n_llhttp__internal__n_error_11;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_17: {\n    state->error = 0x2;\n    state->reason = \"Invalid character in chunk extensions\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_18: {\n    state->error = 0x2;\n    state->reason = \"Invalid character in chunk extensions\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_20: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after chunk extension name\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_5: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_name pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_9;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_19: {\n    state->error = 0x22;\n    state->reason = \"`on_chunk_extension_name` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_name(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_6: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_name pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_size_almost_done;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_21: {\n    state->error = 0x22;\n    state->reason = \"`on_chunk_extension_name` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_name(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_7: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_name pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extensions;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_22: {\n    state->error = 0x22;\n    state->reason = \"`on_chunk_extension_name` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_name(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_25: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after chunk extension value\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_8: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_value pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_10;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_24: {\n    state->error = 0x23;\n    state->reason = \"`on_chunk_extension_value` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_9: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_value pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_size_almost_done;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_26: {\n    state->error = 0x23;\n    state->reason = \"`on_chunk_extension_value` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_28: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after chunk extension value\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_11: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_chunk_size_almost_done;\n      default:\n        goto s_n_llhttp__internal__n_error_28;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_29: {\n    state->error = 0x2;\n    state->reason = \"Invalid character in chunk extensions quote value\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_10: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_value pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extension_quoted_value_done;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_27: {\n    state->error = 0x23;\n    state->reason = \"`on_chunk_extension_value` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_3: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_30;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_30;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_4: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_31;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_31;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_11: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_value pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extensions;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_32: {\n    state->error = 0x23;\n    state->reason = \"`on_chunk_extension_value` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_5: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_6: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_33;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_33;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_12: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_extension_name pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extension_value;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_23: {\n    state->error = 0x22;\n    state->reason = \"`on_chunk_extension_name` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_3: {\n    switch (c_nio_llhttp__on_chunk_extension_name_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_chunk_extension_value;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_12;\n      default:\n        goto s_n_llhttp__internal__n_error_23;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_3: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_name(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_4: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_chunk_extension_name(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_34;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_34;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_35: {\n    state->error = 0xc;\n    state->reason = \"Invalid character in chunk size\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_mul_add_content_length: {\n    switch (c_nio_llhttp__internal__c_mul_add_content_length(state, p, endp, match)) {\n      case 1:\n        goto s_n_llhttp__internal__n_error_36;\n      default:\n        goto s_n_llhttp__internal__n_chunk_size;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_37: {\n    state->error = 0xc;\n    state->reason = \"Invalid character in chunk size\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_body_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_body(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_finish_3: {\n    switch (c_nio_llhttp__internal__c_update_finish_3(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_body_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_39: {\n    state->error = 0xf;\n    state->reason = \"Request has invalid `Transfer-Encoding`\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause: {\n    state->error = 0x15;\n    state->reason = \"on_message_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_message_complete;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_7: {\n    state->error = 0x12;\n    state->reason = \"`on_message_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_message_complete: {\n    switch (c_nio_llhttp__on_message_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_message_complete;\n      case 21:\n        goto s_n_llhttp__internal__n_pause;\n      default:\n        goto s_n_llhttp__internal__n_error_7;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_1: {\n    switch (c_nio_llhttp__internal__c_or_flags_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_2: {\n    switch (c_nio_llhttp__internal__c_or_flags_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_upgrade: {\n    switch (c_nio_llhttp__internal__c_update_upgrade(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_or_flags_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_14: {\n    state->error = 0x15;\n    state->reason = \"Paused by on_headers_complete\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_6: {\n    state->error = 0x11;\n    state->reason = \"User callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete: {\n    switch (c_nio_llhttp__on_headers_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_or_flags_1;\n      case 2:\n        goto s_n_llhttp__internal__n_invoke_update_upgrade;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_14;\n      default:\n        goto s_n_llhttp__internal__n_error_6;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete: {\n    switch (c_nio_llhttp__before_headers_complete(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_flags: {\n    switch (c_nio_llhttp__internal__c_test_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_1;\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_1: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_test_flags;\n      default:\n        goto s_n_llhttp__internal__n_error_5;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_17: {\n    state->error = 0x15;\n    state->reason = \"on_chunk_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_42: {\n    state->error = 0x14;\n    state->reason = \"`on_chunk_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_2: {\n    switch (c_nio_llhttp__on_chunk_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_17;\n      default:\n        goto s_n_llhttp__internal__n_error_42;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_3: {\n    switch (c_nio_llhttp__internal__c_or_flags_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_4: {\n    switch (c_nio_llhttp__internal__c_or_flags_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_upgrade_1: {\n    switch (c_nio_llhttp__internal__c_update_upgrade(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_or_flags_4;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_16: {\n    state->error = 0x15;\n    state->reason = \"Paused by on_headers_complete\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_41: {\n    state->error = 0x11;\n    state->reason = \"User callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete_1: {\n    switch (c_nio_llhttp__on_headers_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete;\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_or_flags_3;\n      case 2:\n        goto s_n_llhttp__internal__n_invoke_update_upgrade_1;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_16;\n      default:\n        goto s_n_llhttp__internal__n_error_41;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete_1: {\n    switch (c_nio_llhttp__before_headers_complete(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_flags_1: {\n    switch (c_nio_llhttp__internal__c_test_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_2;\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_43: {\n    state->error = 0x2;\n    state->reason = \"Expected LF after headers\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_12: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_8(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_test_flags_1;\n      default:\n        goto s_n_llhttp__internal__n_error_43;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_44: {\n    state->error = 0xa;\n    state->reason = \"Invalid header token\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_field: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_field(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_5;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_5;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_13: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_field_colon_discard_ws;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_60: {\n    state->error = 0xb;\n    state->reason = \"Content-Length can't be present with Transfer-Encoding\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_47: {\n    state->error = 0xa;\n    state->reason = \"Invalid header value char\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_15: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_value_discard_ws;\n      default:\n        goto s_n_llhttp__internal__n_error_47;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_49: {\n    state->error = 0xb;\n    state->reason = \"Empty Content-Length\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_18: {\n    state->error = 0x15;\n    state->reason = \"on_header_value_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_field_start;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_48: {\n    state->error = 0x1d;\n    state->reason = \"`on_header_value_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state: {\n    switch (c_nio_llhttp__internal__c_update_header_state(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_5: {\n    switch (c_nio_llhttp__internal__c_or_flags_5(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_6: {\n    switch (c_nio_llhttp__internal__c_or_flags_6(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_7: {\n    switch (c_nio_llhttp__internal__c_or_flags_7(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_8: {\n    switch (c_nio_llhttp__internal__c_or_flags_8(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_header_state_2: {\n    switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n      case 5:\n        goto s_n_llhttp__internal__n_invoke_or_flags_5;\n      case 6:\n        goto s_n_llhttp__internal__n_invoke_or_flags_6;\n      case 7:\n        goto s_n_llhttp__internal__n_invoke_or_flags_7;\n      case 8:\n        goto s_n_llhttp__internal__n_invoke_or_flags_8;\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_header_state_1: {\n    switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n      case 2:\n        goto s_n_llhttp__internal__n_error_49;\n      default:\n        goto s_n_llhttp__internal__n_invoke_load_header_state_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_46: {\n    state->error = 0xa;\n    state->reason = \"Invalid header value char\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_14: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_value_discard_lws;\n      default:\n        goto s_n_llhttp__internal__n_error_46;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_50: {\n    state->error = 0x2;\n    state->reason = \"Expected LF after CR\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_16: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_value_discard_lws;\n      default:\n        goto s_n_llhttp__internal__n_error_50;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_1: {\n    switch (c_nio_llhttp__internal__c_update_header_state_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_header_state_4: {\n    switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n      case 8:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_1;\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_52: {\n    state->error = 0xa;\n    state->reason = \"Unexpected whitespace after header value\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_18: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_load_header_state_4;\n      default:\n        goto s_n_llhttp__internal__n_error_52;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_2: {\n    switch (c_nio_llhttp__internal__c_update_header_state(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_9: {\n    switch (c_nio_llhttp__internal__c_or_flags_5(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_10: {\n    switch (c_nio_llhttp__internal__c_or_flags_6(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_11: {\n    switch (c_nio_llhttp__internal__c_or_flags_7(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_12: {\n    switch (c_nio_llhttp__internal__c_or_flags_8(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_header_state_5: {\n    switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n      case 5:\n        goto s_n_llhttp__internal__n_invoke_or_flags_9;\n      case 6:\n        goto s_n_llhttp__internal__n_invoke_or_flags_10;\n      case 7:\n        goto s_n_llhttp__internal__n_invoke_or_flags_11;\n      case 8:\n        goto s_n_llhttp__internal__n_invoke_or_flags_12;\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_53: {\n    state->error = 0x3;\n    state->reason = \"Missing expected LF after header value\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_51: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after header value\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_17;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_test_lenient_flags_17;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_value_almost_done;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_header_value_almost_done;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_4: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_value_almost_done;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_header_value_almost_done;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_5: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_value_almost_done;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_header_value_almost_done;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_3: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_54;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_54;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_19: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_value_lenient;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_3;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_4: {\n    switch (c_nio_llhttp__internal__c_update_header_state(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_13: {\n    switch (c_nio_llhttp__internal__c_or_flags_5(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_4;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_14: {\n    switch (c_nio_llhttp__internal__c_or_flags_6(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_4;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_15: {\n    switch (c_nio_llhttp__internal__c_or_flags_7(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_4;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_16: {\n    switch (c_nio_llhttp__internal__c_or_flags_8(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_header_state_6: {\n    switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n      case 5:\n        goto s_n_llhttp__internal__n_invoke_or_flags_13;\n      case 6:\n        goto s_n_llhttp__internal__n_invoke_or_flags_14;\n      case 7:\n        goto s_n_llhttp__internal__n_invoke_or_flags_15;\n      case 8:\n        goto s_n_llhttp__internal__n_invoke_or_flags_16;\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_5: {\n    switch (c_nio_llhttp__internal__c_update_header_state_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection_token;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_3: {\n    switch (c_nio_llhttp__internal__c_update_header_state_3(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_6: {\n    switch (c_nio_llhttp__internal__c_update_header_state_6(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_7: {\n    switch (c_nio_llhttp__internal__c_update_header_state_7(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_connection_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_6: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_56;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_56;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_mul_add_content_length_1: {\n    switch (c_nio_llhttp__internal__c_mul_add_content_length_1(state, p, endp, match)) {\n      case 1:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_6;\n      default:\n        goto s_n_llhttp__internal__n_header_value_content_length;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_17: {\n    switch (c_nio_llhttp__internal__c_or_flags_17(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_otherwise;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_7: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_57;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_57;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_55: {\n    state->error = 0x4;\n    state->reason = \"Duplicate Content-Length\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_flags_2: {\n    switch (c_nio_llhttp__internal__c_test_flags_2(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_header_value_content_length;\n      default:\n        goto s_n_llhttp__internal__n_error_55;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_9: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_59;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_59;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_8: {\n    switch (c_nio_llhttp__internal__c_update_header_state_8(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_otherwise;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_value_8: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_value(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_58;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_error_58;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_20: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_20(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_8;\n      default:\n        goto s_n_llhttp__internal__n_header_value_te_chunked;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_type_1: {\n    switch (c_nio_llhttp__internal__c_load_type(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_20;\n      default:\n        goto s_n_llhttp__internal__n_header_value_te_chunked;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_9: {\n    switch (c_nio_llhttp__internal__c_update_header_state_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_and_flags: {\n    switch (c_nio_llhttp__internal__c_and_flags(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_value_te_chunked;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_19: {\n    switch (c_nio_llhttp__internal__c_or_flags_18(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_and_flags;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_21: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_20(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_9;\n      default:\n        goto s_n_llhttp__internal__n_invoke_or_flags_19;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_type_2: {\n    switch (c_nio_llhttp__internal__c_load_type(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_21;\n      default:\n        goto s_n_llhttp__internal__n_invoke_or_flags_19;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_18: {\n    switch (c_nio_llhttp__internal__c_or_flags_18(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_and_flags;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_flags_3: {\n    switch (c_nio_llhttp__internal__c_test_flags_3(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_load_type_2;\n      default:\n        goto s_n_llhttp__internal__n_invoke_or_flags_18;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_or_flags_20: {\n    switch (c_nio_llhttp__internal__c_or_flags_20(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_header_state_9;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_header_state_3: {\n    switch (c_nio_llhttp__internal__c_load_header_state(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_value_connection;\n      case 2:\n        goto s_n_llhttp__internal__n_invoke_test_flags_2;\n      case 3:\n        goto s_n_llhttp__internal__n_invoke_test_flags_3;\n      case 4:\n        goto s_n_llhttp__internal__n_invoke_or_flags_20;\n      default:\n        goto s_n_llhttp__internal__n_header_value;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_22: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_22(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_error_60;\n      default:\n        goto s_n_llhttp__internal__n_header_value_discard_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_flags_4: {\n    switch (c_nio_llhttp__internal__c_test_flags_4(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_22;\n      default:\n        goto s_n_llhttp__internal__n_header_value_discard_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_61: {\n    state->error = 0xf;\n    state->reason = \"Transfer-Encoding can't be present with Content-Length\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_23: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_22(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_error_61;\n      default:\n        goto s_n_llhttp__internal__n_header_value_discard_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_flags_5: {\n    switch (c_nio_llhttp__internal__c_test_flags_2(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_23;\n      default:\n        goto s_n_llhttp__internal__n_header_value_discard_ws;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_19: {\n    state->error = 0x15;\n    state->reason = \"on_header_field_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_header_state;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_45: {\n    state->error = 0x1c;\n    state->reason = \"`on_header_field_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_field_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_field(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_header_field_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_header_field(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_62: {\n    state->error = 0xa;\n    state->reason = \"Invalid header token\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_10: {\n    switch (c_nio_llhttp__internal__c_update_header_state_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_field_general;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_header_state: {\n    switch (c_nio_llhttp__internal__c_store_header_state(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_header_field_colon;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_header_state_11: {\n    switch (c_nio_llhttp__internal__c_update_header_state_1(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_header_field_general;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_4: {\n    state->error = 0x1e;\n    state->reason = \"Unexpected space after start line\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_header_field_start;\n      default:\n        goto s_n_llhttp__internal__n_error_4;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_20: {\n    state->error = 0x15;\n    state->reason = \"on_url_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_headers_start;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_3: {\n    state->error = 0x1a;\n    state->reason = \"`on_url_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_url_complete: {\n    switch (c_nio_llhttp__on_url_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_headers_start;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_20;\n      default:\n        goto s_n_llhttp__internal__n_error_3;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_http_minor: {\n    switch (c_nio_llhttp__internal__c_update_http_minor(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_url_complete;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_http_major: {\n    switch (c_nio_llhttp__internal__c_update_http_major(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_http_minor;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_3: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_63: {\n    state->error = 0x7;\n    state->reason = \"Expected CRLF\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_4: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_lf_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_72: {\n    state->error = 0x17;\n    state->reason = \"Pause on PRI/Upgrade\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_73: {\n    state->error = 0x9;\n    state->reason = \"Expected HTTP/2 Connection Preface\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_70: {\n    state->error = 0x2;\n    state->reason = \"Expected CRLF after version\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_26: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_8(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_headers_start;\n      default:\n        goto s_n_llhttp__internal__n_error_70;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_69: {\n    state->error = 0x9;\n    state->reason = \"Expected CRLF after version\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_25: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_req_http_complete_crlf;\n      default:\n        goto s_n_llhttp__internal__n_error_69;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_71: {\n    state->error = 0x9;\n    state->reason = \"Expected CRLF after version\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_21: {\n    state->error = 0x15;\n    state->reason = \"on_version_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_method_1;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_68: {\n    state->error = 0x21;\n    state->reason = \"`on_version_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_version_complete;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_version_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_67;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_67;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_minor: {\n    switch (c_nio_llhttp__internal__c_load_http_minor(state, p, endp)) {\n      case 9:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_minor_1: {\n    switch (c_nio_llhttp__internal__c_load_http_minor(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1;\n      case 1:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_minor_2: {\n    switch (c_nio_llhttp__internal__c_load_http_minor(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_major: {\n    switch (c_nio_llhttp__internal__c_load_http_major(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_load_http_minor;\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_load_http_minor_1;\n      case 2:\n        goto s_n_llhttp__internal__n_invoke_load_http_minor_2;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_24: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_24(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1;\n      default:\n        goto s_n_llhttp__internal__n_invoke_load_http_major;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_http_minor: {\n    switch (c_nio_llhttp__internal__c_store_http_minor(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_24;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_74;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_74;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_3: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_75;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_75;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_http_major: {\n    switch (c_nio_llhttp__internal__c_store_http_major(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_req_http_dot;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_4: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_76;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_76;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_77: {\n    state->error = 0x8;\n    state->reason = \"Expected HTTP/, RTSP/ or ICE/\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_66: {\n    state->error = 0x8;\n    state->reason = \"Invalid method for HTTP/x.x request\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_22: {\n    state->error = 0x15;\n    state->reason = \"on_protocol_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_method;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_65: {\n    state->error = 0x26;\n    state->reason = \"`on_protocol_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_protocol: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_protocol(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_protocol_3: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_protocol(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_82;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_82;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_79: {\n    state->error = 0x8;\n    state->reason = \"Expected SOURCE method for ICE/x.x request\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_23: {\n    state->error = 0x15;\n    state->reason = \"on_protocol_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_method_2;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_78: {\n    state->error = 0x26;\n    state->reason = \"`on_protocol_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_protocol_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_protocol(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_1;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_1;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_81: {\n    state->error = 0x8;\n    state->reason = \"Invalid method for RTSP/x.x request\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_24: {\n    state->error = 0x15;\n    state->reason = \"on_protocol_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_method_3;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_80: {\n    state->error = 0x26;\n    state->reason = \"`on_protocol_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_protocol_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_protocol(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_2;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_2;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_25: {\n    state->error = 0x15;\n    state->reason = \"on_url_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_req_http_start;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_64: {\n    state->error = 0x1a;\n    state->reason = \"`on_url_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_url_complete_1: {\n    switch (c_nio_llhttp__on_url_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_req_http_start;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_25;\n      default:\n        goto s_n_llhttp__internal__n_error_64;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_5: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_6: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_7: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_lf_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_8: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_83: {\n    state->error = 0x7;\n    state->reason = \"Invalid char in url fragment start\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_9: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_10: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_lf_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_11: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_84: {\n    state->error = 0x7;\n    state->reason = \"Invalid char in url query\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_85: {\n    state->error = 0x7;\n    state->reason = \"Invalid char in url path\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_lf_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_12: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_13: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_lf_to_http09;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_url_14: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_url(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_url_skip_to_http;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_86: {\n    state->error = 0x7;\n    state->reason = \"Double @ in url\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_87: {\n    state->error = 0x7;\n    state->reason = \"Unexpected char in url server\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_88: {\n    state->error = 0x7;\n    state->reason = \"Unexpected char in url server\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_89: {\n    state->error = 0x7;\n    state->reason = \"Unexpected char in url schema\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_90: {\n    state->error = 0x7;\n    state->reason = \"Unexpected char in url schema\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_91: {\n    state->error = 0x7;\n    state->reason = \"Unexpected start char in url\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_is_equal_method: {\n    switch (c_nio_llhttp__internal__c_is_equal_method(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_url_entry_normal;\n      default:\n        goto s_n_llhttp__internal__n_url_entry_connect;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_92: {\n    state->error = 0x6;\n    state->reason = \"Expected space after method\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_29: {\n    state->error = 0x15;\n    state->reason = \"on_method_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_req_first_space_before_url;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_111: {\n    state->error = 0x20;\n    state->reason = \"`on_method_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_method_2: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_method(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_method_1: {\n    switch (c_nio_llhttp__internal__c_store_method(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_method_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_112: {\n    state->error = 0x6;\n    state->reason = \"Invalid method encountered\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_104: {\n    state->error = 0xd;\n    state->reason = \"Invalid status code\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_102: {\n    state->error = 0xd;\n    state->reason = \"Invalid status code\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_100: {\n    state->error = 0xd;\n    state->reason = \"Invalid status code\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_27: {\n    state->error = 0x15;\n    state->reason = \"on_status_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_headers_start;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_96: {\n    state->error = 0x1b;\n    state->reason = \"`on_status_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_status_complete: {\n    switch (c_nio_llhttp__on_status_complete(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_headers_start;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_27;\n      default:\n        goto s_n_llhttp__internal__n_error_96;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_95: {\n    state->error = 0xd;\n    state->reason = \"Invalid response status\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_28: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_1(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete;\n      default:\n        goto s_n_llhttp__internal__n_error_95;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_97: {\n    state->error = 0x2;\n    state->reason = \"Expected LF after CR\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_29: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_8(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete;\n      default:\n        goto s_n_llhttp__internal__n_error_97;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_98: {\n    state->error = 0x19;\n    state->reason = \"Missing expected CR after response line\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_status: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_status(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_30;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_invoke_test_lenient_flags_30;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_status_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_status(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) (p + 1);\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_res_line_almost_done;\n      return s_error;\n    }\n    p++;\n    goto s_n_llhttp__internal__n_res_line_almost_done;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_99: {\n    state->error = 0xd;\n    state->reason = \"Invalid response status\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_mul_add_status_code_2: {\n    switch (c_nio_llhttp__internal__c_mul_add_status_code(state, p, endp, match)) {\n      case 1:\n        goto s_n_llhttp__internal__n_error_100;\n      default:\n        goto s_n_llhttp__internal__n_res_status_code_otherwise;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_101: {\n    state->error = 0xd;\n    state->reason = \"Invalid status code\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_mul_add_status_code_1: {\n    switch (c_nio_llhttp__internal__c_mul_add_status_code(state, p, endp, match)) {\n      case 1:\n        goto s_n_llhttp__internal__n_error_102;\n      default:\n        goto s_n_llhttp__internal__n_res_status_code_digit_3;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_103: {\n    state->error = 0xd;\n    state->reason = \"Invalid status code\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_mul_add_status_code: {\n    switch (c_nio_llhttp__internal__c_mul_add_status_code(state, p, endp, match)) {\n      case 1:\n        goto s_n_llhttp__internal__n_error_104;\n      default:\n        goto s_n_llhttp__internal__n_res_status_code_digit_2;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_105: {\n    state->error = 0xd;\n    state->reason = \"Invalid status code\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_status_code: {\n    switch (c_nio_llhttp__internal__c_update_status_code(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_res_status_code_digit_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_106: {\n    state->error = 0x9;\n    state->reason = \"Expected space after version\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_28: {\n    state->error = 0x15;\n    state->reason = \"on_version_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_res_after_version;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_94: {\n    state->error = 0x21;\n    state->reason = \"`on_version_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_6: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_5: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_93;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_93;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_minor_3: {\n    switch (c_nio_llhttp__internal__c_load_http_minor(state, p, endp)) {\n      case 9:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_minor_4: {\n    switch (c_nio_llhttp__internal__c_load_http_minor(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6;\n      case 1:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_minor_5: {\n    switch (c_nio_llhttp__internal__c_load_http_minor(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_http_major_1: {\n    switch (c_nio_llhttp__internal__c_load_http_major(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_load_http_minor_3;\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_load_http_minor_4;\n      case 2:\n        goto s_n_llhttp__internal__n_invoke_load_http_minor_5;\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_test_lenient_flags_27: {\n    switch (c_nio_llhttp__internal__c_test_lenient_flags_24(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6;\n      default:\n        goto s_n_llhttp__internal__n_invoke_load_http_major_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_http_minor_1: {\n    switch (c_nio_llhttp__internal__c_store_http_minor(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_test_lenient_flags_27;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_7: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_107;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_107;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_8: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_108;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_108;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_http_major_1: {\n    switch (c_nio_llhttp__internal__c_store_http_major(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_res_http_dot;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_version_9: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_version(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_109;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_109;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_114: {\n    state->error = 0x8;\n    state->reason = \"Expected HTTP/, RTSP/ or ICE/\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_30: {\n    state->error = 0x15;\n    state->reason = \"on_protocol_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_res_after_protocol;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_113: {\n    state->error = 0x26;\n    state->reason = \"`on_protocol_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_protocol_4: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_protocol(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_3;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_protocol_complete_3;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_protocol_5: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_protocol(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_115;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_error_115;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_26: {\n    state->error = 0x15;\n    state->reason = \"on_method_complete pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_req_first_space_before_url;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_1: {\n    state->error = 0x20;\n    state->reason = \"`on_method_complete` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_method: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_method(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_method_complete;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_llhttp__on_method_complete;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_type: {\n    switch (c_nio_llhttp__internal__c_update_type(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_span_end_llhttp__on_method;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_store_method: {\n    switch (c_nio_llhttp__internal__c_store_method(state, p, endp, match)) {\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_type;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_110: {\n    state->error = 0x8;\n    state->reason = \"Invalid word encountered\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_span_end_llhttp__on_method_1: {\n    const unsigned char* start;\n    int err;\n    \n    start = state->_span_pos0;\n    state->_span_pos0 = NULL;\n    err = c_nio_llhttp__on_method(state, start, p);\n    if (err != 0) {\n      state->error = err;\n      state->error_pos = (const char*) p;\n      state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_update_type_1;\n      return s_error;\n    }\n    goto s_n_llhttp__internal__n_invoke_update_type_1;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_update_type_2: {\n    switch (c_nio_llhttp__internal__c_update_type(state, p, endp)) {\n      default:\n        goto s_n_llhttp__internal__n_span_start_llhttp__on_method_1;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_31: {\n    state->error = 0x15;\n    state->reason = \"on_message_begin pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_type;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error: {\n    state->error = 0x10;\n    state->reason = \"`on_message_begin` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_message_begin: {\n    switch (c_nio_llhttp__on_message_begin(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_load_type;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_31;\n      default:\n        goto s_n_llhttp__internal__n_error;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_pause_32: {\n    state->error = 0x15;\n    state->reason = \"on_reset pause\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_update_finish;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_error_116: {\n    state->error = 0x1f;\n    state->reason = \"`on_reset` callback error\";\n    state->error_pos = (const char*) p;\n    state->_current = (void*) (intptr_t) s_error;\n    return s_error;\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_llhttp__on_reset: {\n    switch (c_nio_llhttp__on_reset(state, p, endp)) {\n      case 0:\n        goto s_n_llhttp__internal__n_invoke_update_finish;\n      case 21:\n        goto s_n_llhttp__internal__n_pause_32;\n      default:\n        goto s_n_llhttp__internal__n_error_116;\n    }\n    UNREACHABLE;\n  }\n  s_n_llhttp__internal__n_invoke_load_initial_message_completed: {\n    switch (c_nio_llhttp__internal__c_load_initial_message_completed(state, p, endp)) {\n      case 1:\n        goto s_n_llhttp__internal__n_invoke_llhttp__on_reset;\n      default:\n        goto s_n_llhttp__internal__n_invoke_update_finish;\n    }\n    UNREACHABLE;\n  }\n}\n\nint c_nio_llhttp__internal_execute(c_nio_llhttp__internal_t* state, const char* p, const char* endp) {\n  llparse_state_t next;\n\n  /* check lingering errors */\n  if (state->error != 0) {\n    return state->error;\n  }\n\n  /* restart spans */\n  if (state->_span_pos0 != NULL) {\n    state->_span_pos0 = (void*) p;\n  }\n  \n  next = c_nio_llhttp__internal__run(state, (const unsigned char*) p, (const unsigned char*) endp);\n  if (next == s_error) {\n    return state->error;\n  }\n  state->_current = (void*) (intptr_t) next;\n\n  /* execute spans */\n  if (state->_span_pos0 != NULL) {\n    int error;\n  \n    error = ((c_nio_llhttp__internal__span_cb) state->_span_cb0)(state, state->_span_pos0, (const char*) endp);\n    if (error != 0) {\n      state->error = error;\n      state->error_pos = endp;\n      return error;\n    }\n  }\n  \n  return 0;\n}"
  },
  {
    "path": "Sources/CNIOLLHTTP/include/CNIOLLHTTP.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// adaptions for llhttp to make it more straightforward to use from Swift\n\n#ifndef C_NIO_LLHTTP_SWIFT\n#define C_NIO_LLHTTP_SWIFT\n\n#include \"c_nio_llhttp.h\"\n\nstatic inline llhttp_errno_t c_nio_llhttp_execute_swift(llhttp_t *parser,\n                                                        const void *data,\n                                                        size_t len) {\n    return c_nio_llhttp_execute(parser, (const char *)data, len);\n}\n\n#endif\n"
  },
  {
    "path": "Sources/CNIOLLHTTP/include/c_nio_llhttp.h",
    "content": "/* Additional changes for SwiftNIO:\n    - prefixed all symbols by 'c_nio_'\n*/\n\n#ifndef INCLUDE_LLHTTP_H_\n#define INCLUDE_LLHTTP_H_\n\n#define LLHTTP_VERSION_MAJOR 9\n#define LLHTTP_VERSION_MINOR 3\n#define LLHTTP_VERSION_PATCH 0\n\n#ifndef INCLUDE_LLHTTP_ITSELF_H_\n#define INCLUDE_LLHTTP_ITSELF_H_\n#ifdef __cplusplus\n#include <cstdint>\n#else\n#include <stdint.h>\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\ntypedef struct c_nio_llhttp__internal_s c_nio_llhttp__internal_t;\nstruct c_nio_llhttp__internal_s {\n  int32_t _index;\n  void* _span_pos0;\n  void* _span_cb0;\n  int32_t error;\n  const char* reason;\n  const char* error_pos;\n  void* data;\n  void* _current;\n  uint64_t content_length;\n  uint8_t type;\n  uint8_t method;\n  uint8_t http_major;\n  uint8_t http_minor;\n  uint8_t header_state;\n  uint16_t lenient_flags;\n  uint8_t upgrade;\n  uint8_t finish;\n  uint16_t flags;\n  uint16_t status_code;\n  uint8_t initial_message_completed;\n  void* settings;\n};\n\nint c_nio_llhttp__internal_init(c_nio_llhttp__internal_t* s);\nint c_nio_llhttp__internal_execute(c_nio_llhttp__internal_t* s, const char* p, const char* endp);\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n#endif  /* INCLUDE_LLHTTP_ITSELF_H_ */\n\n\n#ifndef LLLLHTTP_C_HEADERS_\n#define LLLLHTTP_C_HEADERS_\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum llhttp_errno {\n  HPE_OK = 0,\n  HPE_INTERNAL = 1,\n  HPE_STRICT = 2,\n  HPE_CR_EXPECTED = 25,\n  HPE_LF_EXPECTED = 3,\n  HPE_UNEXPECTED_CONTENT_LENGTH = 4,\n  HPE_UNEXPECTED_SPACE = 30,\n  HPE_CLOSED_CONNECTION = 5,\n  HPE_INVALID_METHOD = 6,\n  HPE_INVALID_URL = 7,\n  HPE_INVALID_CONSTANT = 8,\n  HPE_INVALID_VERSION = 9,\n  HPE_INVALID_HEADER_TOKEN = 10,\n  HPE_INVALID_CONTENT_LENGTH = 11,\n  HPE_INVALID_CHUNK_SIZE = 12,\n  HPE_INVALID_STATUS = 13,\n  HPE_INVALID_EOF_STATE = 14,\n  HPE_INVALID_TRANSFER_ENCODING = 15,\n  HPE_CB_MESSAGE_BEGIN = 16,\n  HPE_CB_HEADERS_COMPLETE = 17,\n  HPE_CB_MESSAGE_COMPLETE = 18,\n  HPE_CB_CHUNK_HEADER = 19,\n  HPE_CB_CHUNK_COMPLETE = 20,\n  HPE_PAUSED = 21,\n  HPE_PAUSED_UPGRADE = 22,\n  HPE_PAUSED_H2_UPGRADE = 23,\n  HPE_USER = 24,\n  HPE_CB_URL_COMPLETE = 26,\n  HPE_CB_STATUS_COMPLETE = 27,\n  HPE_CB_METHOD_COMPLETE = 32,\n  HPE_CB_VERSION_COMPLETE = 33,\n  HPE_CB_HEADER_FIELD_COMPLETE = 28,\n  HPE_CB_HEADER_VALUE_COMPLETE = 29,\n  HPE_CB_CHUNK_EXTENSION_NAME_COMPLETE = 34,\n  HPE_CB_CHUNK_EXTENSION_VALUE_COMPLETE = 35,\n  HPE_CB_RESET = 31,\n  HPE_CB_PROTOCOL_COMPLETE = 38\n};\ntypedef enum llhttp_errno llhttp_errno_t;\n\nenum llhttp_flags {\n  F_CONNECTION_KEEP_ALIVE = 0x1,\n  F_CONNECTION_CLOSE = 0x2,\n  F_CONNECTION_UPGRADE = 0x4,\n  F_CHUNKED = 0x8,\n  F_UPGRADE = 0x10,\n  F_CONTENT_LENGTH = 0x20,\n  F_SKIPBODY = 0x40,\n  F_TRAILING = 0x80,\n  F_TRANSFER_ENCODING = 0x200\n};\ntypedef enum llhttp_flags llhttp_flags_t;\n\nenum llhttp_lenient_flags {\n  LENIENT_HEADERS = 0x1,\n  LENIENT_CHUNKED_LENGTH = 0x2,\n  LENIENT_KEEP_ALIVE = 0x4,\n  LENIENT_TRANSFER_ENCODING = 0x8,\n  LENIENT_VERSION = 0x10,\n  LENIENT_DATA_AFTER_CLOSE = 0x20,\n  LENIENT_OPTIONAL_LF_AFTER_CR = 0x40,\n  LENIENT_OPTIONAL_CRLF_AFTER_CHUNK = 0x80,\n  LENIENT_OPTIONAL_CR_BEFORE_LF = 0x100,\n  LENIENT_SPACES_AFTER_CHUNK_SIZE = 0x200\n};\ntypedef enum llhttp_lenient_flags llhttp_lenient_flags_t;\n\nenum llhttp_type {\n  HTTP_BOTH = 0,\n  HTTP_REQUEST = 1,\n  HTTP_RESPONSE = 2\n};\ntypedef enum llhttp_type llhttp_type_t;\n\nenum c_nio_llhttp_finish {\n  HTTP_FINISH_SAFE = 0,\n  HTTP_FINISH_SAFE_WITH_CB = 1,\n  HTTP_FINISH_UNSAFE = 2\n};\ntypedef enum c_nio_llhttp_finish c_nio_llhttp_finish_t;\n\nenum llhttp_method {\n  HTTP_DELETE = 0,\n  HTTP_GET = 1,\n  HTTP_HEAD = 2,\n  HTTP_POST = 3,\n  HTTP_PUT = 4,\n  HTTP_CONNECT = 5,\n  HTTP_OPTIONS = 6,\n  HTTP_TRACE = 7,\n  HTTP_COPY = 8,\n  HTTP_LOCK = 9,\n  HTTP_MKCOL = 10,\n  HTTP_MOVE = 11,\n  HTTP_PROPFIND = 12,\n  HTTP_PROPPATCH = 13,\n  HTTP_SEARCH = 14,\n  HTTP_UNLOCK = 15,\n  HTTP_BIND = 16,\n  HTTP_REBIND = 17,\n  HTTP_UNBIND = 18,\n  HTTP_ACL = 19,\n  HTTP_REPORT = 20,\n  HTTP_MKACTIVITY = 21,\n  HTTP_CHECKOUT = 22,\n  HTTP_MERGE = 23,\n  HTTP_MSEARCH = 24,\n  HTTP_NOTIFY = 25,\n  HTTP_SUBSCRIBE = 26,\n  HTTP_UNSUBSCRIBE = 27,\n  HTTP_PATCH = 28,\n  HTTP_PURGE = 29,\n  HTTP_MKCALENDAR = 30,\n  HTTP_LINK = 31,\n  HTTP_UNLINK = 32,\n  HTTP_SOURCE = 33,\n  HTTP_PRI = 34,\n  HTTP_DESCRIBE = 35,\n  HTTP_ANNOUNCE = 36,\n  HTTP_SETUP = 37,\n  HTTP_PLAY = 38,\n  HTTP_PAUSE = 39,\n  HTTP_TEARDOWN = 40,\n  HTTP_GET_PARAMETER = 41,\n  HTTP_SET_PARAMETER = 42,\n  HTTP_REDIRECT = 43,\n  HTTP_RECORD = 44,\n  HTTP_FLUSH = 45,\n  HTTP_QUERY = 46\n};\ntypedef enum llhttp_method llhttp_method_t;\n\nenum llhttp_status {\n  HTTP_STATUS_CONTINUE = 100,\n  HTTP_STATUS_SWITCHING_PROTOCOLS = 101,\n  HTTP_STATUS_PROCESSING = 102,\n  HTTP_STATUS_EARLY_HINTS = 103,\n  HTTP_STATUS_RESPONSE_IS_STALE = 110,\n  HTTP_STATUS_REVALIDATION_FAILED = 111,\n  HTTP_STATUS_DISCONNECTED_OPERATION = 112,\n  HTTP_STATUS_HEURISTIC_EXPIRATION = 113,\n  HTTP_STATUS_MISCELLANEOUS_WARNING = 199,\n  HTTP_STATUS_OK = 200,\n  HTTP_STATUS_CREATED = 201,\n  HTTP_STATUS_ACCEPTED = 202,\n  HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,\n  HTTP_STATUS_NO_CONTENT = 204,\n  HTTP_STATUS_RESET_CONTENT = 205,\n  HTTP_STATUS_PARTIAL_CONTENT = 206,\n  HTTP_STATUS_MULTI_STATUS = 207,\n  HTTP_STATUS_ALREADY_REPORTED = 208,\n  HTTP_STATUS_TRANSFORMATION_APPLIED = 214,\n  HTTP_STATUS_IM_USED = 226,\n  HTTP_STATUS_MISCELLANEOUS_PERSISTENT_WARNING = 299,\n  HTTP_STATUS_MULTIPLE_CHOICES = 300,\n  HTTP_STATUS_MOVED_PERMANENTLY = 301,\n  HTTP_STATUS_FOUND = 302,\n  HTTP_STATUS_SEE_OTHER = 303,\n  HTTP_STATUS_NOT_MODIFIED = 304,\n  HTTP_STATUS_USE_PROXY = 305,\n  HTTP_STATUS_SWITCH_PROXY = 306,\n  HTTP_STATUS_TEMPORARY_REDIRECT = 307,\n  HTTP_STATUS_PERMANENT_REDIRECT = 308,\n  HTTP_STATUS_BAD_REQUEST = 400,\n  HTTP_STATUS_UNAUTHORIZED = 401,\n  HTTP_STATUS_PAYMENT_REQUIRED = 402,\n  HTTP_STATUS_FORBIDDEN = 403,\n  HTTP_STATUS_NOT_FOUND = 404,\n  HTTP_STATUS_METHOD_NOT_ALLOWED = 405,\n  HTTP_STATUS_NOT_ACCEPTABLE = 406,\n  HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,\n  HTTP_STATUS_REQUEST_TIMEOUT = 408,\n  HTTP_STATUS_CONFLICT = 409,\n  HTTP_STATUS_GONE = 410,\n  HTTP_STATUS_LENGTH_REQUIRED = 411,\n  HTTP_STATUS_PRECONDITION_FAILED = 412,\n  HTTP_STATUS_PAYLOAD_TOO_LARGE = 413,\n  HTTP_STATUS_URI_TOO_LONG = 414,\n  HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,\n  HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416,\n  HTTP_STATUS_EXPECTATION_FAILED = 417,\n  HTTP_STATUS_IM_A_TEAPOT = 418,\n  HTTP_STATUS_PAGE_EXPIRED = 419,\n  HTTP_STATUS_ENHANCE_YOUR_CALM = 420,\n  HTTP_STATUS_MISDIRECTED_REQUEST = 421,\n  HTTP_STATUS_UNPROCESSABLE_ENTITY = 422,\n  HTTP_STATUS_LOCKED = 423,\n  HTTP_STATUS_FAILED_DEPENDENCY = 424,\n  HTTP_STATUS_TOO_EARLY = 425,\n  HTTP_STATUS_UPGRADE_REQUIRED = 426,\n  HTTP_STATUS_PRECONDITION_REQUIRED = 428,\n  HTTP_STATUS_TOO_MANY_REQUESTS = 429,\n  HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL = 430,\n  HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,\n  HTTP_STATUS_LOGIN_TIMEOUT = 440,\n  HTTP_STATUS_NO_RESPONSE = 444,\n  HTTP_STATUS_RETRY_WITH = 449,\n  HTTP_STATUS_BLOCKED_BY_PARENTAL_CONTROL = 450,\n  HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451,\n  HTTP_STATUS_CLIENT_CLOSED_LOAD_BALANCED_REQUEST = 460,\n  HTTP_STATUS_INVALID_X_FORWARDED_FOR = 463,\n  HTTP_STATUS_REQUEST_HEADER_TOO_LARGE = 494,\n  HTTP_STATUS_SSL_CERTIFICATE_ERROR = 495,\n  HTTP_STATUS_SSL_CERTIFICATE_REQUIRED = 496,\n  HTTP_STATUS_HTTP_REQUEST_SENT_TO_HTTPS_PORT = 497,\n  HTTP_STATUS_INVALID_TOKEN = 498,\n  HTTP_STATUS_CLIENT_CLOSED_REQUEST = 499,\n  HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,\n  HTTP_STATUS_NOT_IMPLEMENTED = 501,\n  HTTP_STATUS_BAD_GATEWAY = 502,\n  HTTP_STATUS_SERVICE_UNAVAILABLE = 503,\n  HTTP_STATUS_GATEWAY_TIMEOUT = 504,\n  HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505,\n  HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = 506,\n  HTTP_STATUS_INSUFFICIENT_STORAGE = 507,\n  HTTP_STATUS_LOOP_DETECTED = 508,\n  HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED = 509,\n  HTTP_STATUS_NOT_EXTENDED = 510,\n  HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511,\n  HTTP_STATUS_WEB_SERVER_UNKNOWN_ERROR = 520,\n  HTTP_STATUS_WEB_SERVER_IS_DOWN = 521,\n  HTTP_STATUS_CONNECTION_TIMEOUT = 522,\n  HTTP_STATUS_ORIGIN_IS_UNREACHABLE = 523,\n  HTTP_STATUS_TIMEOUT_OCCURED = 524,\n  HTTP_STATUS_SSL_HANDSHAKE_FAILED = 525,\n  HTTP_STATUS_INVALID_SSL_CERTIFICATE = 526,\n  HTTP_STATUS_RAILGUN_ERROR = 527,\n  HTTP_STATUS_SITE_IS_OVERLOADED = 529,\n  HTTP_STATUS_SITE_IS_FROZEN = 530,\n  HTTP_STATUS_IDENTITY_PROVIDER_AUTHENTICATION_ERROR = 561,\n  HTTP_STATUS_NETWORK_READ_TIMEOUT = 598,\n  HTTP_STATUS_NETWORK_CONNECT_TIMEOUT = 599\n};\ntypedef enum llhttp_status llhttp_status_t;\n\n#define HTTP_ERRNO_MAP(XX) \\\n  XX(0, OK, OK) \\\n  XX(1, INTERNAL, INTERNAL) \\\n  XX(2, STRICT, STRICT) \\\n  XX(25, CR_EXPECTED, CR_EXPECTED) \\\n  XX(3, LF_EXPECTED, LF_EXPECTED) \\\n  XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \\\n  XX(30, UNEXPECTED_SPACE, UNEXPECTED_SPACE) \\\n  XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \\\n  XX(6, INVALID_METHOD, INVALID_METHOD) \\\n  XX(7, INVALID_URL, INVALID_URL) \\\n  XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \\\n  XX(9, INVALID_VERSION, INVALID_VERSION) \\\n  XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \\\n  XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \\\n  XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \\\n  XX(13, INVALID_STATUS, INVALID_STATUS) \\\n  XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \\\n  XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \\\n  XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \\\n  XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \\\n  XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \\\n  XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \\\n  XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \\\n  XX(21, PAUSED, PAUSED) \\\n  XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \\\n  XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \\\n  XX(24, USER, USER) \\\n  XX(26, CB_URL_COMPLETE, CB_URL_COMPLETE) \\\n  XX(27, CB_STATUS_COMPLETE, CB_STATUS_COMPLETE) \\\n  XX(32, CB_METHOD_COMPLETE, CB_METHOD_COMPLETE) \\\n  XX(33, CB_VERSION_COMPLETE, CB_VERSION_COMPLETE) \\\n  XX(28, CB_HEADER_FIELD_COMPLETE, CB_HEADER_FIELD_COMPLETE) \\\n  XX(29, CB_HEADER_VALUE_COMPLETE, CB_HEADER_VALUE_COMPLETE) \\\n  XX(34, CB_CHUNK_EXTENSION_NAME_COMPLETE, CB_CHUNK_EXTENSION_NAME_COMPLETE) \\\n  XX(35, CB_CHUNK_EXTENSION_VALUE_COMPLETE, CB_CHUNK_EXTENSION_VALUE_COMPLETE) \\\n  XX(31, CB_RESET, CB_RESET) \\\n  XX(38, CB_PROTOCOL_COMPLETE, CB_PROTOCOL_COMPLETE) \\\n\n\n#define HTTP_METHOD_MAP(XX) \\\n  XX(0, DELETE, DELETE) \\\n  XX(1, GET, GET) \\\n  XX(2, HEAD, HEAD) \\\n  XX(3, POST, POST) \\\n  XX(4, PUT, PUT) \\\n  XX(5, CONNECT, CONNECT) \\\n  XX(6, OPTIONS, OPTIONS) \\\n  XX(7, TRACE, TRACE) \\\n  XX(8, COPY, COPY) \\\n  XX(9, LOCK, LOCK) \\\n  XX(10, MKCOL, MKCOL) \\\n  XX(11, MOVE, MOVE) \\\n  XX(12, PROPFIND, PROPFIND) \\\n  XX(13, PROPPATCH, PROPPATCH) \\\n  XX(14, SEARCH, SEARCH) \\\n  XX(15, UNLOCK, UNLOCK) \\\n  XX(16, BIND, BIND) \\\n  XX(17, REBIND, REBIND) \\\n  XX(18, UNBIND, UNBIND) \\\n  XX(19, ACL, ACL) \\\n  XX(20, REPORT, REPORT) \\\n  XX(21, MKACTIVITY, MKACTIVITY) \\\n  XX(22, CHECKOUT, CHECKOUT) \\\n  XX(23, MERGE, MERGE) \\\n  XX(24, MSEARCH, M-SEARCH) \\\n  XX(25, NOTIFY, NOTIFY) \\\n  XX(26, SUBSCRIBE, SUBSCRIBE) \\\n  XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \\\n  XX(28, PATCH, PATCH) \\\n  XX(29, PURGE, PURGE) \\\n  XX(30, MKCALENDAR, MKCALENDAR) \\\n  XX(31, LINK, LINK) \\\n  XX(32, UNLINK, UNLINK) \\\n  XX(33, SOURCE, SOURCE) \\\n  XX(46, QUERY, QUERY) \\\n\n\n#define RTSP_METHOD_MAP(XX) \\\n  XX(1, GET, GET) \\\n  XX(3, POST, POST) \\\n  XX(6, OPTIONS, OPTIONS) \\\n  XX(35, DESCRIBE, DESCRIBE) \\\n  XX(36, ANNOUNCE, ANNOUNCE) \\\n  XX(37, SETUP, SETUP) \\\n  XX(38, PLAY, PLAY) \\\n  XX(39, PAUSE, PAUSE) \\\n  XX(40, TEARDOWN, TEARDOWN) \\\n  XX(41, GET_PARAMETER, GET_PARAMETER) \\\n  XX(42, SET_PARAMETER, SET_PARAMETER) \\\n  XX(43, REDIRECT, REDIRECT) \\\n  XX(44, RECORD, RECORD) \\\n  XX(45, FLUSH, FLUSH) \\\n\n\n#define HTTP_ALL_METHOD_MAP(XX) \\\n  XX(0, DELETE, DELETE) \\\n  XX(1, GET, GET) \\\n  XX(2, HEAD, HEAD) \\\n  XX(3, POST, POST) \\\n  XX(4, PUT, PUT) \\\n  XX(5, CONNECT, CONNECT) \\\n  XX(6, OPTIONS, OPTIONS) \\\n  XX(7, TRACE, TRACE) \\\n  XX(8, COPY, COPY) \\\n  XX(9, LOCK, LOCK) \\\n  XX(10, MKCOL, MKCOL) \\\n  XX(11, MOVE, MOVE) \\\n  XX(12, PROPFIND, PROPFIND) \\\n  XX(13, PROPPATCH, PROPPATCH) \\\n  XX(14, SEARCH, SEARCH) \\\n  XX(15, UNLOCK, UNLOCK) \\\n  XX(16, BIND, BIND) \\\n  XX(17, REBIND, REBIND) \\\n  XX(18, UNBIND, UNBIND) \\\n  XX(19, ACL, ACL) \\\n  XX(20, REPORT, REPORT) \\\n  XX(21, MKACTIVITY, MKACTIVITY) \\\n  XX(22, CHECKOUT, CHECKOUT) \\\n  XX(23, MERGE, MERGE) \\\n  XX(24, MSEARCH, M-SEARCH) \\\n  XX(25, NOTIFY, NOTIFY) \\\n  XX(26, SUBSCRIBE, SUBSCRIBE) \\\n  XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \\\n  XX(28, PATCH, PATCH) \\\n  XX(29, PURGE, PURGE) \\\n  XX(30, MKCALENDAR, MKCALENDAR) \\\n  XX(31, LINK, LINK) \\\n  XX(32, UNLINK, UNLINK) \\\n  XX(33, SOURCE, SOURCE) \\\n  XX(34, PRI, PRI) \\\n  XX(35, DESCRIBE, DESCRIBE) \\\n  XX(36, ANNOUNCE, ANNOUNCE) \\\n  XX(37, SETUP, SETUP) \\\n  XX(38, PLAY, PLAY) \\\n  XX(39, PAUSE, PAUSE) \\\n  XX(40, TEARDOWN, TEARDOWN) \\\n  XX(41, GET_PARAMETER, GET_PARAMETER) \\\n  XX(42, SET_PARAMETER, SET_PARAMETER) \\\n  XX(43, REDIRECT, REDIRECT) \\\n  XX(44, RECORD, RECORD) \\\n  XX(45, FLUSH, FLUSH) \\\n  XX(46, QUERY, QUERY) \\\n\n\n#define HTTP_STATUS_MAP(XX) \\\n  XX(100, CONTINUE, CONTINUE) \\\n  XX(101, SWITCHING_PROTOCOLS, SWITCHING_PROTOCOLS) \\\n  XX(102, PROCESSING, PROCESSING) \\\n  XX(103, EARLY_HINTS, EARLY_HINTS) \\\n  XX(110, RESPONSE_IS_STALE, RESPONSE_IS_STALE) \\\n  XX(111, REVALIDATION_FAILED, REVALIDATION_FAILED) \\\n  XX(112, DISCONNECTED_OPERATION, DISCONNECTED_OPERATION) \\\n  XX(113, HEURISTIC_EXPIRATION, HEURISTIC_EXPIRATION) \\\n  XX(199, MISCELLANEOUS_WARNING, MISCELLANEOUS_WARNING) \\\n  XX(200, OK, OK) \\\n  XX(201, CREATED, CREATED) \\\n  XX(202, ACCEPTED, ACCEPTED) \\\n  XX(203, NON_AUTHORITATIVE_INFORMATION, NON_AUTHORITATIVE_INFORMATION) \\\n  XX(204, NO_CONTENT, NO_CONTENT) \\\n  XX(205, RESET_CONTENT, RESET_CONTENT) \\\n  XX(206, PARTIAL_CONTENT, PARTIAL_CONTENT) \\\n  XX(207, MULTI_STATUS, MULTI_STATUS) \\\n  XX(208, ALREADY_REPORTED, ALREADY_REPORTED) \\\n  XX(214, TRANSFORMATION_APPLIED, TRANSFORMATION_APPLIED) \\\n  XX(226, IM_USED, IM_USED) \\\n  XX(299, MISCELLANEOUS_PERSISTENT_WARNING, MISCELLANEOUS_PERSISTENT_WARNING) \\\n  XX(300, MULTIPLE_CHOICES, MULTIPLE_CHOICES) \\\n  XX(301, MOVED_PERMANENTLY, MOVED_PERMANENTLY) \\\n  XX(302, FOUND, FOUND) \\\n  XX(303, SEE_OTHER, SEE_OTHER) \\\n  XX(304, NOT_MODIFIED, NOT_MODIFIED) \\\n  XX(305, USE_PROXY, USE_PROXY) \\\n  XX(306, SWITCH_PROXY, SWITCH_PROXY) \\\n  XX(307, TEMPORARY_REDIRECT, TEMPORARY_REDIRECT) \\\n  XX(308, PERMANENT_REDIRECT, PERMANENT_REDIRECT) \\\n  XX(400, BAD_REQUEST, BAD_REQUEST) \\\n  XX(401, UNAUTHORIZED, UNAUTHORIZED) \\\n  XX(402, PAYMENT_REQUIRED, PAYMENT_REQUIRED) \\\n  XX(403, FORBIDDEN, FORBIDDEN) \\\n  XX(404, NOT_FOUND, NOT_FOUND) \\\n  XX(405, METHOD_NOT_ALLOWED, METHOD_NOT_ALLOWED) \\\n  XX(406, NOT_ACCEPTABLE, NOT_ACCEPTABLE) \\\n  XX(407, PROXY_AUTHENTICATION_REQUIRED, PROXY_AUTHENTICATION_REQUIRED) \\\n  XX(408, REQUEST_TIMEOUT, REQUEST_TIMEOUT) \\\n  XX(409, CONFLICT, CONFLICT) \\\n  XX(410, GONE, GONE) \\\n  XX(411, LENGTH_REQUIRED, LENGTH_REQUIRED) \\\n  XX(412, PRECONDITION_FAILED, PRECONDITION_FAILED) \\\n  XX(413, PAYLOAD_TOO_LARGE, PAYLOAD_TOO_LARGE) \\\n  XX(414, URI_TOO_LONG, URI_TOO_LONG) \\\n  XX(415, UNSUPPORTED_MEDIA_TYPE, UNSUPPORTED_MEDIA_TYPE) \\\n  XX(416, RANGE_NOT_SATISFIABLE, RANGE_NOT_SATISFIABLE) \\\n  XX(417, EXPECTATION_FAILED, EXPECTATION_FAILED) \\\n  XX(418, IM_A_TEAPOT, IM_A_TEAPOT) \\\n  XX(419, PAGE_EXPIRED, PAGE_EXPIRED) \\\n  XX(420, ENHANCE_YOUR_CALM, ENHANCE_YOUR_CALM) \\\n  XX(421, MISDIRECTED_REQUEST, MISDIRECTED_REQUEST) \\\n  XX(422, UNPROCESSABLE_ENTITY, UNPROCESSABLE_ENTITY) \\\n  XX(423, LOCKED, LOCKED) \\\n  XX(424, FAILED_DEPENDENCY, FAILED_DEPENDENCY) \\\n  XX(425, TOO_EARLY, TOO_EARLY) \\\n  XX(426, UPGRADE_REQUIRED, UPGRADE_REQUIRED) \\\n  XX(428, PRECONDITION_REQUIRED, PRECONDITION_REQUIRED) \\\n  XX(429, TOO_MANY_REQUESTS, TOO_MANY_REQUESTS) \\\n  XX(430, REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL) \\\n  XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, REQUEST_HEADER_FIELDS_TOO_LARGE) \\\n  XX(440, LOGIN_TIMEOUT, LOGIN_TIMEOUT) \\\n  XX(444, NO_RESPONSE, NO_RESPONSE) \\\n  XX(449, RETRY_WITH, RETRY_WITH) \\\n  XX(450, BLOCKED_BY_PARENTAL_CONTROL, BLOCKED_BY_PARENTAL_CONTROL) \\\n  XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, UNAVAILABLE_FOR_LEGAL_REASONS) \\\n  XX(460, CLIENT_CLOSED_LOAD_BALANCED_REQUEST, CLIENT_CLOSED_LOAD_BALANCED_REQUEST) \\\n  XX(463, INVALID_X_FORWARDED_FOR, INVALID_X_FORWARDED_FOR) \\\n  XX(494, REQUEST_HEADER_TOO_LARGE, REQUEST_HEADER_TOO_LARGE) \\\n  XX(495, SSL_CERTIFICATE_ERROR, SSL_CERTIFICATE_ERROR) \\\n  XX(496, SSL_CERTIFICATE_REQUIRED, SSL_CERTIFICATE_REQUIRED) \\\n  XX(497, HTTP_REQUEST_SENT_TO_HTTPS_PORT, HTTP_REQUEST_SENT_TO_HTTPS_PORT) \\\n  XX(498, INVALID_TOKEN, INVALID_TOKEN) \\\n  XX(499, CLIENT_CLOSED_REQUEST, CLIENT_CLOSED_REQUEST) \\\n  XX(500, INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR) \\\n  XX(501, NOT_IMPLEMENTED, NOT_IMPLEMENTED) \\\n  XX(502, BAD_GATEWAY, BAD_GATEWAY) \\\n  XX(503, SERVICE_UNAVAILABLE, SERVICE_UNAVAILABLE) \\\n  XX(504, GATEWAY_TIMEOUT, GATEWAY_TIMEOUT) \\\n  XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP_VERSION_NOT_SUPPORTED) \\\n  XX(506, VARIANT_ALSO_NEGOTIATES, VARIANT_ALSO_NEGOTIATES) \\\n  XX(507, INSUFFICIENT_STORAGE, INSUFFICIENT_STORAGE) \\\n  XX(508, LOOP_DETECTED, LOOP_DETECTED) \\\n  XX(509, BANDWIDTH_LIMIT_EXCEEDED, BANDWIDTH_LIMIT_EXCEEDED) \\\n  XX(510, NOT_EXTENDED, NOT_EXTENDED) \\\n  XX(511, NETWORK_AUTHENTICATION_REQUIRED, NETWORK_AUTHENTICATION_REQUIRED) \\\n  XX(520, WEB_SERVER_UNKNOWN_ERROR, WEB_SERVER_UNKNOWN_ERROR) \\\n  XX(521, WEB_SERVER_IS_DOWN, WEB_SERVER_IS_DOWN) \\\n  XX(522, CONNECTION_TIMEOUT, CONNECTION_TIMEOUT) \\\n  XX(523, ORIGIN_IS_UNREACHABLE, ORIGIN_IS_UNREACHABLE) \\\n  XX(524, TIMEOUT_OCCURED, TIMEOUT_OCCURED) \\\n  XX(525, SSL_HANDSHAKE_FAILED, SSL_HANDSHAKE_FAILED) \\\n  XX(526, INVALID_SSL_CERTIFICATE, INVALID_SSL_CERTIFICATE) \\\n  XX(527, RAILGUN_ERROR, RAILGUN_ERROR) \\\n  XX(529, SITE_IS_OVERLOADED, SITE_IS_OVERLOADED) \\\n  XX(530, SITE_IS_FROZEN, SITE_IS_FROZEN) \\\n  XX(561, IDENTITY_PROVIDER_AUTHENTICATION_ERROR, IDENTITY_PROVIDER_AUTHENTICATION_ERROR) \\\n  XX(598, NETWORK_READ_TIMEOUT, NETWORK_READ_TIMEOUT) \\\n  XX(599, NETWORK_CONNECT_TIMEOUT, NETWORK_CONNECT_TIMEOUT) \\\n\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n#endif  /* LLLLHTTP_C_HEADERS_ */\n\n\n#ifndef INCLUDE_LLHTTP_API_H_\n#define INCLUDE_LLHTTP_API_H_\n#include <stddef.h>\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(__wasm__)\n#define LLHTTP_EXPORT __attribute__((visibility(\"default\")))\n#elif defined(_WIN32)\n#define LLHTTP_EXPORT __declspec(dllexport)\n#else\n#define LLHTTP_EXPORT\n#endif\n\ntypedef c_nio_llhttp__internal_t llhttp_t;\ntypedef struct llhttp_settings_s llhttp_settings_t;\n\ntypedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);\ntypedef int (*llhttp_cb)(llhttp_t*);\n\nstruct llhttp_settings_s {\n  /* Possible return values 0, -1, `HPE_PAUSED` */\n  llhttp_cb      on_message_begin;\n\n  /* Possible return values 0, -1, HPE_USER */\n  llhttp_data_cb on_protocol;\n  llhttp_data_cb on_url;\n  llhttp_data_cb on_status;\n  llhttp_data_cb on_method;\n  llhttp_data_cb on_version;\n  llhttp_data_cb on_header_field;\n  llhttp_data_cb on_header_value;\n  llhttp_data_cb      on_chunk_extension_name;\n  llhttp_data_cb      on_chunk_extension_value;\n\n  /* Possible return values:\n   * 0  - Proceed normally\n   * 1  - Assume that request/response has no body, and proceed to parsing the\n   *      next message\n   * 2  - Assume absence of body (as above) and make `c_nio_llhttp_execute()` return\n   *      `HPE_PAUSED_UPGRADE`\n   * -1 - Error\n   * `HPE_PAUSED`\n   */\n  llhttp_cb      on_headers_complete;\n\n  /* Possible return values 0, -1, HPE_USER */\n  llhttp_data_cb on_body;\n\n  /* Possible return values 0, -1, `HPE_PAUSED` */\n  llhttp_cb      on_message_complete;\n  llhttp_cb      on_protocol_complete;\n  llhttp_cb      on_url_complete;\n  llhttp_cb      on_status_complete;\n  llhttp_cb      on_method_complete;\n  llhttp_cb      on_version_complete;\n  llhttp_cb      on_header_field_complete;\n  llhttp_cb      on_header_value_complete;\n  llhttp_cb      on_chunk_extension_name_complete;\n  llhttp_cb      on_chunk_extension_value_complete;\n\n  /* When on_chunk_header is called, the current chunk length is stored\n   * in parser->content_length.\n   * Possible return values 0, -1, `HPE_PAUSED`\n   */\n  llhttp_cb      on_chunk_header;\n  llhttp_cb      on_chunk_complete;\n  llhttp_cb      on_reset;\n};\n\n/* Initialize the parser with specific type and user settings.\n *\n * NOTE: lifetime of `settings` has to be at least the same as the lifetime of\n * the `parser` here. In practice, `settings` has to be either a static\n * variable or be allocated with `malloc`, `new`, etc.\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_init(llhttp_t* parser, llhttp_type_t type,\n                 const llhttp_settings_t* settings);\n\nLLHTTP_EXPORT\nllhttp_t* llhttp_alloc(llhttp_type_t type);\n\nLLHTTP_EXPORT\nvoid llhttp_free(llhttp_t* parser);\n\nLLHTTP_EXPORT\nuint8_t c_nio_llhttp_get_type(llhttp_t* parser);\n\nLLHTTP_EXPORT\nuint8_t c_nio_llhttp_get_http_major(llhttp_t* parser);\n\nLLHTTP_EXPORT\nuint8_t c_nio_llhttp_get_http_minor(llhttp_t* parser);\n\nLLHTTP_EXPORT\nuint8_t c_nio_llhttp_get_method(llhttp_t* parser);\n\nLLHTTP_EXPORT\nint c_nio_llhttp_get_status_code(llhttp_t* parser);\n\nLLHTTP_EXPORT\nuint8_t c_nio_llhttp_get_upgrade(llhttp_t* parser);\n\n/* Reset an already initialized parser back to the start state, preserving the\n * existing parser type, callback settings, user data, and lenient flags.\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_reset(llhttp_t* parser);\n\n/* Initialize the settings object */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_settings_init(llhttp_settings_t* settings);\n\n/* Parse full or partial request/response, invoking user callbacks along the\n * way.\n *\n * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing\n * interrupts, and such errno is returned from `c_nio_llhttp_execute()`. If\n * `HPE_PAUSED` was used as a errno, the execution can be resumed with\n * `c_nio_llhttp_resume()` call.\n *\n * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`\n * is returned after fully parsing the request/response. If the user wishes to\n * continue parsing, they need to invoke `c_nio_llhttp_resume_after_upgrade()`.\n *\n * NOTE: if this function ever returns a non-pause type error, it will continue\n * to return the same error upon each successive call up until `c_nio_llhttp_init()`\n * is called.\n */\nLLHTTP_EXPORT\nllhttp_errno_t c_nio_llhttp_execute(llhttp_t* parser, const char* data, size_t len);\n\n/* This method should be called when the other side has no further bytes to\n * send (e.g. shutdown of readable side of the TCP connection.)\n *\n * Requests without `Content-Length` and other messages might require treating\n * all incoming bytes as the part of the body, up to the last byte of the\n * connection. This method will invoke `on_message_complete()` callback if the\n * request was terminated safely. Otherwise a error code would be returned.\n */\nLLHTTP_EXPORT\nllhttp_errno_t c_nio_llhttp_finish(llhttp_t* parser);\n\n/* Returns `1` if the incoming message is parsed until the last byte, and has\n * to be completed by calling `c_nio_llhttp_finish()` on EOF\n */\nLLHTTP_EXPORT\nint c_nio_llhttp_message_needs_eof(const llhttp_t* parser);\n\n/* Returns `1` if there might be any other messages following the last that was\n * successfully parsed.\n */\nLLHTTP_EXPORT\nint c_nio_llhttp_should_keep_alive(const llhttp_t* parser);\n\n/* Make further calls of `c_nio_llhttp_execute()` return `HPE_PAUSED` and set\n * appropriate error reason.\n *\n * Important: do not call this from user callbacks! User callbacks must return\n * `HPE_PAUSED` if pausing is required.\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_pause(llhttp_t* parser);\n\n/* Might be called to resume the execution after the pause in user's callback.\n * See `c_nio_llhttp_execute()` above for details.\n *\n * Call this only if `c_nio_llhttp_execute()` returns `HPE_PAUSED`.\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_resume(llhttp_t* parser);\n\n/* Might be called to resume the execution after the pause in user's callback.\n * See `c_nio_llhttp_execute()` above for details.\n *\n * Call this only if `c_nio_llhttp_execute()` returns `HPE_PAUSED_UPGRADE`\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_resume_after_upgrade(llhttp_t* parser);\n\n/* Returns the latest return error */\nLLHTTP_EXPORT\nllhttp_errno_t c_nio_llhttp_get_errno(const llhttp_t* parser);\n\n/* Returns the verbal explanation of the latest returned error.\n *\n * Note: User callback should set error reason when returning the error. See\n * `c_nio_llhttp_set_error_reason()` for details.\n */\nLLHTTP_EXPORT\nconst char* c_nio_llhttp_get_error_reason(const llhttp_t* parser);\n\n/* Assign verbal description to the returned error. Must be called in user\n * callbacks right before returning the errno.\n *\n * Note: `HPE_USER` error code might be useful in user callbacks.\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_error_reason(llhttp_t* parser, const char* reason);\n\n/* Returns the pointer to the last parsed byte before the returned error. The\n * pointer is relative to the `data` argument of `c_nio_llhttp_execute()`.\n *\n * Note: this method might be useful for counting the number of parsed bytes.\n */\nLLHTTP_EXPORT\nconst char* c_nio_llhttp_get_error_pos(const llhttp_t* parser);\n\n/* Returns textual name of error code */\nLLHTTP_EXPORT\nconst char* c_nio_llhttp_errno_name(llhttp_errno_t err);\n\n/* Returns textual name of HTTP method */\nLLHTTP_EXPORT\nconst char* c_nio_llhttp_method_name(llhttp_method_t method);\n\n/* Returns textual name of HTTP status */\nLLHTTP_EXPORT\nconst char* c_nio_llhttp_status_name(llhttp_status_t status);\n\n/* Enables/disables lenient header value parsing (disabled by default).\n *\n * Lenient parsing disables header value token checks, extending llhttp's\n * protocol support to highly non-compliant clients/server. No\n * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when\n * lenient parsing is \"on\".\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_headers(llhttp_t* parser, int enabled);\n\n\n/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and\n * `Content-Length` headers (disabled by default).\n *\n * Normally `llhttp` would error when `Transfer-Encoding` is present in\n * conjunction with `Content-Length`. This error is important to prevent HTTP\n * request smuggling, but may be less desirable for small number of cases\n * involving legacy servers.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);\n\n\n/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0\n * requests responses.\n *\n * Normally `llhttp` would error on (in strict mode) or discard (in loose mode)\n * the HTTP request/response after the request/response with `Connection: close`\n * and `Content-Length`. This is important to prevent cache poisoning attacks,\n * but might interact badly with outdated and insecure clients. With this flag\n * the extra request/response will be parsed normally.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * poisoning attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);\n\n/* Enables/disables lenient handling of `Transfer-Encoding` header.\n *\n * Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value\n * and another value after it (either in a single header or in multiple\n * headers whose value are internally joined using `, `).\n * This is mandated by the spec to reliably determine request body size and thus\n * avoid request smuggling.\n * With this flag the extra value will be parsed normally.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled);\n\n/* Enables/disables lenient handling of HTTP version.\n *\n * Normally `llhttp` would error when the HTTP version in the request or status line\n * is not `0.9`, `1.0`, `1.1` or `2.0`.\n * With this flag the invalid value will be parsed normally.\n *\n * **Enabling this flag can pose a security issue since you will allow unsupported\n * HTTP versions. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_version(llhttp_t* parser, int enabled);\n\n/* Enables/disables lenient handling of additional data received after a message ends\n * and keep-alive is disabled.\n *\n * Normally `llhttp` would error when additional unexpected data is received if the message\n * contains the `Connection` header with `close` value.\n * With this flag the extra data will discarded without throwing an error.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * poisoning attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled);\n\n/* Enables/disables lenient handling of incomplete CRLF sequences.\n *\n * Normally `llhttp` would error when a CR is not followed by LF when terminating the\n * request line, the status line, the headers or a chunk header.\n * With this flag only a CR is required to terminate such sections.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled);\n\n/*\n * Enables/disables lenient handling of line separators.\n *\n * Normally `llhttp` would error when a LF is not preceded by CR when terminating the\n * request line, the status line, the headers, a chunk header or a chunk data.\n * With this flag only a LF is required to terminate such sections.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled);\n\n/* Enables/disables lenient handling of chunks not separated via CRLF.\n *\n * Normally `llhttp` would error when after a chunk data a CRLF is missing before\n * starting a new chunk.\n * With this flag the new chunk can start immediately after the previous one.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled);\n\n/* Enables/disables lenient handling of spaces after chunk size.\n *\n * Normally `llhttp` would error when after a chunk size is followed by one or more\n * spaces are present instead of a CRLF or `;`.\n * With this flag this check is disabled.\n *\n * **Enabling this flag can pose a security issue since you will be exposed to\n * request smuggling attacks. USE WITH CAUTION!**\n */\nLLHTTP_EXPORT\nvoid c_nio_llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled);\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n#endif  /* INCLUDE_LLHTTP_API_H_ */\n\n\n#endif  /* INCLUDE_LLHTTP_H_ */\n"
  },
  {
    "path": "Sources/CNIOLLHTTP/update_and_patch_llhttp.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\ncase \"$(uname -s)\" in\n    Darwin)\n        sed=\"gsed\"\n        ;;\n    *)\n        sed=\"sed\"\n        ;;\nesac\n\nif ! hash ${sed} 2>/dev/null; then\n    echo \"You need sed \\\"${sed}\\\" to run this script ...\"\n    echo\n    echo \"On macOS: brew install gnu-sed\"\n    exit 42\nfi\n\nrm \"$here\"/*.c\n\ntmpdir=$(mktemp -d /tmp/.llhttp_vendor_XXXXXX)\ncd \"$tmpdir\"\ngit clone https://github.com/nodejs/llhttp.git\ncd llhttp\nnpm install\nmake\n\ncp \"$tmpdir/llhttp/LICENSE\" \"$here\"\ncp \"$tmpdir/llhttp/build/llhttp.h\" \"$here\"\ncp \"$tmpdir/llhttp/build/c/llhttp.c\" \"$here\"\ncp \"$tmpdir/llhttp/src/native/\"*.c \"$here\"\n\ncd \"$here\"\n\n# The sed script in here has gotten a little unwieldy, we should consider doing\n# something smarter. For now it's good enough.\nfor f in *.{c,h}; do\n    ( echo \"/* Additional changes for SwiftNIO:\"\n      echo \"    - prefixed all symbols by 'c_nio_'\"\n      echo \"*/\"\n    ) > \"c_nio_$f\"\n    cat \"$f\" >> \"$here/c_nio_$f\"\n    rm \"$f\"\n    \"$sed\" -i \\\n        -e 's#\"llhttp.h\"#\"include/c_nio_llhttp.h\"#g' \\\n        -e 's/\\b\\(llhttp__after_headers_complete\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp__after_message_complete\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp__before_headers_complete\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp__debug\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp__internal\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp__on_\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_errno_name\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_execute\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_finish\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_errno\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_error_pos\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_error_reason\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_http_major\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_http_minor\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_method\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_status_code\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_type\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_get_upgrade\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_init\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_message_needs_eof\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_method_name\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_pause\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_reset\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_resume\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_resume_after_upgrade\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_error_reason\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_chunked_length\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_data_after_close\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_headers\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_keep_alive\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_optional_crlf_after_chunk\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_optional_lf_after_cr\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_transfer_encoding\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_version\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_settings_init\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_should_keep_alive\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_status_name\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_spaces_after_chunk_size\\)/c_nio_\\1/g' \\\n        -e 's/\\b\\(llhttp_set_lenient_optional_cr_before_lf\\)/c_nio_\\1/g' \\\n        \"$here/c_nio_$f\"\ndone\n\nmv \"$here/c_nio_llhttp.h\" \"$here/include\"\n\ncompiletmp=$(mktemp -d /tmp/.test_compile_XXXXXX)\n\nfor f in *.c; do\n    clang -o \"$compiletmp/$f.o\" -c \"$here/$f\"\n    num_non_nio=$(nm \"$compiletmp/$f.o\" | grep ' T ' | grep -cv c_nio || true)\n\n    test 0 -eq \"$num_non_nio\" || {\n        echo \"ERROR: $num_non_nio exported non-prefixed symbols found\"\n        nm \"$compiletmp/$f.o\" | grep ' T ' | grep -v c_nio\n        exit 1\n    }\ndone\n\npatch -p1 -V none << 'EOF'\ndiff --git a/include/c_nio_llhttp.h b/include/c_nio_llhttp.h\nindex 071e828c6..1e5d99cec 100644\n--- a/include/c_nio_llhttp.h\n+++ b/include/c_nio_llhttp.h\n@@ -11,11 +11,16 @@\n \n #ifndef INCLUDE_LLHTTP_ITSELF_H_\n #define INCLUDE_LLHTTP_ITSELF_H_\n+#ifdef __cplusplus\n+#include <cstdint>\n+#else\n+#include <stdint.h>\n+#endif\n+\n #ifdef __cplusplus\n extern \"C\" {\n #endif\n \n-#include <stdint.h>\n \n typedef struct c_nio_llhttp__internal_s c_nio_llhttp__internal_t;\n struct c_nio_llhttp__internal_s {\nEOF\n\npatch -p1 -V none << 'EOF'\ndiff --git a/include/c_nio_llhttp.h b/include/c_nio_llhttp.h\nindex 1e5d99ce..39cf110a 100644\n--- a/include/c_nio_llhttp.h\n+++ b/include/c_nio_llhttp.h\n@@ -553,10 +553,10 @@ typedef enum llhttp_status llhttp_status_t;\n \n #ifndef INCLUDE_LLHTTP_API_H_\n #define INCLUDE_LLHTTP_API_H_\n+#include <stddef.h>\n #ifdef __cplusplus\n extern \"C\" {\n #endif\n-#include <stddef.h>\n \n #if defined(__wasm__)\n #define LLHTTP_EXPORT __attribute__((visibility(\"default\")))\nEOF\n\nrm -rf \"$compiletmp\"\nrm -rf \"$tmpdir\"\n\n"
  },
  {
    "path": "Sources/CNIOLinux/include/CNIOLinux.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#ifndef C_NIO_LINUX_H\n#define C_NIO_LINUX_H\n\n#ifdef __linux__\n#include <poll.h>\n#include <sys/epoll.h>\n#include <sys/eventfd.h>\n#include <sys/timerfd.h>\n#include <sys/sysinfo.h>\n#include <sys/socket.h>\n#include <sys/utsname.h>\n#include <sys/xattr.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <sys/vfs.h>\n#include <sched.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <pthread.h>\n#include <netinet/ip.h>\n#if __has_include(<linux/magic.h>)\n#include <linux/magic.h>\n#endif\n#if __has_include(<linux/udp.h>)\n#include <linux/udp.h>\n#else\n#include <netinet/udp.h>\n#endif\n#include <linux/vm_sockets.h>\n#include <fcntl.h>\n#include <fts.h>\n#include <stdio.h>\n#include <dirent.h>\n#endif\n\n// We need to include this outside the `#ifdef` so macOS builds don't warn about the missing include,\n// but we also need to make sure the system includes come before it on Linux, so we put it down here\n// between an `#endif/#ifdef` pair rather than at the top.\n#include \"liburing_nio.h\"\n\n#ifdef __linux__\n\n#if __has_include(<linux/mptcp.h>)\n#include <linux/mptcp.h>\n#else\n// A backported copy of the mptcp_info structure to make programming against\n// an uncertain linux kernel easier.\nstruct mptcp_info {\n    uint8_t    mptcpi_subflows;\n    uint8_t    mptcpi_add_addr_signal;\n    uint8_t    mptcpi_add_addr_accepted;\n    uint8_t    mptcpi_subflows_max;\n    uint8_t    mptcpi_add_addr_signal_max;\n    uint8_t    mptcpi_add_addr_accepted_max;\n    uint32_t   mptcpi_flags;\n    uint32_t   mptcpi_token;\n    uint64_t   mptcpi_write_seq;\n    uint64_t   mptcpi_snd_una;\n    uint64_t   mptcpi_rcv_nxt;\n    uint8_t    mptcpi_local_addr_used;\n    uint8_t    mptcpi_local_addr_max;\n    uint8_t    mptcpi_csum_enabled;\n};\n#endif\n\n// Some explanation is required here.\n//\n// Due to SR-6772, we cannot get Swift code to directly see any of the mmsg structures or\n// functions. However, we *can* get C code built by SwiftPM to see them. For this reason we\n// elect to provide a selection of shims to enable Swift code to use recv_mmsg and send_mmsg.\n// Mostly this is fine, but to minimise the overhead we want the Swift code to be able to\n// create the msgvec directly without requiring further memory fussiness in our C shim.\n// That requires us to also construct a C structure that has the same layout as struct mmsghdr.\n//\n// Conveniently glibc has pretty strict ABI stability rules, and this structure is part of the\n// glibc ABI, so we can just reproduce the structure definition here and feel confident that it\n// will be sufficient.\n//\n// If SR-6772 ever gets resolved we can remove this shim.\n//\n// https://bugs.swift.org/browse/SR-6772\n\ntypedef struct {\n    struct msghdr msg_hdr;\n    unsigned int msg_len;\n} CNIOLinux_mmsghdr;\n\ntypedef struct {\n    struct in6_addr ipi6_addr;\n    unsigned int ipi6_ifindex;\n} CNIOLinux_in6_pktinfo;\n\nint CNIOLinux_sendmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags);\nint CNIOLinux_recvmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);\n\nint CNIOLinux_pthread_setname_np(pthread_t thread, const char *name);\nint CNIOLinux_pthread_getname_np(pthread_t thread, char *name, size_t len);\n\n// Non-standard socket stuff.\nint CNIOLinux_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);\n\n// Thread affinity stuff.\nint CNIOLinux_pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);\nint CNIOLinux_pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);\nvoid CNIOLinux_CPU_SET(int cpu, cpu_set_t *set);\nvoid CNIOLinux_CPU_ZERO(cpu_set_t *set);\nint CNIOLinux_CPU_ISSET(int cpu, cpu_set_t *set);\nint CNIOLinux_CPU_SETSIZE();\n\n// cmsghdr handling\nstruct cmsghdr *CNIOLinux_CMSG_FIRSTHDR(const struct msghdr *);\nstruct cmsghdr *CNIOLinux_CMSG_NXTHDR(struct msghdr *, struct cmsghdr *);\nconst void *CNIOLinux_CMSG_DATA(const struct cmsghdr *);\nvoid *CNIOLinux_CMSG_DATA_MUTABLE(struct cmsghdr *);\nsize_t CNIOLinux_CMSG_LEN(size_t);\nsize_t CNIOLinux_CMSG_SPACE(size_t);\n\n// awkward time_T pain\nextern const int CNIOLinux_SO_TIMESTAMP;\nextern const int CNIOLinux_SO_RCVTIMEO;\n\nbool CNIOLinux_supports_udp_segment();\nbool CNIOLinux_supports_udp_gro();\n\nint CNIOLinux_system_info(struct utsname* uname_data);\n\nextern const unsigned long CNIOLinux_IOCTL_VM_SOCKETS_GET_LOCAL_CID;\n\nconst char* CNIOLinux_dirent_dname(struct dirent* ent);\n\nint CNIOLinux_renameat2(int oldfd, const char* old, int newfd, const char* newName, unsigned int flags);\n\nextern const int CNIOLinux_O_TMPFILE;\nextern const int CNIOLinux_AT_EMPTY_PATH;\nextern const unsigned int CNIOLinux_RENAME_NOREPLACE;\nextern const unsigned int CNIOLinux_RENAME_EXCHANGE;\n\nextern const unsigned long CNIOLinux_UTIME_OMIT;\nextern const unsigned long CNIOLinux_UTIME_NOW;\n\n// Filesystem magic constants for cgroup detection\n#ifdef __ANDROID__\n#if defined(__LP64__)\ntypedef uint64_t f_type_t;\n#else\ntypedef uint32_t f_type_t;\n#endif\n#else\n#ifdef __FSWORD_T_TYPE\ntypedef __fsword_t f_type_t;\n#else\ntypedef unsigned long f_type_t;\n#endif\n#endif\n\nextern const f_type_t CNIOLinux_TMPFS_MAGIC;\nextern const f_type_t CNIOLinux_CGROUP2_SUPER_MAGIC;\n\n// Workaround for https://github.com/swiftlang/swift/issues/86149\nf_type_t CNIOLinux_statfs_ftype(const char *path);\n\n// A workaround for incorrect nullability annotations in the Android SDK.\nFTS *CNIOLinux_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **));\n\n#endif\n#endif\n"
  },
  {
    "path": "Sources/CNIOLinux/include/liburing_nio.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#ifndef LIBURING_NIO_H\n#define LIBURING_NIO_H\n\n#ifdef __linux__\n\n#ifdef SWIFTNIO_USE_IO_URING\n\n#if __has_include(<liburing.h>)\n#include <liburing.h>\n#else\n#error \"SWIFTNIO_USE_IO_URING specified but liburing.h not available. You need to install https://github.com/axboe/liburing.\"\n#endif\n\n// OR in the IOSQE_IO_LINK flag, couldn't access the define from Swift\nvoid CNIOLinux_io_uring_set_link_flag(struct io_uring_sqe *sqe);\n\n// No way I managed to get this even when defining _GNU_SOURCE properly. Argh.\nunsigned int CNIOLinux_POLLRDHUP();\n\n#endif\n\n#endif /* __linux__ */\n\n#endif /* LIBURING_NIO_H */\n"
  },
  {
    "path": "Sources/CNIOLinux/liburing_shims.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// Support functions for liburing\n\n// Check if this is needed, copied from shim.c to avoid possible problems due to:\n// Xcode's Archive builds with Xcode's Package support struggle with empty .c files\n// (https://bugs.swift.org/browse/SR-12939).\nvoid CNIOLinux_i_do_nothing_just_working_around_a_darwin_toolchain_bug2(void) {}\n\n#ifdef __linux__\n\n#ifdef SWIFTNIO_USE_IO_URING\n\n#define _GNU_SOURCE\n#include <CNIOLinux.h>\n#include <signal.h>\n#include <sys/poll.h>\n\nvoid CNIOLinux_io_uring_set_link_flag(struct io_uring_sqe *sqe)\n{\n    sqe->flags |= IOSQE_IO_LINK;\n    return;\n}\n\nunsigned int CNIOLinux_POLLRDHUP()\n{\n    return POLLRDHUP;\n}\n\n#endif\n\n#endif\n"
  },
  {
    "path": "Sources/CNIOLinux/shim.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// Xcode's Archive builds with Xcode's Package support struggle with empty .c files\n// (https://bugs.swift.org/browse/SR-12939).\nvoid CNIOLinux_i_do_nothing_just_working_around_a_darwin_toolchain_bug(void) {}\n\n#ifdef __linux__\n\n#ifndef _GNU_SOURCE\n#error You must define _GNU_SOURCE\n#endif\n\n#include <CNIOLinux.h>\n#include <pthread.h>\n#include <sched.h>\n#include <stdio.h>\n#include <sys/prctl.h>\n#include <sys/syscall.h>\n#include <sys/utsname.h>\n#include <unistd.h>\n#include <assert.h>\n#include <time.h>\n#include <sys/ioctl.h>\n#include <sys/stat.h>\n\n_Static_assert(sizeof(CNIOLinux_mmsghdr) == sizeof(struct mmsghdr),\n               \"sizes of CNIOLinux_mmsghdr and struct mmsghdr differ\");\n\n_Static_assert(sizeof(CNIOLinux_in6_pktinfo) == sizeof(struct in6_pktinfo),\n               \"sizes of CNIOLinux_in6_pktinfo and struct in6_pktinfo differ\");\n\nint CNIOLinux_sendmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags) {\n    // This is technically undefined behaviour, but it's basically fine because these types are the same size, and we\n    // don't think the compiler is inclined to blow anything up here.\n    return sendmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags);\n}\n\nint CNIOLinux_recvmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {\n    // This is technically undefined behaviour, but it's basically fine because these types are the same size, and we\n    // don't think the compiler is inclined to blow anything up here.\n    return recvmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags, timeout);\n}\n\nint CNIOLinux_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    return accept4(sockfd, addr, addrlen, flags);\n}\n\nint CNIOLinux_pthread_setname_np(pthread_t thread, const char *name) {\n    return pthread_setname_np(thread, name);\n}\n\nint CNIOLinux_pthread_getname_np(pthread_t thread, char *name, size_t len) {\n#ifdef __ANDROID__\n    // https://android.googlesource.com/platform/bionic/+/8a18af52d9b9344497758ed04907a314a083b204/libc/bionic/pthread_setname_np.cpp#51\n    if (thread == pthread_self()) {\n        return TEMP_FAILURE_RETRY(prctl(PR_GET_NAME, name)) == -1 ? -1 : 0;\n    }\n\n    char comm_name[64];\n    snprintf(comm_name, sizeof(comm_name), \"/proc/self/task/%d/comm\", pthread_gettid_np(thread));\n    int fd = TEMP_FAILURE_RETRY(open(comm_name, O_CLOEXEC | O_RDONLY));\n\n    if (fd == -1) return -1;\n\n    ssize_t n = TEMP_FAILURE_RETRY(read(fd, name, len));\n    close(fd);\n    if (n == -1) return -1;\n\n    // The kernel adds a trailing '\\n' to the /proc file,\n    // so this is actually the normal case for short names.\n    if (n > 0 && name[n - 1] == '\\n') {\n        name[n - 1] = '\\0';\n        return 0;\n    }\n\n    if (n >= 0 && len <= SSIZE_MAX && n == (ssize_t)len) return 1;\n\n    name[n] = '\\0';\n    return 0;\n#else\n    return pthread_getname_np(thread, name, len);\n#endif\n}\n\nint CNIOLinux_pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset) {\n#ifdef __ANDROID__\n    return sched_setaffinity(pthread_gettid_np(thread), cpusetsize, cpuset);\n#else\n    return pthread_setaffinity_np(thread, cpusetsize, cpuset);\n#endif\n}\n\nint CNIOLinux_pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset) {\n#ifdef __ANDROID__\n    return sched_getaffinity(pthread_gettid_np(thread), cpusetsize, cpuset);\n#else\n    return pthread_getaffinity_np(thread, cpusetsize, cpuset);\n#endif\n}\n\nvoid CNIOLinux_CPU_SET(int cpu, cpu_set_t *set) {\n    CPU_SET(cpu, set);\n}\n\nvoid CNIOLinux_CPU_ZERO(cpu_set_t *set) {\n    CPU_ZERO(set);\n}\n\nint CNIOLinux_CPU_ISSET(int cpu, cpu_set_t *set) {\n    return CPU_ISSET(cpu, set);\n}\n\nint CNIOLinux_CPU_SETSIZE() {\n    return CPU_SETSIZE;\n}\n\nstruct cmsghdr *CNIOLinux_CMSG_FIRSTHDR(const struct msghdr *mhdr) {\n    assert(mhdr != NULL);\n    return CMSG_FIRSTHDR(mhdr);\n}\n\nstruct cmsghdr *CNIOLinux_CMSG_NXTHDR(struct msghdr *mhdr, struct cmsghdr *cmsg) {\n    assert(mhdr != NULL);\n    assert(cmsg != NULL);\n    return CMSG_NXTHDR(mhdr, cmsg);\n}\n\nconst void *CNIOLinux_CMSG_DATA(const struct cmsghdr *cmsg) {\n    assert(cmsg != NULL);\n    return CMSG_DATA(cmsg);\n}\n\nvoid *CNIOLinux_CMSG_DATA_MUTABLE(struct cmsghdr *cmsg) {\n    assert(cmsg != NULL);\n    return CMSG_DATA(cmsg);\n}\n\nsize_t CNIOLinux_CMSG_LEN(size_t payloadSizeBytes) {\n    return CMSG_LEN(payloadSizeBytes);\n}\n\nsize_t CNIOLinux_CMSG_SPACE(size_t payloadSizeBytes) {\n    return CMSG_SPACE(payloadSizeBytes);\n}\n\nconst int CNIOLinux_SO_TIMESTAMP = SO_TIMESTAMP;\nconst int CNIOLinux_SO_RCVTIMEO = SO_RCVTIMEO;\n\nbool supports_udp_sockopt(int opt, int value) {\n    int fd = socket(AF_INET, SOCK_DGRAM, 0);\n    if (fd == -1) {\n        return false;\n    }\n    int rc = setsockopt(fd, IPPROTO_UDP, opt, &value, sizeof(value));\n    close(fd);\n    return rc == 0;\n}\n\nbool CNIOLinux_supports_udp_segment() {\n    #ifndef UDP_SEGMENT\n    return false;\n    #else\n    return supports_udp_sockopt(UDP_SEGMENT, 512);\n    #endif\n}\n\nbool CNIOLinux_supports_udp_gro() {\n    #ifndef UDP_GRO\n    return false;\n    #else\n    return supports_udp_sockopt(UDP_GRO, 1);\n    #endif\n}\n\nint CNIOLinux_system_info(struct utsname* uname_data) {\n    return uname(uname_data);\n}\n\nconst unsigned long CNIOLinux_IOCTL_VM_SOCKETS_GET_LOCAL_CID = IOCTL_VM_SOCKETS_GET_LOCAL_CID;\n\nconst char* CNIOLinux_dirent_dname(struct dirent* ent) {\n    return ent->d_name;\n}\n\nint CNIOLinux_renameat2(int oldfd, const char* old, int newfd, const char* newName, unsigned int flags) {\n    // Musl doesn't have renameat2, so we make the raw system call directly\n    return syscall(SYS_renameat2, oldfd, old, newfd, newName, flags);\n}\n\n// Musl also doesn't define the flags for renameat2, so we will do so.\n#ifndef RENAME_NOREPLACE\n#define RENAME_NOREPLACE 1\n#endif\n#ifndef RENAME_EXCHANGE\n#define RENAME_EXCHANGE  2\n#endif\n\nconst int CNIOLinux_O_TMPFILE = O_TMPFILE;\nconst unsigned int CNIOLinux_RENAME_NOREPLACE = RENAME_NOREPLACE;\nconst unsigned int CNIOLinux_RENAME_EXCHANGE = RENAME_EXCHANGE;\nconst int CNIOLinux_AT_EMPTY_PATH = AT_EMPTY_PATH;\n\nconst unsigned long CNIOLinux_UTIME_OMIT = UTIME_OMIT;\nconst unsigned long CNIOLinux_UTIME_NOW = UTIME_NOW;\n\n#ifndef TMPFS_MAGIC\n#define TMPFS_MAGIC 0x01021994\n#endif\n#ifndef CGROUP2_SUPER_MAGIC\n#define CGROUP2_SUPER_MAGIC 0x63677270\n#endif\n\nconst f_type_t CNIOLinux_TMPFS_MAGIC = TMPFS_MAGIC;\nconst f_type_t CNIOLinux_CGROUP2_SUPER_MAGIC = CGROUP2_SUPER_MAGIC;\n\nf_type_t CNIOLinux_statfs_ftype(const char *path) {\n    struct statfs fs;\n    f_type_t f_type = 0;\n    if (statfs(path, &fs) == 0) {\n        f_type = fs.f_type;\n    }\n    return f_type;\n}\n\nFTS *CNIOLinux_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)) {\n    return fts_open(path_argv, options, compar);\n}\n#endif\n"
  },
  {
    "path": "Sources/CNIOOpenBSD/include/CNIOOpenBSD.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#ifndef C_NIO_OPENBSD_H\n#define C_NIO_OPENBSD_H\n\n#if defined(__OpenBSD__)\n#include <sys/types.h>\n#include <sys/event.h>\n#include <pthread_np.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/un.h>\n#include <sys/utsname.h>\n#include <dirent.h>\n#include <fts.h>\n#include <ifaddrs.h>\n#include <net/if.h>\n#include <netinet/in.h>\n#include <netinet/ip.h>\n#include <pthread.h>\n#include <stdbool.h>\n\n\n// Some explanation is required here.\n//\n// Due to SR-6772, we cannot get Swift code to directly see any of the mmsg structures or\n// functions. However, we *can* get C code built by SwiftPM to see them. For this reason we\n// elect to provide a selection of shims to enable Swift code to use recv_mmsg and send_mmsg.\n// Mostly this is fine, but to minimise the overhead we want the Swift code to be able to\n// create the msgvec directly without requiring further memory fussiness in our C shim.\n// That requires us to also construct a C structure that has the same layout as struct mmsghdr.\n//\n// Conveniently glibc has pretty strict ABI stability rules, and this structure is part of the\n// glibc ABI, so we can just reproduce the structure definition here and feel confident that it\n// will be sufficient.\n//\n// If SR-6772 ever gets resolved we can remove this shim.\n//\n// https://bugs.swift.org/browse/SR-6772\n\ntypedef struct {\n    struct msghdr msg_hdr;\n    unsigned int msg_len;\n} CNIOOpenBSD_mmsghdr;\n\ntypedef struct {\n    struct in6_addr ipi6_addr;\n    unsigned int ipi6_ifindex;\n} CNIOOpenBSD_in6_pktinfo;\n\nint CNIOOpenBSD_sendmmsg(int sockfd, CNIOOpenBSD_mmsghdr *msgvec, unsigned int vlen, int flags);\nint CNIOOpenBSD_recvmmsg(int sockfd, CNIOOpenBSD_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);\n\nint CNIOOpenBSD_pthread_set_name_np(pthread_t thread, const char *name);\nint CNIOOpenBSD_pthread_get_name_np(pthread_t thread, char *name, size_t len);\n\n// Non-standard socket stuff.\nint CNIOOpenBSD_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);\n\n// cmsghdr handling\nstruct cmsghdr *CNIOOpenBSD_CMSG_FIRSTHDR(const struct msghdr *);\nstruct cmsghdr *CNIOOpenBSD_CMSG_NXTHDR(struct msghdr *, struct cmsghdr *);\nconst void *CNIOOpenBSD_CMSG_DATA(const struct cmsghdr *);\nvoid *CNIOOpenBSD_CMSG_DATA_MUTABLE(struct cmsghdr *);\nsize_t CNIOOpenBSD_CMSG_LEN(size_t);\nsize_t CNIOOpenBSD_CMSG_SPACE(size_t);\n\n// awkward time_T pain\nextern const int CNIOOpenBSD_SO_TIMESTAMP;\nextern const int CNIOOpenBSD_SO_RCVTIMEO;\n\nint CNIOOpenBSD_system_info(struct utsname *uname_data);\n\nextern const unsigned long CNIOOpenBSD_IOCTL_VM_SOCKETS_GET_LOCAL_CID;\n\nconst char* CNIOOpenBSD_dirent_dname(struct dirent *ent);\n\nextern const unsigned long CNIOOpenBSD_UTIME_OMIT;\nextern const unsigned long CNIOOpenBSD_UTIME_NOW;\n\nextern const long CNIOOpenBSD_UDP_MAX_SEGMENTS;\n\n// A workaround for incorrect nullability annotations in the Android SDK.\n// Probably unnecessary on BSD, but copying for consistency for now.\nFTS *CNIOOpenBSD_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **));\n\n#endif\n#endif\n"
  },
  {
    "path": "Sources/CNIOOpenBSD/shim.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// Xcode's Archive builds with Xcode's Package support struggle with empty .c files\n// (https://bugs.swift.org/browse/SR-12939).\nvoid CNIOOpenBSD_i_do_nothing_just_working_around_a_darwin_toolchain_bug(void) {}\n\n#if defined(__OpenBSD__)\n\n#include <CNIOOpenBSD.h>\n#include <pthread.h>\n#include <assert.h>\n#include <unistd.h>\n\nint CNIOOpenBSD_pthread_set_name_np(pthread_t thread, const char *name) {\n    pthread_set_name_np(thread, name);\n    return 0;\n}\n\nint CNIOOpenBSD_pthread_get_name_np(pthread_t thread, char *name, size_t len) {\n    pthread_get_name_np(thread, name, len);\n    return 0;\n}\n\nint CNIOOpenBSD_sendmmsg(int sockfd, CNIOOpenBSD_mmsghdr *msgvec, unsigned int vlen, int flags) {\n    // This is technically undefined behaviour, but it's basically fine because these types are the same size, and we\n    // don't think the compiler is inclined to blow anything up here.\n    // This comment is from CNIOLinux, but I haven't reverified this applies for OpenBSD.\n    return sendmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags);\n}\n\nint CNIOOpenBSD_recvmmsg(int sockfd, CNIOOpenBSD_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {\n    // This is technically undefined behaviour, but it's basically fine because these types are the same size, and we\n    // don't think the compiler is inclined to blow anything up here.\n    // This comment is from CNIOLinux, but I haven't reverified this applies for OpenBSD.\n    return recvmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags, timeout);\n}\n\nint CNIOOpenBSD_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {\n    return accept4(sockfd, addr, addrlen, flags);\n}\n\nstruct cmsghdr *CNIOOpenBSD_CMSG_FIRSTHDR(const struct msghdr *mhdr) {\n    assert(mhdr != NULL);\n    return CMSG_FIRSTHDR(mhdr);\n}\n\nstruct cmsghdr *CNIOOpenBSD_CMSG_NXTHDR(struct msghdr *mhdr, struct cmsghdr *cmsg) {\n    assert(mhdr != NULL);\n    assert(cmsg != NULL);\n    return CMSG_NXTHDR(mhdr, cmsg);\n}\n\nconst void *CNIOOpenBSD_CMSG_DATA(const struct cmsghdr *cmsg) {\n    assert(cmsg != NULL);\n    return CMSG_DATA(cmsg);\n}\n\nvoid *CNIOOpenBSD_CMSG_DATA_MUTABLE(struct cmsghdr *cmsg) {\n    assert(cmsg != NULL);\n    return CMSG_DATA(cmsg);\n}\n\nsize_t CNIOOpenBSD_CMSG_LEN(size_t payloadSizeBytes) {\n    return CMSG_LEN(payloadSizeBytes);\n}\n\nsize_t CNIOOpenBSD_CMSG_SPACE(size_t payloadSizeBytes) {\n    return CMSG_SPACE(payloadSizeBytes);\n}\n\nconst int CNIOOpenBSD_SO_TIMESTAMP = SO_TIMESTAMP;\nconst int CNIOOpenBSD_SO_RCVTIMEO = SO_RCVTIMEO;\n\nbool supports_udp_sockopt(int opt, int value) {\n    int fd = socket(AF_INET, SOCK_DGRAM, 0);\n    if (fd == -1) {\n        return false;\n    }\n    int rc = setsockopt(fd, IPPROTO_UDP, opt, &value, sizeof(value));\n    close(fd);\n    return rc == 0;\n}\n\nbool CNIOOpenBSD_supports_udp_segment() {\n    #ifndef UDP_SEGMENT\n    return false;\n    #else\n    return supports_udp_sockopt(UDP_SEGMENT, 512);\n    #endif\n}\n\nbool CNIOOpenBSD_supports_udp_gro() {\n    #ifndef UDP_GRO\n    return false;\n    #else\n    return supports_udp_sockopt(UDP_GRO, 1);\n    #endif\n}\n\nint CNIOOpenBSD_system_info(struct utsname* uname_data) {\n    return uname(uname_data);\n}\n\nconst char* CNIOOpenBSD_dirent_dname(struct dirent* ent) {\n    return ent->d_name;\n}\n\nconst unsigned long CNIOOpenBSD_UTIME_OMIT = UTIME_OMIT;\nconst unsigned long CNIOOpenBSD_UTIME_NOW = UTIME_NOW;\n\n#ifdef UDP_MAX_SEGMENTS\nconst long CNIOOpenBSD_UDP_MAX_SEGMENTS = UDP_MAX_SEGMENTS;\n#endif\nconst long CNIOOpenBSD_UDP_MAX_SEGMENTS = -1;\n\nFTS *CNIOOpenBSD_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)) {\n    return fts_open(path_argv, options, compar);\n}\n#endif\n"
  },
  {
    "path": "Sources/CNIOPosix/event_loop_id.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#include \"include/CNIOPosix.h\"\n\n// Once we support C23, this should become `thread_local`.\n// DO NOT TOUCH DIRECTLY, use `c_nio_posix_{get,set}_el_id`\n_Thread_local uintptr_t _c_nio_posix_thread_local_el_id;\n\n// Once we support C23, this should become `thread_local`.\n// DO NOT TOUCH DIRECTLY, use `c_nio_posix_{get,set}_el_ptr`\n_Thread_local void * _c_nio_posix_thread_local_el_ptr;\n"
  },
  {
    "path": "Sources/CNIOPosix/include/CNIOPosix.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#pragma once\n\n#include <inttypes.h>\n\nextern _Thread_local uintptr_t _c_nio_posix_thread_local_el_id;\n\nstatic inline uintptr_t c_nio_posix_get_el_id(void) {\n    return _c_nio_posix_thread_local_el_id;\n}\n\nstatic inline void c_nio_posix_set_el_id(uintptr_t id) {\n    _c_nio_posix_thread_local_el_id = id;\n}\n\nextern _Thread_local void * _c_nio_posix_thread_local_el_ptr;\n\nstatic inline void * c_nio_posix_get_el_ptr(void) {\n    return _c_nio_posix_thread_local_el_ptr;\n}\n\nstatic inline void c_nio_posix_set_el_ptr(void *id) {\n    _c_nio_posix_thread_local_el_ptr = id;\n}\n"
  },
  {
    "path": "Sources/CNIOSHA1/c_nio_sha1.c",
    "content": "/* Additional changes for SwiftNIO:\n    - prefixed all symbols by 'c_nio_'\n    - removed the _KERNEL include guards\n    - defined the __min_size macro inline\n    - included sys/endian.h on Android\n    - use welcoming language (soundness check)\n    - ensure BYTE_ORDER is defined\n*/\n/*\t$KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp $\t*/\n/*-\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the project nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/*\n * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)\n * based on: http://csrc.nist.gov/fips/fip180-1.txt\n * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>\n */\n\n#include \"include/CNIOSHA1.h\"\n#include <string.h>\n#if !defined(bzero)\n#define bzero(b,l) memset((b), '\\0', (l))\n#endif\n#if !defined(bcopy)\n#define bcopy(s,d,l) memmove((d), (s), (l))\n#endif\n#ifdef __ANDROID__\n#include <sys/endian.h>\n#elif defined(__linux__) || defined(__APPLE__) || defined(__wasm32__) || defined(__FreeBSD__) || defined(__OpenBSD__)\n#include <sys/types.h>\n#elif defined(_WIN32) || defined(_WIN64)\n\t#ifndef LITTLE_ENDIAN\n\t#define LITTLE_ENDIAN 1234\n\t#endif\n\t#ifndef BIG_ENDIAN\n\t#define BIG_ENDIAN 4321\n\t#endif\n\t#ifndef BYTE_ORDER\n\t#define BYTE_ORDER LITTLE_ENDIAN\n\t#endif\n#endif\n\n\n/* soundness check */\n#if !defined(BYTE_ORDER)\n#error \"BYTE_ORDER not defined\"\n#elif BYTE_ORDER != BIG_ENDIAN\n# if BYTE_ORDER != LITTLE_ENDIAN\n#  define unsupported 1\n# endif\n#endif\n\n#ifndef unsupported\n\n/* constant table */\nstatic uint32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };\n#define\tK(t)\t_K[(t) / 20]\n\n#define\tF0(b, c, d)\t(((b) & (c)) | ((~(b)) & (d)))\n#define\tF1(b, c, d)\t(((b) ^ (c)) ^ (d))\n#define\tF2(b, c, d)\t(((b) & (c)) | ((b) & (d)) | ((c) & (d)))\n#define\tF3(b, c, d)\t(((b) ^ (c)) ^ (d))\n\n#define\tS(n, x)\t\t(((x) << (n)) | ((x) >> (32 - n)))\n\n#define\tH(n)\t(ctxt->h.b32[(n)])\n#define\tCOUNT\t(ctxt->count)\n#define\tBCOUNT\t(ctxt->c.b64[0] / 8)\n#define\tW(n)\t(ctxt->m.b32[(n)])\n\n#define\tPUTBYTE(x)\t{ \\\n\tctxt->m.b8[(COUNT % 64)] = (x);\t\t\\\n\tCOUNT++;\t\t\t\t\\\n\tCOUNT %= 64;\t\t\t\t\\\n\tctxt->c.b64[0] += 8;\t\t\t\\\n\tif (COUNT % 64 == 0)\t\t\t\\\n\t\tsha1_step(ctxt);\t\t\\\n     }\n\n#define\tPUTPAD(x)\t{ \\\n\tctxt->m.b8[(COUNT % 64)] = (x);\t\t\\\n\tCOUNT++;\t\t\t\t\\\n\tCOUNT %= 64;\t\t\t\t\\\n\tif (COUNT % 64 == 0)\t\t\t\\\n\t\tsha1_step(ctxt);\t\t\\\n     }\n\nstatic void sha1_step(struct sha1_ctxt *);\n\nstatic void\nsha1_step(struct sha1_ctxt *ctxt)\n{\n\tuint32_t\ta, b, c, d, e;\n\tsize_t t, s;\n\tuint32_t\ttmp;\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tstruct sha1_ctxt tctxt;\n\tbcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);\n\tctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];\n\tctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];\n\tctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];\n\tctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];\n\tctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];\n\tctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];\n\tctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];\n\tctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];\n\tctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];\n\tctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];\n\tctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];\n\tctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];\n\tctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];\n\tctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];\n\tctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];\n\tctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];\n\tctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];\n\tctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];\n\tctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];\n\tctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];\n\tctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];\n\tctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];\n\tctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];\n\tctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];\n\tctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];\n\tctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];\n\tctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];\n\tctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];\n\tctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];\n\tctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];\n\tctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];\n\tctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];\n#endif\n\n\ta = H(0); b = H(1); c = H(2); d = H(3); e = H(4);\n\n\tfor (t = 0; t < 20; t++) {\n\t\ts = t & 0x0f;\n\t\tif (t >= 16) {\n\t\t\tW(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));\n\t\t}\n\t\ttmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);\n\t\te = d; d = c; c = S(30, b); b = a; a = tmp;\n\t}\n\tfor (t = 20; t < 40; t++) {\n\t\ts = t & 0x0f;\n\t\tW(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));\n\t\ttmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);\n\t\te = d; d = c; c = S(30, b); b = a; a = tmp;\n\t}\n\tfor (t = 40; t < 60; t++) {\n\t\ts = t & 0x0f;\n\t\tW(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));\n\t\ttmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);\n\t\te = d; d = c; c = S(30, b); b = a; a = tmp;\n\t}\n\tfor (t = 60; t < 80; t++) {\n\t\ts = t & 0x0f;\n\t\tW(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));\n\t\ttmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);\n\t\te = d; d = c; c = S(30, b); b = a; a = tmp;\n\t}\n\n\tH(0) = H(0) + a;\n\tH(1) = H(1) + b;\n\tH(2) = H(2) + c;\n\tH(3) = H(3) + d;\n\tH(4) = H(4) + e;\n\n\tbzero(&ctxt->m.b8[0], 64);\n}\n\n/*------------------------------------------------------------*/\n\nvoid\nc_nio_sha1_init(struct sha1_ctxt *ctxt)\n{\n\tbzero(ctxt, sizeof(struct sha1_ctxt));\n\tH(0) = 0x67452301;\n\tH(1) = 0xefcdab89;\n\tH(2) = 0x98badcfe;\n\tH(3) = 0x10325476;\n\tH(4) = 0xc3d2e1f0;\n}\n\nvoid\nc_nio_sha1_pad(struct sha1_ctxt *ctxt)\n{\n\tsize_t padlen;\t\t/*pad length in bytes*/\n\tsize_t padstart;\n\n\tPUTPAD(0x80);\n\n\tpadstart = COUNT % 64;\n\tpadlen = 64 - padstart;\n\tif (padlen < 8) {\n\t\tbzero(&ctxt->m.b8[padstart], padlen);\n\t\tCOUNT += padlen;\n\t\tCOUNT %= 64;\n\t\tsha1_step(ctxt);\n\t\tpadstart = COUNT % 64;\t/* should be 0 */\n\t\tpadlen = 64 - padstart;\t/* should be 64 */\n\t}\n\tbzero(&ctxt->m.b8[padstart], padlen - 8);\n\tCOUNT += (padlen - 8);\n\tCOUNT %= 64;\n#if BYTE_ORDER == BIG_ENDIAN\n\tPUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);\n\tPUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);\n\tPUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);\n\tPUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);\n#else\n\tPUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);\n\tPUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);\n\tPUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);\n\tPUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);\n#endif\n}\n\nvoid\nc_nio_sha1_loop(struct sha1_ctxt *ctxt, const uint8_t *input, size_t len)\n{\n\tsize_t gaplen;\n\tsize_t gapstart;\n\tsize_t off;\n\tsize_t copysiz;\n\n\toff = 0;\n\n\twhile (off < len) {\n\t\tgapstart = COUNT % 64;\n\t\tgaplen = 64 - gapstart;\n\n\t\tcopysiz = (gaplen < len - off) ? gaplen : len - off;\n\t\tbcopy(&input[off], &ctxt->m.b8[gapstart], copysiz);\n\t\tCOUNT += copysiz;\n\t\tCOUNT %= 64;\n\t\tctxt->c.b64[0] += copysiz * 8;\n\t\tif (COUNT % 64 == 0)\n\t\t\tsha1_step(ctxt);\n\t\toff += copysiz;\n\t}\n}\n\nvoid\nc_nio_sha1_result(struct sha1_ctxt *ctxt, char digest0[static SHA1_RESULTLEN])\n{\n\tuint8_t *digest;\n\n\tdigest = (uint8_t *)digest0;\n\tc_nio_sha1_pad(ctxt);\n#if BYTE_ORDER == BIG_ENDIAN\n\tbcopy(&ctxt->h.b8[0], digest, SHA1_RESULTLEN);\n#else\n\tdigest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];\n\tdigest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];\n\tdigest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];\n\tdigest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];\n\tdigest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];\n\tdigest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];\n\tdigest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];\n\tdigest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];\n\tdigest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];\n\tdigest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];\n#endif\n}\n\n#endif /*unsupported*/\n"
  },
  {
    "path": "Sources/CNIOSHA1/include/CNIOSHA1.h",
    "content": "/* Additional changes for SwiftNIO:\n    - prefixed all symbols by 'c_nio_'\n    - removed the _KERNEL include guards\n    - defined the __min_size macro inline\n    - included sys/endian.h on Android\n    - use welcoming language (soundness check)\n    - ensure BYTE_ORDER is defined\n*/\n/*\t$FreeBSD$\t*/\n/*\t$KAME: sha1.h,v 1.5 2000/03/27 04:36:23 sumikawa Exp $\t*/\n\n/*-\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the project nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n/*\n * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)\n * based on: http://csrc.nist.gov/fips/fip180-1.txt\n * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>\n */\n\n#ifndef _CRYPTO_SHA1_H_\n#define _CRYPTO_SHA1_H_\n#include <stdint.h>\n#include <stddef.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct sha1_ctxt {\n\tunion {\n\t\tuint8_t\t\tb8[20];\n\t\tuint32_t\tb32[5];\n\t} h;\n\tunion {\n\t\tuint8_t\t\tb8[8];\n\t\tuint64_t\tb64[1];\n\t} c;\n\tunion {\n\t\tuint8_t\t\tb8[64];\n\t\tuint32_t\tb32[16];\n\t} m;\n\tuint8_t\tcount;\n};\ntypedef struct sha1_ctxt SHA1_CTX;\n\n#define\tSHA1_RESULTLEN\t(160/8)\n\n#ifdef __cplusplus\n#define __min_size(x)\t(x)\n#else\n#define __min_size(x)\tstatic (x)\n#endif\n\nextern void c_nio_sha1_init(struct sha1_ctxt *);\nextern void c_nio_sha1_pad(struct sha1_ctxt *);\nextern void c_nio_sha1_loop(struct sha1_ctxt *, const uint8_t *, size_t);\nextern void c_nio_sha1_result(struct sha1_ctxt *, char[__min_size(SHA1_RESULTLEN)]);\n\n/* compatibilty with other SHA1 source codes */\n#define SHA1Init(x)\t\tc_nio_sha1_init((x))\n#define SHA1Update(x, y, z)\tc_nio_sha1_loop((x), (y), (z))\n#define SHA1Final(x, y)\t\tc_nio_sha1_result((y), (x))\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /*_CRYPTO_SHA1_H_*/\n"
  },
  {
    "path": "Sources/CNIOSHA1/update_and_patch_sha1.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\ncase \"$(uname -s)\" in\n    Darwin)\n        sed=\"gsed\"\n        ;;\n    *)\n        sed=\"sed\"\n        ;;\nesac\n\nfor f in sha1.c sha1.h; do\n    ( echo \"/* Additional changes for SwiftNIO:\"\n      echo \"    - prefixed all symbols by 'c_nio_'\"\n      echo \"    - removed the _KERNEL include guards\"\n      echo \"    - defined the __min_size macro inline\"\n      echo \"    - included sys/endian.h on Android\"\n      echo \"    - use welcoming language (soundness check)\"\n      echo \"    - ensure BYTE_ORDER is defined\"\n      echo \"*/\"\n      curl -Ls \"https://raw.githubusercontent.com/freebsd/freebsd/master/sys/crypto/$f\" # ignore-unacceptable-language\n    ) > \"$here/c_nio_$f\"\n\n    for func in sha1_init sha1_pad sha1_loop sha1_result; do\n        \"$sed\" -i \\\n            -e \"s/$func/c_nio_$func/g\" \\\n            \"$here/c_nio_$f\"\n    done\ndone\n\n$sed -e $'/#define _CRYPTO_SHA1_H_/a #include <stdint.h>\\\\\\n#include <stddef.h>' \\\n     -e 's/u_int\\([0-9]\\+\\)_t/uint\\1_t/g'                                        \\\n     -e 's%#ifdef _KERNEL%#define __min_size(x)\tstatic (x)%g'                    \\\n     -e 's%#endif /\\* _KERNEL \\*/%%g'                                            \\\n     -i \"$here/c_nio_sha1.h\"\n\n$sed -e 's/u_int\\([0-9]\\+\\)_t/uint\\1_t/g'                                        \\\n     -e '/^#include/d'                                                           \\\n     -e $'/__FBSDID/c #include \"include/CNIOSHA1.h\"\\\\n#include <string.h>\\\\n#if !defined(bzero)\\\\n#define bzero(b,l) memset((b), \\'\\\\\\\\0\\', (l))\\\\n#endif\\\\n#if !defined(bcopy)\\\\n#define bcopy(s,d,l) memmove((d), (s), (l))\\\\n#endif\\\\n#ifdef __ANDROID__\\\\n#include <sys/endian.h>\\\\n#elif defined(__linux__) || defined(__APPLE__)\\\\n#include <sys/types.h>\\\\n#endif' \\\n     -e 's/sanit[y]/soundness/g'                                                 \\\n     -e 's/#if BYTE_ORDER != BIG_ENDIAN/#if !defined(BYTE_ORDER)\\\\n#error \"BYTE_ORDER not defined\"\\\\n#elif BYTE_ORDER != BIG_ENDIAN/' \\\n     -i \"$here/c_nio_sha1.c\"\n\nmv \"$here/c_nio_sha1.h\" \"$here/include/CNIOSHA1.h\"\n\ntmp=$(mktemp -d /tmp/.test_compile_XXXXXX)\n\nclang -o \"$tmp/test.o\" -c \"$here/c_nio_sha1.c\"\nnum_non_nio=$(nm \"$tmp/test.o\" | grep ' T ' | grep -vc c_nio)\n\ntest 0 -eq \"$num_non_nio\" || {\n    echo \"ERROR: $num_non_nio exported non-prefixed symbols found\"\n    exit 1\n}\n\nrm -rf \"$tmp\"\n"
  },
  {
    "path": "Sources/CNIOWASI/CNIOWASI.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n"
  },
  {
    "path": "Sources/CNIOWASI/include/CNIOWASI.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) YEARS Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#pragma once\n\n#if __wasi__\n\n#include <fcntl.h>\n#include <time.h>\n\nstatic inline void CNIOWASI_gettime(struct timespec *tv) {\n    // ClangImporter doesn't support `CLOCK_MONOTONIC` declaration in WASILibc, thus we have to define a bridge manually\n    clock_gettime(CLOCK_MONOTONIC, tv);\n}\n\nstatic inline int CNIOWASI_O_CREAT() {\n    // ClangImporter doesn't support `O_CREATE` declaration in WASILibc, thus we have to define a bridge manually\n    return O_CREAT;\n}\n\n#endif\n"
  },
  {
    "path": "Sources/CNIOWindows/WSAStartup.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if defined(_WIN32)\n\n#include <Winsock2.h>\n\n#include <stdlib.h>\n\nvoid NIOWSAStartup(void) {\n    WSADATA wsa;\n    WORD wVersionRequested = MAKEWORD(2, 2);\n    int startup = WSAStartup(wVersionRequested, &wsa);\n    if (startup != 0) {\n        _exit(EXIT_FAILURE);\n    }\n}\n\n// The function pointer type for C initializers\ntypedef void (__cdecl *NIOWindowsStartup)(void);\n\n// Declare a function pointer to your function, and put it in the .CRT$XCU section\n#pragma section(\".CRT$XCU\", read)\n__declspec(allocate(\".CRT$XCU\")) NIOWindowsStartup NIOWSAStartup_ptr = NIOWSAStartup;\n\n#endif\n"
  },
  {
    "path": "Sources/CNIOWindows/include/CNIOWindows.h",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#ifndef C_NIO_WINDOWS_H\n#define C_NIO_WINDOWS_H\n\n#if defined(_WIN32)\n\n#include <WinSock2.h>\n#include <time.h>\n#include <stdint.h>\n#include <basetsd.h>\n\n#define NIO(name) CNIOWindows_ ## name\n\n// This is a DDK type which is not available in the WinSDK as it is not part of\n// the shared, usermode (um), or ucrt portions of the code.  We must replicate\n// this datastructure manually from the MSDN references or the DDK.\n// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_reparse_data_buffer\ntypedef struct NIO(_REPARSE_DATA_BUFFER) {\n  ULONG   ReparseTag;\n  USHORT  ReparseDataLength;\n  USHORT  Reserved;\n  union {\n    struct {\n      USHORT  SubstituteNameOffset;\n      USHORT  SubstituteNameLength;\n      USHORT  PrintNameOffset;\n      USHORT  PrintNameLength;\n      ULONG   Flags;\n      WCHAR   PathBuffer[1];\n    } SymbolicLinkReparseBuffer;\n    struct {\n      USHORT  SubstituteNameOffset;\n      USHORT  SubstituteNameLength;\n      USHORT  PrintNameOffset;\n      USHORT  PrintNameLength;\n      WCHAR   PathBuffer[1];\n    } MountPointReparseBuffer;\n    struct {\n      UCHAR   DataBuffer[1];\n    } GenericReparsaeBuffer;\n  } DUMMYUNIONNAME;\n} NIO(REPARSE_DATA_BUFFER), *NIO(PREPARSE_DATA_BUFFER);\n\ntypedef struct {\n  WSAMSG msg_hdr;\n  unsigned int msg_len;\n} NIO(mmsghdr);\n\nstatic inline __attribute__((__always_inline__)) int\nNIO(getsockopt)(SOCKET s, int level, int optname, void *optval, int *optlen) {\n  return getsockopt(s, level, optname, optval, optlen);\n}\n\nstatic inline __attribute__((__always_inline__)) int\nNIO(recv)(SOCKET s, void *buf, int len, int flags) {\n  return recv(s, buf, len, flags);\n}\n\nstatic inline __attribute__((__always_inline__)) int\nNIO(recvfrom)(SOCKET s, void *buf, int len, int flags, SOCKADDR *from,\n              int *fromlen) {\n  return recvfrom(s, buf, len, flags, from, fromlen);\n}\n\nstatic inline __attribute__((__always_inline__)) int\nNIO(send)(SOCKET s, const void *buf, int len, int flags) {\n  return send(s, buf, len, flags);\n}\n\nstatic inline __attribute__((__always_inline__)) int\nNIO(setsockopt)(SOCKET s, int level, int optname, const void *optval,\n                int optlen) {\n  return setsockopt(s, level, optname, optval, optlen);\n}\n\nstatic inline __attribute__((__always_inline__)) int\nNIO(sendto)(SOCKET s, const void *buf, int len, int flags, const SOCKADDR *to,\n            int tolen) {\n  return sendto(s, buf, len, flags, to, tolen);\n}\n\nint NIO(sendmmsg)(SOCKET s, NIO(mmsghdr) *msgvec, unsigned int vlen, int flags);\n\nint NIO(recvmmsg)(SOCKET s, NIO(mmsghdr) *msgvec, unsigned int vlen, int flags,\n                  struct timespec *timeout);\n\n\nconst void *NIO(CMSG_DATA)(const WSACMSGHDR *);\nvoid *NIO(CMSG_DATA_MUTABLE)(LPWSACMSGHDR);\n\nWSACMSGHDR *NIO(CMSG_FIRSTHDR)(const WSAMSG *);\nWSACMSGHDR *NIO(CMSG_NXTHDR)(const WSAMSG *, LPWSACMSGHDR);\n\nsize_t NIO(CMSG_LEN)(size_t);\nsize_t NIO(CMSG_SPACE)(size_t);\n\nint NIO(errno)(void);\n\nDWORD NIO(FormatGetLastError)(DWORD errorCode, LPSTR errorMsg);\n\n#undef NIO\n\n#endif\n\n#endif\n"
  },
  {
    "path": "Sources/CNIOWindows/include/module.modulemap",
    "content": "module CNIOWindows {\n  header \"CNIOWindows.h\"\n  export *\n}\n"
  },
  {
    "path": "Sources/CNIOWindows/shim.c",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if defined(_WIN32)\n\n#include \"CNIOWindows.h\"\n\n#include <assert.h>\n#include <errno.h>\n#include <winbase.h>\n\nint CNIOWindows_sendmmsg(SOCKET s, CNIOWindows_mmsghdr *msgvec, unsigned int vlen,\n                         int flags) {\n  assert(!\"sendmmsg not implemented\");\n  abort();\n}\n\nint CNIOWindows_recvmmsg(SOCKET s, CNIOWindows_mmsghdr *msgvec,\n                         unsigned int vlen, int flags,\n                         struct timespec *timeout) {\n  assert(!\"recvmmsg not implemented\");\n  abort();\n}\n\nconst void *CNIOWindows_CMSG_DATA(const WSACMSGHDR *pcmsg) {\n  return WSA_CMSG_DATA(pcmsg);\n}\n\nvoid *CNIOWindows_CMSG_DATA_MUTABLE(LPWSACMSGHDR pcmsg) {\n  return WSA_CMSG_DATA(pcmsg);\n}\n\nWSACMSGHDR *CNIOWindows_CMSG_FIRSTHDR(const WSAMSG *msg) {\n  return WSA_CMSG_FIRSTHDR(msg);\n}\n\nWSACMSGHDR *CNIOWindows_CMSG_NXTHDR(const WSAMSG *msg, LPWSACMSGHDR cmsg) {\n  return WSA_CMSG_NXTHDR(msg, cmsg);\n}\n\nsize_t CNIOWindows_CMSG_LEN(size_t length) {\n  return WSA_CMSG_LEN(length);\n}\n\nsize_t CNIOWindows_CMSG_SPACE(size_t length) {\n  return WSA_CMSG_SPACE(length);\n}\n\nint CNIOWindows_errno(void) {\n    return errno;\n}\n\nDWORD CNIOWindows_FormatGetLastError(DWORD errorCode, LPSTR errorMsg) {\n  return FormatMessage(\n    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n    NULL,\n    errorCode,\n    0, // Default language\n    errorMsg,\n    0,\n    NULL\n  );\n}\n\n#endif\n"
  },
  {
    "path": "Sources/NIO/Docs.docc/Articles/Debugging Allocation Regressions.md",
    "content": "# Debugging Allocation Regressions\n\nThis document explains different approaches to debugging allocation regressions.\n\n## Overview\n\nIf you're not familiar with running SwiftNIO's allocation counting tests then\ntake a look at <doc:Running-Alloction-Counting-Tests> first.\n\nThe exact allocation counts are _not_ directly comparable between different\noperating systems and even different versions of the same operating system.\nEvery new Swift version will also introduce differences (hopefully decreasing\nover time).\n\nThis means that if you get hit by a CI failure, you will have to first reproduce\nthe regression locally by running the allocation counter tests once on `main`\nand then again on your failing branch. Sometimes the allocation will be platform\nspecific and you may have to reproduce it in a container.\n\nHow you diagnose regressions depends on the nature of the change. It may be\npossible to diagnose regressions from inspection; did the change introduce any\nunnecessary allocations? Are there any intermediate allocations (such as from a\ncollection resizing where capacity could've been reserved) which could be\navoided?\n\nMost cases aren't so straightforward and require a different approach, such as:\n- Looking at the allocation traces in Instruments (macOS only)\n- Diffing allocation traces\n\n## Instruments\n\nTo look at allocation traces in Instruments:\n\n1. Start Instruments\n2. Choose the \"Allocations\" instrument\n3. Tap the executable selector in the toolbar\n4. Click \"Choose Target...\"\n5. Select the binary for the test\n6. Click \"Choose\"\n7. Press the record button\n\nNow you should have a full Instruments allocations trace of the test run. To\nmake sense of what's going on, switch the allocation lifespan from \"Created &\nPersisted\" to \"Created & Destroyed\". After that you should be able to see the\ntype of the allocation and how many times it got allocated. Clicking on the\nlittle arrow next to the type name will reveal each individual allocation of\nthis type and the responsible stack trace.\n\n## Collecting allocation traces\n\nAs you're looking for an allocation regression you should have two versions of\nthe binary you're debugging: a before and an after. A useful way to find the\nregression is to collect and compare all of the allocation stacks for each\nversion of the program.\n\nHow you collect the stacks depends on the platform you're investigating.\nSwiftNIO provides scripts for `dtrace` (macOS) and `bpftrace` (Linux) to collect\nstacks that lead to allocations. You can also use `heaptrack` on Linux where\n`bpftrace` isn't available. The following sections explain how to collection\nallocation traces using each tool.\n\n### DTrace (macOS)\n\nOn macOS you can use `dtrace`. SwiftNIO provides the `malloc-aggregation.d`\nscript in the `dev` directory for collecting stacks. You can run it with:\n\n```\nsudo ./malloc-aggregation.d -c your-executable\n```\n\nTo make analysis easier you can demangle the symbols with `swift demangle`:\n\n```\nsudo ./malloc-aggregation.d -c your-executable | swift demangle\n```\n\n### BFPTrace (Linux)\n\nOn Linux, and where available, you can use `bpftrace`. SwiftNIO provides the\n`malloc-aggregation.bt` script in the `dev` directory for collecting stacks.\n\nYou'll need to install `bpftrace` first, on Ubuntu you can run:\n\n```\napt-get update && apt-get install -y bpftrace\n```\n\nThe script is very similar to the DTrace script and you can run it by passing\nyour executable as an argument, for example:\n\n```\nsudo ./malloc-aggregation.bt -c your-executable\n```\n\nHowever, `bpftrace` tends to work better if PID-based tracing is used instead.\nThis is because `bpftrace` has a [known limitation where symbolication fails if\nthe process being traced has existed before `bpftrace`\ndoes](https://github.com/bpftrace/bpftrace/issues/2118#issuecomment-1008694821).\nThis can still be resolved using tools like `llvm-symbolizer`, but it's\ntrickier.\n\nYou can pass the PID of your program to the script via the `-p` option, for\nexample:\n\n```\nsudo ./malloc-aggregation.bt -p <PID>\n```\n\nYou can start your executable in the background and capture the PID to pass\nto `malloc-aggreation.bt` using:\n\n```\nyour-executable & PID=$! && sudo ./malloc-aggregation.bt -p $PID\n```\n\n### Heaptrack (Linux)\n\nIn some cases we don't have access to Linux kernel headers, which prevents us\nfrom using `bpftrace`, but there is the\n[heaptrack](https://github.com/KDE/heaptrack) tool which can also capture\nallocation stacks.\n\nTo install heaptrack on Ubuntu run:\n\n```\napt-get update && apt-get install -y heaptrack\n```\n\nGetting allocation stacks from `heaptrack` is a two-step process. First you need\nto run your binary with `heaptrack`:\n\n```\nheaptrack /path/to/executable_to_test\n```\n\nThis will produce a `.gz` file which `heaptrack_print` can analyze:\n\n```\nheaptrack_print \\\n    --print-allocators yes \\\n    --print-peaks no \\\n    --print-temporary no \\\n    --peak-limit 1000 \\\n    --sub-peak-limit 1000 \\\n    heaptrack_capture.gz\n```\n\nThere are many options for `heaptrack_print`, the command above will print out\nthe top allocating stacks. Note `--peak-limit` and `--sub-peak-limit`, these\ndefault to quite low values so raising them is important to avoid information\nloss that can make analysis more difficult.\n\nYou can also pipe the result of `heaptrack_print` through `swift demangle` to\nmake analysis easier.\n\n## Diffing allocation traces\n\nOnce you've captured two allocation traces for your program you can diff them to\nwork out where any regression was introduced. Each of the tools outlined\npreviously produce output in different formats although they are broadly similar\nto:\n\n\n```\n...\n      libsystem_malloc.dylib`malloc\n      libswiftCore.dylib`swift_slowAlloc+0x19\n      libswiftCore.dylib`swift_allocObject+0x27\n      test_1_reqs_1000_conn`SelectableEventLoop.run()+0x231\n      test_1_reqs_1000_conn`closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:)+0x106\n      test_1_reqs_1000_conn`partial apply for closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:)+0x2d\n      test_1_reqs_1000_conn`thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()+0xf\n      test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()+0x11\n      test_1_reqs_1000_conn`closure #1 in static ThreadOpsPosix.run(handle:args:detachThread:)+0x1e4\n      libsystem_pthread.dylib`_pthread_start+0x94\n      libsystem_pthread.dylib`thread_start+0xf\n   231000\n...\n```\n\nThe output will contain many blocks like this. Each block means that the\nspecific stack trace is responsible for some number of allocations: in the\nexample above, 231000 allocations.\n\nThe output from `bpftrace` and `heaptrack` will differ slightly to this. To make\nanalysis easier we built a tool to parse and analyze the stacks.\n\n### stackdiff\n\nThe `stackdiff` tool is a CLI tool for parsing and analyzing stack traces\ncollected by `dtrace`, `bpftrace`, and `heaptrack`. It's available in the\n`dev/stackdiff` directory of the `swift-nio` repository. You can build it from\nthe `stackdiff` directiroy with `swift build -c release`. The tool has three\nsubcommands:\n\n1. `dump`,\n2. `diff`, and\n3. `merge`.\n\n#### stackdiff dump\n\nThe `dump` subcommand parses and prints stacks collected via `dtrace`,\n`bpftrace`, or `heaptrack`. You must provide the stack traces as an argument\nalong with the format of the input. For example, if you collected the allocation\ntraces using DTrace into `allocs.txt` you should run:\n\n```\nstackdiff dump --format dtrace allocs.txt\n```\n\nBy default only stacks with 1000 allocations or more are included. You can\nchange this with `--min-allocations`:\n\n```\nstackdiff dump --format dtrace --min-allocations 10000 allocs.txt\n```\n\nYou can also filter traces so that only stacks containing a given string are\nincluded:\n\n```\nstackdiff dump --format dtrace --filter swift_slowAlloc allocs.txt\n```\n\nSee the help with `stackdiff dump --help` to learn about other options.\n\n#### stackdiff diff\n\nThe `diff` subcommand parses stacks from two input files and prints the stacks\nwhich are unique to each input file as well as the stacks which are common to\nboth input files but have differing allocation counts. You can apply the same\noptions as the `dump` command.\n\nTo print the diff between two `heaptrack` outputs use:\n\n```\nstackdiff diff --format heaptrack before.txt after.txt\n```\n\nThis will print out a few different sections:\n1. Allocation traces present only in \"before.txt\",\n2. Allocation traces present only in \"after.txt\",\n3. Allocation traces present only in \"before.txt\" and \"after.txt\" but with\n   differing allocation counts.\n4. A summary of the allactions.\n\nUsing this information can help you to narrow down where the allocation was\nintroduced. In some cases there will be many stacks which are unique to each\nfile but are subtly different. These often hide the true cause of the\nregression. The `merge` command makes finding these differences easier.\n\n#### stackdiff merge\n\nThe `merge` subcommand is much like `diff` but interactively allows you to pair\nup unique stacks from one file with those from another. This is done by\ncomputing a textual similarity between stacks and offering them to you to either\naccept or reject. Once you've matched analyzed the unique traces across the\nfiles you should be left with the _actual_ difference.\n\nYou can call `merge` like you do for `diff`:\n\n```\nstackdiff merge --format heaptrack before.txt after.txt\n```\n\nYou'll first be presented with a summary of the differences between the two\ninputs:\n\n```\nInput A\n- File: before.txt\n- Allocations: 623000\n- Stacks: 373\n- Stacks only in A: 22\n\nInput B\n- File: after.txt\n- Allocations: 624000\n- Stacks: 374\n- Stacks only in B: 23\n\nAllocation delta (A-B): -1000\n\nAbout to start merging stacks, hit enter to continue ...\n```\n\nThe tool refers to inputs `A` and `B` when merging, these correspond to the\nfiles printed in the summary (i.e. the first and second positional arguments\npassed to `merge`.) For each it prints the total number of allocations which\nhaven't been filtered out in each file, the number of stacks in each file, and\nthe unique stacks in each. In this case there are 22 stacks in `A` which aren't\npresent in `B`, and `23` stacks in `B` which aren't in `A`. It's likely that 22\nof the stacks are the practically speaking the same with one additional stack in\n`B`. You can also see that the allocation delta is -1000, meaning that `B` has\n1000 allocations more than `A`.\n\nYou'll then need to hit enter to start merging stacks. When you do, you'll be\npresented with output like this:\n\n```\nFinding candidates for stack 1 of 22 (S1) from A only ...\nLooking at candidate stack 1 of 23 (S2) ...\n\nAllocations:\n       |     A |      B |    Net\n    S1 | 10000 |      0 |  10000\n    S2 |     0 | -10000 | -10000\n Total | 10000 | -10000 |      0\n\nStack similarity: 0.7441860465116279\n\nS1| ...skipping 3 common lines...\nS1| libswiftCore.dylib`_ContiguousArrayBuffer.init(_uninitializedCount:minimumCapacity:)\nS1| ...skipping 3 common lines...\n\nS2| ...skipping 3 common lines...\nS2| libswiftCore.dylib`_allocateStringStorage(codeUnitCapacity:)\nS2| libswiftCore.dylib`_StringGuts.reserveCapacity(_:)\nS2| libswiftCore.dylib`String.init(repeating:count:)\nS2| ...skipping 3 common lines...\n\nAccept ([y]es/no/skip/expand)?:\n```\n\nThe first two lines tell you your progress, in this case that you're looking at\nthe first stack which is only present in `A` and evaluating it against the first\ncandidate stack:\n\n```\nFinding candidates for stack 1 of 22 (S1) from A only ...\nLooking at candidate stack 1 of 23 (S2) ...\n```\n\nAfter this is a table indicating the allocations and where they come from:\n\n```\nAllocations:\n       |     A |      B |    Net\n    S1 | 10000 |      0 |  10000\n    S2 |     0 | -10000 | -10000\n Total | 10000 | -10000 |      0\n```\n\nThe `S1` and `S2` labels apply to the two stacks we're looking at and the two\n`A` and `B` columns indicate how many allocations from that stack are associated\nwith the two input files. Allocations from `B` are always treated as negative\n(we're diffing `A` and `B` so conceptually subtracting `B` from `A`.)\n\nBelow the table you can see the similarity score of 0.74:\n\n```\nStack similarity: 0.7441860465116279\n```\n\nScores above 0.9 are considered strong matches, below 0.55 are weak.\n\nThe two stacks `S1` and `S2` are printed next:\n\n```\nS1| ...skipping 3 common lines...\nS1| libswiftCore.dylib`_ContiguousArrayBuffer.init(_uninitializedCount:minimumCapacity:)\nS1| ...skipping 3 common lines...\n\nS2| ...skipping 3 common lines...\nS2| libswiftCore.dylib`_allocateStringStorage(codeUnitCapacity:)\nS2| libswiftCore.dylib`_StringGuts.reserveCapacity(_:)\nS2| libswiftCore.dylib`String.init(repeating:count:)\nS2| ...skipping 3 common lines...\n```\n\nTheir common prefix and suffix are hidden to make their differences more\nobvious. Finally you're asked for input:\n\n```\nAccept ([y]es/no/skip/expand)?:\n```\n\nIf you think the stacks are effectively the same then enter `y` or `yes` and hit\nenter (or just hit enter, as this is the default option). If you don't think the\nstacks match up then enter `n` or `no` and hit enter, you'll then be presented\nwith a similar output but with a different candidate for `S2`. If there are no\ncandidates remaining or you enter `s` or `skip` then `S1` will not be paired and\nyou'll be presented with the next stack for `S1`. Finally, you can else enter\n`e` or `expand` to expand out the common lines.\n\nOnce you've finished merging stacks you'll be presented with all the unmerged\nstacks, in other words, those which haven't been paired up between `A` and `B`\nand common stacks which have a non-zero allocation count:\n\n```\nFinished merging stacks, removing stacks with net zero allocations.\nStacks remaining: 1\nNet allocations: -1000\n\nALLOCATIONS: -1000\nlibsystem_malloc.dylib`malloc_type_malloc\nlibswiftCore.dylib`swift::swift_slowAllocTyped(unsigned long, unsigned long, unsigned long long)\nlibswiftCore.dylib`swift_allocObject\nlibswiftCore.dylib`_allocateStringStorage(codeUnitCapacity:)\nlibswiftCore.dylib`_StringGuts.reserveCapacity(_:)\nlibswiftCore.dylib`String.init(repeating:count:)\ndo-some-allocs`specialized static do_some_allocs.main()\ndo-some-allocs`do_some_allocs_main\ndyld`start\n```\n\nThis means that the one remaining stack was from `B` and has 1000 allocations.\n"
  },
  {
    "path": "Sources/NIO/Docs.docc/Articles/Running Alloction Counting Tests.md",
    "content": "# Running Allocation Counting Tests\n\nThis document explains the different type of allocation counting tests and how\nto run them.\n\n## Overview\n\nAllocations are expensive so are often a good proxy for measuring performance in\nan application: reducing unnecessary allocations _typically_ leads to an\nincrease in performance. SwiftNIO has a number of tests which record allocations\nand check the results against a threshold. These are run as part of CI and help\nus to avoid introducing allocation regressions.\n\nSwiftNIO uses two frameworks for running allocation tests:\n\n1. The [`package-benchmark`](https://github.com/ordo-one/package-benchmark)\n   package.\n2. A homegrown allocation counting framework.\n\n## Running package-benchmark benchmarks\n\nThe `package-benchmark` benchmarks live in the `Benchmarks` directory of the\n`swift-nio` repository. To run the benchmarks you'll need to install `jemalloc`,\nrefer to the instructions in the `package-benchmark` [Getting\nStarted](https://swiftpackageindex.com/ordo-one/package-benchmark/documentation/benchmark/gettingstarted#Installing-Prerequisites-and-Platform-Support)\nguide to do this.\n\nTo run all the benchmarks without checking against the thresholds run the\nfollowing command from the `Benchmarks` directory:\n\n```sh\n$ swift package benchmark\n```\n\nTo list the available benchmarks run:\n\n```sh\n$ swift package benchmark list\n```\n\nTo run a subset of benchmarks you can provide a regular expression to the\n`--filter` option. For example to run just the \"WaitOnPromise\" benchmark:\n\n\n```sh\n$ swift package benchmark --filter WaitOnPromise\n```\n\nEach benchmark has a threshold associated with it. These are stored in the\n`Benchmarks/Thresholds` directory. There are thresholds for each version of\nSwift that SwiftNIO supports.\n\nTo run the benchmarks and check against the thresholds, in this case the nightly\nbuilds of Swift's `main` branch you can run:\n\n```sh\n$ swift package benchmark threshold check --path Thresholds/nightly-main\n```\n\nSometimes you'll need to run a benchmark _without_ invoking it via `swift\npackage benchmark`. The easiest way to do this is to first invoke `swift\npackage benchmark` and then run the benchmark binary which was built as a\nside effect:\n\n```sh\n$ ./.build/release/NIOCoreBenchmarks --filter WaitOnPromise\n```\n\n## Running the homegrown benchmarks\n\nMost of SwiftNIO's allocation counting tests are written using its own framework\nwhich predates `package-benchmark`. The source for the framework lives in\n`IntegrationTests/allocation-counter-tests-framework` and is used across the\nvarious `swift-nio-*` repositories and more besides. In the `swift-nio`\nrepository the tests live in\n`IntegrationTests/tests_04_performance/test_01_resources`.\n\nThe following commands assume your current working directory is\n`IntegrationTests/tests_04_performance/test_01_resources`.\n\nTo run all tests written for this framework:\n\n```sh\n$ ./run-nio-alloc-counter-tests.sh\n```\n\nThe invocation of this script will take a while because it has to build all of\nSwiftNIO in release mode first, then it compiles the integration tests and runs\nthem all, multiple times.\n\nTo run a single test specify the file containing it as an argument to the\nscript:\n\n```sh\n$ ./run-nio-alloc-counter-tests.sh test_future_lots_of_callbacks.swift\n```\n\nYou'll notice that when you run the script that it builds SwiftNIO and\nthe test each time. In the output you should see some lines like:\n\n```\n...\nFetching /private/tmp/.nio_alloc_counter_tests_5jMMhk/swift-nio\nFetching /private/tmp/.nio_alloc_counter_tests_5jMMhk/HookedFunctions\nFetching /private/tmp/.nio_alloc_counter_tests_5jMMhk/AtomicCounter\n...\n```\n\nThe `/private/tmp/.nio_alloc_counter_tests_5jMMhk` directory contains\na regular Swift package which you can modify to iterate more quickly, \njust don't forget to build it whith `-c release`!\n\n### Understanding the output\n\nThe output of the script will look something like:\n\n```\n- /Users/johannes/devel/swift-nio/IntegrationTests/tests_04_performance/test_01_resources/test_future_lots_of_callbacks.swift\ntest_future_lots_of_callbacks.remaining_allocations: 0\ntest_future_lots_of_callbacks.total_allocations: 75001\ntest_future_lots_of_callbacks.total_allocated_bytes: 4138056\nDEBUG: [[\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0]]\n```\n\nwith this kind of block repeated for each allocation counter test. Let's go\nthrough and understand each line. The first line is the name of the specific\nallocation test. The most relevant part is the file name\n(`test_future_lots_of_callbacks.swift`). For this test, we seem to be testing\nhow many allocations futures with many callbacks are doing.\n\n```\n- /Users/johannes/devel/swift-nio/IntegrationTests/tests_04_performance/test_01_resources/test_future_lots_of_callbacks.swift\n```\n\nNext, we see\n\n```\ntest_future_lots_of_callbacks.remaining_allocations: 0\ntest_future_lots_of_callbacks.total_allocations: 75001\ntest_future_lots_of_callbacks.total_allocated_bytes: 4138056\n```\n\nwhich are the aggregate values. The first line says `remaining_allocations: 0`,\nwhich means that this allocation test didn't leak, which is good! Then, we see\n\n```\ntest_future_lots_of_callbacks.total_allocations: 75001\n```\n\nwhich means that by the end of the test, we saw 75001 allocations in total. As a\nrule, we usually run the workload of every allocation test 1000 times. That\nmeans you want to divide 75001 by the 1000 runs to get the number of allocations\nper run. In other words: each iteration of this allocation test allocated 75\ntimes. The extra one allocation is just some noise that we have to ignore: these\nare usually inserted by operations in the Swift runtime that need to initialize\nsome state. In many (especially multi-threaded test cases) there is some noise,\nwhich is why we run the workload repeatedly, which makes it easy to tell the\nsignal from the noise.\n\nFinally, we see\n\n```\ntest_future_lots_of_callbacks.total_allocated_bytes: 4138056\n```\n\nWhich is the total number of bytes allocated by this test.\n\nLast of all, we see\n\n```\nDEBUG: [[\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0]]\n```\n\nwhich are just the exact numbers of each of the 10 runs we considered.\nNote, the lines are prefixed with `DEBUG:` to make analysis of the output\neasier, it does _not_ mean we're running in debug mode. If you see a lot of\nfluctuation between the runs, then the allocation test doesn't allocate\ndeterministically which would be something you want to fix. In the example\nabove, we're totally stable to the last byte of allocated memory, so we have\nnothing to worry about with this test.\n"
  },
  {
    "path": "Sources/NIO/Docs.docc/index.md",
    "content": "# ``NIO`` <!-- SwiftNIO -->\n\nEvent-driven, non-blocking, network application framework for high performance protocol servers & clients.\n\n## Overview\n\nSwiftNIO is a cross-platform asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.\n\nIt's like Netty, but written for Swift.\n\n### Repository organization\n\nThe SwiftNIO project is split across multiple repositories:\n\nRepo | Usage\n--|--\n[swift-nio][repo-nio] | SwiftNIO core\n[swift-nio-ssl][repo-nio-ssl] | TLS (SSL) support\n[swift-nio-http2][repo-nio-http2] | HTTP/2 support\n[swift-nio-extras][repo-nio-extras] | Useful additions around SwiftNIO\n[swift-nio-transport-services][repo-nio-transport-services] | First-class support for macOS, iOS, tvOS, and watchOS\n[swift-nio-ssh][repo-nio-ssh] | SSH support\n\n### Modules\n\nSwiftNIO has a number of products that provide different functionality. This package includes the following products:\n\n- ``NIO``. This is an umbrella module exporting [NIOCore][module-core], [NIOEmbedded][module-embedded] and [NIOPosix][module-posix].\n- [NIOCore][module-core]. This provides the core abstractions and types for using SwiftNIO (see [\"Conceptual Overview\"](#Conceptual-Overview) for more details). Most NIO extension projects that provide things like new [`EventLoop`s][el] and [`Channel`s][c] or new protocol implementations should only need to depend on [NIOCore][module-core].\n- [NIOPosix][module-posix]. This provides the primary [`EventLoopGroup`][elg], [`EventLoop`][el], and [`Channel`s][c] for use on POSIX-based systems. This is our high performance core I/O layer. In general, this should only be imported by projects that plan to do some actual I/O, such as high-level protocol implementations or applications.\n- [NIOEmbedded][module-embedded]. This provides [`EmbeddedChannel`][ec] and [`EmbeddedEventLoop`][eel], implementations of the [NIOCore][module-core] abstractions that provide fine-grained control over their execution. These are most often used for testing, but can also be used to drive protocol implementations in a way that is decoupled from networking altogether.\n- [NIOConcurrencyHelpers][module-concurrency-helpers]. This provides a few low-level concurrency primitives that are used by NIO implementations, such as locks and atomics.\n- [NIOFoundationCompat][module-foundation-compatibility]. This extends a number of NIO types for better interoperation with Foundation data types. If you are working with Foundation data types such as `Data`, you should import this.\n- [NIOTLS][module-tls]. This provides a few common abstraction types for working with multiple TLS implementations. Note that this doesn't provide TLS itself: please investigate [swift-nio-ssl][repo-nio-ssl] and [swift-nio-transport-services][repo-nio-transport-services] for concrete implementations.\n- [NIOHTTP1][module-http1]. This provides a low-level HTTP/1.1 protocol implementation.\n- [NIOWebSocket][module-websocket]. This provides a low-level WebSocket protocol implementation.\n- [NIOTestUtils][module-test-utilities]. This provides a number of helpers for testing projects that use SwiftNIO.\n- [_NIOFileSystem][module-filesystem]. This provides `async` APIs for interacting with the file system.\n\n### Conceptual Overview\n\nSwiftNIO is fundamentally a low-level tool for building high-performance networking applications in Swift. It particularly targets those use-cases where using a \"thread-per-connection\" model of concurrency is inefficient or untenable. This is a common limitation when building servers that use a large number of relatively low-utilization connections, such as HTTP servers.\n\nTo achieve its goals SwiftNIO extensively uses \"non-blocking I/O\": hence the name! Non-blocking I/O differs from the more common blocking I/O model because the application does not wait for data to be sent to or received from the network: instead, SwiftNIO asks for the kernel to notify it when I/O operations can be performed without waiting.\n\nSwiftNIO does not aim to provide high-level solutions like, for example, web frameworks do. Instead, SwiftNIO is focused on providing the low-level building blocks for these higher-level applications. When it comes to building a web application, most users will not want to use SwiftNIO directly: instead, they'll want to use one of the many great web frameworks available in the Swift ecosystem. Those web frameworks, however, may choose to use SwiftNIO under the covers to provide their networking support.\n\nThe following sections will describe the low-level tools that SwiftNIO provides, and provide a quick overview of how to work with them. If you feel comfortable with these concepts, then you can skip right ahead to the other sections of this document.\n\n#### Basic Architecture\n\nThe basic building blocks of SwiftNIO are the following 8 types of objects:\n\n- [`EventLoopGroup`][elg], a protocol, provided by [NIOCore][module-core].\n- [`EventLoop`][el], a protocol, provided by [NIOCore][module-core].\n- [`Channel`][c], a protocol, provided by [NIOCore][module-core].\n- [`ChannelHandler`][ch], a protocol, provided by [NIOCore][module-core].\n- `Bootstrap`, several related structures, provided by [NIOCore][module-core].\n- [`ByteBuffer`][bb], a struct, provided by [NIOCore][module-core].\n- [`EventLoopFuture`][elf], a generic class, provided by [NIOCore][module-core].\n- [`EventLoopPromise`][elp], a generic struct, provided by [NIOCore][module-core].\n\nAll SwiftNIO applications are ultimately constructed of these various components.\n\n##### EventLoops and EventLoopGroups\n\nThe basic I/O primitive of SwiftNIO is the event loop. The event loop is an object that waits for events (usually I/O related events, such as \"data received\") to happen and then fires some kind of callback when they do. In almost all SwiftNIO applications there will be relatively few event loops: usually only one or two per CPU core the application wants to use. Generally speaking event loops run for the entire lifetime of your application, spinning in an endless loop dispatching events.\n\nEvent loops are gathered together into event loop *groups*. These groups provide a mechanism to distribute work around the event loops. For example, when listening for inbound connections the listening socket will be registered on one event loop. However, we don't want all connections that are accepted on that listening socket to be registered with the same event loop, as that would potentially overload one event loop while leaving the others empty. For that reason, the event loop group provides the ability to spread load across multiple event loops.\n\nIn SwiftNIO today there is one [`EventLoopGroup`][elg] implementation, and two [`EventLoop`][el] implementations. For production applications there is the [`MultiThreadedEventLoopGroup`][mtelg], an [`EventLoopGroup`][elg] that creates a number of threads (using the POSIX [`pthreads`][pthreads] library) and places one `SelectableEventLoop` on each one. The `SelectableEventLoop` is an event loop that uses a selector (either [`kqueue`][kqueue] or [`epoll`][epoll] depending on the target system) to manage I/O events from file descriptors and to dispatch work. These [`EventLoop`s][el] and [`EventLoopGroup`s][elg] are provided by the [NIOPosix][module-posix] module. Additionally, there is the [`EmbeddedEventLoop`][eel], which is a dummy event loop that is used primarily for testing purposes, provided by the [NIOEmbedded][module-embedded] module.\n\n[`EventLoop`][el]s have a number of important properties. Most vitally, they are the way all work gets done in SwiftNIO applications. In order to ensure thread-safety, any work that wants to be done on almost any of the other objects in SwiftNIO must be dispatched via an [`EventLoop`][el]. [`EventLoop`][el] objects own almost all the other objects in a SwiftNIO application, and understanding their execution model is critical for building high-performance SwiftNIO applications.\n\n##### Channels, Channel Handlers, Channel Pipelines, and Channel Contexts\n\nWhile [`EventLoop`][el]s are critical to the way SwiftNIO works, most users will not interact with them substantially beyond asking them to create [`EventLoopPromise`][elp]s and to schedule work. The parts of a SwiftNIO application most users will spend the most time interacting with are [`Channel`][c]s and [`ChannelHandler`][ch]s.\n\nAlmost every file descriptor that a user interacts with in a SwiftNIO program is associated with a single [`Channel`][c]. The [`Channel`][c] owns this file descriptor, and is responsible for managing its lifetime. It is also responsible for processing inbound and outbound events on that file descriptor: whenever the event loop has an event that corresponds to a file descriptor, it will notify the [`Channel`][c] that owns that file descriptor.\n\n[`Channel`][c]s by themselves, however, are not useful. After all, it is a rare application that doesn't want to do anything with the data it sends or receives on a socket! So the other important part of the [`Channel`][c] is the [`ChannelPipeline`][cp].\n\nA [`ChannelPipeline`][cp] is a sequence of objects, called [`ChannelHandler`][ch]s, that process events on a [`Channel`][c]. The [`ChannelHandler`][ch]s process these events one after another, in order, mutating and transforming events as they go. This can be thought of as a data processing pipeline; hence the name [`ChannelPipeline`][cp].\n\nAll [`ChannelHandler`][ch]s are either Inbound or Outbound handlers, or both. Inbound handlers process \"inbound\" events: events like reading data from a socket, reading socket close, or other kinds of events initiated by remote peers. Outbound handlers process \"outbound\" events, such as writes, connection attempts, and local socket closes.\n\nEach handler processes the events in order. For example, read events are passed from the front of the pipeline to the back, one handler at a time, while write events are passed from the back of the pipeline to the front. Each handler may, at any time, generate either inbound or outbound events that will be sent to the next handler in whichever direction is appropriate. This allows handlers to split up reads, coalesce writes, delay connection attempts, and generally perform arbitrary transformations of events.\n\nIn general, [`ChannelHandler`][ch]s are designed to be highly re-usable components. This means they tend to be designed to be as small as possible, performing one specific data transformation. This allows handlers to be composed together in novel and flexible ways, which helps with code reuse and encapsulation.\n\n[`ChannelHandler`][ch]s are able to keep track of where they are in a [`ChannelPipeline`][cp] by using a [`ChannelHandlerContext`][chc]. These objects contain references to the previous and next channel handler in the pipeline, ensuring that it is always possible for a [`ChannelHandler`][ch] to emit events while it remains in a pipeline.\n\nSwiftNIO ships with many [`ChannelHandler`][ch]s built in that provide useful functionality, such as HTTP parsing. In addition, high-performance applications will want to provide as much of their logic as possible in [`ChannelHandler`][ch]s, as it helps avoid problems with context switching.\n\nAdditionally, SwiftNIO ships with a few [`Channel`][c] implementations. In particular, it ships with `ServerSocketChannel`, a [`Channel`][c] for sockets that accept inbound connections; `SocketChannel`, a [`Channel`][c] for TCP connections; and `DatagramChannel`, a [`Channel`][c] for UDP sockets. All of these are provided by the [NIOPosix][module-posix] module. It also provides[`EmbeddedChannel`][ec], a [`Channel`][c] primarily used for testing, provided by the [NIOEmbedded][module-embedded] module.\n\n###### A Note on Blocking\n\nOne of the important notes about [`ChannelPipeline`][cp]s is that they are thread-safe. This is very important for writing SwiftNIO applications, as it allows you to write much simpler [`ChannelHandler`][ch]s in the knowledge that they will not require synchronization.\n\nHowever, this is achieved by dispatching all code on the [`ChannelPipeline`][cp] on the same thread as the [`EventLoop`][el]. This means that, as a general rule, [`ChannelHandler`][ch]s **must not** call blocking code without dispatching it to a background thread. If a [`ChannelHandler`][ch] blocks for any reason, all [`Channel`][c]s attached to the parent [`EventLoop`][el] will be unable to progress until the blocking call completes.\n\nThis is a common concern while writing SwiftNIO applications. If it is useful to write code in a blocking style, it is highly recommended that you dispatch work to a different thread when you're done with it in your pipeline.\n\n##### Bootstrap\n\nWhile it is possible to configure and register [`Channel`][c]s with [`EventLoop`][el]s directly, it is generally more useful to have a higher-level abstraction to handle this work.\n\nFor this reason, SwiftNIO ships a number of `Bootstrap` objects whose purpose is to streamline the creation of channels. Some `Bootstrap` objects also provide other functionality, such as support for Happy Eyeballs for making TCP connection attempts.\n\nCurrently SwiftNIO ships with three `Bootstrap` objects in the [NIOPosix][module-posix] module: [`ServerBootstrap`][sb], for bootstrapping listening channels; [`ClientBootstrap`][cb], for bootstrapping client TCP channels; and [`DatagramBootstrap`][db] for bootstrapping UDP channels.\n\n##### ByteBuffer\n\nThe majority of the work in a SwiftNIO application involves shuffling buffers of bytes around. At the very least, data is sent and received to and from the network in the form of buffers of bytes. For this reason it's very important to have a high-performance data structure that is optimized for the kind of work SwiftNIO applications perform.\n\nFor this reason, SwiftNIO provides [`ByteBuffer`][bb], a fast copy-on-write byte buffer that forms a key building block of most SwiftNIO applications. This type is provided by the [NIOCore][module-core] module.\n\n[`ByteBuffer`][bb] provides a number of useful features, and in addition provides a number of hooks to use it in an \"unsafe\" mode. This turns off bounds checking for improved performance, at the cost of potentially opening your application up to memory correctness problems.\n\nIn general, it is highly recommended that you use the [`ByteBuffer`][bb] in its safe mode at all times.\n\nFor more details on the API of [`ByteBuffer`][bb], please see our API documentation, linked below.\n\n##### Promises and Futures\n\nOne major difference between writing concurrent code and writing synchronous code is that not all actions will complete immediately. For example, when you write data on a channel, it is possible that the event loop will not be able to immediately flush that write out to the network. For this reason, SwiftNIO provides [`EventLoopPromise<T>`][elp] and [`EventLoopFuture<T>`][elf] to manage operations that complete *asynchronously*. These types are provided by the [NIOCore][module-core] module.\n\nAn [`EventLoopFuture<T>`][elf] is essentially a container for the return value of a function that will be populated *at some time in the future*. Each [`EventLoopFuture<T>`][elf] has a corresponding [`EventLoopPromise<T>`][elp], which is the object that the result will be put into. When the promise is succeeded, the future will be fulfilled.\n\nIf you had to poll the future to detect when it completed that would be quite inefficient, so [`EventLoopFuture<T>`][elf] is designed to have managed callbacks. Essentially, you can chain callbacks off the future that will be executed when a result is available. The [`EventLoopFuture<T>`][elf] will even carefully arrange the scheduling to ensure that these callbacks always execute on the event loop that initially created the promise, which helps ensure that you don't need too much synchronization around [`EventLoopFuture<T>`][elf] callbacks.\n\nAnother important topic for consideration is the difference between how the promise passed to `close` works as opposed to `closeFuture` on a [`Channel`][c]. For example, the promise passed into `close` will succeed after the [`Channel`][c] is closed down but before the [`ChannelPipeline`][cp] is completely cleared out. This will allow you to take action on the [`ChannelPipeline`][cp] before it is completely cleared out, if needed. If it is desired to wait for the [`Channel`][c] to close down and the [`ChannelPipeline`][cp] to be cleared out without any further action, then the better option would be to wait for the `closeFuture` to succeed.\n\nThere are several functions for applying callbacks to [`EventLoopFuture<T>`][elf], depending on how and when you want them to execute. Details of these functions is left to the API documentation.\n\n#### Design Philosophy\n\nSwiftNIO is designed to be a powerful tool for building networked applications and frameworks, but it is not intended to be the perfect solution for all levels of abstraction. SwiftNIO is tightly focused on providing the basic I/O primitives and protocol implementations at low levels of abstraction, leaving more expressive but slower abstractions to the wider community to build. The intention is that SwiftNIO will be a building block for server-side applications, not necessarily the framework those applications will use directly.\n\nApplications that need extremely high performance from their networking stack may choose to use SwiftNIO directly in order to reduce the overhead of their abstractions. These applications should be able to maintain extremely high performance with relatively little maintenance cost. SwiftNIO also focuses on providing useful abstractions for this use-case, such that extremely high performance network servers can be built directly.\n\nThe core SwiftNIO repository will contain a few extremely important protocol implementations, such as HTTP, directly in tree. However, we believe that most protocol implementations should be decoupled from the release cycle of the underlying networking stack, as the release cadence is likely to be very different (either much faster or much slower). For this reason, we actively encourage the community to develop and maintain their protocol implementations out-of-tree. Indeed, some first-party SwiftNIO protocol implementations, including our TLS and HTTP/2 bindings, are developed out-of-tree!\n\n## Topics\n\n### Allocation Tests\n\n- <doc:Running-Alloction-Counting-Tests>\n- <doc:Debugging-Allocation-Regressions>\n\n\n<!-- links -->\n\n[repo-nio]: https://github.com/apple/swift-nio\n[repo-nio-extras]: https://github.com/apple/swift-nio-extras\n[repo-nio-http2]: https://github.com/apple/swift-nio-http2\n[repo-nio-ssl]: https://github.com/apple/swift-nio-ssl\n[repo-nio-transport-services]: https://github.com/apple/swift-nio-transport-services\n[repo-nio-ssh]: https://github.com/apple/swift-nio-ssh\n\n[module-core]: ./NIOCore\n[module-posix]: ./NIOPosix\n[module-embedded]: ./NIOEmbedded\n[module-concurrency-helpers]: ./NIOConcurrencyHelpers\n[module-foundation-compatibility]: ./NIOFoundationCompat\n[module-http1]: ./NIOHTTP1\n[module-tls]: ./NIOTLS\n[module-websocket]: ./NIOWebSocket\n[module-test-utilities]: ./NIOTestUtils\n[module-filesystem]: ./_NIOFileSystem\n\n[ch]: ./NIOCore/ChannelHandler\n[c]: ./NIOCore/Channel\n[chc]: ./NIOCore/ChannelHandlerContext\n[ec]: ./NIOEmbedded/EmbeddedChannel\n[el]: ./NIOCore/EventLoop\n[eel]: ./NIOEmbedded/EmbeddedEventLoop\n[elg]: ./NIOCore/EventLoopGroup\n[bb]: ./NIOCore/ByteBuffer\n[elf]: ./NIOCore/EventLoopFuture\n[elp]: ./NIOCore/EventLoopPromise\n[cp]: ./NIOCore/ChannelPipeline\n[mtelg]: ./NIOPosix/MultiThreadedEventLoopGroup\n[sb]: ./NIOPosix/ServerBootstrap\n[cb]: ./NIOPosix/ClientBootstrap\n[db]: ./NIOPosix/DatagramBootstrap\n[pthreads]: https://en.wikipedia.org/wiki/POSIX_Threads\n[kqueue]: https://en.wikipedia.org/wiki/Kqueue\n[epoll]: https://en.wikipedia.org/wiki/Epoll\n\n<!--\nNIOCore NIOEmbedded NIOPosix NIOHTTP1 NIOFoundationCompat NIOWebSocket NIOConcurrencyHelpers NIOTLS NIOTestUtils\n-->\n"
  },
  {
    "path": "Sources/NIO/Exports.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n@_exported import NIOCore\n@_exported import NIOEmbedded\n@_exported import NIOPosix\n"
  },
  {
    "path": "Sources/NIOAsyncAwaitDemo/AsyncChannelIO.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOHTTP1\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nstruct AsyncChannelIO<Request: Sendable, Response: Sendable> {\n    let channel: Channel\n\n    init(_ channel: Channel) {\n        self.channel = channel\n    }\n\n    func start() async throws -> AsyncChannelIO<Request, Response> {\n        try await channel.eventLoop.submit {\n            try channel.pipeline.syncOperations.addHandler(\n                RequestResponseHandler<HTTPRequestHead, NIOHTTPClientResponseFull>()\n            )\n        }.get()\n        return self\n    }\n\n    func sendRequest(_ request: Request) async throws -> Response {\n        let responsePromise: EventLoopPromise<Response> = channel.eventLoop.makePromise()\n        try await self.channel.writeAndFlush((request, responsePromise)).get()\n        return try await responsePromise.futureResult.get()\n    }\n\n    func close() async throws {\n        try await self.channel.close()\n    }\n}\n"
  },
  {
    "path": "Sources/NIOAsyncAwaitDemo/FullRequestResponse.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// THIS FILE IS MOSTLY COPIED FROM swift-nio-extras\n\nimport NIOCore\nimport NIOHTTP1\n\npublic final class MakeFullRequestHandler: ChannelOutboundHandler, Sendable {\n    public typealias OutboundOut = HTTPClientRequestPart\n    public typealias OutboundIn = HTTPRequestHead\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let req = Self.unwrapOutboundIn(data)\n\n        context.write(Self.wrapOutboundOut(.head(req)), promise: nil)\n        context.write(Self.wrapOutboundOut(.end(nil)), promise: promise)\n    }\n}\n\n/// `RequestResponseHandler` receives a `Request` alongside an `EventLoopPromise<Response>` from the `Channel`'s\n/// outbound side. It will fulfill the promise with the `Response` once it's received from the `Channel`'s inbound\n/// side.\n///\n/// `RequestResponseHandler` does support pipelining `Request`s and it will send them pipelined further down the\n/// `Channel`. Should `RequestResponseHandler` receive an error from the `Channel`, it will fail all promises meant for\n/// the outstanding `Response`s and close the `Channel`. All requests enqueued after an error occurred will be immediately\n/// failed with the first error the channel received.\n///\n/// `RequestResponseHandler` requires that the `Response`s arrive on `Channel` in the same order as the `Request`s\n/// were submitted.\npublic final class RequestResponseHandler<Request: Sendable, Response: Sendable>: ChannelDuplexHandler {\n    public typealias InboundIn = Response\n    public typealias InboundOut = Never\n    public typealias OutboundIn = (Request, EventLoopPromise<Response>)\n    public typealias OutboundOut = Request\n\n    private enum State {\n        case operational\n        case error(Error)\n\n        var isOperational: Bool {\n            switch self {\n            case .operational:\n                return true\n            case .error:\n                return false\n            }\n        }\n    }\n\n    private var state: State = .operational\n    private var promiseBuffer: CircularBuffer<EventLoopPromise<Response>>\n\n    /// Create a new `RequestResponseHandler`.\n    ///\n    /// - Parameters:\n    ///    - initialBufferCapacity: `RequestResponseHandler` saves the promises for all outstanding responses in a\n    ///          buffer. `initialBufferCapacity` is the initial capacity for this buffer. You usually do not need to set\n    ///          this parameter unless you intend to pipeline very deeply and don't want the buffer to resize.\n    public init(initialBufferCapacity: Int = 4) {\n        self.promiseBuffer = CircularBuffer(initialCapacity: initialBufferCapacity)\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        switch self.state {\n        case .error:\n            // We failed any outstanding promises when we entered the error state and will fail any\n            // new promises in write.\n            assert(self.promiseBuffer.count == 0)\n        case .operational:\n            let promiseBuffer = self.promiseBuffer\n            self.promiseBuffer.removeAll()\n            for promise in promiseBuffer {\n                promise.fail(ChannelError.eof)\n            }\n        }\n        context.fireChannelInactive()\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        guard self.state.isOperational else {\n            // we're in an error state, ignore further responses\n            assert(self.promiseBuffer.count == 0)\n            return\n        }\n\n        let response = Self.unwrapInboundIn(data)\n        let promise = self.promiseBuffer.removeFirst()\n\n        promise.succeed(response)\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        guard self.state.isOperational else {\n            assert(self.promiseBuffer.count == 0)\n            return\n        }\n        self.state = .error(error)\n        let promiseBuffer = self.promiseBuffer\n        self.promiseBuffer.removeAll()\n        context.close(promise: nil)\n        for promise in promiseBuffer {\n            promise.fail(error)\n        }\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let (request, responsePromise) = Self.unwrapOutboundIn(data)\n        switch self.state {\n        case .error(let error):\n            assert(self.promiseBuffer.count == 0)\n            responsePromise.fail(error)\n            promise?.fail(error)\n        case .operational:\n            self.promiseBuffer.append(responsePromise)\n            context.write(Self.wrapOutboundOut(request), promise: promise)\n        }\n    }\n}\n\n@available(*, unavailable)\nextension RequestResponseHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOAsyncAwaitDemo/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc makeHTTPChannel(\n    host: String,\n    port: Int,\n    group: EventLoopGroup\n) async throws -> AsyncChannelIO<HTTPRequestHead, NIOHTTPClientResponseFull> {\n    let channel = try await ClientBootstrap(group: group)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHTTPClientHandlers()\n                try channel.pipeline.syncOperations.addHandler(\n                    NIOHTTPClientResponseAggregator(maxContentLength: 1_000_000)\n                )\n                try channel.pipeline.syncOperations.addHandler(MakeFullRequestHandler())\n            }\n        }\n        .connect(host: host, port: port).get()\n\n    return try await AsyncChannelIO<HTTPRequestHead, NIOHTTPClientResponseFull>(channel).start()\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc main() async {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    do {\n        let channel = try await makeHTTPChannel(host: \"httpbin.org\", port: 80, group: group)\n        print(\"OK, connected to \\(channel)\")\n\n        print(\"Sending request 1\", terminator: \"\")\n        let response1 = try await channel.sendRequest(\n            HTTPRequestHead(\n                version: .http1_1,\n                method: .GET,\n                uri: \"/base64/SGVsbG8gV29ybGQsIGZyb20gSFRUUEJpbiEgCg==\",\n                headers: [\"host\": \"httpbin.org\"]\n            )\n        )\n        print(\", response:\", String(buffer: response1.body ?? ByteBuffer()))\n\n        print(\"Sending request 2\", terminator: \"\")\n        let response2 = try await channel.sendRequest(\n            HTTPRequestHead(\n                version: .http1_1,\n                method: .GET,\n                uri: \"/get\",\n                headers: [\"host\": \"httpbin.org\"]\n            )\n        )\n        print(\", response:\", String(buffer: response2.body ?? ByteBuffer()))\n\n        try await channel.close()\n\n        print(\"Shutting down event loop group...\")\n        try await group.shutdownGracefully()\n\n        print(\"all, done\")\n    } catch {\n        print(\"ERROR: \\(error)\")\n        print(\"Shutting down event loop group (possibly for a second time)...\")\n        do {\n            try await group.shutdownGracefully()\n        } catch {\n            print(\"Error shutting down event loop group: \\(error)\")\n        }\n    }\n}\n\nlet dg = DispatchGroup()\ndg.enter()\nif #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) {\n    Task {\n        await main()\n        dg.leave()\n    }\n} else {\n    dg.leave()\n}\ndg.wait()\n"
  },
  {
    "path": "Sources/NIOChatClient/README.md",
    "content": "# NIOChatClient\n\nThis sample application provides a client for the `NIOChatServer`. Invoke\nit using one of the following syntaxes:\n\n```bash\nswift run NIOChatClient  # Connects to a server on ::1, port 9999.\nswift run NIOChatClient 9899  # Connects to a server on ::1, port 9899\nswift run NIOChatClient /path/to/unix/socket  # Connects to a server using the given UNIX socket\nswift run NIOChatClient chat.example.com 9899  # Connects to a server on chat.example.com:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOChatClient/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOPosix\n\nprivate final class ChatHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let buffer = Self.unwrapInboundIn(data)\n        print(String(buffer: buffer))\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n}\n\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\nlet bootstrap = ClientBootstrap(group: group)\n    // Enable SO_REUSEADDR.\n    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n    .channelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandler(ChatHandler())\n        }\n    }\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\n// First argument is the program path\nlet arguments = CommandLine.arguments\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\n\nlet defaultHost = \"::1\"\nlet defaultPort = 9999\n\nenum ConnectTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n}\n\nlet connectTarget: ConnectTo\nswitch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {\ncase (.some(let h), _, .some(let p)):\n    // we got two arguments, let's interpret that as host and port\n    connectTarget = .ip(host: h, port: p)\ncase (.some(let portString), .none, _):\n    // couldn't parse as number, expecting unix domain socket path\n    connectTarget = .unixDomainSocket(path: portString)\ncase (_, .some(let p), _):\n    // only one argument --> port\n    connectTarget = .ip(host: defaultHost, port: p)\ndefault:\n    connectTarget = .ip(host: defaultHost, port: defaultPort)\n}\n\nlet channel = try { () -> Channel in\n    switch connectTarget {\n    case .ip(let host, let port):\n        return try bootstrap.connect(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try bootstrap.connect(unixDomainSocketPath: path).wait()\n    }\n}()\n\n// In production code, you should check if `channel.remoteAddress` is actually\n// present, as in rare situations it can be `nil`.\nprint(\"ChatClient connected to ChatServer: \\(channel.remoteAddress!), happy chatting\\n. Press ^D to exit.\")\n\nwhile let line = readLine(strippingNewline: false) {\n    let buffer = channel.allocator.buffer(string: line)\n    try! channel.writeAndFlush(buffer).wait()\n}\n\n// EOF, close connect\ntry! channel.close().wait()\n\nprint(\"ChatClient closed\")\n"
  },
  {
    "path": "Sources/NIOChatServer/README.md",
    "content": "# NIOChatServer\n\nThis sample application provides a chat server that allows multile users to speak to one another. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOChatServer  # Binds the server on ::1, port 9999.\nswift run NIOChatServer 9899  # Binds the server on ::1, port 9899\nswift run NIOChatServer /path/to/unix/socket  # Binds the server using the given UNIX socket\nswift run NIOChatServer 192.168.0.5 9899  # Binds the server on 192.168.0.5:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOChatServer/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nprivate let newLine = \"\\n\".utf8.first!\n\n/// Very simple example codec which will buffer inbound data until a `\\n` was found.\nfinal class LineDelimiterCodec: ByteToMessageDecoder {\n    public typealias InboundIn = ByteBuffer\n    public typealias InboundOut = ByteBuffer\n\n    public var cumulationBuffer: ByteBuffer?\n\n    public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        let readable = buffer.withUnsafeReadableBytes { $0.firstIndex(of: newLine) }\n        if let r = readable {\n            context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: r + 1)!))\n            return .continue\n        }\n        return .needMoreData\n    }\n}\n\n/// This `ChannelInboundHandler` demonstrates a few things:\n///   * Synchronisation between `EventLoop`s.\n///   * Mixing `Dispatch` and SwiftNIO.\n///   * `Channel`s are thread-safe, `ChannelHandlerContext`s are not.\n///\n/// As we are using an `MultiThreadedEventLoopGroup` that uses more then 1 thread we need to ensure proper\n/// synchronization on the shared state in the `ChatHandler` (as the same instance is shared across\n/// child `Channel`s). For this a serial `DispatchQueue` is used when we modify the shared state (the `Dictionary`).\n/// As `ChannelHandlerContext` is not thread-safe we need to ensure we only operate on the `Channel` itself while\n/// `Dispatch` executed the submitted block.\nfinal class ChatHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n\n    // All access to channels is guarded by channelsSyncQueue.\n    private let channelsSyncQueue = DispatchQueue(label: \"channelsQueue\")\n    private var channels: [ObjectIdentifier: Channel] = [:]\n\n    public func channelActive(context: ChannelHandlerContext) {\n        // In production code, you should check if `context.remoteAddress` is actually\n        // present, as in rare situations it can be `nil`.\n        let remoteAddress = context.remoteAddress!\n        let channel = context.channel\n        self.channelsSyncQueue.async {\n            // broadcast the message to all the connected clients except the one that just became active.\n            self.writeToAll(\n                channels: self.channels,\n                allocator: channel.allocator,\n                message: \"(ChatServer) - New client connected with address: \\(remoteAddress)\\n\"\n            )\n\n            self.channels[ObjectIdentifier(channel)] = channel\n        }\n\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeString(\"(ChatServer) - Welcome to: \\(context.localAddress!)\\n\")\n        context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        let channel = context.channel\n        self.channelsSyncQueue.async {\n            if self.channels.removeValue(forKey: ObjectIdentifier(channel)) != nil {\n                // Broadcast the message to all the connected clients except the one that just was disconnected.\n                self.writeToAll(\n                    channels: self.channels,\n                    allocator: channel.allocator,\n                    message: \"(ChatServer) - Client disconnected\\n\"\n                )\n            }\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let id = ObjectIdentifier(context.channel)\n        var read = Self.unwrapInboundIn(data)\n\n        // 64 should be good enough for the ipaddress\n        var buffer = context.channel.allocator.buffer(capacity: read.readableBytes + 64)\n\n        // In production code, you should check if `context.remoteAddress` is actually\n        // present, as in rare situations it can be `nil`.\n        buffer.writeString(\"(\\(context.remoteAddress!)) - \")\n        buffer.writeBuffer(&read)\n        self.channelsSyncQueue.async { [buffer] in\n            // broadcast the message to all the connected clients except the one that wrote it.\n            self.writeToAll(channels: self.channels.filter { id != $0.key }, buffer: buffer)\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n\n    private func writeToAll(channels: [ObjectIdentifier: Channel], allocator: ByteBufferAllocator, message: String) {\n        let buffer = allocator.buffer(string: message)\n        self.writeToAll(channels: channels, buffer: buffer)\n    }\n\n    private func writeToAll(channels: [ObjectIdentifier: Channel], buffer: ByteBuffer) {\n        for channel in channels {\n            channel.value.writeAndFlush(buffer, promise: nil)\n        }\n    }\n}\n\n/// access to the internal state is protected by `channelsSyncQueue`\nextension ChatHandler: @unchecked Sendable {}\n\n// We need to share the same ChatHandler for all as it keeps track of all\n// connected clients. For this ChatHandler MUST be thread-safe!\nlet chatHandler = ChatHandler()\n\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\nlet bootstrap = ServerBootstrap(group: group)\n    // Specify backlog and enable SO_REUSEADDR for the server itself\n    .serverChannelOption(.backlog, value: 256)\n    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n    // Set the handlers that are applied to the accepted Channels\n    .childChannelInitializer { channel in\n        // Add handler that will buffer data until a \\n is received\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCodec()))\n            try channel.pipeline.syncOperations.addHandler(chatHandler)\n        }\n    }\n\n    // Enable SO_REUSEADDR for the accepted Channels\n    .childChannelOption(.socketOption(.so_reuseaddr), value: 1)\n    .childChannelOption(.maxMessagesPerRead, value: 16)\n    .childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator())\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\n// First argument is the program path\nlet arguments = CommandLine.arguments\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\n\nlet defaultHost = \"::1\"\nlet defaultPort = 9999\n\nenum BindTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n}\n\nlet bindTarget: BindTo\nswitch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {\ncase (.some(let h), _, .some(let p)):\n    // we got two arguments, let's interpret that as host and port\n    bindTarget = .ip(host: h, port: p)\n\ncase (let portString?, .none, _):\n    // Couldn't parse as number, expecting unix domain socket path.\n    bindTarget = .unixDomainSocket(path: portString)\n\ncase (_, let p?, _):\n    // Only one argument --> port.\n    bindTarget = .ip(host: defaultHost, port: p)\n\ndefault:\n    bindTarget = .ip(host: defaultHost, port: defaultPort)\n}\n\nlet channel = try { () -> Channel in\n    switch bindTarget {\n    case .ip(let host, let port):\n        return try bootstrap.bind(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try bootstrap.bind(unixDomainSocketPath: path).wait()\n    }\n}()\n\nguard let localAddress = channel.localAddress else {\n    fatalError(\n        \"Address was unable to bind. Please check that the socket was not closed or that the address family was understood.\"\n    )\n}\nprint(\"Server started and listening on \\(localAddress)\")\n\n// This will never unblock as we don't close the ServerChannel.\ntry channel.closeFuture.wait()\n\nprint(\"ChatServer closed\")\n"
  },
  {
    "path": "Sources/NIOConcurrencyHelpers/NIOAtomic.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOAtomics\n\n/// The protocol that all types that can be made atomic must conform to.\n///\n/// **Do not add conformance to this protocol for arbitrary types**. Only a small range\n/// of types have appropriate atomic operations supported by the CPU, and those types\n/// already have conformances implemented.\n@preconcurrency\npublic protocol NIOAtomicPrimitive {\n    associatedtype AtomicWrapper\n    static var nio_atomic_create_with_existing_storage: @Sendable (UnsafeMutablePointer<AtomicWrapper>, Self) -> Void {\n        get\n    }\n    static var nio_atomic_compare_and_exchange: @Sendable (UnsafeMutablePointer<AtomicWrapper>, Self, Self) -> Bool {\n        get\n    }\n    static var nio_atomic_add: @Sendable (UnsafeMutablePointer<AtomicWrapper>, Self) -> Self { get }\n    static var nio_atomic_sub: @Sendable (UnsafeMutablePointer<AtomicWrapper>, Self) -> Self { get }\n    static var nio_atomic_exchange: @Sendable (UnsafeMutablePointer<AtomicWrapper>, Self) -> Self { get }\n    static var nio_atomic_load: @Sendable (UnsafeMutablePointer<AtomicWrapper>) -> Self { get }\n    static var nio_atomic_store: @Sendable (UnsafeMutablePointer<AtomicWrapper>, Self) -> Void { get }\n}\n\nextension Bool: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic__Bool\n    public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic__Bool_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic__Bool_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic__Bool_add\n    public static let nio_atomic_sub = catmc_nio_atomic__Bool_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic__Bool_exchange\n    public static let nio_atomic_load = catmc_nio_atomic__Bool_load\n    public static let nio_atomic_store = catmc_nio_atomic__Bool_store\n}\n\nextension Int8: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_int_least8_t\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_int_least8_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_int_least8_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_int_least8_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_int_least8_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_int_least8_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_int_least8_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_int_least8_t_store\n}\n\nextension UInt8: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_uint_least8_t\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_uint_least8_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uint_least8_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_uint_least8_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_uint_least8_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_uint_least8_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_uint_least8_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_uint_least8_t_store\n}\n\nextension Int16: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_int_least16_t\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_int_least16_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_int_least16_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_int_least16_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_int_least16_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_int_least16_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_int_least16_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_int_least16_t_store\n}\n\nextension UInt16: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_uint_least16_t\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_uint_least16_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uint_least16_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_uint_least16_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_uint_least16_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_uint_least16_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_uint_least16_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_uint_least16_t_store\n}\n\nextension Int32: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_int_least32_t\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_int_least32_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_int_least32_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_int_least32_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_int_least32_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_int_least32_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_int_least32_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_int_least32_t_store\n}\n\nextension UInt32: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_uint_least32_t\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_uint_least32_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uint_least32_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_uint_least32_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_uint_least32_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_uint_least32_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_uint_least32_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_uint_least32_t_store\n}\n\nextension Int64: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_long_long\n    public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_long_long_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_long_long_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_long_long_add\n    public static let nio_atomic_sub = catmc_nio_atomic_long_long_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_long_long_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_long_long_load\n    public static let nio_atomic_store = catmc_nio_atomic_long_long_store\n}\n\nextension UInt64: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_unsigned_long_long\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_unsigned_long_long_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_unsigned_long_long_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_unsigned_long_long_add\n    public static let nio_atomic_sub = catmc_nio_atomic_unsigned_long_long_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_unsigned_long_long_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_unsigned_long_long_load\n    public static let nio_atomic_store = catmc_nio_atomic_unsigned_long_long_store\n}\n\n#if os(Windows)\nextension Int: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_intptr_t\n    public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_intptr_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_intptr_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_intptr_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_intptr_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_intptr_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_intptr_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_intptr_t_store\n}\n\nextension UInt: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_uintptr_t\n    public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_uintptr_t_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uintptr_t_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_uintptr_t_add\n    public static let nio_atomic_sub = catmc_nio_atomic_uintptr_t_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_uintptr_t_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_uintptr_t_load\n    public static let nio_atomic_store = catmc_nio_atomic_uintptr_t_store\n}\n#else\nextension Int: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_long\n    public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_long_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_long_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_long_add\n    public static let nio_atomic_sub = catmc_nio_atomic_long_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_long_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_long_load\n    public static let nio_atomic_store = catmc_nio_atomic_long_store\n}\n\nextension UInt: NIOAtomicPrimitive {\n    public typealias AtomicWrapper = catmc_nio_atomic_unsigned_long\n    public static let nio_atomic_create_with_existing_storage =\n        catmc_nio_atomic_unsigned_long_create_with_existing_storage\n    public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_unsigned_long_compare_and_exchange\n    public static let nio_atomic_add = catmc_nio_atomic_unsigned_long_add\n    public static let nio_atomic_sub = catmc_nio_atomic_unsigned_long_sub\n    public static let nio_atomic_exchange = catmc_nio_atomic_unsigned_long_exchange\n    public static let nio_atomic_load = catmc_nio_atomic_unsigned_long_load\n    public static let nio_atomic_store = catmc_nio_atomic_unsigned_long_store\n}\n#endif\n\n/// An encapsulation of an atomic primitive object.\n///\n/// Atomic objects support a wide range of atomic operations:\n///\n/// - Compare and swap\n/// - Add\n/// - Subtract\n/// - Exchange\n/// - Load current value\n/// - Store current value\n///\n/// Atomic primitives are useful when building constructs that need to\n/// communicate or cooperate across multiple threads. In the case of\n/// SwiftNIO this usually involves communicating across multiple event loops.\n///\n/// By necessity, all atomic values are references: after all, it makes no\n/// sense to talk about managing an atomic value when each time it's modified\n/// the thread that modified it gets a local copy!\n@available(*, deprecated, message: \"please use ManagedAtomic from https://github.com/apple/swift-atomics instead\")\npublic final class NIOAtomic<T: NIOAtomicPrimitive> {\n    @usableFromInline\n    typealias Manager = ManagedBufferPointer<Void, T.AtomicWrapper>\n\n    /// Create an atomic object with `value`\n    @inlinable\n    @available(OpenBSD, unavailable, message: \"malloc_size is unavailable.\")\n    public static func makeAtomic(value: T) -> NIOAtomic {\n        let manager = Manager(bufferClass: self, minimumCapacity: 1) { _, _ in }\n        manager.withUnsafeMutablePointerToElements {\n            T.nio_atomic_create_with_existing_storage($0, value)\n        }\n        return manager.buffer as! NIOAtomic<T>\n    }\n\n    /// Atomically compares the value against `expected` and, if they are equal,\n    /// replaces the value with `desired`.\n    ///\n    /// This implementation conforms to C11's `atomic_compare_exchange_strong`. This\n    /// means that the compare-and-swap will always succeed if `expected` is equal to\n    /// value. Additionally, it uses a *sequentially consistent ordering*. For more\n    /// details on atomic memory models, check the documentation for C11's\n    /// `stdatomic.h`.\n    ///\n    /// - Parameter expected: The value that this object must currently hold for the\n    ///     compare-and-swap to succeed.\n    /// - Parameter desired: The new value that this object will hold if the compare\n    ///     succeeds.\n    /// - Returns: `True` if the exchange occurred, or `False` if `expected` did not\n    ///     match the current value and so no exchange occurred.\n    @inlinable\n    public func compareAndExchange(expected: T, desired: T) -> Bool {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {\n            T.nio_atomic_compare_and_exchange($0, expected, desired)\n        }\n    }\n\n    /// Atomically adds `rhs` to this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter rhs: The value to add to this object.\n    /// - Returns: The previous value of this object, before the addition occurred.\n    @inlinable\n    @discardableResult\n    public func add(_ rhs: T) -> T {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {\n            T.nio_atomic_add($0, rhs)\n        }\n    }\n\n    /// Atomically subtracts `rhs` from this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter rhs: The value to subtract from this object.\n    /// - Returns: The previous value of this object, before the subtraction occurred.\n    @inlinable\n    @discardableResult\n    public func sub(_ rhs: T) -> T {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {\n            T.nio_atomic_sub($0, rhs)\n        }\n    }\n\n    /// Atomically exchanges `value` for the current value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter value: The new value to set this object to.\n    /// - Returns: The value previously held by this object.\n    @inlinable\n    public func exchange(with value: T) -> T {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {\n            T.nio_atomic_exchange($0, value)\n        }\n    }\n\n    /// Atomically loads and returns the value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Returns: The value of this object\n    @inlinable\n    public func load() -> T {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {\n            T.nio_atomic_load($0)\n        }\n    }\n\n    /// Atomically replaces the value of this object with `value`.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter value: The new value to set the object to.\n    @inlinable\n    public func store(_ value: T) {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {\n            T.nio_atomic_store($0, value)\n        }\n    }\n\n    deinit {\n        Manager(unsafeBufferObject: self).withUnsafeMutablePointers { headerPtr, elementsPtr in\n            elementsPtr.deinitialize(count: 1)\n            headerPtr.deinitialize(count: 1)\n        }\n    }\n}\n\n@available(*, deprecated)\nextension NIOAtomic: Sendable {}\n"
  },
  {
    "path": "Sources/NIOConcurrencyHelpers/NIOLock.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin)\nimport Darwin\n#elseif os(Windows)\nimport ucrt\nimport WinSDK\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#if canImport(wasi_pthread)\nimport wasi_pthread\n#endif\n#else\n#error(\"The concurrency NIOLock module was unable to identify your C library.\")\n#endif\n\n#if os(Windows)\n@usableFromInline\ntypealias LockPrimitive = SRWLOCK\n#elseif os(FreeBSD) || os(OpenBSD)\n@usableFromInline\ntypealias LockPrimitive = pthread_mutex_t?\n#else\n@usableFromInline\ntypealias LockPrimitive = pthread_mutex_t\n#endif\n\n@usableFromInline\nenum LockOperations: Sendable {}\n\nextension LockOperations {\n    @inlinable\n    static func create(_ mutex: UnsafeMutablePointer<LockPrimitive>) {\n        mutex.assertValidAlignment()\n\n        #if os(Windows)\n        InitializeSRWLock(mutex)\n        #elseif os(FreeBSD) || os(OpenBSD)\n        var attr = pthread_mutexattr_t(bitPattern: 0)\n        pthread_mutexattr_init(&attr)\n        let err = pthread_mutex_init(mutex, &attr)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        var attr = pthread_mutexattr_t()\n        pthread_mutexattr_init(&attr)\n        debugOnly {\n            pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK))\n        }\n\n        let err = pthread_mutex_init(mutex, &attr)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #endif\n    }\n\n    @inlinable\n    static func destroy(_ mutex: UnsafeMutablePointer<LockPrimitive>) {\n        mutex.assertValidAlignment()\n\n        #if os(Windows)\n        // SRWLOCK does not need to be free'd\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_mutex_destroy(mutex)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #endif\n    }\n\n    @inlinable\n    static func lock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {\n        mutex.assertValidAlignment()\n\n        #if os(Windows)\n        AcquireSRWLockExclusive(mutex)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_mutex_lock(mutex)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #endif\n    }\n\n    @inlinable\n    static func unlock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {\n        mutex.assertValidAlignment()\n\n        #if os(Windows)\n        ReleaseSRWLockExclusive(mutex)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_mutex_unlock(mutex)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #endif\n    }\n}\n\n// Tail allocate both the mutex and a generic value using ManagedBuffer.\n// Both the header pointer and the elements pointer are stable for\n// the class's entire lifetime.\n//\n// However, for safety reasons, we elect to place the lock in the \"elements\"\n// section of the buffer instead of the head. The reasoning here is subtle,\n// so buckle in.\n//\n// _As a practical matter_, the implementation of ManagedBuffer ensures that\n// the pointer to the header is stable across the lifetime of the class, and so\n// each time you call `withUnsafeMutablePointers` or `withUnsafeMutablePointerToHeader`\n// the value of the header pointer will be the same. This is because ManagedBuffer uses\n// `Builtin.addressOf` to load the value of the header, and that does ~magic~ to ensure\n// that it does not invoke any weird Swift accessors that might copy the value.\n//\n// _However_, the header is also available via the `.header` field on the ManagedBuffer.\n// This presents a problem! The reason there's an issue is that `Builtin.addressOf` and friends\n// do not interact with Swift's exclusivity model. That is, the various `with` functions do not\n// conceptually trigger a mutating access to `.header`. For elements this isn't a concern because\n// there's literally no other way to perform the access, but for `.header` it's entirely possible\n// to accidentally recursively read it.\n//\n// Our implementation is free from these issues, so we don't _really_ need to worry about it.\n// However, out of an abundance of caution, we store the Value in the header, and the LockPrimitive\n// in the trailing elements. We still don't use `.header`, but it's better to be safe than sorry,\n// and future maintainers will be happier that we were cautious.\n//\n// See also: https://github.com/apple/swift/pull/40000\n@usableFromInline\nfinal class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {\n\n    @inlinable\n    static func create(value: Value) -> Self {\n        let buffer = Self.create(minimumCapacity: 1) { _ in\n            value\n        }\n        // Intentionally using a force cast here to avoid a miss compiliation in 5.10.\n        // This is as fast as an unsafeDownCast since ManagedBuffer is inlined and the optimizer\n        // can eliminate the upcast/downcast pair\n        let storage = buffer as! Self\n\n        storage.withUnsafeMutablePointers { _, lockPtr in\n            LockOperations.create(lockPtr)\n        }\n\n        return storage\n    }\n\n    @inlinable\n    func lock() {\n        self.withUnsafeMutablePointerToElements { lockPtr in\n            LockOperations.lock(lockPtr)\n        }\n    }\n\n    @inlinable\n    func unlock() {\n        self.withUnsafeMutablePointerToElements { lockPtr in\n            LockOperations.unlock(lockPtr)\n        }\n    }\n\n    @inlinable\n    deinit {\n        self.withUnsafeMutablePointerToElements { lockPtr in\n            LockOperations.destroy(lockPtr)\n        }\n    }\n\n    @inlinable\n    func withLockPrimitive<T>(_ body: (UnsafeMutablePointer<LockPrimitive>) throws -> T) rethrows -> T {\n        try self.withUnsafeMutablePointerToElements { lockPtr in\n            try body(lockPtr)\n        }\n    }\n\n    @inlinable\n    func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {\n        try self.withUnsafeMutablePointers { valuePtr, lockPtr in\n            LockOperations.lock(lockPtr)\n            defer { LockOperations.unlock(lockPtr) }\n            return try mutate(&valuePtr.pointee)\n        }\n    }\n}\n\n// This compiler guard is here becaue `ManagedBuffer` is already declaring\n// Sendable unavailability after 6.1, which `LockStorage` inherits.\n#if compiler(<6.2)\n@available(*, unavailable)\nextension LockStorage: Sendable {}\n#endif\n\n/// A threading lock based on `libpthread` instead of `libdispatch`.\n///\n/// - Note: ``NIOLock`` has reference semantics.\n///\n/// This object provides a lock on top of a single `pthread_mutex_t`. This kind\n/// of lock is safe to use with `libpthread`-based threading models, such as the\n/// one used by NIO. On Windows, the lock is based on the substantially similar\n/// `SRWLOCK` type.\npublic struct NIOLock {\n    @usableFromInline\n    internal let _storage: LockStorage<Void>\n\n    /// Create a new lock.\n    @inlinable\n    public init() {\n        self._storage = .create(value: ())\n    }\n\n    /// Acquire the lock.\n    ///\n    /// Whenever possible, consider using `withLock` instead of this method and\n    /// `unlock`, to simplify lock handling.\n    @inlinable\n    public func lock() {\n        self._storage.lock()\n    }\n\n    /// Release the lock.\n    ///\n    /// Whenever possible, consider using `withLock` instead of this method and\n    /// `lock`, to simplify lock handling.\n    @inlinable\n    public func unlock() {\n        self._storage.unlock()\n    }\n\n    @inlinable\n    internal func withLockPrimitive<T>(_ body: (UnsafeMutablePointer<LockPrimitive>) throws -> T) rethrows -> T {\n        try self._storage.withLockPrimitive(body)\n    }\n}\n\nextension NIOLock {\n    /// Acquire the lock for the duration of the given block.\n    ///\n    /// This convenience method should be preferred to `lock` and `unlock` in\n    /// most situations, as it ensures that the lock will be released regardless\n    /// of how `body` exits.\n    ///\n    /// - Parameter body: The block to execute while holding the lock.\n    /// - Returns: The value returned by the block.\n    @inlinable\n    public func withLock<T>(_ body: () throws -> T) rethrows -> T {\n        self.lock()\n        defer {\n            self.unlock()\n        }\n        return try body()\n    }\n\n    @inlinable\n    public func withLockVoid(_ body: () throws -> Void) rethrows {\n        try self.withLock(body)\n    }\n}\n\nextension NIOLock: @unchecked Sendable {}\n\nextension UnsafeMutablePointer {\n    @inlinable\n    func assertValidAlignment() {\n        assert(UInt(bitPattern: self) % UInt(MemoryLayout<Pointee>.alignment) == 0)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOConcurrencyHelpers/NIOLockedValueBox.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Provides locked access to `Value`.\n///\n/// - Note: ``NIOLockedValueBox`` has reference semantics and holds the `Value`\n///         alongside a lock behind a reference.\n///\n/// This is no different than creating a ``Lock`` and protecting all\n/// accesses to a value using the lock. But it's easy to forget to actually\n/// acquire/release the lock in the correct place. ``NIOLockedValueBox`` makes\n/// that much easier.\npublic struct NIOLockedValueBox<Value> {\n\n    @usableFromInline\n    internal let _storage: LockStorage<Value>\n\n    /// Initialize the `Value`.\n    @inlinable\n    public init(_ value: Value) {\n        self._storage = .create(value: value)\n    }\n\n    /// Access the `Value`, allowing mutation of it.\n    @inlinable\n    public func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {\n        try self._storage.withLockedValue(mutate)\n    }\n\n    /// Provides an unsafe view over the lock and its value.\n    ///\n    /// This can be beneficial when you require fine grained control over the lock in some\n    /// situations but don't want lose the benefits of ``withLockedValue(_:)`` in others by\n    /// switching to ``NIOLock``.\n    public var unsafe: Unsafe {\n        Unsafe(_storage: self._storage)\n    }\n\n    /// Provides an unsafe view over the lock and its value.\n    public struct Unsafe {\n        @usableFromInline\n        let _storage: LockStorage<Value>\n\n        /// Manually acquire the lock.\n        @inlinable\n        public func lock() {\n            self._storage.lock()\n        }\n\n        /// Manually release the lock.\n        @inlinable\n        public func unlock() {\n            self._storage.unlock()\n        }\n\n        /// Mutate the value, assuming the lock has been acquired manually.\n        ///\n        /// - Parameter mutate: A closure with scoped access to the value.\n        /// - Returns: The result of the `mutate` closure.\n        @inlinable\n        public func withValueAssumingLockIsAcquired<Result>(\n            _ mutate: (_ value: inout Value) throws -> Result\n        ) rethrows -> Result {\n            try self._storage.withUnsafeMutablePointerToHeader { value in\n                try mutate(&value.pointee)\n            }\n        }\n    }\n}\n\nextension NIOLockedValueBox: @unchecked Sendable where Value: Sendable {}\n\nextension NIOLockedValueBox.Unsafe: @unchecked Sendable where Value: Sendable {}\n"
  },
  {
    "path": "Sources/NIOConcurrencyHelpers/NIOThreadPoolWorkAvailable.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin)\nimport Darwin\n#elseif os(Windows)\nimport ucrt\nimport WinSDK\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#if canImport(wasi_pthread)\nimport wasi_pthread\n#endif\n#else\n#error(\"The NIOThreadPoolWorkAvailable module was unable to identify your C library.\")\n#endif\n\n/// A specialized synchronization primitive for ``NIOThreadPool`` that uses\n/// `pthread_cond_signal` (wake-one) instead of `pthread_cond_broadcast` (wake-all)\n/// when work is enqueued, eliminating the thundering-herd problem.\n///\n/// This type manages a `workAvailable` counter under a mutex, paired with a\n/// condition variable. Threads waiting for work block until `workAvailable > 0`.\n@usableFromInline\npackage struct NIOThreadPoolWorkAvailable: @unchecked Sendable {\n    @usableFromInline\n    final class _Storage {\n        @usableFromInline\n        let lock: NIOLock\n\n        @usableFromInline\n        var workAvailable: Int\n\n        #if os(Windows)\n        @usableFromInline\n        let cond: UnsafeMutablePointer<CONDITION_VARIABLE> =\n            UnsafeMutablePointer.allocate(capacity: 1)\n        #elseif os(FreeBSD) || os(OpenBSD)\n        @usableFromInline\n        let cond: UnsafeMutablePointer<pthread_cond_t?> =\n            UnsafeMutablePointer.allocate(capacity: 1)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        @usableFromInline\n        let cond: UnsafeMutablePointer<pthread_cond_t> =\n            UnsafeMutablePointer.allocate(capacity: 1)\n        #endif\n\n        @usableFromInline\n        init() {\n            self.lock = NIOLock()\n            self.workAvailable = 0\n            #if os(Windows)\n            InitializeConditionVariable(self.cond)\n            #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n            let err = pthread_cond_init(self.cond, nil)\n            precondition(err == 0, \"\\(#function) failed in pthread_cond_init with error \\(err)\")\n            #endif\n        }\n\n        deinit {\n            #if os(Windows)\n            // condition variables do not need to be explicitly destroyed\n            self.cond.deallocate()\n            #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n            let err = pthread_cond_destroy(self.cond)\n            precondition(err == 0, \"\\(#function) failed in pthread_cond_destroy with error \\(err)\")\n            self.cond.deallocate()\n            #endif\n        }\n    }\n\n    @usableFromInline\n    let _storage: _Storage\n\n    @usableFromInline\n    package enum Signal: Sendable {\n        /// No signal after unlock.\n        case none\n        /// Wake one waiting thread (``pthread_cond_signal``).\n        case signalOne\n        /// Wake all waiting threads (``pthread_cond_broadcast``).\n        case broadcastAll\n    }\n\n    @inlinable\n    package init() {\n        self._storage = _Storage()\n    }\n\n    /// Lock, run `body`, apply the returned delta to `workAvailable`,\n    /// unlock, then signal as indicated by the return value.\n    @inlinable\n    package func withLock<Result>(\n        _ body: () -> (workDelta: Int, signal: Signal, result: Result)\n    ) -> Result {\n        self._storage.lock.lock()\n        let (workDelta, signal, result) = body()\n        self._storage.workAvailable += workDelta\n        self._storage.lock.unlock()\n        self._signal(signal)\n        return result\n    }\n\n    /// Lock, run `body`, set `workAvailable` to the returned value if non-nil,\n    /// unlock, then signal as indicated. Use for shutdown where an\n    /// absolute value is needed rather than a delta.\n    @inlinable\n    package func withLockSettingWorkAvailable<Result>(\n        _ body: () -> (workAvailable: Int?, signal: Signal, result: Result)\n    ) -> Result {\n        self._storage.lock.lock()\n        let (workAvailable, signal, result) = body()\n        if let workAvailable = workAvailable {\n            self._storage.workAvailable = workAvailable\n        }\n        self._storage.lock.unlock()\n        self._signal(signal)\n        return result\n    }\n\n    /// Lock, wait while `workAvailable <= 0`, run `body`, apply the\n    /// returned delta to `workAvailable`, unlock, then signal as indicated.\n    @inlinable\n    package func withLockWaitingForWork<Result>(\n        _ body: () -> (workDelta: Int, signal: Signal, result: Result)\n    ) -> Result {\n        self._storage.lock.lock()\n        while self._storage.workAvailable <= 0 {\n            self._storage.lock.withLockPrimitive { mutex in\n                #if os(Windows)\n                let ok = SleepConditionVariableSRW(self._storage.cond, mutex, INFINITE, 0)\n                precondition(\n                    ok,\n                    \"\\(#function) failed in SleepConditionVariableSRW with error \\(GetLastError())\"\n                )\n                #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n                let err = pthread_cond_wait(self._storage.cond, mutex)\n                precondition(err == 0, \"\\(#function) failed in pthread_cond_wait with error \\(err)\")\n                #endif\n            }\n        }\n        let (workDelta, signal, result) = body()\n        self._storage.workAvailable += workDelta\n        self._storage.lock.unlock()\n        self._signal(signal)\n        return result\n    }\n\n    @inlinable\n    func _signal(_ signal: Signal) {\n        switch signal {\n        case .none:\n            break\n        case .signalOne:\n            #if os(Windows)\n            WakeConditionVariable(self._storage.cond)\n            #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n            let err = pthread_cond_signal(self._storage.cond)\n            precondition(err == 0, \"\\(#function) failed in pthread_cond_signal with error \\(err)\")\n            #endif\n        case .broadcastAll:\n            #if os(Windows)\n            WakeAllConditionVariable(self._storage.cond)\n            #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n            let err = pthread_cond_broadcast(self._storage.cond)\n            precondition(err == 0, \"\\(#function) failed in pthread_cond_broadcast with error \\(err)\")\n            #endif\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOConcurrencyHelpers/atomics.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOAtomics\n\n#if canImport(Darwin)\nimport Darwin\nprivate func sys_sched_yield() {\n    pthread_yield_np()\n}\n#elseif os(Windows)\nimport ucrt\nimport WinSDK\nprivate func sys_sched_yield() {\n    Sleep(0)\n}\n#else\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"The concurrency atomics module was unable to identify your C library.\")\n#endif\n\nprivate func sys_sched_yield() {\n    _ = sched_yield()\n}\n#endif\n\n/// An atomic primitive object.\n///\n/// Before using `UnsafeEmbeddedAtomic`, please consider whether your needs can be met by `Atomic` instead.\n/// `UnsafeEmbeddedAtomic` is a value type, but atomics are heap-allocated. Thus, it is only safe to\n/// use `UnsafeEmbeddedAtomic` in situations where the atomic can be guaranteed to be cleaned up (via calling `destroy`).\n/// If you cannot make these guarantees, use `Atomic` instead, which manages this for you.\n///\n/// Atomic objects support a wide range of atomic operations:\n///\n/// - Compare and swap\n/// - Add\n/// - Subtract\n/// - Exchange\n/// - Load current value\n/// - Store current value\n///\n/// Atomic primitives are useful when building constructs that need to\n/// communicate or cooperate across multiple threads. In the case of\n/// SwiftNIO this usually involves communicating across multiple event loops.\n@available(*, deprecated, message: \"please use UnsafeAtomic from https://github.com/apple/swift-atomics instead\")\npublic struct UnsafeEmbeddedAtomic<T: AtomicPrimitive> {\n    @usableFromInline\n    internal let value: OpaquePointer\n\n    /// Create an atomic object with `value`.\n    @inlinable\n    public init(value: T) {\n        self.value = T.atomic_create(value)\n    }\n\n    /// Atomically compares the value against `expected` and, if they are equal,\n    /// replaces the value with `desired`.\n    ///\n    /// This implementation conforms to C11's `atomic_compare_exchange_strong`. This\n    /// means that the compare-and-swap will always succeed if `expected` is equal to\n    /// value. Additionally, it uses a *sequentially consistent ordering*. For more\n    /// details on atomic memory models, check the documentation for C11's\n    /// `stdatomic.h`.\n    ///\n    /// - Parameter expected: The value that this object must currently hold for the\n    ///     compare-and-swap to succeed.\n    /// - Parameter desired: The new value that this object will hold if the compare\n    ///     succeeds.\n    /// - Returns: `True` if the exchange occurred, or `False` if `expected` did not\n    ///     match the current value and so no exchange occurred.\n    @inlinable\n    public func compareAndExchange(expected: T, desired: T) -> Bool {\n        T.atomic_compare_and_exchange(self.value, expected, desired)\n    }\n\n    /// Atomically adds `rhs` to this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter rhs: The value to add to this object.\n    /// - Returns: The previous value of this object, before the addition occurred.\n    @discardableResult\n    @inlinable\n    public func add(_ rhs: T) -> T {\n        T.atomic_add(self.value, rhs)\n    }\n\n    /// Atomically subtracts `rhs` from this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter rhs: The value to subtract from this object.\n    /// - Returns: The previous value of this object, before the subtraction occurred.\n    @discardableResult\n    @inlinable\n    public func sub(_ rhs: T) -> T {\n        T.atomic_sub(self.value, rhs)\n    }\n\n    /// Atomically exchanges `value` for the current value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter value: The new value to set this object to.\n    /// - Returns: The value previously held by this object.\n    @inlinable\n    public func exchange(with value: T) -> T {\n        T.atomic_exchange(self.value, value)\n    }\n\n    /// Atomically loads and returns the value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Returns: The value of this object\n    @inlinable\n    public func load() -> T {\n        T.atomic_load(self.value)\n    }\n\n    /// Atomically replaces the value of this object with `value`.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter value: The new value to set the object to.\n    @inlinable\n    public func store(_ value: T) {\n        T.atomic_store(self.value, value)\n    }\n\n    /// Destroy the atomic value.\n    ///\n    /// This method is the source of the unsafety of this structure. This *must* be called, or you will leak memory with each\n    /// atomic.\n    public func destroy() {\n        T.atomic_destroy(self.value)\n    }\n}\n\n@available(*, deprecated)\nextension UnsafeEmbeddedAtomic: @unchecked Sendable where T: Sendable {}\n\n/// An encapsulation of an atomic primitive object.\n///\n/// Atomic objects support a wide range of atomic operations:\n///\n/// - Compare and swap\n/// - Add\n/// - Subtract\n/// - Exchange\n/// - Load current value\n/// - Store current value\n///\n/// Atomic primitives are useful when building constructs that need to\n/// communicate or cooperate across multiple threads. In the case of\n/// SwiftNIO this usually involves communicating across multiple event loops.\n///\n/// By necessity, all atomic values are references: after all, it makes no\n/// sense to talk about managing an atomic value when each time it's modified\n/// the thread that modified it gets a local copy!\n@available(*, deprecated, message: \"please use ManagedAtomic from https://github.com/apple/swift-atomics instead\")\npublic final class Atomic<T: AtomicPrimitive> {\n    @usableFromInline\n    internal let embedded: UnsafeEmbeddedAtomic<T>\n\n    /// Create an atomic object with `value`.\n    @inlinable\n    public init(value: T) {\n        self.embedded = UnsafeEmbeddedAtomic(value: value)\n    }\n\n    /// Atomically compares the value against `expected` and, if they are equal,\n    /// replaces the value with `desired`.\n    ///\n    /// This implementation conforms to C11's `atomic_compare_exchange_strong`. This\n    /// means that the compare-and-swap will always succeed if `expected` is equal to\n    /// value. Additionally, it uses a *sequentially consistent ordering*. For more\n    /// details on atomic memory models, check the documentation for C11's\n    /// `stdatomic.h`.\n    ///\n    /// - Parameter expected: The value that this object must currently hold for the\n    ///     compare-and-swap to succeed.\n    /// - Parameter desired: The new value that this object will hold if the compare\n    ///     succeeds.\n    /// - Returns: `True` if the exchange occurred, or `False` if `expected` did not\n    ///     match the current value and so no exchange occurred.\n    @inlinable\n    public func compareAndExchange(expected: T, desired: T) -> Bool {\n        self.embedded.compareAndExchange(expected: expected, desired: desired)\n    }\n\n    /// Atomically adds `rhs` to this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter rhs: The value to add to this object.\n    /// - Returns: The previous value of this object, before the addition occurred.\n    @discardableResult\n    @inlinable\n    public func add(_ rhs: T) -> T {\n        self.embedded.add(rhs)\n    }\n\n    /// Atomically subtracts `rhs` from this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter rhs: The value to subtract from this object.\n    /// - Returns: The previous value of this object, before the subtraction occurred.\n    @discardableResult\n    @inlinable\n    public func sub(_ rhs: T) -> T {\n        self.embedded.sub(rhs)\n    }\n\n    /// Atomically exchanges `value` for the current value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter value: The new value to set this object to.\n    /// - Returns: The value previously held by this object.\n    @inlinable\n    public func exchange(with value: T) -> T {\n        self.embedded.exchange(with: value)\n    }\n\n    /// Atomically loads and returns the value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Returns: The value of this object\n    @inlinable\n    public func load() -> T {\n        self.embedded.load()\n    }\n\n    /// Atomically replaces the value of this object with `value`.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - Parameter value: The new value to set the object to.\n    @inlinable\n    public func store(_ value: T) {\n        self.embedded.store(value)\n    }\n\n    deinit {\n        self.embedded.destroy()\n    }\n}\n\n@available(*, deprecated)\nextension Atomic: @unchecked Sendable where T: Sendable {}\n\n/// The protocol that all types that can be made atomic must conform to.\n///\n/// **Do not add conformance to this protocol for arbitrary types**. Only a small range\n/// of types have appropriate atomic operations supported by the CPU, and those types\n/// already have conformances implemented.\n@preconcurrency\npublic protocol AtomicPrimitive {\n    static var atomic_create: @Sendable (Self) -> OpaquePointer { get }\n    static var atomic_destroy: @Sendable (OpaquePointer) -> Void { get }\n    static var atomic_compare_and_exchange: @Sendable (OpaquePointer, Self, Self) -> Bool { get }\n    static var atomic_add: @Sendable (OpaquePointer, Self) -> Self { get }\n    static var atomic_sub: @Sendable (OpaquePointer, Self) -> Self { get }\n    static var atomic_exchange: @Sendable (OpaquePointer, Self) -> Self { get }\n    static var atomic_load: @Sendable (OpaquePointer) -> Self { get }\n    static var atomic_store: @Sendable (OpaquePointer, Self) -> Void { get }\n}\n\nextension Bool: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic__Bool_create\n    public static let atomic_destroy = catmc_atomic__Bool_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic__Bool_compare_and_exchange\n    public static let atomic_add = catmc_atomic__Bool_add\n    public static let atomic_sub = catmc_atomic__Bool_sub\n    public static let atomic_exchange = catmc_atomic__Bool_exchange\n    public static let atomic_load = catmc_atomic__Bool_load\n    public static let atomic_store = catmc_atomic__Bool_store\n}\n\nextension Int8: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_int_least8_t_create\n    public static let atomic_destroy = catmc_atomic_int_least8_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_int_least8_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_int_least8_t_add\n    public static let atomic_sub = catmc_atomic_int_least8_t_sub\n    public static let atomic_exchange = catmc_atomic_int_least8_t_exchange\n    public static let atomic_load = catmc_atomic_int_least8_t_load\n    public static let atomic_store = catmc_atomic_int_least8_t_store\n}\n\nextension UInt8: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_uint_least8_t_create\n    public static let atomic_destroy = catmc_atomic_uint_least8_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_uint_least8_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_uint_least8_t_add\n    public static let atomic_sub = catmc_atomic_uint_least8_t_sub\n    public static let atomic_exchange = catmc_atomic_uint_least8_t_exchange\n    public static let atomic_load = catmc_atomic_uint_least8_t_load\n    public static let atomic_store = catmc_atomic_uint_least8_t_store\n}\n\nextension Int16: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_int_least16_t_create\n    public static let atomic_destroy = catmc_atomic_int_least16_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_int_least16_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_int_least16_t_add\n    public static let atomic_sub = catmc_atomic_int_least16_t_sub\n    public static let atomic_exchange = catmc_atomic_int_least16_t_exchange\n    public static let atomic_load = catmc_atomic_int_least16_t_load\n    public static let atomic_store = catmc_atomic_int_least16_t_store\n}\n\nextension UInt16: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_uint_least16_t_create\n    public static let atomic_destroy = catmc_atomic_uint_least16_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_uint_least16_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_uint_least16_t_add\n    public static let atomic_sub = catmc_atomic_uint_least16_t_sub\n    public static let atomic_exchange = catmc_atomic_uint_least16_t_exchange\n    public static let atomic_load = catmc_atomic_uint_least16_t_load\n    public static let atomic_store = catmc_atomic_uint_least16_t_store\n}\n\nextension Int32: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_int_least32_t_create\n    public static let atomic_destroy = catmc_atomic_int_least32_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_int_least32_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_int_least32_t_add\n    public static let atomic_sub = catmc_atomic_int_least32_t_sub\n    public static let atomic_exchange = catmc_atomic_int_least32_t_exchange\n    public static let atomic_load = catmc_atomic_int_least32_t_load\n    public static let atomic_store = catmc_atomic_int_least32_t_store\n}\n\nextension UInt32: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_uint_least32_t_create\n    public static let atomic_destroy = catmc_atomic_uint_least32_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_uint_least32_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_uint_least32_t_add\n    public static let atomic_sub = catmc_atomic_uint_least32_t_sub\n    public static let atomic_exchange = catmc_atomic_uint_least32_t_exchange\n    public static let atomic_load = catmc_atomic_uint_least32_t_load\n    public static let atomic_store = catmc_atomic_uint_least32_t_store\n}\n\nextension Int64: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_long_long_create\n    public static let atomic_destroy = catmc_atomic_long_long_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_long_long_compare_and_exchange\n    public static let atomic_add = catmc_atomic_long_long_add\n    public static let atomic_sub = catmc_atomic_long_long_sub\n    public static let atomic_exchange = catmc_atomic_long_long_exchange\n    public static let atomic_load = catmc_atomic_long_long_load\n    public static let atomic_store = catmc_atomic_long_long_store\n}\n\nextension UInt64: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_unsigned_long_long_create\n    public static let atomic_destroy = catmc_atomic_unsigned_long_long_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_unsigned_long_long_compare_and_exchange\n    public static let atomic_add = catmc_atomic_unsigned_long_long_add\n    public static let atomic_sub = catmc_atomic_unsigned_long_long_sub\n    public static let atomic_exchange = catmc_atomic_unsigned_long_long_exchange\n    public static let atomic_load = catmc_atomic_unsigned_long_long_load\n    public static let atomic_store = catmc_atomic_unsigned_long_long_store\n}\n\n#if os(Windows)\nextension Int: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_intptr_t_create\n    public static let atomic_destroy = catmc_atomic_intptr_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_intptr_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_intptr_t_add\n    public static let atomic_sub = catmc_atomic_intptr_t_sub\n    public static let atomic_exchange = catmc_atomic_intptr_t_exchange\n    public static let atomic_load = catmc_atomic_intptr_t_load\n    public static let atomic_store = catmc_atomic_intptr_t_store\n}\n\nextension UInt: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_uintptr_t_create\n    public static let atomic_destroy = catmc_atomic_uintptr_t_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_uintptr_t_compare_and_exchange\n    public static let atomic_add = catmc_atomic_uintptr_t_add\n    public static let atomic_sub = catmc_atomic_uintptr_t_sub\n    public static let atomic_exchange = catmc_atomic_uintptr_t_exchange\n    public static let atomic_load = catmc_atomic_uintptr_t_load\n    public static let atomic_store = catmc_atomic_uintptr_t_store\n}\n#else\nextension Int: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_long_create\n    public static let atomic_destroy = catmc_atomic_long_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_long_compare_and_exchange\n    public static let atomic_add = catmc_atomic_long_add\n    public static let atomic_sub = catmc_atomic_long_sub\n    public static let atomic_exchange = catmc_atomic_long_exchange\n    public static let atomic_load = catmc_atomic_long_load\n    public static let atomic_store = catmc_atomic_long_store\n}\n\nextension UInt: AtomicPrimitive {\n    public static let atomic_create = catmc_atomic_unsigned_long_create\n    public static let atomic_destroy = catmc_atomic_unsigned_long_destroy\n    public static let atomic_compare_and_exchange = catmc_atomic_unsigned_long_compare_and_exchange\n    public static let atomic_add = catmc_atomic_unsigned_long_add\n    public static let atomic_sub = catmc_atomic_unsigned_long_sub\n    public static let atomic_exchange = catmc_atomic_unsigned_long_exchange\n    public static let atomic_load = catmc_atomic_unsigned_long_load\n    public static let atomic_store = catmc_atomic_unsigned_long_store\n}\n#endif\n\n/// `AtomicBox` is a heap-allocated box which allows lock-free access to an instance of a Swift class.\n///\n/// - warning: The use of `AtomicBox` should be avoided because it requires an implementation of a spin-lock\n///            (more precisely a CAS loop) to operate correctly.\n@available(\n    *,\n    deprecated,\n    message: \"AtomicBox is deprecated without replacement because the original implementation doesn't work.\"\n)\n@available(OpenBSD, unavailable, message: \"malloc_size is unavailable.\")\npublic final class AtomicBox<T: AnyObject> {\n    private let storage: NIOAtomic<UInt>\n\n    public init(value: T) {\n        let ptr = Unmanaged<T>.passRetained(value)\n        self.storage = NIOAtomic.makeAtomic(value: UInt(bitPattern: ptr.toOpaque()))\n    }\n\n    deinit {\n        let oldPtrBits = self.storage.exchange(with: 0xdeadbee)\n        let oldPtr = Unmanaged<T>.fromOpaque(UnsafeRawPointer(bitPattern: oldPtrBits)!)\n        oldPtr.release()\n    }\n\n    /// Atomically compares the value against `expected` and, if they are equal,\n    /// replaces the value with `desired`.\n    ///\n    /// This implementation conforms to C11's `atomic_compare_exchange_strong`. This\n    /// means that the compare-and-swap will always succeed if `expected` is equal to\n    /// value. Additionally, it uses a *sequentially consistent ordering*. For more\n    /// details on atomic memory models, check the documentation for C11's\n    /// `stdatomic.h`.\n    ///\n    ///\n    /// - warning: The implementation of `exchange` contains a _Compare and Exchange loop_, ie. it may busy wait with\n    ///            100% CPU load.\n    ///\n    /// - Parameter expected: The value that this object must currently hold for the\n    ///     compare-and-swap to succeed.\n    /// - Parameter desired: The new value that this object will hold if the compare\n    ///     succeeds.\n    /// - Returns: `True` if the exchange occurred, or `False` if `expected` did not\n    ///     match the current value and so no exchange occurred.\n    public func compareAndExchange(expected: T, desired: T) -> Bool {\n        withExtendedLifetime(desired) {\n            let expectedPtr = Unmanaged<T>.passUnretained(expected)\n            let desiredPtr = Unmanaged<T>.passUnretained(desired)\n            let expectedPtrBits = UInt(bitPattern: expectedPtr.toOpaque())\n            let desiredPtrBits = UInt(bitPattern: desiredPtr.toOpaque())\n\n            while true {\n                if self.storage.compareAndExchange(expected: expectedPtrBits, desired: desiredPtrBits) {\n                    if desiredPtrBits != expectedPtrBits {\n                        _ = desiredPtr.retain()\n                        expectedPtr.release()\n                    }\n                    return true\n                } else {\n                    let currentPtrBits = self.storage.load()\n                    if currentPtrBits == 0 || currentPtrBits == expectedPtrBits {\n                        sys_sched_yield()\n                        continue\n                    } else {\n                        return false\n                    }\n                }\n            }\n        }\n    }\n\n    /// Atomically exchanges `value` for the current value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - warning: The implementation of `exchange` contains a _Compare and Exchange loop_, ie. it may busy wait with\n    ///            100% CPU load.\n    ///\n    /// - Parameter value: The new value to set this object to.\n    /// - Returns: The value previously held by this object.\n    public func exchange(with value: T) -> T {\n        let newPtr = Unmanaged<T>.passRetained(value)\n        let newPtrBits = UInt(bitPattern: newPtr.toOpaque())\n\n        // step 1: We need to actually CAS loop here to swap out a non-0 value with the new one.\n        var oldPtrBits: UInt = 0\n        while true {\n            let speculativeVal = self.storage.load()\n            guard speculativeVal != 0 else {\n                sys_sched_yield()\n                continue\n            }\n            if self.storage.compareAndExchange(expected: speculativeVal, desired: newPtrBits) {\n                oldPtrBits = speculativeVal\n                break\n            }\n        }\n\n        // step 2: After having gained 'ownership' of the old value, we can release the Unmanaged.\n        let oldPtr = Unmanaged<T>.fromOpaque(UnsafeRawPointer(bitPattern: oldPtrBits)!)\n        return oldPtr.takeRetainedValue()\n    }\n\n    /// Atomically loads and returns the value of this object.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - warning: The implementation of `exchange` contains a _Compare and Exchange loop_, ie. it may busy wait with\n    ///            100% CPU load.\n    ///\n    /// - Returns: The value of this object\n    public func load() -> T {\n        // step 1: We need to gain ownership of the value by successfully swapping 0 (marker value) in.\n        var ptrBits: UInt = 0\n        while true {\n            let speculativeVal = self.storage.load()\n            guard speculativeVal != 0 else {\n                sys_sched_yield()\n                continue\n            }\n            if self.storage.compareAndExchange(expected: speculativeVal, desired: 0) {\n                ptrBits = speculativeVal\n                break\n            }\n        }\n\n        // step 2: We now consumed a +1'd version of val, so we have all the time in the world to retain it.\n        let ptr = Unmanaged<T>.fromOpaque(UnsafeRawPointer(bitPattern: ptrBits)!)\n        let value = ptr.takeUnretainedValue()\n\n        // step 3: Now, let's exchange it back into the store\n        let casWorked = self.storage.compareAndExchange(expected: 0, desired: ptrBits)\n        precondition(casWorked)  // this _has_ to work because `0` means we own it exclusively.\n        return value\n    }\n\n    /// Atomically replaces the value of this object with `value`.\n    ///\n    /// This implementation uses a *relaxed* memory ordering. This guarantees nothing\n    /// more than that this operation is atomic: there is no guarantee that any other\n    /// event will be ordered before or after this one.\n    ///\n    /// - warning: The implementation of `exchange` contains a _Compare and Exchange loop_, ie. it may busy wait with\n    ///            100% CPU load.\n    ///\n    /// - Parameter value: The new value to set the object to.\n    public func store(_ value: T) {\n        _ = self.exchange(with: value)\n    }\n}\n\n@available(*, deprecated)\n@available(OpenBSD, unavailable, message: \"malloc_size is unavailable.\")\nextension AtomicBox: @unchecked Sendable where T: Sendable {}\n"
  },
  {
    "path": "Sources/NIOConcurrencyHelpers/lock.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin)\nimport Darwin\n#elseif os(Windows)\nimport ucrt\nimport WinSDK\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#if canImport(wasi_pthread)\nimport wasi_pthread\n#endif\n#else\n#error(\"The concurrency lock module was unable to identify your C library.\")\n#endif\n\n/// A threading lock based on `libpthread` instead of `libdispatch`.\n///\n/// This object provides a lock on top of a single `pthread_mutex_t`. This kind\n/// of lock is safe to use with `libpthread`-based threading models, such as the\n/// one used by NIO. On Windows, the lock is based on the substantially similar\n/// `SRWLOCK` type.\n@available(*, deprecated, renamed: \"NIOLock\")\npublic final class Lock {\n    #if os(Windows)\n    fileprivate let mutex: UnsafeMutablePointer<SRWLOCK> =\n        UnsafeMutablePointer.allocate(capacity: 1)\n    #elseif os(FreeBSD) || os(OpenBSD)\n    fileprivate let mutex: UnsafeMutablePointer<pthread_mutex_t?> =\n        UnsafeMutablePointer.allocate(capacity: 1)\n    #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n    fileprivate let mutex: UnsafeMutablePointer<pthread_mutex_t> =\n        UnsafeMutablePointer.allocate(capacity: 1)\n    #endif\n\n    /// Create a new lock.\n    public init() {\n        #if os(Windows)\n        InitializeSRWLock(self.mutex)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        #if os(FreeBSD) || os(OpenBSD)\n        var attr = pthread_mutexattr_t(bitPattern: 0)\n        #else\n        var attr = pthread_mutexattr_t()\n        #endif\n        var err = pthread_mutexattr_init(&attr)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutexattr_init with error \\(err)\")\n        debugOnly {\n            #if os(FreeBSD) || os(OpenBSD)\n            pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK.rawValue))\n            #else\n            pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK))\n            #endif\n        }\n\n        err = pthread_mutex_init(self.mutex, &attr)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        // `pthread_mutexattr_t` only lives during init; destroy here instead of deinit.\n        let attrDestroyErr = pthread_mutexattr_destroy(&attr)\n        precondition(\n            attrDestroyErr == 0,\n            \"\\(#function) failed in pthread_mutexattr_destroy with error \\(attrDestroyErr)\"\n        )\n        #endif\n    }\n\n    deinit {\n        #if os(Windows)\n        mutex.deallocate()\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_mutex_destroy(self.mutex)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        mutex.deallocate()\n        #endif\n    }\n\n    /// Acquire the lock.\n    ///\n    /// Whenever possible, consider using `withLock` instead of this method and\n    /// `unlock`, to simplify lock handling.\n    public func lock() {\n        #if os(Windows)\n        AcquireSRWLockExclusive(self.mutex)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_mutex_lock(self.mutex)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #endif\n    }\n\n    /// Release the lock.\n    ///\n    /// Whenever possible, consider using `withLock` instead of this method and\n    /// `lock`, to simplify lock handling.\n    public func unlock() {\n        #if os(Windows)\n        ReleaseSRWLockExclusive(self.mutex)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_mutex_unlock(self.mutex)\n        precondition(err == 0, \"\\(#function) failed in pthread_mutex with error \\(err)\")\n        #endif\n    }\n\n    /// Acquire the lock for the duration of the given block.\n    ///\n    /// This convenience method should be preferred to `lock` and `unlock` in\n    /// most situations, as it ensures that the lock will be released regardless\n    /// of how `body` exits.\n    ///\n    /// - Parameter body: The block to execute while holding the lock.\n    /// - Returns: The value returned by the block.\n    @inlinable\n    public func withLock<T>(_ body: () throws -> T) rethrows -> T {\n        self.lock()\n        defer {\n            self.unlock()\n        }\n        return try body()\n    }\n\n    // specialise Void return (for performance)\n    @inlinable\n    public func withLockVoid(_ body: () throws -> Void) rethrows {\n        try self.withLock(body)\n    }\n}\n\n/// A `Lock` with a built-in state variable.\n///\n/// This class provides a convenience addition to `Lock`: it provides the ability to wait\n/// until the state variable is set to a specific value to acquire the lock.\npublic final class ConditionLock<T: Equatable> {\n    private var _value: T\n    private let mutex: NIOLock\n    #if os(Windows)\n    private let cond: UnsafeMutablePointer<CONDITION_VARIABLE> =\n        UnsafeMutablePointer.allocate(capacity: 1)\n    #elseif os(FreeBSD) || os(OpenBSD)\n    private let cond: UnsafeMutablePointer<pthread_cond_t?> =\n        UnsafeMutablePointer.allocate(capacity: 1)\n    #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n    private let cond: UnsafeMutablePointer<pthread_cond_t> =\n        UnsafeMutablePointer.allocate(capacity: 1)\n    #endif\n\n    /// Create the lock, and initialize the state variable to `value`.\n    ///\n    /// - Parameter value: The initial value to give the state variable.\n    public init(value: T) {\n        self._value = value\n        self.mutex = NIOLock()\n        #if os(Windows)\n        InitializeConditionVariable(self.cond)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_cond_init(self.cond, nil)\n        precondition(err == 0, \"\\(#function) failed in pthread_cond with error \\(err)\")\n        #endif\n    }\n\n    deinit {\n        #if os(Windows)\n        // condition variables do not need to be explicitly destroyed\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_cond_destroy(self.cond)\n        precondition(err == 0, \"\\(#function) failed in pthread_cond with error \\(err)\")\n        self.cond.deallocate()\n        #endif\n    }\n\n    /// Acquire the lock, regardless of the value of the state variable.\n    public func lock() {\n        self.mutex.lock()\n    }\n\n    /// Release the lock, regardless of the value of the state variable.\n    public func unlock() {\n        self.mutex.unlock()\n    }\n\n    /// The value of the state variable.\n    ///\n    /// Obtaining the value of the state variable requires acquiring the lock.\n    /// This means that it is not safe to access this property while holding the\n    /// lock: it is only safe to use it when not holding it.\n    public var value: T {\n        self.lock()\n        defer {\n            self.unlock()\n        }\n        return self._value\n    }\n\n    /// Acquire the lock when the state variable is equal to `wantedValue`.\n    ///\n    /// - Parameter wantedValue: The value to wait for the state variable\n    ///     to have before acquiring the lock.\n    public func lock(whenValue wantedValue: T) {\n        self.lock()\n        while true {\n            if self._value == wantedValue {\n                break\n            }\n            self.mutex.withLockPrimitive { mutex in\n                #if os(Windows)\n                let result = SleepConditionVariableSRW(self.cond, mutex, INFINITE, 0)\n                precondition(result, \"\\(#function) failed in SleepConditionVariableSRW with error \\(GetLastError())\")\n                #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n                let err = pthread_cond_wait(self.cond, mutex)\n                precondition(err == 0, \"\\(#function) failed in pthread_cond with error \\(err)\")\n                #endif\n            }\n        }\n    }\n\n    /// Acquire the lock when the state variable is equal to `wantedValue`,\n    /// waiting no more than `timeoutSeconds` seconds.\n    ///\n    /// - Parameter wantedValue: The value to wait for the state variable\n    ///     to have before acquiring the lock.\n    /// - Parameter timeoutSeconds: The number of seconds to wait to acquire\n    ///     the lock before giving up.\n    /// - Returns: `true` if the lock was acquired, `false` if the wait timed out.\n    public func lock(whenValue wantedValue: T, timeoutSeconds: Double) -> Bool {\n        precondition(timeoutSeconds >= 0)\n\n        #if os(Windows)\n        var dwMilliseconds: DWORD = DWORD(timeoutSeconds * 1000)\n\n        self.lock()\n        while true {\n            if self._value == wantedValue {\n                return true\n            }\n\n            let dwWaitStart = timeGetTime()\n            let result = self.mutex.withLockPrimitive { mutex in\n                SleepConditionVariableSRW(self.cond, mutex, dwMilliseconds, 0)\n            }\n            if !result {\n                let dwError = GetLastError()\n                if dwError == ERROR_TIMEOUT {\n                    self.unlock()\n                    return false\n                }\n                fatalError(\"SleepConditionVariableSRW: \\(dwError)\")\n            }\n            // NOTE: this may be a spurious wakeup, adjust the timeout accordingly\n            dwMilliseconds = dwMilliseconds - (timeGetTime() - dwWaitStart)\n        }\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let nsecPerSec: Int64 = 1_000_000_000\n        self.lock()\n        // the timeout as a (seconds, nano seconds) pair\n        let timeoutNS = Int64(timeoutSeconds * Double(nsecPerSec))\n\n        var curTime = timeval()\n        gettimeofday(&curTime, nil)\n\n        let allNSecs: Int64 = timeoutNS + Int64(curTime.tv_usec) * 1000\n        let tvSec = curTime.tv_sec + time_t((allNSecs / nsecPerSec))\n\n        var timeoutAbs = timespec(\n            tv_sec: tvSec,\n            tv_nsec: Int(allNSecs % nsecPerSec)\n        )\n        assert(timeoutAbs.tv_nsec >= 0 && timeoutAbs.tv_nsec < Int(nsecPerSec))\n        assert(timeoutAbs.tv_sec >= curTime.tv_sec)\n        return self.mutex.withLockPrimitive { mutex -> Bool in\n            while true {\n                if self._value == wantedValue {\n                    return true\n                }\n                switch pthread_cond_timedwait(self.cond, mutex, &timeoutAbs) {\n                case 0:\n                    continue\n                case ETIMEDOUT:\n                    self.unlock()\n                    return false\n                case let e:\n                    fatalError(\"caught error \\(e) when calling pthread_cond_timedwait\")\n                }\n            }\n        }\n        #else\n        return true\n        #endif\n    }\n\n    /// Release the lock, setting the state variable to `newValue`.\n    ///\n    /// - Parameter newValue: The value to give to the state variable when we\n    ///     release the lock.\n    public func unlock(withValue newValue: T) {\n        self._value = newValue\n        self.unlock()\n        #if os(Windows)\n        WakeAllConditionVariable(self.cond)\n        #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))\n        let err = pthread_cond_broadcast(self.cond)\n        precondition(err == 0, \"\\(#function) failed in pthread_cond with error \\(err)\")\n        #endif\n    }\n}\n\n/// A utility function that runs the body code only in debug builds, without\n/// emitting compiler warnings.\n///\n/// This is currently the only way to do this in Swift: see\n/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.\n@inlinable\ninternal func debugOnly(_ body: () -> Void) {\n    assert(\n        {\n            body()\n            return true\n        }()\n    )\n}\n\n@available(*, deprecated)\nextension Lock: @unchecked Sendable {}\nextension ConditionLock: @unchecked Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/AddressedEnvelope.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A data structure for processing addressed datagrams, such as those used by UDP.\n///\n/// The AddressedEnvelope is used extensively on `DatagramChannel`s in order to keep track\n/// of source or destination address metadata: that is, where some data came from or where\n/// it is going.\npublic struct AddressedEnvelope<DataType> {\n    public var remoteAddress: SocketAddress\n    public var data: DataType\n    /// Any metadata associated with this `AddressedEnvelope`\n    public var metadata: Metadata? = nil\n\n    public init(remoteAddress: SocketAddress, data: DataType) {\n        self.remoteAddress = remoteAddress\n        self.data = data\n    }\n\n    public init(remoteAddress: SocketAddress, data: DataType, metadata: Metadata?) {\n        self.remoteAddress = remoteAddress\n        self.data = data\n        self.metadata = metadata\n    }\n\n    /// Any metadata associated with an `AddressedEnvelope`\n    public struct Metadata: Hashable, Sendable {\n        /// Details of any congestion state.\n        public var ecnState: NIOExplicitCongestionNotificationState\n        public var packetInfo: NIOPacketInfo?\n        /// The UDP segment size for Generic Segmentation Offload (GSO).\n        ///\n        /// When set, this enables per-message GSO, allowing the kernel to split this datagram\n        /// into multiple segments of the specified size. The maximum segment size is platform-dependent\n        /// and can be queried via `System.udpMaxSegments`.\n        ///\n        /// On non-Linux platforms, writes with a non-nil `segmentSize` will fail with\n        /// `ChannelError.operationUnsupported`. The error will be propagated to the write promise\n        /// (if attached).\n        public var segmentSize: Int?\n\n        public init(ecnState: NIOExplicitCongestionNotificationState) {\n            self.ecnState = ecnState\n            self.packetInfo = nil\n            self.segmentSize = nil\n        }\n\n        public init(ecnState: NIOExplicitCongestionNotificationState, packetInfo: NIOPacketInfo?) {\n            self.ecnState = ecnState\n            self.packetInfo = packetInfo\n            self.segmentSize = nil\n        }\n\n        public init(\n            ecnState: NIOExplicitCongestionNotificationState,\n            packetInfo: NIOPacketInfo?,\n            segmentSize: Int?\n        ) {\n            self.ecnState = ecnState\n            self.packetInfo = packetInfo\n            self.segmentSize = segmentSize\n        }\n    }\n}\n\nextension AddressedEnvelope: CustomStringConvertible {\n    public var description: String {\n        \"AddressedEnvelope { remoteAddress: \\(self.remoteAddress), data: \\(self.data) }\"\n    }\n}\n\nextension AddressedEnvelope: Equatable where DataType: Equatable {}\n\nextension AddressedEnvelope: Hashable where DataType: Hashable {}\n\nextension AddressedEnvelope: Sendable where DataType: Sendable {}\n\n/// Possible Explicit Congestion Notification States\npublic enum NIOExplicitCongestionNotificationState: Hashable, Sendable {\n    /// Non-ECN Capable Transport.\n    case transportNotCapable\n    /// ECN Capable Transport (flag 0).\n    case transportCapableFlag0\n    /// ECN Capable Transport (flag 1).\n    case transportCapableFlag1\n    /// Congestion Experienced.\n    case congestionExperienced\n}\n\npublic struct NIOPacketInfo: Hashable, Sendable {\n    public var destinationAddress: SocketAddress\n    public var interfaceIndex: Int\n\n    public init(destinationAddress: SocketAddress, interfaceIndex: Int) {\n        self.destinationAddress = destinationAddress\n        self.interfaceIndex = interfaceIndex\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncAwaitSupport.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if DEBUG\n/// A Swift Continuation that behaves like a `CheckedContinuation` in Debug mode\n/// and like a `UnsafeContinuation` in release mode.\n///\n/// - Note: Only use this for code paths that have proven to be safe for at least one year.\n///         All usages must have a comment that states, why it is safe to use NIOUnsafeContinuation.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@usableFromInline\ntypealias NIOUnsafeContinuation<Success, Failure: Error> = CheckedContinuation<Success, Failure>\n\n#if compiler(>=6.1)\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@inlinable\nfunc withNIOUnsafeThrowingContinuation<T>(\n    isolation: isolated (any Actor)? = #isolation,\n    _ fn: (NIOUnsafeContinuation<T, any Error>) -> Void\n) async throws -> sending T {\n    try await withCheckedThrowingContinuation(isolation: isolation, fn)\n}\n#else\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@inlinable\nfunc withNIOUnsafeThrowingContinuation<T: Sendable>(\n    isolation: isolated (any Actor)? = #isolation,\n    _ fn: (NIOUnsafeContinuation<T, any Error>) -> Void\n) async throws -> T {\n    try await withCheckedThrowingContinuation(isolation: isolation, fn)\n}\n#endif  // compiler 6.0\n#else\n/// A Swift Continuation that behaves like a `CheckedContinuation` in Debug mode\n/// and like a `UnsafeContinuation` in release mode.\n///\n/// - Note: Only use this for code paths that have proven to be safe for at least one year.\n///         All usages must have a comment that states, why it is safe to use NIOUnsafeContinuation.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@usableFromInline\ntypealias NIOUnsafeContinuation<Success, Failure: Error> = UnsafeContinuation<Success, Failure>\n\n#if compiler(>=6.1)\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@inlinable\nfunc withNIOUnsafeThrowingContinuation<T>(\n    isolation: isolated (any Actor)? = #isolation,\n    _ fn: (NIOUnsafeContinuation<T, any Error>) -> Void\n) async throws -> sending T {\n    try await withUnsafeThrowingContinuation(isolation: isolation, fn)\n}\n#else\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@inlinable\nfunc withNIOUnsafeThrowingContinuation<T: Sendable>(\n    isolation: isolated (any Actor)? = #isolation,\n    _ fn: (NIOUnsafeContinuation<T, any Error>) -> Void\n) async throws -> T {\n    try await withUnsafeThrowingContinuation(isolation: isolation, fn)\n}\n#endif  // compiler 6.0\n#endif  // release build\n\nextension EventLoopFuture {\n    /// Get the value/error from an `EventLoopFuture` in an `async` context.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// This function can be used to bridge an `EventLoopFuture` into the `async` world. Ie. if you're in an `async`\n    /// function and want to get the result of this future.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @preconcurrency\n    @inlinable\n    public func get() async throws -> Value where Value: Sendable {\n        try await withUnsafeThrowingContinuation { (cont: UnsafeContinuation<UnsafeTransfer<Value>, Error>) in\n            self.whenComplete { result in\n                switch result {\n                case .success(let value):\n                    cont.resume(returning: UnsafeTransfer(value))\n                case .failure(let error):\n                    cont.resume(throwing: error)\n                }\n            }\n        }.wrappedValue\n    }\n}\n\n#if canImport(Dispatch)\nextension EventLoopGroup {\n    /// Shuts down the event loop gracefully.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    public func shutdownGracefully() async throws {\n        try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in\n            self.shutdownGracefully { error in\n                if let error = error {\n                    cont.resume(throwing: error)\n                } else {\n                    cont.resume()\n                }\n            }\n        }\n    }\n}\n#endif\n\nextension EventLoopPromise {\n    /// Complete a future with the result (or error) of the `async` function `body`.\n    ///\n    /// This function can be used to bridge the `async` world into an `EventLoopPromise`.\n    ///\n    /// - Parameters:\n    ///   - body: The `async` function to run.\n    /// - Returns: A `Task` which was created to `await` the `body`.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @discardableResult\n    @preconcurrency\n    @inlinable\n    public func completeWithTask(\n        _ body: @escaping @Sendable () async throws -> Value\n    ) -> Task<Void, Never> where Value: Sendable {\n        Task {\n            do {\n                let value = try await body()\n                self.succeed(value)\n            } catch {\n                self.fail(error)\n            }\n        }\n    }\n}\n\nextension Channel {\n    /// Shortcut for calling `write` and `flush`.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    @preconcurrency\n    public func writeAndFlush<T: Sendable>(_ data: T) async throws {\n        try await self.writeAndFlush(data).get()\n    }\n\n    /// Set `option` to `value` on this `Channel`.\n    /// - Parameters:\n    ///   - option: The option to set.\n    ///   - value: The new value of the option.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    public func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) async throws {\n        try await self.setOption(option, value: value).get()\n    }\n\n    /// Get the value of `option` for this `Channel`.\n    /// - Parameter option: The option to get.\n    /// - Returns: The value of the option.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    public func getOption<Option: ChannelOption>(_ option: Option) async throws -> Option.Value {\n        try await self.getOption(option).get()\n    }\n}\n\nextension ChannelOutboundInvoker {\n    /// Register on an `EventLoop` and so have all its IO handled.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func register(file: StaticString = #fileID, line: UInt = #line) async throws {\n        try await self.register(file: file, line: line).get()\n    }\n\n    /// Bind to a `SocketAddress`.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - address: the `SocketAddress` to which we should bind the `Channel`.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind(to address: SocketAddress, file: StaticString = #fileID, line: UInt = #line) async throws {\n        try await self.bind(to: address, file: file, line: line).get()\n    }\n\n    /// Connect to a `SocketAddress`.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - address: the `SocketAddress` to which we should connect the `Channel`.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect(to address: SocketAddress, file: StaticString = #fileID, line: UInt = #line) async throws {\n        try await self.connect(to: address, file: file, line: line).get()\n    }\n\n    /// Shortcut for calling `write` and `flush`.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable: avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func writeAndFlush(_ data: NIOAny, file: StaticString = #fileID, line: UInt = #line) async throws {\n        try await self.writeAndFlush(data, file: file, line: line).get()\n    }\n\n    /// Close the `Channel` and so the connection if one exists.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - mode: the `CloseMode` that is used\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func close(mode: CloseMode = .all, file: StaticString = #fileID, line: UInt = #line) async throws {\n        try await self.close(mode: mode, file: file, line: line).get()\n    }\n\n    /// Trigger a custom user outbound event which will flow through the `ChannelPipeline`.\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    /// - Parameters:\n    ///   - event: the event itself.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @preconcurrency\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func triggerUserOutboundEvent(\n        _ event: Any & Sendable,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) async throws {\n        try await self.triggerUserOutboundEvent(event, file: file, line: line).get()\n    }\n}\n\nextension ChannelPipeline {\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @preconcurrency\n    public func addHandler(\n        _ handler: ChannelHandler & Sendable,\n        name: String? = nil,\n        position: ChannelPipeline.Position = .last\n    ) async throws {\n        try await self.addHandler(handler, name: name, position: position).get()\n    }\n\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @preconcurrency\n    public func removeHandler(_ handler: RemovableChannelHandler & Sendable) async throws {\n        try await self.removeHandler(handler).get()\n    }\n\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func removeHandler(name: String) async throws {\n        try await self.removeHandler(name: name).get()\n    }\n\n    ///\n    /// - warning: This method currently violates Structured Concurrency because cancellation isn't respected.\n    ///\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @available(\n        *,\n        deprecated,\n        message: \"Use .syncOperations.removeHandler(context:) instead, this method is not Sendable-safe.\"\n    )\n    public func removeHandler(context: ChannelHandlerContext) async throws {\n        try await self.removeHandler(context: context).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @available(\n        *,\n        deprecated,\n        message:\n            \"ChannelHandlerContext is not Sendable and it is therefore not safe to be used outside of its EventLoop\"\n    )\n\n    @preconcurrency\n    public func context(handler: ChannelHandler & Sendable) async throws -> ChannelHandlerContext {\n        try await self.context(handler: handler).map { UnsafeTransfer($0) }.get().wrappedValue\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @available(\n        *,\n        deprecated,\n        message:\n            \"ChannelHandlerContext is not Sendable and it is therefore not safe to be used outside of its EventLoop\"\n    )\n    public func context(name: String) async throws -> ChannelHandlerContext {\n        try await self.context(name: name).map { UnsafeTransfer($0) }.get().wrappedValue\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @available(\n        *,\n        deprecated,\n        message:\n            \"ChannelHandlerContext is not Sendable and it is therefore not safe to be used outside of its EventLoop\"\n    )\n    @inlinable\n    @preconcurrency\n    public func context<Handler: ChannelHandler & _NIOCoreSendableMetatype>(\n        handlerType: Handler.Type\n    ) async throws -> ChannelHandlerContext {\n        try await self.context(handlerType: handlerType).map { UnsafeTransfer($0) }.get().wrappedValue\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @preconcurrency\n    public func addHandlers(\n        _ handlers: [ChannelHandler & Sendable],\n        position: ChannelPipeline.Position = .last\n    ) async throws {\n        try await self.addHandlers(handlers, position: position).map { UnsafeTransfer($0) }.get().wrappedValue\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @preconcurrency\n    public func addHandlers(\n        _ handlers: (ChannelHandler & Sendable)...,\n        position: ChannelPipeline.Position = .last\n    ) async throws {\n        try await self.addHandlers(handlers, position: position)\n    }\n}\n\n/// An error that is thrown when the number of bytes in an AsyncSequence exceeds the limit.\n///\n/// When collecting the bytes from an AsyncSequence, there is a limit up to where the content\n/// exceeds a certain threshold beyond which the content isn't matching an expected reasonable\n/// size to be processed. This error is generally thrown when it is discovered that there are more\n/// more bytes in a sequence than what was specified as the maximum. It could be that this upTo\n/// limit should be increased, or that the sequence has unexpected content in it.\npublic struct NIOTooManyBytesError: Error {\n    /// Current limit on the maximum number of bytes in the sequence\n    public var maxBytes: Int?\n\n    @available(\n        *,\n        deprecated,\n        message: \"Construct the NIOTooManyBytesError with the maxBytes limit that triggered this error\"\n    )\n    public init() {\n        self.maxBytes = nil\n    }\n\n    public init(maxBytes: Int) {\n        self.maxBytes = maxBytes\n    }\n}\n\nextension NIOTooManyBytesError: Equatable {\n    public static func == (lhs: NIOTooManyBytesError, rhs: NIOTooManyBytesError) -> Bool {\n        // Equality of the maxBytes isn't of consequence\n        true\n    }\n}\n\nextension NIOTooManyBytesError: Hashable {\n    public func hash(into hasher: inout Hasher) {\n        // All errors of this type hash to the same value since maxBytes isn't of consequence\n        hasher.combine(7)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension AsyncSequence where Element: RandomAccessCollection, Element.Element == UInt8 {\n    /// Accumulates an `AsyncSequence` of `RandomAccessCollection`s into a single `accumulationBuffer`.\n    /// - Parameters:\n    ///   - accumulationBuffer: buffer to write all the elements of `self` into\n    ///   - maxBytes: The maximum number of bytes this method is allowed to write into `accumulationBuffer`\n    /// - Throws: `NIOTooManyBytesError` if the the sequence contains more than `maxBytes`.\n    /// Note that previous elements of `self` might already be write to `accumulationBuffer`.\n    @inlinable\n    public func collect(\n        upTo maxBytes: Int,\n        into accumulationBuffer: inout ByteBuffer\n    ) async throws {\n        precondition(maxBytes >= 0, \"`maxBytes` must be greater than or equal to zero\")\n        var bytesRead = 0\n        for try await fragment in self {\n            bytesRead += fragment.count\n            guard bytesRead <= maxBytes else {\n                throw NIOTooManyBytesError(maxBytes: maxBytes)\n            }\n            accumulationBuffer.writeBytes(fragment)\n        }\n    }\n\n    /// Accumulates an `AsyncSequence` of `RandomAccessCollection`s into a single ``ByteBuffer``.\n    /// - Parameters:\n    ///   - maxBytes: The maximum number of bytes this method is allowed to accumulate\n    ///   - allocator: Allocator used for allocating the result `ByteBuffer`\n    /// - Throws: `NIOTooManyBytesError` if the the sequence contains more than `maxBytes`.\n    @inlinable\n    public func collect(\n        upTo maxBytes: Int,\n        using allocator: ByteBufferAllocator\n    ) async throws -> ByteBuffer {\n        precondition(maxBytes >= 0, \"`maxBytes` must be greater than or equal to zero\")\n        var accumulationBuffer = allocator.buffer(capacity: Swift.min(maxBytes, 1024))\n        try await self.collect(upTo: maxBytes, into: &accumulationBuffer)\n        return accumulationBuffer\n    }\n}\n\n// MARK: optimised methods for ByteBuffer\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension AsyncSequence where Element == ByteBuffer {\n    /// Accumulates an `AsyncSequence` of ``ByteBuffer``s into a single `accumulationBuffer`.\n    /// - Parameters:\n    ///   - accumulationBuffer: buffer to write all the elements of `self` into\n    ///   - maxBytes: The maximum number of bytes this method is allowed to write into `accumulationBuffer`\n    /// - Throws: ``NIOTooManyBytesError`` if the the sequence contains more than `maxBytes`.\n    /// Note that previous elements of `self` might be already write to `accumulationBuffer`.\n    @inlinable\n    public func collect(\n        upTo maxBytes: Int,\n        into accumulationBuffer: inout ByteBuffer\n    ) async throws {\n        precondition(maxBytes >= 0, \"`maxBytes` must be greater than or equal to zero\")\n        var bytesRead = 0\n        for try await fragment in self {\n            bytesRead += fragment.readableBytes\n            guard bytesRead <= maxBytes else {\n                throw NIOTooManyBytesError(maxBytes: maxBytes)\n            }\n            accumulationBuffer.writeImmutableBuffer(fragment)\n        }\n    }\n\n    /// Accumulates an `AsyncSequence` of ``ByteBuffer``s into a single ``ByteBuffer``.\n    /// - Parameters:\n    ///   - maxBytes: The maximum number of bytes this method is allowed to accumulate\n    /// - Throws: `NIOTooManyBytesError` if the the sequence contains more than `maxBytes`.\n    @inlinable\n    public func collect(\n        upTo maxBytes: Int\n    ) async throws -> ByteBuffer {\n        precondition(maxBytes >= 0, \"`maxBytes` must be greater than or equal to zero\")\n        // we use the first `ByteBuffer` to accumulate all subsequent `ByteBuffer`s into.\n        // this has also the benefit of not copying at all,\n        // if the async sequence contains only one element.\n        var iterator = self.makeAsyncIterator()\n        guard var head = try await iterator.next() else {\n            return ByteBuffer()\n        }\n        guard head.readableBytes <= maxBytes else {\n            throw NIOTooManyBytesError(maxBytes: maxBytes)\n        }\n\n        let tail = AsyncSequenceFromIterator(iterator)\n        // it is guaranteed that\n        // `maxBytes >= 0 && head.readableBytes >= 0 && head.readableBytes <= maxBytes`\n        // This implies that `maxBytes - head.readableBytes >= 0`\n        // we can therefore use wrapping subtraction\n        try await tail.collect(upTo: maxBytes &- head.readableBytes, into: &head)\n        return head\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@usableFromInline\nstruct AsyncSequenceFromIterator<AsyncIterator: AsyncIteratorProtocol>: AsyncSequence {\n    @usableFromInline typealias Element = AsyncIterator.Element\n\n    @usableFromInline var iterator: AsyncIterator\n\n    @inlinable init(_ iterator: AsyncIterator) {\n        self.iterator = iterator\n    }\n\n    @inlinable func makeAsyncIterator() -> AsyncIterator {\n        self.iterator\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension AsyncSequenceFromIterator: Sendable where AsyncIterator: Sendable {}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension EventLoop {\n    @preconcurrency\n    @inlinable\n    public func makeFutureWithTask<Return: Sendable>(\n        _ body: @Sendable @escaping () async throws -> Return\n    ) -> EventLoopFuture<Return> {\n        let promise = self.makePromise(of: Return.self)\n        promise.completeWithTask(body)\n        return promise.futureResult\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncChannel/AsyncChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Wraps a NIO ``Channel`` object into a form suitable for use in Swift Concurrency.\n///\n/// ``NIOAsyncChannel`` abstracts the notion of a NIO ``Channel`` into something that\n/// can safely be used in a structured concurrency context. In particular, this exposes\n/// the following functionality:\n///\n/// - reads are presented as an `AsyncSequence`\n/// - writes can be written to with async functions on a writer, providing back pressure\n/// - channels can be closed seamlessly\n///\n/// This type does not replace the full complexity of NIO's ``Channel``. In particular, it\n/// does not expose the following functionality:\n///\n/// - user events\n/// - traditional NIO back pressure such as writability signals and the channel's read call\n///\n/// Users are encouraged to separate their ``ChannelHandler``s into those that implement\n/// protocol-specific logic (such as parsers and encoders) and those that implement business\n/// logic. Protocol-specific logic should be implemented as a ``ChannelHandler``, while business\n/// logic should use ``NIOAsyncChannel`` to consume and produce data to the network.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncChannel<Inbound: Sendable, Outbound: Sendable>: Sendable {\n    public struct Configuration: Sendable {\n        /// The back pressure strategy of the ``NIOAsyncChannel/inbound``.\n        public var backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark\n\n        /// If outbound half closure should be enabled. Outbound half closure is triggered once\n        /// the ``NIOAsyncChannelOutboundWriter`` is either finished or deinitialized.\n        public var isOutboundHalfClosureEnabled: Bool\n\n        /// The ``NIOAsyncChannel/inbound`` message's type.\n        public var inboundType: Inbound.Type\n\n        /// The ``NIOAsyncChannel/outbound`` message's type.\n        public var outboundType: Outbound.Type\n\n        /// Initializes a new ``NIOAsyncChannel/Configuration``.\n        ///\n        /// - Parameters:\n        ///   - backPressureStrategy: The back pressure strategy of the ``NIOAsyncChannel/inbound``. Defaults\n        ///     to a watermarked strategy (lowWatermark: 2, highWatermark: 10).\n        ///   - isOutboundHalfClosureEnabled: If outbound half closure should be enabled. Outbound half closure is triggered once\n        ///     the ``NIOAsyncChannelOutboundWriter`` is either finished or deinitialized. Defaults to `false`.\n        ///   - inboundType: The ``NIOAsyncChannel/inbound`` message's type.\n        ///   - outboundType: The ``NIOAsyncChannel/outbound`` message's type.\n        public init(\n            backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark = .init(\n                lowWatermark: 2,\n                highWatermark: 10\n            ),\n            isOutboundHalfClosureEnabled: Bool = false,\n            inboundType: Inbound.Type = Inbound.self,\n            outboundType: Outbound.Type = Outbound.self\n        ) {\n            self.backPressureStrategy = backPressureStrategy\n            self.isOutboundHalfClosureEnabled = isOutboundHalfClosureEnabled\n            self.inboundType = inboundType\n            self.outboundType = outboundType\n        }\n    }\n\n    /// The underlying channel being wrapped by this ``NIOAsyncChannel``.\n    public let channel: Channel\n\n    /// The stream of inbound messages.\n    ///\n    /// - Important: The `inbound` stream is a unicast `AsyncSequence` and only one iterator can be created.\n    @available(*, deprecated, message: \"Use the executeThenClose scoped method instead.\")\n    public var inbound: NIOAsyncChannelInboundStream<Inbound> {\n        self._inbound\n    }\n    /// The writer for writing outbound messages.\n    @available(*, deprecated, message: \"Use the executeThenClose scoped method instead.\")\n    public var outbound: NIOAsyncChannelOutboundWriter<Outbound> {\n        self._outbound\n    }\n\n    @usableFromInline\n    let _inbound: NIOAsyncChannelInboundStream<Inbound>\n    @usableFromInline\n    let _outbound: NIOAsyncChannelOutboundWriter<Outbound>\n\n    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel``.\n    ///\n    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because\n    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.\n    ///\n    /// - Parameters:\n    ///   - channel: The ``Channel`` to wrap.\n    ///   - configuration: The ``NIOAsyncChannel``s configuration.\n    @inlinable\n    public init(\n        wrappingChannelSynchronously channel: Channel,\n        configuration: Configuration = .init()\n    ) throws {\n        channel.eventLoop.preconditionInEventLoop()\n        self.channel = channel\n        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(\n            backPressureStrategy: configuration.backPressureStrategy,\n            isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled,\n            closeOnDeinit: false\n        )\n    }\n\n    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel`` where the outbound type is `Never`.\n    ///\n    /// This initializer will finish the ``NIOAsyncChannel/outbound`` immediately.\n    ///\n    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because\n    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.\n    ///\n    /// - Parameters:\n    ///   - channel: The ``Channel`` to wrap.\n    ///   - configuration: The ``NIOAsyncChannel``s configuration.\n    @inlinable\n    public init(\n        wrappingChannelSynchronously channel: Channel,\n        configuration: Configuration = .init()\n    ) throws where Outbound == Never {\n        channel.eventLoop.preconditionInEventLoop()\n        self.channel = channel\n        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(\n            backPressureStrategy: configuration.backPressureStrategy,\n            isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled,\n            closeOnDeinit: false\n        )\n\n        self._outbound.finish()\n    }\n\n    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel``.\n    ///\n    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because\n    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.\n    ///\n    /// - Parameters:\n    ///   - channel: The ``Channel`` to wrap.\n    ///   - configuration: The ``NIOAsyncChannel``s configuration.\n    @available(\n        *,\n        deprecated,\n        renamed: \"init(wrappingChannelSynchronously:configuration:)\",\n        message: \"This method has been deprecated since it defaults to deinit based resource teardown\"\n    )\n    @inlinable\n    public init(\n        synchronouslyWrapping channel: Channel,\n        configuration: Configuration = .init()\n    ) throws {\n        channel.eventLoop.preconditionInEventLoop()\n        self.channel = channel\n        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(\n            backPressureStrategy: configuration.backPressureStrategy,\n            isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled,\n            closeOnDeinit: true\n        )\n    }\n\n    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel`` where the outbound type is `Never`.\n    ///\n    /// This initializer will finish the ``NIOAsyncChannel/outbound`` immediately.\n    ///\n    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because\n    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.\n    ///\n    /// - Parameters:\n    ///   - channel: The ``Channel`` to wrap.\n    ///   - configuration: The ``NIOAsyncChannel``s configuration.\n    @inlinable\n    @available(\n        *,\n        deprecated,\n        renamed: \"init(wrappingChannelSynchronously:configuration:)\",\n        message: \"This method has been deprecated since it defaults to deinit based resource teardown\"\n    )\n    public init(\n        synchronouslyWrapping channel: Channel,\n        configuration: Configuration = .init()\n    ) throws where Outbound == Never {\n        channel.eventLoop.preconditionInEventLoop()\n        self.channel = channel\n        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(\n            backPressureStrategy: configuration.backPressureStrategy,\n            isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled,\n            closeOnDeinit: true\n        )\n\n        self._outbound.finish()\n    }\n\n    @inlinable\n    internal init(\n        channel: Channel,\n        inboundStream: NIOAsyncChannelInboundStream<Inbound>,\n        outboundWriter: NIOAsyncChannelOutboundWriter<Outbound>\n    ) {\n        channel.eventLoop.preconditionInEventLoop()\n        self.channel = channel\n        self._inbound = inboundStream\n        self._outbound = outboundWriter\n    }\n\n    /// This method is only used from our server bootstrap to allow us to run the child channel initializer\n    /// at the right moment.\n    ///\n    /// - Important: This is not considered stable API and should not be used.\n    @inlinable\n    @available(\n        *,\n        deprecated,\n        message: \"This method has been deprecated since it defaults to deinit based resource teardown\"\n    )\n    public static func _wrapAsyncChannelWithTransformations(\n        synchronouslyWrapping channel: Channel,\n        backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        isOutboundHalfClosureEnabled: Bool = false,\n        channelReadTransformation: @Sendable @escaping (Channel) -> EventLoopFuture<Inbound>\n    ) throws -> NIOAsyncChannel<Inbound, Outbound> where Outbound == Never {\n        channel.eventLoop.preconditionInEventLoop()\n        let (inboundStream, outboundWriter):\n            (NIOAsyncChannelInboundStream<Inbound>, NIOAsyncChannelOutboundWriter<Outbound>) =\n                try channel._syncAddAsyncHandlersWithTransformations(\n                    backPressureStrategy: backPressureStrategy,\n                    isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled,\n                    closeOnDeinit: true,\n                    channelReadTransformation: channelReadTransformation\n                )\n\n        outboundWriter.finish()\n\n        return .init(\n            channel: channel,\n            inboundStream: inboundStream,\n            outboundWriter: outboundWriter\n        )\n    }\n\n    /// This method is only used from our server bootstrap to allow us to run the child channel initializer\n    /// at the right moment.\n    ///\n    /// - Important: This is not considered stable API and should not be used.\n    @inlinable\n    public static func _wrapAsyncChannelWithTransformations(\n        wrappingChannelSynchronously channel: Channel,\n        backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        isOutboundHalfClosureEnabled: Bool = false,\n        channelReadTransformation: @Sendable @escaping (Channel) -> EventLoopFuture<Inbound>\n    ) throws -> NIOAsyncChannel<Inbound, Outbound> where Outbound == Never {\n        channel.eventLoop.preconditionInEventLoop()\n        let (inboundStream, outboundWriter):\n            (NIOAsyncChannelInboundStream<Inbound>, NIOAsyncChannelOutboundWriter<Outbound>) =\n                try channel._syncAddAsyncHandlersWithTransformations(\n                    backPressureStrategy: backPressureStrategy,\n                    isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled,\n                    closeOnDeinit: false,\n                    channelReadTransformation: channelReadTransformation\n                )\n\n        outboundWriter.finish()\n\n        return .init(\n            channel: channel,\n            inboundStream: inboundStream,\n            outboundWriter: outboundWriter\n        )\n    }\n\n    /// Provides scoped access to the inbound and outbound side of the underlying ``Channel``.\n    ///\n    /// - Important: After this method returned the underlying ``Channel`` will be closed.\n    ///\n    /// - Parameter body: A closure that gets scoped access to the inbound and outbound.\n    @_disfavoredOverload\n    public func executeThenClose<Result>(\n        _ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>, _ outbound: NIOAsyncChannelOutboundWriter<Outbound>)\n            async throws -> Result\n    ) async throws -> Result {\n        let result: Result\n        do {\n            result = try await body(self._inbound, self._outbound)\n        } catch let bodyError {\n            do {\n                self._outbound.finish()\n                try await self.channel.close().get()\n                throw bodyError\n            } catch {\n                throw bodyError\n            }\n        }\n\n        self._outbound.finish()\n        // We ignore errors from close, since all we care about is that the channel has been closed\n        // at this point.\n        self.channel.close(promise: nil)\n        // `closeFuture` should never be failed, so we could ignore the error. However, do an\n        // assertionFailure to guide bad Channel implementations that are incorrectly failing this\n        // future to stop failing it.\n        do {\n            try await self.channel.closeFuture.get()\n        } catch {\n            assertionFailure(\n                \"\"\"\n                The channel's closeFuture should never be failed, but it was failed with error: \\(error).\n                This is an error in the channel's implementation.\n                Refer to `Channel/closeFuture`'s documentation for more information.\n                \"\"\"\n            )\n        }\n        return result\n    }\n\n    /// Provides scoped access to the inbound and outbound side of the underlying ``Channel``.\n    ///\n    /// - Important: After this method returned the underlying ``Channel`` will be closed.\n    ///\n    /// - Parameters:\n    ///     - actor: actor where this function should be isolated to\n    ///     - body: A closure that gets scoped access to the inbound and outbound.\n    public func executeThenClose<Result>(\n        isolation actor: isolated (any Actor)? = #isolation,\n        _ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>, _ outbound: NIOAsyncChannelOutboundWriter<Outbound>)\n            async throws -> sending Result\n    ) async throws -> sending Result {\n        let result: Result\n        do {\n            result = try await body(self._inbound, self._outbound)\n        } catch let bodyError {\n            do {\n                self._outbound.finish()\n                try await self.channel.close().get()\n                throw bodyError\n            } catch {\n                throw bodyError\n            }\n        }\n\n        self._outbound.finish()\n        // We ignore errors from close, since all we care about is that the channel has been closed\n        // at this point.\n        self.channel.close(promise: nil)\n        // `closeFuture` should never be failed, so we could ignore the error. However, do an\n        // assertionFailure to guide bad Channel implementations that are incorrectly failing this\n        // future to stop failing it.\n        do {\n            try await self.channel.closeFuture.get()\n        } catch {\n            assertionFailure(\n                \"\"\"\n                The channel's closeFuture should never be failed, but it was failed with error: \\(error).\n                This is an error in the channel's implementation.\n                Refer to `Channel/closeFuture`'s documentation for more information.\n                \"\"\"\n            )\n        }\n\n        return result\n    }\n}\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannel {\n    /// Provides scoped access to the inbound side of the underlying ``Channel``.\n    ///\n    /// - Important: After this method returned the underlying ``Channel`` will be closed.\n    ///\n    /// - Parameter body: A closure that gets scoped access to the inbound.\n    @_disfavoredOverload\n    public func executeThenClose<Result>(\n        _ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>) async throws -> Result\n    ) async throws -> Result where Outbound == Never {\n        let result: Result\n        do {\n            result = try await body(self._inbound)\n        } catch let bodyError {\n            do {\n                self._outbound.finish()\n                try await self.channel.close().get()\n                throw bodyError\n            } catch {\n                throw bodyError\n            }\n        }\n\n        self._outbound.finish()\n        // We ignore errors from close, since all we care about is that the channel has been closed\n        // at this point.\n        self.channel.close(promise: nil)\n        // `closeFuture` should never be failed, so we could ignore the error. However, do an\n        // assertionFailure to guide bad Channel implementations that are incorrectly failing this\n        // future to stop failing it.\n        do {\n            try await self.channel.closeFuture.get()\n        } catch {\n            assertionFailure(\n                \"\"\"\n                The channel's closeFuture should never be failed, but it was failed with error: \\(error).\n                This is an error in the channel's implementation.\n                Refer to `Channel/closeFuture`'s documentation for more information.\n                \"\"\"\n            )\n        }\n        return result\n    }\n\n    /// Provides scoped access to the inbound side of the underlying ``Channel``.\n    ///\n    /// - Important: After this method returned the underlying ``Channel`` will be closed.\n    ///\n    /// - Parameters:\n    ///     - actor: actor where this function should be isolated to\n    ///     - body: A closure that gets scoped access to the inbound.\n    public func executeThenClose<Result>(\n        isolation actor: isolated (any Actor)? = #isolation,\n        _ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>) async throws -> sending Result\n    ) async throws -> sending Result where Outbound == Never {\n        let result: Result\n        do {\n            result = try await body(self._inbound)\n        } catch let bodyError {\n            do {\n                self._outbound.finish()\n                try await self.channel.close().get()\n                throw bodyError\n            } catch {\n                throw bodyError\n            }\n        }\n\n        self._outbound.finish()\n        // We ignore errors from close, since all we care about is that the channel has been closed\n        // at this point.\n        self.channel.close(promise: nil)\n        // `closeFuture` should never be failed, so we could ignore the error. However, do an\n        // assertionFailure to guide bad Channel implementations that are incorrectly failing this\n        // future to stop failing it.\n        do {\n            try await self.channel.closeFuture.get()\n        } catch {\n            assertionFailure(\n                \"\"\"\n                The channel's closeFuture should never be failed, but it was failed with error: \\(error).\n                This is an error in the channel's implementation.\n                Refer to `Channel/closeFuture`'s documentation for more information.\n                \"\"\"\n            )\n        }\n\n        return result\n    }\n}\n\nextension Channel {\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    func _syncAddAsyncHandlers<Inbound: Sendable, Outbound: Sendable>(\n        backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark?,\n        isOutboundHalfClosureEnabled: Bool,\n        closeOnDeinit: Bool\n    ) throws -> (NIOAsyncChannelInboundStream<Inbound>, NIOAsyncChannelOutboundWriter<Outbound>) {\n        self.eventLoop.assertInEventLoop()\n\n        let handler = NIOAsyncChannelHandler<Inbound, Inbound, Outbound>(\n            eventLoop: self.eventLoop,\n            transformation: .syncWrapping { $0 },\n            isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled\n        )\n\n        let inboundStream = try NIOAsyncChannelInboundStream(\n            eventLoop: self.eventLoop,\n            handler: handler,\n            backPressureStrategy: backPressureStrategy,\n            closeOnDeinit: closeOnDeinit\n        )\n\n        let writer = try NIOAsyncChannelOutboundWriter<Outbound>(\n            eventLoop: self.eventLoop,\n            handler: handler,\n            isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled,\n            closeOnDeinit: closeOnDeinit\n        )\n\n        try self.pipeline.syncOperations.addHandler(handler)\n        return (inboundStream, writer)\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    func _syncAddAsyncHandlersWithTransformations<ChannelReadResult>(\n        backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark?,\n        isOutboundHalfClosureEnabled: Bool,\n        closeOnDeinit: Bool,\n        channelReadTransformation: @Sendable @escaping (Channel) -> EventLoopFuture<ChannelReadResult>\n    ) throws -> (NIOAsyncChannelInboundStream<ChannelReadResult>, NIOAsyncChannelOutboundWriter<Never>) {\n        self.eventLoop.assertInEventLoop()\n\n        let handler = NIOAsyncChannelHandler<Channel, ChannelReadResult, Never>(\n            eventLoop: self.eventLoop,\n            transformation: .transformation(channelReadTransformation: channelReadTransformation),\n            isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled\n        )\n\n        let inboundStream = try NIOAsyncChannelInboundStream(\n            eventLoop: self.eventLoop,\n            handler: handler,\n            backPressureStrategy: backPressureStrategy,\n            closeOnDeinit: closeOnDeinit\n        )\n\n        let writer = try NIOAsyncChannelOutboundWriter<Never>(\n            eventLoop: self.eventLoop,\n            handler: handler,\n            isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled,\n            closeOnDeinit: closeOnDeinit\n        )\n\n        try self.pipeline.syncOperations.addHandler(handler)\n        return (inboundStream, writer)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncChannel/AsyncChannelHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\n\n/// A ``ChannelHandler`` that is used to transform the inbound portion of a NIO\n/// ``Channel`` into an asynchronous sequence that supports back-pressure. It's also used\n/// to write the outbound portion of a NIO ``Channel`` from Swift Concurrency with back-pressure\n/// support.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@usableFromInline\ninternal final class NIOAsyncChannelHandler<InboundIn: Sendable, ProducerElement: Sendable, OutboundOut: Sendable> {\n    @usableFromInline\n    enum _ProducingState: Sendable {\n        // Not .stopProducing\n        case keepProducing\n\n        // .stopProducing but not read()\n        case producingPaused\n\n        // .stopProducing and read()\n        case producingPausedWithOutstandingRead\n    }\n\n    @usableFromInline\n    typealias Source = NIOThrowingAsyncSequenceProducer<\n        ProducerElement,\n        Error,\n        NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n        NIOAsyncChannelHandlerProducerDelegate\n    >.Source\n\n    /// The source of the asynchronous sequence.\n    @usableFromInline\n    var source: Source?\n\n    /// The channel handler's context.\n    @usableFromInline\n    var context: ChannelHandlerContext?\n\n    /// An array of reads which will be yielded to the source with the next channel read complete.\n    @usableFromInline\n    var buffer: [ProducerElement] = []\n\n    /// The current producing state.\n    @usableFromInline\n    var producingState: _ProducingState = .keepProducing\n\n    /// The event loop.\n    @usableFromInline\n    let eventLoop: EventLoop\n\n    /// A type indicating what kind of transformation to apply to reads.\n    @usableFromInline\n    enum Transformation {\n        /// A synchronous transformation is applied to incoming reads. This is used when sync wrapping a channel.\n        case syncWrapping((InboundIn) -> ProducerElement)\n        case transformation(\n            channelReadTransformation: @Sendable (InboundIn) -> EventLoopFuture<ProducerElement>\n        )\n    }\n\n    /// The transformation applied to incoming reads.\n    @usableFromInline\n    let transformation: Transformation\n\n    @usableFromInline\n    typealias Writer = NIOAsyncWriter<\n        OutboundOut,\n        NIOAsyncChannelHandlerWriterDelegate<OutboundOut>\n    >\n\n    @usableFromInline\n    typealias Sink = Writer.Sink\n\n    /// The sink of the ``NIOAsyncWriter``.\n    @usableFromInline\n    var sink: Sink?\n\n    /// The writer of the ``NIOAsyncWriter``.\n    ///\n    /// The reference is retained until `channelActive` is fired. This avoids situations\n    /// where `deinit` is called on the unfinished writer because the `Channel` was never returned\n    /// to the caller (e.g. because a connect failed or or happy-eyeballs created multiple\n    /// channels).\n    ///\n    /// Effectively `channelActive` is used at the point in time at which NIO cedes ownership of\n    /// the writer to the caller.\n    @usableFromInline\n    var writer: Writer?\n\n    @usableFromInline\n    let isOutboundHalfClosureEnabled: Bool\n\n    @inlinable\n    init(\n        eventLoop: EventLoop,\n        transformation: Transformation,\n        isOutboundHalfClosureEnabled: Bool\n    ) {\n        self.eventLoop = eventLoop\n        self.transformation = transformation\n        self.isOutboundHalfClosureEnabled = isOutboundHalfClosureEnabled\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelHandler: ChannelInboundHandler {\n    @usableFromInline\n    typealias InboundIn = InboundIn\n\n    @inlinable\n    func handlerAdded(context: ChannelHandlerContext) {\n        self.context = context\n    }\n\n    @inlinable\n    func handlerRemoved(context: ChannelHandlerContext) {\n        self._finishSource(context: context)\n        self.sink?.finish(error: ChannelError._ioOnClosedChannel)\n        self.context = nil\n        self.writer = nil\n    }\n\n    @inlinable\n    func channelActive(context: ChannelHandlerContext) {\n        // Drop the writer ref, the caller is responsible for it now.\n        self.writer = nil\n        context.fireChannelActive()\n    }\n\n    @inlinable\n    func channelInactive(context: ChannelHandlerContext) {\n        self._finishSource(context: context)\n        self.sink?.finish(error: ChannelError._ioOnClosedChannel)\n        context.fireChannelInactive()\n    }\n\n    @inlinable\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch event {\n        case ChannelEvent.inputClosed:\n            self._finishSource(context: context)\n        case ChannelEvent.outputClosed:\n            self.sink?.finish()\n        default:\n            break\n        }\n\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    @inlinable\n    func channelWritabilityChanged(context: ChannelHandlerContext) {\n        self.sink?.setWritability(to: context.channel.isWritable)\n        context.fireChannelWritabilityChanged()\n    }\n\n    @inlinable\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self._finishSource(with: error, context: context)\n        context.fireErrorCaught(error)\n    }\n\n    @inlinable\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let unwrapped = NIOAsyncChannelHandler.unwrapInboundIn(data)\n\n        switch self.transformation {\n        case .syncWrapping(let transformation):\n            self.buffer.append(transformation(unwrapped))\n            // We forward on reads here to enable better channel composition.\n            context.fireChannelRead(data)\n\n        case .transformation(let channelReadTransformation):\n            // The unsafe transfers here are required because we need to use self in whenComplete\n            // We are making sure to be on our event loop so we can safely use self in whenComplete\n            channelReadTransformation(unwrapped)\n                .hop(to: context.eventLoop)\n                .assumeIsolatedUnsafeUnchecked()\n                .whenComplete { result in\n                    switch result {\n                    case .success:\n                        // We have to fire through the original data now. Since our channelReadTransformation\n                        // is the channel initializer. Once that's done we need to fire the channel as a read\n                        // so that it hits channelRead0 in the base socket channel.\n                        context.fireChannelRead(data)\n                    case .failure:\n                        break\n                    }\n                    self._transformationCompleted(context: context, result: result)\n                }\n        }\n    }\n\n    @inlinable\n    func channelReadComplete(context: ChannelHandlerContext) {\n        self._deliverReads(context: context)\n        context.fireChannelReadComplete()\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelHandler: ChannelOutboundHandler {\n    @usableFromInline\n    typealias OutboundIn = Any\n\n    @usableFromInline\n    typealias OutboundOut = OutboundOut\n\n    @inlinable\n    func read(context: ChannelHandlerContext) {\n        switch self.producingState {\n        case .keepProducing:\n            context.read()\n        case .producingPaused:\n            self.producingState = .producingPausedWithOutstandingRead\n        case .producingPausedWithOutstandingRead:\n            break\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelHandler {\n    @inlinable\n    func _transformationCompleted(\n        context: ChannelHandlerContext,\n        result: Result<ProducerElement, Error>\n    ) {\n        context.eventLoop.preconditionInEventLoop()\n\n        switch result {\n        case .success(let transformed):\n            self.buffer.append(transformed)\n            // We are delivering out of band here since the future can complete at any point\n            self._deliverReads(context: context)\n\n        case .failure:\n            // Transformation failed. Nothing to really do here this must be handled in the transformation\n            // futures themselves.\n            break\n        }\n    }\n\n    @inlinable\n    func _finishSource(with error: Error? = nil, context: ChannelHandlerContext) {\n        guard let source = self.source else {\n            return\n        }\n\n        // We need to deliver the reads first to buffer them in the source.\n        self._deliverReads(context: context)\n\n        if let error = error {\n            source.finish(error)\n        } else {\n            source.finish()\n        }\n\n        // We can nil the source here, as we're no longer going to use it.\n        self.source = nil\n    }\n\n    @inlinable\n    func _deliverReads(context: ChannelHandlerContext) {\n        if self.buffer.isEmpty {\n            return\n        }\n\n        guard let source = self.source else {\n            self.buffer.removeAll()\n            return\n        }\n\n        let result = source.yield(contentsOf: self.buffer)\n        switch result {\n        case .produceMore, .dropped:\n            break\n        case .stopProducing:\n            if self.producingState != .producingPausedWithOutstandingRead {\n                self.producingState = .producingPaused\n            }\n        }\n        self.buffer.removeAll(keepingCapacity: true)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelHandler {\n    @inlinable\n    func _didTerminate() {\n        self.eventLoop.preconditionInEventLoop()\n        self.source = nil\n\n        // Wedges the read open forever, we'll never read again.\n        self.producingState = .producingPausedWithOutstandingRead\n    }\n\n    @inlinable\n    func _produceMore() {\n        self.eventLoop.preconditionInEventLoop()\n\n        switch self.producingState {\n        case .producingPaused:\n            self.producingState = .keepProducing\n\n        case .producingPausedWithOutstandingRead:\n            self.producingState = .keepProducing\n            self.context?.read()\n\n        case .keepProducing:\n            break\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@usableFromInline\nstruct NIOAsyncChannelHandlerProducerDelegate: @unchecked Sendable, NIOAsyncSequenceProducerDelegate {\n    @usableFromInline\n    let eventLoop: EventLoop\n\n    @usableFromInline\n    let _didTerminate: () -> Void\n\n    @usableFromInline\n    let _produceMore: () -> Void\n\n    @inlinable\n    init<InboundIn, ProducerElement, OutboundOut>(\n        handler: NIOAsyncChannelHandler<InboundIn, ProducerElement, OutboundOut>\n    ) {\n        self.eventLoop = handler.eventLoop\n        self._didTerminate = handler._didTerminate\n        self._produceMore = handler._produceMore\n    }\n\n    @inlinable\n    func didTerminate() {\n        if self.eventLoop.inEventLoop {\n            self._didTerminate()\n        } else {\n            self.eventLoop.execute {\n                self._didTerminate()\n            }\n        }\n    }\n\n    @inlinable\n    func produceMore() {\n        if self.eventLoop.inEventLoop {\n            self._produceMore()\n        } else {\n            self.eventLoop.execute {\n                self._produceMore()\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@usableFromInline\nstruct NIOAsyncChannelHandlerWriterDelegate<Element: Sendable>: NIOAsyncWriterSinkDelegate, @unchecked Sendable {\n    @usableFromInline\n    let eventLoop: EventLoop\n\n    @usableFromInline\n    let _didYieldContentsOf: (Deque<Element>) -> Void\n\n    @usableFromInline\n    let _didYield: (Element) -> Void\n\n    @usableFromInline\n    let _didTerminate: ((any Error)?) -> Void\n\n    @inlinable\n    init<InboundIn, ProducerElement>(handler: NIOAsyncChannelHandler<InboundIn, ProducerElement, Element>) {\n        self.eventLoop = handler.eventLoop\n        self._didYieldContentsOf = handler._didYield(sequence:)\n        self._didYield = handler._didYield(element:)\n        self._didTerminate = handler._didTerminate(error:)\n    }\n\n    @inlinable\n    func didYield(contentsOf sequence: Deque<Element>) {\n        if self.eventLoop.inEventLoop {\n            self._didYieldContentsOf(sequence)\n        } else {\n            self.eventLoop.execute {\n                self._didYieldContentsOf(sequence)\n            }\n        }\n    }\n\n    @inlinable\n    func didYield(_ element: Element) {\n        if self.eventLoop.inEventLoop {\n            self._didYield(element)\n        } else {\n            self.eventLoop.execute {\n                self._didYield(element)\n            }\n        }\n    }\n\n    @inlinable\n    func didTerminate(error: (any Error)?) {\n        if self.eventLoop.inEventLoop {\n            self._didTerminate(error)\n        } else {\n            self.eventLoop.execute {\n                self._didTerminate(error)\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelHandler {\n    @inlinable\n    func _didYield(sequence: Deque<OutboundOut>) {\n        // This is always called from an async context, so we must loop-hop.\n        // Because we always loop-hop, we're always at the top of a stack frame. As this\n        // is the only source of writes for us, and as this channel handler doesn't implement\n        // func write(), we cannot possibly re-entrantly write. That means we can skip many of the\n        // awkward re-entrancy protections NIO usually requires, and can safely just do an iterative\n        // write.\n        self.eventLoop.preconditionInEventLoop()\n        guard let context = self.context else {\n            // Already removed from the channel by now, we can stop.\n            return\n        }\n\n        self._doOutboundWrites(context: context, writes: sequence)\n    }\n\n    @inlinable\n    func _didYield(element: OutboundOut) {\n        // This is always called from an async context, so we must loop-hop.\n        // Because we always loop-hop, we're always at the top of a stack frame. As this\n        // is the only source of writes for us, and as this channel handler doesn't implement\n        // func write(), we cannot possibly re-entrantly write. That means we can skip many of the\n        // awkward re-entrancy protections NIO usually requires, and can safely just do an iterative\n        // write.\n        self.eventLoop.preconditionInEventLoop()\n        guard let context = self.context else {\n            // Already removed from the channel by now, we can stop.\n            return\n        }\n\n        self._doOutboundWrite(context: context, write: element)\n    }\n\n    @inlinable\n    func _didTerminate(error: Error?) {\n        self.eventLoop.preconditionInEventLoop()\n\n        if self.isOutboundHalfClosureEnabled {\n            self.context?.close(mode: .output, promise: nil)\n        }\n\n        self.sink = nil\n    }\n\n    @inlinable\n    func _doOutboundWrites(context: ChannelHandlerContext, writes: Deque<OutboundOut>) {\n        for write in writes {\n            context.write(NIOAsyncChannelHandler.wrapOutboundOut(write), promise: nil)\n        }\n\n        context.flush()\n    }\n\n    @inlinable\n    func _doOutboundWrite(context: ChannelHandlerContext, write: OutboundOut) {\n        context.write(NIOAsyncChannelHandler.wrapOutboundOut(write), promise: nil)\n        context.flush()\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@available(*, unavailable)\nextension NIOAsyncChannelHandler: Sendable {}\n\n@available(*, unavailable)\nextension NIOAsyncChannelHandler.Transformation: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncChannel/AsyncChannelInboundStream.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// The inbound message asynchronous sequence of a ``NIOAsyncChannel``.\n///\n/// This is a unicast async sequence that allows a single iterator to be created.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncChannelInboundStream<Inbound: Sendable>: Sendable {\n    @usableFromInline\n    typealias Producer = NIOThrowingAsyncSequenceProducer<\n        Inbound,\n        Error,\n        NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n        NIOAsyncChannelHandlerProducerDelegate\n    >\n\n    /// A source used for driving a ``NIOAsyncChannelInboundStream`` during tests.\n    public struct TestSource: Sendable {\n        @usableFromInline\n        internal let continuation: AsyncThrowingStream<Inbound, Error>.Continuation\n\n        @inlinable\n        init(continuation: AsyncThrowingStream<Inbound, Error>.Continuation) {\n            self.continuation = continuation\n        }\n\n        /// Yields the element to the inbound stream.\n        ///\n        /// - Parameter element: The element to yield to the inbound stream.\n        @inlinable\n        public func yield(_ element: Inbound) {\n            self.continuation.yield(element)\n        }\n\n        /// Finished the inbound stream.\n        ///\n        /// - Parameter error: The error to throw, or nil, to finish normally.\n        @inlinable\n        public func finish(throwing error: Error? = nil) {\n            self.continuation.finish(throwing: error)\n        }\n    }\n\n    @usableFromInline\n    enum _Backing: Sendable {\n        case asyncStream(AsyncThrowingStream<Inbound, Error>)\n        case producer(Producer)\n    }\n\n    /// The underlying async sequence.\n    @usableFromInline\n    let _backing: _Backing\n\n    /// Creates a new stream with a source for testing.\n    ///\n    /// This is useful for writing unit tests where you want to drive a ``NIOAsyncChannelInboundStream``.\n    ///\n    /// - Returns: A tuple containing the input stream and a test source to drive it.\n    @inlinable\n    public static func makeTestingStream() -> (Self, TestSource) {\n        var continuation: AsyncThrowingStream<Inbound, Error>.Continuation!\n        let stream = AsyncThrowingStream<Inbound, Error> { continuation = $0 }\n        let source = TestSource(continuation: continuation)\n        let inputStream = Self(stream: stream)\n        return (inputStream, source)\n    }\n\n    @inlinable\n    init(stream: AsyncThrowingStream<Inbound, Error>) {\n        self._backing = .asyncStream(stream)\n    }\n\n    @inlinable\n    init<ProducerElement: Sendable, Outbound: Sendable>(\n        eventLoop: any EventLoop,\n        handler: NIOAsyncChannelHandler<ProducerElement, Inbound, Outbound>,\n        backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark?,\n        closeOnDeinit: Bool\n    ) throws {\n        eventLoop.preconditionInEventLoop()\n        let strategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark\n\n        if let userProvided = backPressureStrategy {\n            strategy = userProvided\n        } else {\n            // Default strategy. These numbers are fairly arbitrary, but they line up with the default value of\n            // maxMessagesPerRead.\n            strategy = .init(lowWatermark: 2, highWatermark: 10)\n        }\n\n        let sequence = Producer.makeSequence(\n            backPressureStrategy: strategy,\n            finishOnDeinit: closeOnDeinit,\n            delegate: NIOAsyncChannelHandlerProducerDelegate(handler: handler)\n        )\n\n        handler.source = sequence.source\n        self._backing = .producer(sequence.sequence)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelInboundStream: AsyncSequence {\n    public typealias Element = Inbound\n\n    public struct AsyncIterator: AsyncIteratorProtocol {\n        @usableFromInline\n        enum _Backing {\n            case asyncStream(AsyncThrowingStream<Inbound, Error>.Iterator)\n            case producer(Producer.AsyncIterator)\n        }\n\n        @usableFromInline var _backing: _Backing\n\n        @inlinable\n        init(_ backing: NIOAsyncChannelInboundStream<Inbound>._Backing) {\n            switch backing {\n            case .asyncStream(let asyncStream):\n                self._backing = .asyncStream(asyncStream.makeAsyncIterator())\n            case .producer(let producer):\n                self._backing = .producer(producer.makeAsyncIterator())\n            }\n        }\n\n        @inlinable\n        public mutating func next() async throws -> Element? {\n            switch self._backing {\n            case .asyncStream(var iterator):\n                defer {\n                    self._backing = .asyncStream(iterator)\n                }\n                let value = try await iterator.next()\n                return value\n\n            case .producer(let iterator):\n                return try await iterator.next()\n            }\n        }\n    }\n\n    @inlinable\n    public func makeAsyncIterator() -> AsyncIterator {\n        AsyncIterator(self._backing)\n    }\n}\n\n/// The ``NIOAsyncChannelInboundStream/AsyncIterator`` MUST NOT be shared across `Task`s. With marking this as\n/// unavailable we are explicitly declaring this.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@available(*, unavailable)\nextension NIOAsyncChannelInboundStream.AsyncIterator: Sendable {}\n\n@available(*, unavailable)\nextension NIOAsyncChannelInboundStream.AsyncIterator._Backing: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncChannel/AsyncChannelOutboundWriter.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A ``NIOAsyncChannelOutboundWriter`` is used to write and flush new outbound messages in a channel.\n///\n/// The writer acts as a bridge between the Concurrency and NIO world. It allows to write and flush messages into the\n/// underlying ``Channel``. Furthermore, it respects back-pressure of the channel by suspending the calls to write until\n/// the channel becomes writable again.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncChannelOutboundWriter<OutboundOut: Sendable>: Sendable {\n    @usableFromInline\n    typealias _Writer = NIOAsyncWriter<\n        OutboundOut,\n        NIOAsyncChannelHandlerWriterDelegate<OutboundOut>\n    >\n\n    /// An `AsyncSequence` backing a ``NIOAsyncChannelOutboundWriter`` for testing purposes.\n    public struct TestSink: AsyncSequence {\n        public typealias Element = OutboundOut\n\n        @usableFromInline\n        internal let stream: AsyncStream<OutboundOut>\n\n        @usableFromInline\n        internal let continuation: AsyncStream<OutboundOut>.Continuation\n\n        @inlinable\n        init(\n            stream: AsyncStream<OutboundOut>,\n            continuation: AsyncStream<OutboundOut>.Continuation\n        ) {\n            self.stream = stream\n            self.continuation = continuation\n        }\n\n        public func makeAsyncIterator() -> AsyncIterator {\n            AsyncIterator(iterator: self.stream.makeAsyncIterator())\n        }\n\n        public struct AsyncIterator: AsyncIteratorProtocol {\n            @usableFromInline\n            internal var iterator: AsyncStream<OutboundOut>.AsyncIterator\n\n            @inlinable\n            init(iterator: AsyncStream<OutboundOut>.AsyncIterator) {\n                self.iterator = iterator\n            }\n\n            public mutating func next() async -> Element? {\n                await self.iterator.next()\n            }\n        }\n    }\n\n    @usableFromInline\n    enum Backing: Sendable {\n        case asyncStream(AsyncStream<OutboundOut>.Continuation)\n        case writer(_Writer)\n    }\n\n    @usableFromInline\n    internal let _backing: Backing\n\n    /// Creates a new ``NIOAsyncChannelOutboundWriter`` backed by a ``NIOAsyncChannelOutboundWriter/TestSink``.\n    /// This is mostly useful for testing purposes where one wants to observe the written data.\n    @inlinable\n    public static func makeTestingWriter() -> (Self, TestSink) {\n        var continuation: AsyncStream<OutboundOut>.Continuation!\n        let asyncStream = AsyncStream<OutboundOut> { continuation = $0 }\n        let writer = Self(continuation: continuation)\n        let sink = TestSink(stream: asyncStream, continuation: continuation)\n\n        return (writer, sink)\n    }\n\n    @inlinable\n    init<InboundIn, ProducerElement>(\n        eventLoop: any EventLoop,\n        handler: NIOAsyncChannelHandler<InboundIn, ProducerElement, OutboundOut>,\n        isOutboundHalfClosureEnabled: Bool,\n        closeOnDeinit: Bool\n    ) throws {\n        eventLoop.preconditionInEventLoop()\n        let writer = _Writer.makeWriter(\n            elementType: OutboundOut.self,\n            isWritable: true,\n            finishOnDeinit: closeOnDeinit,\n            delegate: .init(handler: handler)\n        )\n\n        handler.sink = writer.sink\n        handler.writer = writer.writer\n\n        self._backing = .writer(writer.writer)\n    }\n\n    @inlinable\n    init(continuation: AsyncStream<OutboundOut>.Continuation) {\n        self._backing = .asyncStream(continuation)\n    }\n\n    /// Send a write into the ``ChannelPipeline`` and flush it right away.\n    ///\n    /// This method suspends if the underlying channel is not writable and will resume once the it becomes writable again.\n    @inlinable\n    public func write(_ data: OutboundOut) async throws {\n        switch self._backing {\n        case .asyncStream(let continuation):\n            continuation.yield(data)\n        case .writer(let writer):\n            try await writer.yield(data)\n        }\n    }\n\n    /// Send a sequence of writes into the ``ChannelPipeline`` and flush them right away.\n    ///\n    /// This method suspends if the underlying channel is not writable and will resume once the it becomes writable again.\n    @inlinable\n    public func write<Writes: Sequence>(contentsOf sequence: Writes) async throws where Writes.Element == OutboundOut {\n        switch self._backing {\n        case .asyncStream(let continuation):\n            for data in sequence {\n                continuation.yield(data)\n            }\n        case .writer(let writer):\n            try await writer.yield(contentsOf: sequence)\n        }\n    }\n\n    /// Send an asynchronous sequence of writes into the ``ChannelPipeline``.\n    ///\n    /// This will flush after every write.\n    ///\n    /// This method suspends if the underlying channel is not writable and will resume once the it becomes writable again.\n    @inlinable\n    public func write<Writes: AsyncSequence>(contentsOf sequence: Writes) async throws\n    where Writes.Element == OutboundOut {\n        for try await data in sequence {\n            try await self.write(data)\n        }\n    }\n\n    /// Finishes the writer.\n    ///\n    /// This might trigger a half closure if the ``NIOAsyncChannel`` was configured to support it.\n    public func finish() {\n        switch self._backing {\n        case .asyncStream(let continuation):\n            continuation.finish()\n        case .writer(let writer):\n            writer.finish()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelOutboundWriter.TestSink: Sendable {}\n\n@available(*, unavailable)\nextension NIOAsyncChannelOutboundWriter.TestSink.AsyncIterator: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncSequences/NIOAsyncSequenceProducer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\n\n/// A protocol for the back-pressure strategy of the ``NIOAsyncSequenceProducer``.\n///\n/// A back-pressure strategy is invoked when new elements are yielded to the sequence or\n/// when a ``NIOAsyncSequenceProducer/AsyncIterator`` requested the next value. The responsibility of the strategy is\n/// to determine whether more elements need to be produced .\n///\n/// If more elements need to be produced, either the ``NIOAsyncSequenceProducerDelegate/produceMore()``\n/// method will be called or a ``NIOAsyncSequenceProducer/Source/YieldResult`` will be returned that indicates\n/// to produce more.\n///\n/// - Important: The methods of this protocol are guaranteed to be called serially. Furthermore, the implementation of these\n/// methods **MUST NOT** do any locking or call out to any other Task/Thread.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic protocol NIOAsyncSequenceProducerBackPressureStrategy: Sendable {\n    /// This method is called after new elements were yielded by the producer to the source.\n    ///\n    /// - Parameter bufferDepth: The current depth of the internal buffer of the sequence. The buffer contains all\n    /// the yielded but not yet consumed elements.\n    /// - Returns: Returns whether more elements should be produced.\n    mutating func didYield(bufferDepth: Int) -> Bool\n\n    /// This method is called after the consumer consumed an element.\n    /// More specifically this method is called after `next` was called on an iterator of the ``NIOAsyncSequenceProducer``.\n    ///\n    /// - Parameter bufferDepth: The current depth of the internal buffer of the sequence. The buffer contains all\n    /// the yielded but not yet consumed elements.\n    /// - Returns: Returns whether the producer should produce more elements.\n    mutating func didConsume(bufferDepth: Int) -> Bool\n}\n\n/// The delegate of ``NIOAsyncSequenceProducer``.\n///\n/// - Important: The calls to ``NIOAsyncSequenceProducerDelegate/produceMore()`` and ``NIOAsyncSequenceProducerDelegate/didTerminate()``\n/// are being done on arbitrary threads. To ensure that your conforming type is able to implement back-pressure correctly your must synchronize\n/// your calls to ``NIOAsyncSequenceProducer/Source/yield(contentsOf:)`` and callbacks on this delegate.\n/// We recommend dispatching from the arbitrary thread that called ``NIOAsyncSequenceProducerDelegate/produceMore()`` and ``NIOAsyncSequenceProducerDelegate/didTerminate()``\n/// onto the thread that is calling ``NIOAsyncSequenceProducer/Source/yield(contentsOf:)``.\n/// This way you synchronize the receiving the result of a yield call and the callbacks of the delegate on the same thread.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic protocol NIOAsyncSequenceProducerDelegate: Sendable {\n    /// This method is called once the back-pressure strategy of the ``NIOAsyncSequenceProducer`` determined\n    /// that the producer needs to start producing more elements. Furthermore, it will also only be called if ``NIOAsyncSequenceProducer/Source/yield(_:)``\n    /// returned a ``NIOAsyncSequenceProducer/Source/YieldResult/stopProducing`` to indicate that new elements should be produced now.\n    /// Except, in the case where ``NIOAsyncSequenceProducer/Source/yield(contentsOf:)`` has never been called.\n    ///\n    /// - Note: ``NIOAsyncSequenceProducerDelegate/produceMore()`` will never be called after\n    /// ``NIOAsyncSequenceProducerDelegate/didTerminate()`` was called.\n    ///\n    /// - Important: This is only called as a result of the consumer calling ``NIOAsyncSequenceProducer/AsyncIterator/next()``.\n    /// It is never called as a result of a producer calling ``NIOAsyncSequenceProducer/Source/yield(_:)``.\n    func produceMore()\n\n    /// This method is called once the ``NIOAsyncSequenceProducer`` is terminated.\n    ///\n    /// Termination happens if:\n    /// - The ``NIOAsyncSequenceProducer/AsyncIterator`` is deinited.\n    /// - The ``NIOAsyncSequenceProducer`` deinited and no iterator is alive.\n    /// - The consuming `Task` is cancelled (e.g. `for await let element in`).\n    /// - The source finished and all remaining buffered elements have been consumed.\n    ///\n    /// - Note: This is guaranteed to be called _exactly_ once.\n    func didTerminate()\n}\n\n/// This is an `AsyncSequence` that supports a unicast `AsyncIterator`.\n///\n/// The goal of this sequence is to produce a stream of elements from the _synchronous_ world\n/// (e.g. elements from a ``Channel`` pipeline) and vend it to the _asynchronous_ world for consumption.\n/// Furthermore, it provides facilities to implement a back-pressure strategy which\n/// observes the number of elements that are yielded and consumed. This allows to signal the source to request more data.\n///\n/// - Note: It is recommended to never directly expose this type from APIs, but rather wrap it. This is due to the fact that\n/// this type has three generic parameters where at least two should be known statically and it is really awkward to spell out this type.\n/// Moreover, having a wrapping type allows to optimize this to specialized calls if all generic types are known.\n///\n/// - Important: This sequence is a unicast sequence that only supports a single ``NIOAsyncSequenceProducer/AsyncIterator``.\n/// If you try to create more than one iterator it will result in a `fatalError`.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncSequenceProducer<\n    Element: Sendable,\n    Strategy: NIOAsyncSequenceProducerBackPressureStrategy,\n    Delegate: NIOAsyncSequenceProducerDelegate\n>: Sendable {\n    /// Simple struct for the return type of ``NIOAsyncSequenceProducer/makeSequence(elementType:backPressureStrategy:delegate:)``.\n    ///\n    /// This struct contains two properties:\n    /// 1. The ``source`` which should be retained by the producer and is used\n    /// to yield new elements to the sequence.\n    /// 2. The ``sequence`` which is the actual `AsyncSequence` and\n    /// should be passed to the consumer.\n    public struct NewSequence: Sendable {\n        /// The source of the ``NIOAsyncSequenceProducer`` used to yield and finish.\n        public let source: Source\n        /// The actual sequence which should be passed to the consumer.\n        public let sequence: NIOAsyncSequenceProducer\n\n        @usableFromInline\n        internal init(\n            source: Source,\n            sequence: NIOAsyncSequenceProducer\n        ) {\n            self.source = source\n            self.sequence = sequence\n        }\n    }\n\n    @usableFromInline\n    internal let _throwingSequence:\n        NIOThrowingAsyncSequenceProducer<\n            Element,\n            Never,\n            Strategy,\n            Delegate\n        >\n\n    /// Initializes a new ``NIOAsyncSequenceProducer`` and a ``NIOAsyncSequenceProducer/Source``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOAsyncSequenceProducer/Source`` and\n    /// a ``NIOAsyncSequenceProducer``. The source MUST be held by the caller and\n    /// used to signal new elements or finish. The sequence MUST be passed to the actual consumer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying source.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - backPressureStrategy: The back-pressure strategy of the sequence.\n    ///   - finishOnDeinit: Indicates if ``NIOAsyncSequenceProducer/Source/finish()`` should be called on deinit of the the source.\n    ///   We do not recommend to rely on  deinit based resource tear down.\n    ///   - delegate: The delegate of the sequence\n    /// - Returns: A ``NIOAsyncSequenceProducer/Source`` and a ``NIOAsyncSequenceProducer``.\n    @inlinable\n    public static func makeSequence(\n        elementType: Element.Type = Element.self,\n        backPressureStrategy: Strategy,\n        finishOnDeinit: Bool,\n        delegate: Delegate\n    ) -> NewSequence {\n        let newSequence = NIOThrowingAsyncSequenceProducer.makeNonThrowingSequence(\n            elementType: Element.self,\n            backPressureStrategy: backPressureStrategy,\n            finishOnDeinit: finishOnDeinit,\n            delegate: delegate\n        )\n\n        let sequence = self.init(throwingSequence: newSequence.sequence)\n\n        return .init(source: Source(throwingSource: newSequence.source), sequence: sequence)\n    }\n\n    /// Initializes a new ``NIOAsyncSequenceProducer`` and a ``NIOAsyncSequenceProducer/Source``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOAsyncSequenceProducer/Source`` and\n    /// a ``NIOAsyncSequenceProducer``. The source MUST be held by the caller and\n    /// used to signal new elements or finish. The sequence MUST be passed to the actual consumer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying source.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - backPressureStrategy: The back-pressure strategy of the sequence.\n    ///   - delegate: The delegate of the sequence\n    /// - Returns: A ``NIOAsyncSequenceProducer/Source`` and a ``NIOAsyncSequenceProducer``.\n    @inlinable\n    @available(\n        *,\n        deprecated,\n        renamed: \"makeSequence(elementType:backPressureStrategy:finishOnDeinit:delegate:)\",\n        message: \"This method has been deprecated since it defaults to deinit based resource teardown\"\n    )\n    public static func makeSequence(\n        elementType: Element.Type = Element.self,\n        backPressureStrategy: Strategy,\n        delegate: Delegate\n    ) -> NewSequence {\n        let newSequence = NIOThrowingAsyncSequenceProducer.makeNonThrowingSequence(\n            elementType: Element.self,\n            backPressureStrategy: backPressureStrategy,\n            finishOnDeinit: true,\n            delegate: delegate\n        )\n\n        let sequence = self.init(throwingSequence: newSequence.sequence)\n\n        return .init(source: Source(throwingSource: newSequence.source), sequence: sequence)\n    }\n\n    @inlinable\n    internal init(\n        throwingSequence: NIOThrowingAsyncSequenceProducer<Element, Never, Strategy, Delegate>\n    ) {\n        self._throwingSequence = throwingSequence\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncSequenceProducer: AsyncSequence {\n    public func makeAsyncIterator() -> AsyncIterator {\n        AsyncIterator(throwingIterator: self._throwingSequence.makeAsyncIterator())\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncSequenceProducer {\n    public struct AsyncIterator: AsyncIteratorProtocol {\n        @usableFromInline\n        internal let _throwingIterator:\n            NIOThrowingAsyncSequenceProducer<\n                Element,\n                Never,\n                Strategy,\n                Delegate\n            >.AsyncIterator\n\n        fileprivate init(\n            throwingIterator: NIOThrowingAsyncSequenceProducer<\n                Element,\n                Never,\n                Strategy,\n                Delegate\n            >.AsyncIterator\n        ) {\n            self._throwingIterator = throwingIterator\n        }\n\n        @inlinable\n        public func next() async -> Element? {\n            // this call will only throw if cancelled and we want to just return nil in that case\n            try? await self._throwingIterator.next()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncSequenceProducer {\n    /// A struct to interface between the synchronous code of the producer and the asynchronous consumer.\n    /// This type allows the producer to synchronously `yield` new elements to the ``NIOAsyncSequenceProducer``\n    /// and to `finish` the sequence.\n    public struct Source {\n        @usableFromInline\n        typealias ThrowingSource = NIOThrowingAsyncSequenceProducer<\n            Element,\n            Never,\n            Strategy,\n            Delegate\n        >.Source\n\n        @usableFromInline\n        internal var _throwingSource: ThrowingSource\n\n        @usableFromInline\n        internal init(throwingSource: ThrowingSource) {\n            self._throwingSource = throwingSource\n        }\n\n        /// The result of a call to ``NIOAsyncSequenceProducer/Source/yield(_:)``.\n        public enum YieldResult: Hashable, Sendable {\n            /// Indicates that the caller should produce more elements for now. The delegate's ``NIOAsyncSequenceProducerDelegate/produceMore()``\n            /// will **NOT** get called, since the demand was already signalled through this ``NIOAsyncSequenceProducer/Source/YieldResult``.\n            case produceMore\n            /// Indicates that the caller should stop producing elements. The delegate's ``NIOAsyncSequenceProducerDelegate/produceMore()``\n            /// will get called once production should be resumed.\n            case stopProducing\n            /// Indicates that the yielded elements have been dropped because the sequence already terminated.\n            case dropped\n        }\n\n        /// Yields a sequence of new elements to the ``NIOAsyncSequenceProducer``.\n        ///\n        /// If there is an ``NIOAsyncSequenceProducer/AsyncIterator`` awaiting the next element, it will get resumed right away.\n        /// Otherwise, the element will get buffered.\n        ///\n        /// If the ``NIOAsyncSequenceProducer`` is terminated this will drop the elements\n        /// and return ``YieldResult/dropped``.\n        ///\n        /// This can be called more than once and returns to the caller immediately\n        /// without blocking for any awaiting consumption from the iteration.\n        ///\n        /// - Parameter sequence: The sequence to yield.\n        /// - Returns: A ``NIOAsyncSequenceProducer/Source/YieldResult`` that indicates if the yield was successful\n        /// and if more elements should be produced.\n        @inlinable\n        public func yield<S: Sequence>(contentsOf sequence: S) -> YieldResult where S.Element == Element {\n            switch self._throwingSource.yield(contentsOf: sequence) {\n            case .stopProducing:\n                return .stopProducing\n            case .produceMore:\n                return .produceMore\n            case .dropped:\n                return .dropped\n            }\n        }\n\n        /// Yields a new elements to the ``NIOAsyncSequenceProducer``.\n        ///\n        /// If there is an ``NIOAsyncSequenceProducer/AsyncIterator`` awaiting the next element, it will get resumed right away.\n        /// Otherwise, the element will get buffered.\n        ///\n        /// If the ``NIOAsyncSequenceProducer`` is terminated this will drop the elements\n        /// and return ``YieldResult/dropped``.\n        ///\n        /// This can be called more than once and returns to the caller immediately\n        /// without blocking for any awaiting consumption from the iteration.\n        ///\n        /// - Parameter element: The element to yield.\n        /// - Returns: A ``NIOAsyncSequenceProducer/Source/YieldResult`` that indicates if the yield was successful\n        /// and if more elements should be produced.\n        @inlinable\n        public func yield(_ element: Element) -> YieldResult {\n            self.yield(contentsOf: CollectionOfOne(element))\n        }\n\n        /// Finishes the sequence.\n        ///\n        /// Calling this function signals the sequence that there won't be any subsequent elements yielded.\n        ///\n        /// If there are still buffered elements and there is an ``NIOAsyncSequenceProducer/AsyncIterator`` consuming the sequence,\n        /// then termination of the sequence only happens once all elements have been consumed by the ``NIOAsyncSequenceProducer/AsyncIterator``.\n        /// Otherwise, the buffered elements will be dropped.\n        ///\n        /// - Note: Calling this function more than once has no effect.\n        @inlinable\n        public func finish() {\n            self._throwingSource.finish()\n        }\n    }\n}\n\n/// The ``NIOAsyncSequenceProducer/AsyncIterator`` MUST NOT be shared across `Task`s. With marking this as\n/// unavailable we are explicitly declaring this.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@available(*, unavailable)\nextension NIOAsyncSequenceProducer.AsyncIterator: Sendable {}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncSequenceProducer.Source: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncSequences/NIOAsyncSequenceProducerStrategies.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\npublic enum NIOAsyncSequenceProducerBackPressureStrategies: Sendable {\n    /// A high-low watermarked back-pressure strategy for a ``NIOAsyncSequenceProducer``.\n    ///\n    /// This strategy does the following:\n    /// - On yield it keeps on demanding more elements from the producer as long as the number of buffered elements hasn't reached the `highWatermark`.\n    /// - On consume it starts to demand again from the producer once the number of buffered elements reach the `lowWatermark`.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public struct HighLowWatermark: NIOAsyncSequenceProducerBackPressureStrategy {\n        private let lowWatermark: Int\n        private let highWatermark: Int\n        private var hasOustandingDemand: Bool = true\n\n        /// Initializes a new ``NIOAsyncSequenceProducerBackPressureStrategies/HighLowWatermark``.\n        ///\n        /// - Parameters:\n        ///   - lowWatermark: The low watermark where demand should start.\n        ///   - highWatermark: The high watermark where demand should be stopped.\n        public init(lowWatermark: Int, highWatermark: Int) {\n            precondition(lowWatermark <= highWatermark)\n            self.lowWatermark = lowWatermark\n            self.highWatermark = highWatermark\n        }\n\n        public mutating func didYield(bufferDepth: Int) -> Bool {\n            // We are demanding more until we reach the high watermark\n            if bufferDepth >= self.highWatermark {\n                self.hasOustandingDemand = false\n            }\n\n            return self.hasOustandingDemand\n        }\n\n        public mutating func didConsume(bufferDepth: Int) -> Bool {\n            // We start demanding again once we are below the low watermark\n            if bufferDepth < self.lowWatermark {\n                self.hasOustandingDemand = true\n            }\n\n            return self.hasOustandingDemand\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport DequeModule\nimport NIOConcurrencyHelpers\nimport _NIODataStructures\n\n@usableFromInline\nlet _asyncWriterYieldIDCounter = ManagedAtomic<UInt64>(0)\n\n/// The delegate of the ``NIOAsyncWriter``. It is the consumer of the yielded writes to the ``NIOAsyncWriter``.\n/// Furthermore, the delegate gets informed when the ``NIOAsyncWriter`` terminated.\n///\n/// - Important: The methods on the delegate might be called on arbitrary threads and the implementation must ensure\n/// that proper synchronization is in place.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic protocol NIOAsyncWriterSinkDelegate: Sendable {\n    /// The `Element` type of the delegate and the writer.\n    associatedtype Element: Sendable\n\n    /// This method is called once a sequence was yielded to the ``NIOAsyncWriter``.\n    ///\n    /// If the ``NIOAsyncWriter`` was writable when the sequence was yielded, the sequence will be forwarded\n    /// right away to the delegate. If the ``NIOAsyncWriter`` was _NOT_ writable then the sequence will be buffered\n    /// until the ``NIOAsyncWriter`` becomes writable again.\n    ///\n    /// The delegate might reentrantly call ``NIOAsyncWriter/Sink/setWritability(to:)`` while still processing writes.\n    func didYield(contentsOf sequence: Deque<Element>)\n\n    /// This method is called once a single element was yielded to the ``NIOAsyncWriter``.\n    ///\n    /// If the ``NIOAsyncWriter`` was writable when the sequence was yielded, the sequence will be forwarded\n    /// right away to the delegate. If the ``NIOAsyncWriter`` was _NOT_ writable then the sequence will be buffered\n    /// until the ``NIOAsyncWriter`` becomes writable again.\n    ///\n    /// - Note: This a fast path that you can optionally implement. By default this will just call ``NIOAsyncWriterSinkDelegate/didYield(contentsOf:)``.\n    ///\n    /// The delegate might reentrantly call ``NIOAsyncWriter/Sink/setWritability(to:)`` while still processing writes.\n    func didYield(_ element: Element)\n\n    /// This method is called once the ``NIOAsyncWriter`` is terminated.\n    ///\n    /// Termination happens if:\n    /// - The ``NIOAsyncWriter`` is deinited and all yielded elements have been delivered to the delegate.\n    /// - ``NIOAsyncWriter/finish()`` is called and all yielded elements have been delivered to the delegate.\n    /// - ``NIOAsyncWriter/finish(error:)`` is called and all yielded elements have been delivered to the delegate.\n    ///\n    /// - Note: This is guaranteed to be called _at most_ once.\n    ///\n    /// - Parameter error: The error that terminated the ``NIOAsyncWriter``. If the writer was terminated without an\n    /// error this value is `nil`. This can be either the error passed to ``NIOAsyncWriter/finish(error:)``.\n    func didTerminate(error: Error?)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncWriterSinkDelegate {\n    @inlinable\n    public func didYield(_ element: Element) {\n        self.didYield(contentsOf: .init(CollectionOfOne(element)))\n    }\n}\n\n/// Errors thrown by the ``NIOAsyncWriter``.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncWriterError: Error, Hashable, CustomStringConvertible {\n    @usableFromInline\n    internal enum _Code: String, Hashable, Sendable {\n        case alreadyFinished\n    }\n\n    @usableFromInline\n    let _code: _Code\n\n    public var file: String\n\n    public var line: Int\n\n    @inlinable\n    init(_code: _Code, file: String, line: Int) {\n        self._code = _code\n        self.file = file\n        self.line = line\n    }\n\n    @inlinable\n    public static func == (lhs: NIOAsyncWriterError, rhs: NIOAsyncWriterError) -> Bool {\n        lhs._code == rhs._code\n    }\n\n    @inlinable\n    public func hash(into hasher: inout Hasher) {\n        hasher.combine(self._code)\n    }\n\n    /// Indicates that the ``NIOAsyncWriter`` has already finished and is not accepting any more writes.\n    @inlinable\n    public static func alreadyFinished(file: String = #fileID, line: Int = #line) -> Self {\n        .init(_code: .alreadyFinished, file: file, line: line)\n    }\n\n    @inlinable\n    public var description: String {\n        \"NIOAsyncWriterError.\\(self._code.rawValue): \\(self.file):\\(self.line)\"\n    }\n}\n\n/// A ``NIOAsyncWriter`` is a type used to bridge elements from the Swift Concurrency domain into\n/// a synchronous world. The `Task`s that are yielding to the ``NIOAsyncWriter`` are the producers.\n/// Whereas the ``NIOAsyncWriterSinkDelegate`` is the consumer.\n///\n/// Additionally, the ``NIOAsyncWriter`` allows the consumer to set the writability by calling ``NIOAsyncWriter/Sink/setWritability(to:)``.\n/// This allows the implementation of flow control on the consumer side. Any call to ``NIOAsyncWriter/yield(contentsOf:)`` or ``NIOAsyncWriter/yield(_:)``\n/// will suspend if the ``NIOAsyncWriter`` is not writable and will be resumed after the ``NIOAsyncWriter`` becomes writable again\n/// or if the ``NIOAsyncWriter`` has finished.\n///\n/// - Note: It is recommended to never directly expose this type from APIs, but rather wrap it. This is due to the fact that\n/// this type has two generic parameters where at least the `Delegate` should be known statically and it is really awkward to spell out this type.\n/// Moreover, having a wrapping type allows to optimize this to specialized calls if all generic types are known.\n///\n/// - Note: This struct has reference semantics. Once all copies of a writer have been dropped ``NIOAsyncWriterSinkDelegate/didTerminate(error:)`` will be called.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncWriter<\n    Element,\n    Delegate: NIOAsyncWriterSinkDelegate\n>: Sendable where Delegate.Element == Element {\n    /// Simple struct for the return type of ``NIOAsyncWriter/makeWriter(elementType:isWritable:delegate:)``.\n    ///\n    /// This struct contains two properties:\n    /// 1. The ``sink`` which should be retained by the consumer and is used to set the writability.\n    /// 2. The ``writer`` which is the actual ``NIOAsyncWriter`` and should be passed to the producer.\n    public struct NewWriter: Sendable {\n        /// The ``sink`` which **MUST** be retained by the consumer and is used to set the writability.\n        public let sink: Sink\n        /// The ``writer`` which is the actual ``NIOAsyncWriter`` and should be passed to the producer.\n        public let writer: NIOAsyncWriter\n\n        @inlinable\n        internal init(\n            sink: Sink,\n            writer: NIOAsyncWriter\n        ) {\n            self.sink = sink\n            self.writer = writer\n        }\n    }\n\n    /// This class is needed to hook the deinit to observe once all references to the ``NIOAsyncWriter`` are dropped.\n    @usableFromInline\n    internal final class InternalClass: Sendable {\n        @usableFromInline\n        internal let _storage: Storage\n\n        @usableFromInline\n        internal let _finishOnDeinit: Bool\n\n        @inlinable\n        init(storage: Storage, finishOnDeinit: Bool) {\n            self._storage = storage\n            self._finishOnDeinit = finishOnDeinit\n        }\n\n        @inlinable\n        deinit {\n            if !self._finishOnDeinit && !self._storage.isWriterFinished {\n                preconditionFailure(\"Deinited NIOAsyncWriter without calling finish()\")\n            } else {\n                // We need to call finish here to resume any suspended continuation.\n                self._storage.writerFinish(error: nil)\n            }\n        }\n    }\n\n    @usableFromInline\n    internal let _internalClass: InternalClass\n\n    @inlinable\n    internal var _storage: Storage {\n        self._internalClass._storage\n    }\n\n    /// Initializes a new ``NIOAsyncWriter`` and a ``NIOAsyncWriter/Sink``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOAsyncWriter/Sink`` and\n    /// a ``NIOAsyncWriter``. The sink MUST be held by the caller and is used to set the writability.\n    /// The writer MUST be passed to the actual producer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying sink.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - isWritable: The initial writability state of the writer.\n    ///   - delegate: The delegate of the writer.\n    /// - Returns: A ``NIOAsyncWriter/NewWriter``.\n    @inlinable\n    @available(\n        *,\n        deprecated,\n        renamed: \"makeWriter(elementType:isWritable:finishOnDeinit:delegate:)\",\n        message: \"This method has been deprecated since it defaults to deinit based resource teardown\"\n    )\n    public static func makeWriter(\n        elementType: Element.Type = Element.self,\n        isWritable: Bool,\n        delegate: Delegate\n    ) -> NewWriter {\n        let writer = Self(\n            isWritable: isWritable,\n            finishOnDeinit: true,\n            delegate: delegate\n        )\n        let sink = Sink(storage: writer._storage, finishOnDeinit: true)\n\n        return .init(sink: sink, writer: writer)\n    }\n\n    /// Initializes a new ``NIOAsyncWriter`` and a ``NIOAsyncWriter/Sink``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOAsyncWriter/Sink`` and\n    /// a ``NIOAsyncWriter``. The sink MUST be held by the caller and is used to set the writability.\n    /// The writer MUST be passed to the actual producer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying sink.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - isWritable: The initial writability state of the writer.\n    ///   - finishOnDeinit: Indicates if ``NIOAsyncWriter/finish()`` should be called on deinit. We do not recommend to rely on\n    ///   deinit based resource tear down.\n    ///   - delegate: The delegate of the writer.\n    /// - Returns: A ``NIOAsyncWriter/NewWriter``.\n    @inlinable\n    public static func makeWriter(\n        elementType: Element.Type = Element.self,\n        isWritable: Bool,\n        finishOnDeinit: Bool,\n        delegate: Delegate\n    ) -> NewWriter {\n        let writer = Self(\n            isWritable: isWritable,\n            finishOnDeinit: finishOnDeinit,\n            delegate: delegate\n        )\n        let sink = Sink(storage: writer._storage, finishOnDeinit: finishOnDeinit)\n\n        return .init(sink: sink, writer: writer)\n    }\n\n    @inlinable\n    internal init(\n        isWritable: Bool,\n        finishOnDeinit: Bool,\n        delegate: Delegate\n    ) {\n        let storage = Storage(\n            isWritable: isWritable,\n            delegate: delegate\n        )\n        self._internalClass = .init(storage: storage, finishOnDeinit: finishOnDeinit)\n    }\n\n    /// Yields a sequence of new elements to the ``NIOAsyncWriter``.\n    ///\n    /// If the ``NIOAsyncWriter`` is writable the sequence will get forwarded to the ``NIOAsyncWriterSinkDelegate`` immediately.\n    /// Otherwise, the sequence will be buffered and the call to ``NIOAsyncWriter/yield(contentsOf:)`` will get suspended until the ``NIOAsyncWriter``\n    /// becomes writable again.\n    ///\n    /// If the calling `Task` gets cancelled at any point the call to ``NIOAsyncWriter/yield(contentsOf:)``\n    /// will be resumed. Consequently, the provided elements will not be yielded.\n    ///\n    /// This can be called more than once and from multiple `Task`s at the same time.\n    ///\n    /// - Parameter sequence: The sequence to yield.\n    @inlinable\n    public func yield<S: Sequence>(contentsOf sequence: S) async throws where S.Element == Element {\n        try await self._storage.yield(contentsOf: sequence)\n    }\n\n    /// Yields an element to the ``NIOAsyncWriter``.\n    ///\n    /// If the ``NIOAsyncWriter`` is writable the element will get forwarded to the ``NIOAsyncWriterSinkDelegate`` immediately.\n    /// Otherwise, the element will be buffered and the call to ``NIOAsyncWriter/yield(_:)`` will get suspended until the ``NIOAsyncWriter``\n    /// becomes writable again.\n    ///\n    /// If the calling `Task` gets cancelled at any point the call to ``NIOAsyncWriter/yield(_:)``\n    /// will be resumed. Consequently, the provided element will not be yielded.\n    ///\n    /// This can be called more than once and from multiple `Task`s at the same time.\n    ///\n    /// - Parameter element: The element to yield.\n    @inlinable\n    public func yield(_ element: Element) async throws {\n        try await self._storage.yield(element: element)\n    }\n\n    /// Finishes the writer.\n    ///\n    /// Calling this function signals the writer that any suspended calls to ``NIOAsyncWriter/yield(contentsOf:)``\n    /// or ``NIOAsyncWriter/yield(_:)`` will be resumed. Any subsequent calls to ``NIOAsyncWriter/yield(contentsOf:)``\n    /// or ``NIOAsyncWriter/yield(_:)`` will throw.\n    ///\n    /// Any element that have been yielded before the writer has been finished which have not been delivered yet are continued\n    /// to be buffered and will be delivered once the writer becomes writable again.\n    ///\n    /// - Note: Calling this function more than once has no effect.\n    @inlinable\n    public func finish() {\n        self._storage.writerFinish(error: nil)\n    }\n\n    /// Finishes the writer.\n    ///\n    /// Calling this function signals the writer that any suspended calls to ``NIOAsyncWriter/yield(contentsOf:)``\n    /// or ``NIOAsyncWriter/yield(_:)`` will be resumed. Any subsequent calls to ``NIOAsyncWriter/yield(contentsOf:)``\n    /// or ``NIOAsyncWriter/yield(_:)`` will throw.\n    ///\n    /// Any element that have been yielded before the writer has been finished which have not been delivered yet are continued\n    /// to be buffered and will be delivered once the writer becomes writable again.\n    ///\n    /// - Note: Calling this function more than once has no effect.\n    /// - Parameter error: The error indicating why the writer finished.\n    @inlinable\n    public func finish(error: Error) {\n        self._storage.writerFinish(error: error)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncWriter {\n    /// The underlying sink of the ``NIOAsyncWriter``. This type allows to set the writability of the ``NIOAsyncWriter``.\n    ///\n    /// - Important: Once all copies to the ``NIOAsyncWriter/Sink`` are destroyed the ``NIOAsyncWriter`` will get finished.\n    public struct Sink: Sendable {\n        /// This class is needed to hook the deinit to observe once all references to the ``NIOAsyncWriter/Sink`` are dropped.\n        @usableFromInline\n        internal final class InternalClass: Sendable {\n            @usableFromInline\n            internal let _storage: Storage\n\n            @usableFromInline\n            internal let _finishOnDeinit: Bool\n\n            @inlinable\n            init(storage: Storage, finishOnDeinit: Bool) {\n                self._storage = storage\n                self._finishOnDeinit = finishOnDeinit\n            }\n\n            @inlinable\n            deinit {\n                if !self._finishOnDeinit && !self._storage.isSinkFinished {\n                    preconditionFailure(\"Deinited NIOAsyncWriter.Sink without calling sink.finish()\")\n                } else {\n                    // We need to call finish here to resume any suspended continuation.\n                    self._storage.sinkFinish(error: nil)\n                }\n            }\n        }\n\n        @usableFromInline\n        internal let _internalClass: InternalClass\n\n        @inlinable\n        internal var _storage: Storage {\n            self._internalClass._storage\n        }\n\n        @inlinable\n        init(storage: Storage, finishOnDeinit: Bool) {\n            self._internalClass = .init(storage: storage, finishOnDeinit: finishOnDeinit)\n        }\n\n        /// Sets the writability of the ``NIOAsyncWriter``.\n        ///\n        /// If the writer becomes writable again all suspended yields will be resumed and the produced elements will be forwarded via\n        /// the ``NIOAsyncWriterSinkDelegate/didYield(contentsOf:)`` method. If the writer becomes unwritable all\n        /// subsequent calls to ``NIOAsyncWriterSinkDelegate/didYield(contentsOf:)`` will suspend.\n        ///\n        /// - Parameter writability: The new writability of the ``NIOAsyncWriter``.\n        @inlinable\n        public func setWritability(to writability: Bool) {\n            self._storage.setWritability(to: writability)\n        }\n\n        /// Finishes the sink which will result in the ``NIOAsyncWriter`` being finished.\n        ///\n        /// Calling this function signals the writer that any suspended or subsequent calls to ``NIOAsyncWriter/yield(contentsOf:)``\n        /// or ``NIOAsyncWriter/yield(_:)`` will return a ``NIOAsyncWriterError/alreadyFinished(file:line:)`` error.\n        ///\n        /// - Note: Calling this function more than once has no effect.\n        @inlinable\n        public func finish() {\n            self._storage.sinkFinish(error: nil)\n        }\n\n        /// Finishes the sink which will result in the ``NIOAsyncWriter`` being finished.\n        ///\n        /// Calling this function signals the writer that any suspended or subsequent calls to ``NIOAsyncWriter/yield(contentsOf:)``\n        /// or ``NIOAsyncWriter/yield(_:)`` will return the passed error parameter.\n        ///\n        /// - Note: Calling this function more than once has no effect.\n        @inlinable\n        public func finish(error: Error) {\n            self._storage.sinkFinish(error: error)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncWriter {\n    /// This is the underlying storage of the writer. The goal of this is to synchronize the access to all state.\n    @usableFromInline\n    internal struct Storage: Sendable {\n        /// Internal type to generate unique yield IDs.\n        ///\n        /// This type has reference semantics.\n        @usableFromInline\n        struct YieldIDGenerator: Sendable {\n            /// A struct representing a unique yield ID.\n            @usableFromInline\n            struct YieldID: Equatable, Sendable {\n                @usableFromInline\n                internal var value: UInt64\n\n                @inlinable\n                init(value: UInt64) {\n                    self.value = value\n                }\n\n                @inlinable\n                static func == (lhs: Self, rhs: Self) -> Bool {\n                    lhs.value == rhs.value\n                }\n            }\n\n            @inlinable\n            func generateUniqueYieldID() -> YieldID {\n                // Using relaxed is fine here since we do not need any strict ordering just a\n                // unique ID for every yield.\n                .init(value: _asyncWriterYieldIDCounter.loadThenWrappingIncrement(ordering: .relaxed))\n            }\n        }\n\n        /// The counter used to assign an ID to all our yields.\n        @usableFromInline\n        internal let _yieldIDGenerator = YieldIDGenerator()\n        /// The state machine.\n        @usableFromInline\n        internal let _state: NIOLockedValueBox<State>\n\n        @usableFromInline\n        struct State: Sendable {\n            @usableFromInline\n            var stateMachine: StateMachine\n            @usableFromInline\n            var didSuspend: (@Sendable () -> Void)?\n\n            @inlinable\n            init(stateMachine: StateMachine) {\n                self.stateMachine = stateMachine\n                self.didSuspend = nil\n            }\n        }\n\n        /// Hook used in testing.\n        @usableFromInline\n        internal func _setDidSuspend(_ didSuspend: (@Sendable () -> Void)?) {\n            self._state.withLockedValue {\n                $0.didSuspend = didSuspend\n            }\n        }\n\n        @inlinable\n        internal var isWriterFinished: Bool {\n            self._state.withLockedValue { $0.stateMachine.isWriterFinished }\n        }\n\n        @inlinable\n        internal var isSinkFinished: Bool {\n            self._state.withLockedValue { $0.stateMachine.isSinkFinished }\n        }\n\n        @inlinable\n        internal init(\n            isWritable: Bool,\n            delegate: Delegate\n        ) {\n            let state = State(stateMachine: StateMachine(isWritable: isWritable, delegate: delegate))\n            self._state = NIOLockedValueBox(state)\n        }\n\n        @inlinable\n        internal func setWritability(to writability: Bool) {\n            // We must not resume the continuation while holding the lock\n            // because it can deadlock in combination with the underlying ulock\n            // in cases where we race with a cancellation handler\n            let action = self._state.withLockedValue {\n                $0.stateMachine.setWritability(to: writability)\n            }\n\n            switch action {\n            case .resumeContinuations(let suspendedYields):\n                for yield in suspendedYields {\n                    yield.continuation.resume(returning: .retry)\n                }\n\n            case .none:\n                return\n            }\n        }\n\n        @inlinable\n        internal func yield<S: Sequence>(contentsOf sequence: S) async throws\n        where S.Element == Element {\n            let yieldID = self._yieldIDGenerator.generateUniqueYieldID()\n            while true {\n                switch try await self._yield(contentsOf: sequence, yieldID: yieldID) {\n                case .retry:\n                    continue\n                case .yielded:\n                    return\n                }\n            }\n        }\n\n        @inlinable\n        internal func _yield<S: Sequence>(\n            contentsOf sequence: S,\n            yieldID: StateMachine.YieldID?\n        ) async throws -> StateMachine.YieldResult where S.Element == Element {\n            let yieldID = yieldID ?? self._yieldIDGenerator.generateUniqueYieldID()\n\n            return try await withTaskCancellationHandler {\n                let action = self._state.withLockedValue {\n                    $0.stateMachine.yield(yieldID: yieldID)\n                }\n\n                switch action {\n                case .callDidYield(let delegate):\n                    // We are allocating a new Deque for every write here\n                    delegate.didYield(contentsOf: Deque(sequence))\n                    self.unbufferQueuedEvents()\n                    return .yielded\n\n                case .throwError(let error):\n                    throw error\n\n                case .suspendTask:\n                    // Holding the lock here *should* be safe but because of a bug in the runtime\n                    // it isn't, so drop the lock, create the continuation and then try again.\n                    //\n                    // See https://github.com/swiftlang/swift/issues/85668\n                    //\n                    // Dropping and reacquiring the lock may result in yields being reordered but\n                    // only from the perspective of when this function was entered. For example:\n                    //\n                    // - T1 calls _yield\n                    // - T2 calls _yield\n                    // - T2 returns from _yield\n                    // - T1 returns from _yield\n                    //\n                    // This is fine: the async writer doesn't offer any ordering guarantees for\n                    // calls made from different threads.\n                    //\n                    // Within a thread there is no possibility of re-ordering as the call only\n                    // returns once the write has been yielded.\n                    //\n                    // We switched to using NIOUnsafeContinuation after running with\n                    // CheckedContinuation for more than a year. Now we use NIOUnsafeContinuation\n                    // to reduce runtime costs.\n                    return try await withNIOUnsafeThrowingContinuation {\n                        (continuation: NIOUnsafeContinuation<StateMachine.YieldResult, Error>) in\n                        let (action, didSuspend) = self._state.withLockedValue {\n                            state -> (NIOAsyncWriter.StateMachine.YieldAction, (@Sendable () -> Void)?) in\n                            let yieldAction = state.stateMachine.yield(yieldID: yieldID)\n                            switch yieldAction {\n                            case .callDidYield, .throwError:\n                                return (yieldAction, nil)\n                            case .suspendTask:\n                                switch state.stateMachine.yield(\n                                    continuation: continuation,\n                                    yieldID: yieldID\n                                ) {\n                                case .cancelled:\n                                    return (.throwError(CancellationError()), nil)\n                                case .suspended:\n                                    return (yieldAction, state.didSuspend)\n                                }\n                            }\n                        }\n\n                        switch action {\n                        case .callDidYield(let delegate):\n                            delegate.didYield(contentsOf: Deque(sequence))\n                            self.unbufferQueuedEvents()\n                            continuation.resume(returning: .yielded)\n\n                        case .throwError(let error):\n                            continuation.resume(throwing: error)\n\n                        case .suspendTask:\n                            didSuspend?()\n                        }\n                    }\n                }\n            } onCancel: {\n                // We must not resume the continuation while holding the lock\n                // because it can deadlock in combination with the underlying ulock\n                // in cases where we race with a cancellation handler\n                let action = self._state.withLockedValue {\n                    $0.stateMachine.cancel(yieldID: yieldID)\n                }\n\n                switch action {\n                case .resumeContinuationWithCancellationError(let continuation):\n                    continuation.resume(throwing: CancellationError())\n\n                case .none:\n                    break\n                }\n            }\n        }\n\n        @inlinable\n        internal func yield(element: Element) async throws {\n            let yieldID = self._yieldIDGenerator.generateUniqueYieldID()\n            while true {\n                switch try await self._yield(element: element, yieldID: yieldID) {\n                case .retry:\n                    continue\n                case .yielded:\n                    return\n                }\n            }\n        }\n\n        @inlinable\n        internal func _yield(\n            element: Element,\n            yieldID: StateMachine.YieldID?\n        ) async throws -> StateMachine.YieldResult {\n            let yieldID = yieldID ?? self._yieldIDGenerator.generateUniqueYieldID()\n\n            return try await withTaskCancellationHandler {\n                let action = self._state.withLockedValue {\n                    $0.stateMachine.yield(yieldID: yieldID)\n                }\n\n                switch action {\n                case .callDidYield(let delegate):\n                    delegate.didYield(element)\n                    self.unbufferQueuedEvents()\n                    return .yielded\n\n                case .throwError(let error):\n                    throw error\n\n                case .suspendTask:\n                    // Holding the lock here *should* be safe but because of a bug in the runtime\n                    // it isn't, so drop the lock, create the continuation and then try again.\n                    //\n                    // See https://github.com/swiftlang/swift/issues/85668\n                    //\n                    // Dropping and reacquiring the lock may result in yields being reordered but\n                    // only from the perspective of when this function was entered. For example:\n                    //\n                    // - T1 calls _yield\n                    // - T2 calls _yield\n                    // - T2 returns from _yield\n                    // - T1 returns from _yield\n                    //\n                    // This is fine: the async writer doesn't offer any ordering guarantees for\n                    // calls made from different threads.\n                    //\n                    // Within a thread there is no possibility of re-ordering as the call only\n                    // returns once the write has been yielded.\n                    //\n                    // We switched to using NIOUnsafeContinuation after running with\n                    // CheckedContinuation for more than a year. Now we use NIOUnsafeContinuation\n                    // to reduce runtime costs.\n                    return try await withNIOUnsafeThrowingContinuation {\n                        (continuation: NIOUnsafeContinuation<StateMachine.YieldResult, Error>) in\n                        let (action, didSuspend) = self._state.withLockedValue {\n                            state -> (NIOAsyncWriter.StateMachine.YieldAction, (@Sendable () -> Void)?) in\n                            let yieldAction = state.stateMachine.yield(yieldID: yieldID)\n                            switch yieldAction {\n                            case .callDidYield, .throwError:\n                                return (yieldAction, nil)\n                            case .suspendTask:\n                                switch state.stateMachine.yield(\n                                    continuation: continuation,\n                                    yieldID: yieldID\n                                ) {\n                                case .cancelled:\n                                    return (.throwError(CancellationError()), nil)\n                                case .suspended:\n                                    return (yieldAction, state.didSuspend)\n                                }\n                            }\n                        }\n\n                        switch action {\n                        case .callDidYield(let delegate):\n                            delegate.didYield(element)\n                            self.unbufferQueuedEvents()\n                            continuation.resume(returning: .yielded)\n\n                        case .throwError(let error):\n                            continuation.resume(throwing: error)\n\n                        case .suspendTask:\n                            didSuspend?()\n                        }\n                    }\n                }\n            } onCancel: {\n                // We must not resume the continuation while holding the lock\n                // because it can deadlock in combination with the underlying lock\n                // in cases where we race with a cancellation handler\n                let action = self._state.withLockedValue {\n                    $0.stateMachine.cancel(yieldID: yieldID)\n                }\n\n                switch action {\n                case .resumeContinuationWithCancellationError(let continuation):\n                    continuation.resume(throwing: CancellationError())\n\n                case .none:\n                    break\n                }\n            }\n        }\n\n        @inlinable\n        internal func writerFinish(error: Error?) {\n            // We must not resume the continuation while holding the lock\n            // because it can deadlock in combination with the underlying ulock\n            // in cases where we race with a cancellation handler\n            let action = self._state.withLockedValue {\n                $0.stateMachine.writerFinish(error: error)\n            }\n\n            switch action {\n            case .callDidTerminate(let delegate):\n                delegate.didTerminate(error: error)\n\n            case .resumeContinuations(let suspendedYields):\n                for yield in suspendedYields {\n                    yield.continuation.resume(returning: .retry)\n                }\n\n            case .none:\n                break\n            }\n        }\n\n        @inlinable\n        internal func sinkFinish(error: Error?) {\n            // We must not resume the continuation while holding the lock\n            // because it can deadlock in combination with the underlying ulock\n            // in cases where we race with a cancellation handler\n            let action = self._state.withLockedValue {\n                $0.stateMachine.sinkFinish(error: error)\n            }\n\n            switch action {\n            case .resumeContinuationsWithError(let suspendedYields, let error):\n                for yield in suspendedYields {\n                    yield.continuation.resume(throwing: error)\n                }\n\n            case .none:\n                break\n            }\n        }\n\n        @inlinable\n        internal func unbufferQueuedEvents() {\n            while let action = self._state.withLockedValue({ $0.stateMachine.unbufferQueuedEvents() }) {\n                switch action {\n                case .callDidTerminate(let delegate, let error):\n                    delegate.didTerminate(error: error)\n\n                case .resumeContinuations(let suspendedYields):\n                    for yield in suspendedYields {\n                        yield.continuation.resume(returning: .retry)\n                    }\n                    return\n                }\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncWriter {\n    @usableFromInline\n    internal struct StateMachine: Sendable {\n        @usableFromInline\n        typealias YieldID = Storage.YieldIDGenerator.YieldID\n        /// This is a small helper struct to encapsulate the two different values for a suspended yield.\n        @usableFromInline\n        internal struct SuspendedYield: Sendable {\n            /// The yield's ID.\n            @usableFromInline\n            var yieldID: YieldID\n            /// The yield's produced sequence of elements.\n            /// The yield's continuation.\n            @usableFromInline\n            var continuation: NIOUnsafeContinuation<YieldResult, Error>\n\n            @inlinable\n            init(yieldID: YieldID, continuation: NIOUnsafeContinuation<YieldResult, Error>) {\n                self.yieldID = yieldID\n                self.continuation = continuation\n            }\n        }\n        /// The internal result of a yield.\n        @usableFromInline\n        internal enum YieldResult: Sendable {\n            /// Indicates that the elements got yielded to the sink.\n            case yielded\n            /// Indicates that the yield should be retried.\n            case retry\n        }\n\n        /// The current state of our ``NIOAsyncWriter``.\n        @usableFromInline\n        internal enum State: Sendable, CustomStringConvertible {\n            /// The initial state before either a call to ``NIOAsyncWriter/yield(contentsOf:)`` or\n            /// ``NIOAsyncWriter/finish(completion:)`` happened.\n            case initial(\n                isWritable: Bool,\n                delegate: Delegate\n            )\n\n            /// The state after a call to ``NIOAsyncWriter/yield(contentsOf:)``.\n            case streaming(\n                isWritable: Bool,\n                inDelegateOutcall: Bool,\n                cancelledYields: [YieldID],\n                suspendedYields: _TinyArray<SuspendedYield>,\n                delegate: Delegate\n            )\n\n            /// The state once the writer finished and there are still tasks that need to write. This can happen if:\n            /// 1. The ``NIOAsyncWriter`` was deinited\n            /// 2. ``NIOAsyncWriter/finish(completion:)`` was called.\n            case writerFinished(\n                isWritable: Bool,\n                inDelegateOutcall: Bool,\n                suspendedYields: _TinyArray<SuspendedYield>,\n                cancelledYields: [YieldID],\n                // These are the yields that have been enqueued before the writer got finished.\n                bufferedYieldIDs: _TinyArray<YieldID>,\n                delegate: Delegate,\n                error: Error?\n            )\n\n            /// The state once the sink has been finished or the writer has been finished and all elements\n            /// have been delivered to the delegate.\n            case finished(sinkError: Error?)\n\n            /// Internal state to avoid CoW.\n            case modifying\n\n            @usableFromInline\n            var description: String {\n                switch self {\n                case .initial(let isWritable, _):\n                    return \"initial(isWritable: \\(isWritable))\"\n                case .streaming(let isWritable, let inDelegateOutcall, let cancelledYields, let suspendedYields, _):\n                    return\n                        \"streaming(isWritable: \\(isWritable), inDelegateOutcall: \\(inDelegateOutcall), cancelledYields: \\(cancelledYields.count), suspendedYields: \\(suspendedYields.count))\"\n                case .writerFinished(\n                    let isWritable,\n                    let inDelegateOutcall,\n                    let suspendedYields,\n                    let cancelledYields,\n                    let bufferedYieldIDs,\n                    _,\n                    _\n                ):\n                    return\n                        \"writerFinished(isWritable: \\(isWritable), inDelegateOutcall: \\(inDelegateOutcall), suspendedYields: \\(suspendedYields.count), cancelledYields: \\(cancelledYields.count), bufferedYieldIDs: \\(bufferedYieldIDs.count)\"\n                case .finished:\n                    return \"finished\"\n                case .modifying:\n                    return \"modifying\"\n                }\n            }\n        }\n\n        /// The state machine's current state.\n        @usableFromInline\n        internal var _state: State\n\n        @inlinable\n        internal var isWriterFinished: Bool {\n            switch self._state {\n            case .initial, .streaming:\n                return false\n            case .writerFinished, .finished:\n                return true\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        @inlinable\n        internal var isSinkFinished: Bool {\n            switch self._state {\n            case .initial, .streaming, .writerFinished:\n                return false\n            case .finished:\n                return true\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        @inlinable\n        init(\n            isWritable: Bool,\n            delegate: Delegate\n        ) {\n            self._state = .initial(isWritable: isWritable, delegate: delegate)\n        }\n\n        /// Actions returned by `setWritability()`.\n        @usableFromInline\n        enum SetWritabilityAction: Sendable {\n            /// Indicates that all writer continuations should be resumed.\n            case resumeContinuations(_TinyArray<SuspendedYield>)\n        }\n\n        @inlinable\n        internal mutating func setWritability(to newWritability: Bool) -> SetWritabilityAction? {\n            switch self._state {\n            case .initial(_, let delegate):\n                // We just need to store the new writability state\n                self._state = .initial(isWritable: newWritability, delegate: delegate)\n\n                return .none\n\n            case .streaming(\n                let isWritable,\n                let inDelegateOutcall,\n                let cancelledYields,\n                let suspendedYields,\n                let delegate\n            ):\n                if isWritable == newWritability {\n                    // The writability didn't change so we can just early exit here\n                    return .none\n                }\n\n                if newWritability && !inDelegateOutcall {\n                    // We became writable again. This means we have to resume all the continuations.\n                    self._state = .streaming(\n                        isWritable: newWritability,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: .init(),\n                        delegate: delegate\n                    )\n\n                    return .resumeContinuations(suspendedYields)\n                } else if newWritability && inDelegateOutcall {\n                    // We became writable but are in a delegate outcall.\n                    // We just have to store the new writability here.\n                    self._state = .streaming(\n                        isWritable: newWritability,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n                    return .none\n                } else {\n                    // We became unwritable nothing really to do here\n                    self._state = .streaming(\n                        isWritable: newWritability,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n                    return .none\n                }\n\n            case .writerFinished(\n                _,\n                let inDelegateOutcall,\n                let suspendedYields,\n                let cancelledYields,\n                let bufferedYieldIDs,\n                let delegate,\n                let error\n            ):\n                if !newWritability {\n                    // We are not writable so we can't deliver the outstanding elements\n                    return .none\n                }\n\n                if newWritability && !inDelegateOutcall {\n                    // We became writable again. This means we have to resume all the continuations.\n                    self._state = .writerFinished(\n                        isWritable: newWritability,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: .init(),\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n\n                    return .resumeContinuations(suspendedYields)\n                } else if newWritability && inDelegateOutcall {\n                    // We became writable but are in a delegate outcall.\n                    // We just have to store the new writability here.\n                    self._state = .writerFinished(\n                        isWritable: newWritability,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n                    return .none\n                } else {\n                    // We became unwritable nothing really to do here\n                    self._state = .writerFinished(\n                        isWritable: newWritability,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n                    return .none\n                }\n\n            case .finished:\n                // We are already finished nothing to do here\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `yield()`.\n        @usableFromInline\n        enum YieldAction: Sendable {\n            /// Indicates that ``NIOAsyncWriterSinkDelegate/didYield(contentsOf:)`` should be called.\n            case callDidYield(Delegate)\n            /// Indicates that the calling `Task` should get suspended.\n            case suspendTask\n            /// Indicates the given error should be thrown.\n            case throwError(Error)\n\n            @inlinable\n            init(isWritable: Bool, delegate: Delegate) {\n                if isWritable {\n                    self = .callDidYield(delegate)\n                } else {\n                    self = .suspendTask\n                }\n            }\n        }\n\n        @inlinable\n        internal mutating func yield(\n            yieldID: YieldID\n        ) -> YieldAction {\n            switch self._state {\n            case .initial(let isWritable, let delegate):\n                // We can transition to streaming now\n\n                self._state = .streaming(\n                    isWritable: isWritable,\n                    inDelegateOutcall: isWritable,  // If we are writable we are going to make an outcall\n                    cancelledYields: [],\n                    suspendedYields: .init(),\n                    delegate: delegate\n                )\n\n                return .init(isWritable: isWritable, delegate: delegate)\n\n            case .streaming(\n                let isWritable,\n                let inDelegateOutcall,\n                var cancelledYields,\n                let suspendedYields,\n                let delegate\n            ):\n                self._state = .modifying\n\n                if let index = cancelledYields.firstIndex(of: yieldID) {\n                    // We already marked the yield as cancelled. We have to remove it and\n                    // throw a CancellationError.\n                    cancelledYields.remove(at: index)\n\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n\n                    return .throwError(CancellationError())\n                } else {\n                    // Yield hasn't been marked as cancelled.\n\n                    switch (isWritable, inDelegateOutcall) {\n                    case (true, false):\n                        self._state = .streaming(\n                            isWritable: isWritable,\n                            inDelegateOutcall: true,  // We are now making a call to the delegate\n                            cancelledYields: cancelledYields,\n                            suspendedYields: suspendedYields,\n                            delegate: delegate\n                        )\n                        return .callDidYield(delegate)\n\n                    case (true, true), (false, _):\n                        self._state = .streaming(\n                            isWritable: isWritable,\n                            inDelegateOutcall: inDelegateOutcall,\n                            cancelledYields: cancelledYields,\n                            suspendedYields: suspendedYields,\n                            delegate: delegate\n                        )\n                        return .suspendTask\n                    }\n                }\n\n            case .writerFinished(\n                let isWritable,\n                let inDelegateOutcall,\n                let suspendedYields,\n                var cancelledYields,\n                let bufferedYieldIDs,\n                let delegate,\n                let error\n            ):\n                if bufferedYieldIDs.contains(yieldID) {\n                    // This yield was buffered before we became finished so we still have to deliver it\n                    self._state = .modifying\n\n                    if let index = cancelledYields.firstIndex(of: yieldID) {\n                        // We already marked the yield as cancelled. We have to remove it and\n                        // throw a CancellationError.\n                        cancelledYields.remove(at: index)\n\n                        self._state = .writerFinished(\n                            isWritable: isWritable,\n                            inDelegateOutcall: inDelegateOutcall,\n                            suspendedYields: suspendedYields,\n                            cancelledYields: cancelledYields,\n                            bufferedYieldIDs: bufferedYieldIDs,\n                            delegate: delegate,\n                            error: error\n                        )\n\n                        return .throwError(CancellationError())\n                    } else {\n                        // Yield hasn't been marked as cancelled.\n\n                        switch (isWritable, inDelegateOutcall) {\n                        case (true, false):\n                            self._state = .writerFinished(\n                                isWritable: isWritable,\n                                inDelegateOutcall: true,  // We are now making a call to the delegate\n                                suspendedYields: suspendedYields,\n                                cancelledYields: cancelledYields,\n                                bufferedYieldIDs: bufferedYieldIDs,\n                                delegate: delegate,\n                                error: error\n                            )\n\n                            return .callDidYield(delegate)\n                        case (true, true), (false, _):\n                            self._state = .writerFinished(\n                                isWritable: isWritable,\n                                inDelegateOutcall: inDelegateOutcall,\n                                suspendedYields: suspendedYields,\n                                cancelledYields: cancelledYields,\n                                bufferedYieldIDs: bufferedYieldIDs,\n                                delegate: delegate,\n                                error: error\n                            )\n                            return .suspendTask\n                        }\n                    }\n                } else {\n                    // We are already finished and still tried to write something\n                    return .throwError(NIOAsyncWriterError.alreadyFinished())\n                }\n\n            case .finished(let sinkError):\n                // We are already finished and still tried to write something\n                return .throwError(sinkError ?? NIOAsyncWriterError.alreadyFinished())\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        @usableFromInline\n        enum YieldWithContinuationAction {\n            // The yield was cancelled; fail the continuation.\n            case cancelled\n            // The yield was suspended.\n            case suspended\n        }\n\n        /// This method is called as a result of the above `yield` method if it decided that the task needs to get suspended.\n        @inlinable\n        internal mutating func yield(\n            continuation: NIOUnsafeContinuation<YieldResult, Error>,\n            yieldID: YieldID\n        ) -> YieldWithContinuationAction {\n            switch self._state {\n            case .streaming(\n                let isWritable,\n                let inDelegateOutcall,\n                var cancelledYields,\n                var suspendedYields,\n                let delegate\n            ):\n                self._state = .modifying\n\n                if let index = cancelledYields.firstIndex(of: yieldID) {\n                    cancelledYields.remove(at: index)\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n                    return .cancelled\n                } else {\n                    // We have a suspended yield at this point that hasn't been cancelled yet.\n                    // We need to store the yield now.\n\n                    let suspendedYield = SuspendedYield(\n                        yieldID: yieldID,\n                        continuation: continuation\n                    )\n                    suspendedYields.append(suspendedYield)\n\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n\n                    return .suspended\n                }\n\n            case .writerFinished(\n                let isWritable,\n                let inDelegateOutcall,\n                var suspendedYields,\n                var cancelledYields,\n                let bufferedYieldIDs,\n                let delegate,\n                let error\n            ):\n                self._state = .modifying\n\n                if let index = cancelledYields.firstIndex(of: yieldID) {\n                    cancelledYields.remove(at: index)\n                    self._state = .writerFinished(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n                    return .cancelled\n                } else {\n                    // We have a suspended yield at this point that hasn't been cancelled yet.\n                    // It was buffered before we became finished, so we still have to deliver it.\n                    // We need to store the yield now.\n                    let suspendedYield = SuspendedYield(\n                        yieldID: yieldID,\n                        continuation: continuation\n                    )\n                    suspendedYields.append(suspendedYield)\n\n                    self._state = .writerFinished(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n\n                    return .suspended\n                }\n\n            case .initial, .finished:\n                preconditionFailure(\"This should have already been handled by `yield()`\")\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `cancel()`.\n        @usableFromInline\n        enum CancelAction: Sendable {\n            /// Indicates that the continuation should be resumed with a `CancellationError`.\n            case resumeContinuationWithCancellationError(NIOUnsafeContinuation<YieldResult, Error>)\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        internal mutating func cancel(\n            yieldID: YieldID\n        ) -> CancelAction {\n            switch self._state {\n            case .initial(let isWritable, let delegate):\n                // We got a cancel before the yield happened. This means we\n                // need to transition to streaming and store our cancelled state.\n\n                self._state = .streaming(\n                    isWritable: isWritable,\n                    inDelegateOutcall: false,\n                    cancelledYields: [yieldID],\n                    suspendedYields: .init(),\n                    delegate: delegate\n                )\n\n                return .none\n\n            case .streaming(\n                let isWritable,\n                let inDelegateOutcall,\n                var cancelledYields,\n                var suspendedYields,\n                let delegate\n            ):\n                if let index = suspendedYields.firstIndex(where: { $0.yieldID == yieldID }) {\n                    self._state = .modifying\n                    // We have a suspended yield for the id. We need to resume the continuation now.\n\n                    // Removing can be quite expensive if it produces a gap in the array.\n                    // Since we are not expecting a lot of elements in this array it should be fine\n                    // to just remove. If this turns out to be a performance pitfall, we can\n                    // swap the elements before removing. So that we always remove the last element.\n                    let suspendedYield = suspendedYields.remove(at: index)\n\n                    // We are keeping the elements that the yield produced.\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n\n                    return .resumeContinuationWithCancellationError(suspendedYield.continuation)\n\n                } else {\n                    self._state = .modifying\n                    // There is no suspended yield. This can mean that we either already yielded\n                    // or that the call to `yield` is coming afterwards. We need to store\n                    // the ID here. However, if the yield already happened we will never remove the\n                    // stored ID. The only way to avoid doing this would be storing every ID\n                    cancelledYields.append(yieldID)\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n\n                    return .none\n                }\n\n            case .writerFinished(\n                let isWritable,\n                let inDelegateOutcall,\n                var suspendedYields,\n                var cancelledYields,\n                let bufferedYieldIDs,\n                let delegate,\n                let error\n            ):\n                guard bufferedYieldIDs.contains(yieldID) else {\n                    return .none\n                }\n                if let index = suspendedYields.firstIndex(where: { $0.yieldID == yieldID }) {\n                    self._state = .modifying\n                    // We have a suspended yield for the id. We need to resume the continuation now.\n\n                    // Removing can be quite expensive if it produces a gap in the array.\n                    // Since we are not expecting a lot of elements in this array it should be fine\n                    // to just remove. If this turns out to be a performance pitfall, we can\n                    // swap the elements before removing. So that we always remove the last element.\n                    let suspendedYield = suspendedYields.remove(at: index)\n\n                    // We are keeping the elements that the yield produced.\n                    self._state = .writerFinished(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n\n                    return .resumeContinuationWithCancellationError(suspendedYield.continuation)\n\n                } else {\n                    self._state = .modifying\n                    // There is no suspended yield. This can mean that we either already yielded\n                    // or that the call to `yield` is coming afterwards. We need to store\n                    // the ID here. However, if the yield already happened we will never remove the\n                    // stored ID. The only way to avoid doing this would be storing every ID\n                    cancelledYields.append(yieldID)\n                    self._state = .writerFinished(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n\n                    return .none\n                }\n\n            case .finished:\n                // We are already finished and there is nothing to do\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `writerFinish()`.\n        @usableFromInline\n        enum WriterFinishAction: Sendable {\n            /// Indicates that ``NIOAsyncWriterSinkDelegate/didTerminate(completion:)`` should be called.\n            case callDidTerminate(Delegate)\n            /// Indicates that all continuations should be resumed.\n            case resumeContinuations(_TinyArray<SuspendedYield>)\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        internal mutating func writerFinish(error: Error?) -> WriterFinishAction {\n            switch self._state {\n            case .initial(_, let delegate):\n                // Nothing was ever written so we can transition to finished\n                self._state = .finished(sinkError: nil)\n\n                return .callDidTerminate(delegate)\n\n            case .streaming(\n                let isWritable,\n                let inDelegateOutcall,\n                let cancelledYields,\n                let suspendedYields,\n                let delegate\n            ):\n                // We are currently streaming and the writer got finished.\n                if suspendedYields.isEmpty {\n                    if inDelegateOutcall {\n                        // We are in an outcall already and have to buffer\n                        // the didTerminate call.\n                        self._state = .writerFinished(\n                            isWritable: isWritable,\n                            inDelegateOutcall: inDelegateOutcall,\n                            suspendedYields: .init(),\n                            cancelledYields: cancelledYields,\n                            bufferedYieldIDs: .init(),\n                            delegate: delegate,\n                            error: error\n                        )\n                        return .none\n                    } else {\n                        // We have no elements left and are not in an outcall so we\n                        // can transition to finished directly\n                        self._state = .finished(sinkError: nil)\n                        return .callDidTerminate(delegate)\n                    }\n                } else {\n                    // There are still suspended writer tasks which we need to deliver once we become writable again\n                    self._state = .writerFinished(\n                        isWritable: isWritable,\n                        inDelegateOutcall: inDelegateOutcall,\n                        suspendedYields: suspendedYields,\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: _TinyArray(suspendedYields.map { $0.yieldID }),\n                        delegate: delegate,\n                        error: error\n                    )\n\n                    return .none\n                }\n\n            case .writerFinished, .finished:\n                // We are already finished and there is nothing to do\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `sinkFinish()`.\n        @usableFromInline\n        enum SinkFinishAction: Sendable {\n            /// Indicates that all continuations should be resumed with the given error.\n            case resumeContinuationsWithError(_TinyArray<SuspendedYield>, Error)\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        internal mutating func sinkFinish(error: Error?) -> SinkFinishAction {\n            switch self._state {\n            case .initial(_, _):\n                // Nothing was ever written so we can transition to finished\n                self._state = .finished(sinkError: error)\n\n                return .none\n\n            case .streaming(_, _, _, let suspendedYields, _):\n                // We are currently streaming and the sink got finished.\n                // We can transition to finished and need to resume all continuations.\n                self._state = .finished(sinkError: error)\n                return .resumeContinuationsWithError(\n                    suspendedYields,\n                    error ?? NIOAsyncWriterError.alreadyFinished()\n                )\n\n            case .writerFinished(_, _, let suspendedYields, _, _, _, _):\n                // The writer already got finished and the sink got finished too now.\n                // We can transition to finished and need to resume all continuations.\n                self._state = .finished(sinkError: error)\n                return .resumeContinuationsWithError(\n                    suspendedYields,\n                    error ?? NIOAsyncWriterError.alreadyFinished()\n                )\n\n            case .finished:\n                // We are already finished and there is nothing to do\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `sinkFinish()`.\n        @usableFromInline\n        enum UnbufferQueuedEventsAction: Sendable {\n            case resumeContinuations(_TinyArray<SuspendedYield>)\n            case callDidTerminate(Delegate, Error?)\n        }\n\n        @inlinable\n        internal mutating func unbufferQueuedEvents() -> UnbufferQueuedEventsAction? {\n            switch self._state {\n            case .initial:\n                preconditionFailure(\"Invalid state\")\n\n            case .streaming(\n                let isWritable,\n                let inDelegateOutcall,\n                let cancelledYields,\n                let suspendedYields,\n                let delegate\n            ):\n                precondition(inDelegateOutcall, \"We must be in a delegate outcall when we unbuffer events\")\n                // We have to resume the other suspended yields now.\n\n                if suspendedYields.isEmpty {\n                    // There are no other writer suspended writer tasks so we can just return\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: false,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: suspendedYields,\n                        delegate: delegate\n                    )\n                    return .none\n                } else {\n                    // We have to resume the other suspended yields now.\n                    self._state = .streaming(\n                        isWritable: isWritable,\n                        inDelegateOutcall: false,\n                        cancelledYields: cancelledYields,\n                        suspendedYields: .init(),\n                        delegate: delegate\n                    )\n                    return .resumeContinuations(suspendedYields)\n                }\n\n            case .writerFinished(\n                let isWritable,\n                let inDelegateOutcall,\n                let suspendedYields,\n                let cancelledYields,\n                let bufferedYieldIDs,\n                let delegate,\n                let error\n            ):\n                precondition(inDelegateOutcall, \"We must be in a delegate outcall when we unbuffer events\")\n                if suspendedYields.isEmpty {\n                    // We were the last writer task and can now call didTerminate\n                    self._state = .finished(sinkError: nil)\n                    return .callDidTerminate(delegate, error)\n                } else {\n                    // There are still other writer tasks that need to be resumed\n                    self._state = .modifying\n\n                    self._state = .writerFinished(\n                        isWritable: isWritable,\n                        inDelegateOutcall: false,\n                        suspendedYields: .init(),\n                        cancelledYields: cancelledYields,\n                        bufferedYieldIDs: bufferedYieldIDs,\n                        delegate: delegate,\n                        error: error\n                    )\n\n                    return .resumeContinuations(suspendedYields)\n                }\n\n            case .finished:\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/AsyncSequences/NIOThrowingAsyncSequenceProducer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\n\n/// This is an `AsyncSequence` that supports a unicast `AsyncIterator`.\n///\n/// The goal of this sequence is to produce a stream of elements from the _synchronous_ world\n/// (e.g. elements from a ``Channel`` pipeline) and vend it to the _asynchronous_ world for consumption.\n/// Furthermore, it provides facilities to implement a back-pressure strategy which\n/// observes the number of elements that are yielded and consumed. This allows to signal the source to request more data.\n///\n/// - Note: It is recommended to never directly expose this type from APIs, but rather wrap it. This is due to the fact that\n/// this type has three generic parameters where at least two should be known statically and it is really awkward to spell out this type.\n/// Moreover, having a wrapping type allows to optimize this to specialized calls if all generic types are known.\n///\n/// - Important: This sequence is a unicast sequence that only supports a single ``NIOThrowingAsyncSequenceProducer/AsyncIterator``.\n/// If you try to create more than one iterator it will result in a `fatalError`.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOThrowingAsyncSequenceProducer<\n    Element: Sendable,\n    Failure: Error,\n    Strategy: NIOAsyncSequenceProducerBackPressureStrategy,\n    Delegate: NIOAsyncSequenceProducerDelegate\n>: Sendable {\n    /// Simple struct for the return type of ``NIOThrowingAsyncSequenceProducer/makeSequence(elementType:failureType:backPressureStrategy:delegate:)-8qauq``.\n    ///\n    /// This struct contains two properties:\n    /// 1. The ``source`` which should be retained by the producer and is used\n    /// to yield new elements to the sequence.\n    /// 2. The ``sequence`` which is the actual `AsyncSequence` and\n    /// should be passed to the consumer.\n    public struct NewSequence: Sendable {\n        /// The source of the ``NIOThrowingAsyncSequenceProducer`` used to yield and finish.\n        public let source: Source\n        /// The actual sequence which should be passed to the consumer.\n        public let sequence: NIOThrowingAsyncSequenceProducer\n\n        @inlinable\n        internal init(\n            source: Source,\n            sequence: NIOThrowingAsyncSequenceProducer\n        ) {\n            self.source = source\n            self.sequence = sequence\n        }\n    }\n\n    /// This class is needed to hook the deinit to observe once all references to the ``NIOThrowingAsyncSequenceProducer`` are dropped.\n    ///\n    /// If we get move-only types we should be able to drop this class and use the `deinit` of the ``AsyncIterator`` struct itself.\n    @usableFromInline\n    internal final class InternalClass: Sendable {\n        @usableFromInline\n        internal let _storage: Storage\n\n        @inlinable\n        init(storage: Storage) {\n            self._storage = storage\n        }\n\n        @inlinable\n        deinit {\n            _storage.sequenceDeinitialized()\n        }\n    }\n\n    @usableFromInline\n    internal let _internalClass: InternalClass\n\n    @usableFromInline\n    internal var _storage: Storage {\n        self._internalClass._storage\n    }\n\n    /// Initializes a new ``NIOThrowingAsyncSequenceProducer`` and a ``NIOThrowingAsyncSequenceProducer/Source``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOThrowingAsyncSequenceProducer/Source`` and\n    /// a ``NIOThrowingAsyncSequenceProducer``. The source MUST be held by the caller and\n    /// used to signal new elements or finish. The sequence MUST be passed to the actual consumer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying source.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - failureType: The failure type of the sequence. Must be `Swift.Error`\n    ///   - backPressureStrategy: The back-pressure strategy of the sequence.\n    ///   - finishOnDeinit: Indicates if ``NIOThrowingAsyncSequenceProducer/Source/finish()`` should be called on deinit of the.\n    ///   We do not recommend to rely on  deinit based resource tear down.\n    ///   - delegate: The delegate of the sequence\n    /// - Returns: A ``NIOThrowingAsyncSequenceProducer/Source`` and a ``NIOThrowingAsyncSequenceProducer``.\n    @inlinable\n    public static func makeSequence(\n        elementType: Element.Type = Element.self,\n        failureType: Failure.Type = Error.self,\n        backPressureStrategy: Strategy,\n        finishOnDeinit: Bool,\n        delegate: Delegate\n    ) -> NewSequence where Failure == Error {\n        let sequence = Self(\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        let source = Source(storage: sequence._storage, finishOnDeinit: finishOnDeinit)\n\n        return .init(source: source, sequence: sequence)\n    }\n\n    /// Initializes a new ``NIOThrowingAsyncSequenceProducer`` and a ``NIOThrowingAsyncSequenceProducer/Source``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOThrowingAsyncSequenceProducer/Source`` and\n    /// a ``NIOThrowingAsyncSequenceProducer``. The source MUST be held by the caller and\n    /// used to signal new elements or finish. The sequence MUST be passed to the actual consumer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying source.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - failureType: The failure type of the sequence.\n    ///   - backPressureStrategy: The back-pressure strategy of the sequence.\n    ///   - delegate: The delegate of the sequence\n    /// - Returns: A ``NIOThrowingAsyncSequenceProducer/Source`` and a ``NIOThrowingAsyncSequenceProducer``.\n    @available(\n        *,\n        deprecated,\n        message: \"Support for a generic Failure type is deprecated. Failure type must be `any Swift.Error`.\"\n    )\n    @inlinable\n    public static func makeSequence(\n        elementType: Element.Type = Element.self,\n        failureType: Failure.Type = Failure.self,\n        backPressureStrategy: Strategy,\n        delegate: Delegate\n    ) -> NewSequence {\n        let sequence = Self(\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        let source = Source(storage: sequence._storage, finishOnDeinit: true)\n\n        return .init(source: source, sequence: sequence)\n    }\n\n    /// Initializes a new ``NIOThrowingAsyncSequenceProducer`` and a ``NIOThrowingAsyncSequenceProducer/Source``.\n    ///\n    /// - Important: This method returns a struct containing a ``NIOThrowingAsyncSequenceProducer/Source`` and\n    /// a ``NIOThrowingAsyncSequenceProducer``. The source MUST be held by the caller and\n    /// used to signal new elements or finish. The sequence MUST be passed to the actual consumer and MUST NOT be held by the\n    /// caller. This is due to the fact that deiniting the sequence is used as part of a trigger to terminate the underlying source.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the sequence.\n    ///   - failureType: The failure type of the sequence. Must be `Swift.Error`\n    ///   - backPressureStrategy: The back-pressure strategy of the sequence.\n    ///   - delegate: The delegate of the sequence\n    /// - Returns: A ``NIOThrowingAsyncSequenceProducer/Source`` and a ``NIOThrowingAsyncSequenceProducer``.\n    @inlinable\n    @available(\n        *,\n        deprecated,\n        renamed: \"makeSequence(elementType:failureType:backPressureStrategy:finishOnDeinit:delegate:)\",\n        message: \"This method has been deprecated since it defaults to deinit based resource teardown\"\n    )\n    public static func makeSequence(\n        elementType: Element.Type = Element.self,\n        failureType: Failure.Type = Error.self,\n        backPressureStrategy: Strategy,\n        delegate: Delegate\n    ) -> NewSequence where Failure == Error {\n        let sequence = Self(\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        let source = Source(storage: sequence._storage, finishOnDeinit: true)\n\n        return .init(source: source, sequence: sequence)\n    }\n\n    /// only used internally by``NIOAsyncSequenceProducer`` to reuse most of the code\n    @inlinable\n    internal static func makeNonThrowingSequence(\n        elementType: Element.Type = Element.self,\n        backPressureStrategy: Strategy,\n        finishOnDeinit: Bool,\n        delegate: Delegate\n    ) -> NewSequence where Failure == Never {\n        let sequence = Self(\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        let source = Source(storage: sequence._storage, finishOnDeinit: finishOnDeinit)\n\n        return .init(source: source, sequence: sequence)\n    }\n\n    @inlinable\n    internal init(\n        backPressureStrategy: Strategy,\n        delegate: Delegate\n    ) {\n        let storage = Storage(\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        self._internalClass = .init(storage: storage)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOThrowingAsyncSequenceProducer: AsyncSequence {\n    @inlinable\n    public func makeAsyncIterator() -> AsyncIterator {\n        AsyncIterator(storage: self._internalClass._storage)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOThrowingAsyncSequenceProducer {\n    public struct AsyncIterator: AsyncIteratorProtocol {\n        /// This class is needed to hook the deinit to observe once all references to an instance of the ``AsyncIterator`` are dropped.\n        ///\n        /// If we get move-only types we should be able to drop this class and use the `deinit` of the ``AsyncIterator`` struct itself.\n        @usableFromInline\n        internal final class InternalClass: Sendable {\n            @usableFromInline\n            internal let _storage: Storage\n\n            @inlinable\n            init(storage: Storage) {\n                self._storage = storage\n                self._storage.iteratorInitialized()\n            }\n\n            @inlinable\n            deinit {\n                self._storage.iteratorDeinitialized()\n            }\n\n            @inlinable\n            internal func next() async throws -> Element? {\n                try await self._storage.next()\n            }\n        }\n\n        @usableFromInline\n        internal let _internalClass: InternalClass\n\n        @inlinable\n        init(storage: Storage) {\n            self._internalClass = InternalClass(storage: storage)\n        }\n\n        @inlinable\n        public func next() async throws -> Element? {\n            try await self._internalClass.next()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOThrowingAsyncSequenceProducer {\n    /// A struct to interface between the synchronous code of the producer and the asynchronous consumer.\n    /// This type allows the producer to synchronously `yield` new elements to the ``NIOThrowingAsyncSequenceProducer``\n    /// and to `finish` the sequence.\n    ///\n    /// - Note: This struct has reference semantics. Once all copies of a source have been dropped ``NIOThrowingAsyncSequenceProducer/Source/finish()``.\n    /// This will resume any suspended continuation.\n    public struct Source {\n        /// This class is needed to hook the deinit to observe once all references to the ``NIOThrowingAsyncSequenceProducer/Source`` are dropped.\n        ///\n        /// - Important: This is safe to be unchecked ``Sendable`` since the `storage` is ``Sendable`` and `immutable`.\n        @usableFromInline\n        internal final class InternalClass: Sendable {\n            @usableFromInline\n            internal let _storage: Storage\n\n            @usableFromInline\n            internal let _finishOnDeinit: Bool\n\n            @inlinable\n            init(storage: Storage, finishOnDeinit: Bool) {\n                self._storage = storage\n                self._finishOnDeinit = finishOnDeinit\n            }\n\n            @inlinable\n            deinit {\n                if !self._finishOnDeinit && !self._storage.isFinished {\n                    preconditionFailure(\"Deinited NIOAsyncSequenceProducer.Source without calling source.finish()\")\n                } else {\n                    // We need to call finish here to resume any suspended continuation.\n                    self._storage.finish(nil)\n                }\n            }\n        }\n\n        @usableFromInline\n        internal let _internalClass: InternalClass\n\n        @usableFromInline\n        internal var _storage: Storage {\n            self._internalClass._storage\n        }\n\n        @inlinable\n        internal init(storage: Storage, finishOnDeinit: Bool) {\n            self._internalClass = .init(storage: storage, finishOnDeinit: finishOnDeinit)\n        }\n\n        /// The result of a call to ``NIOThrowingAsyncSequenceProducer/Source/yield(_:)``.\n        public enum YieldResult: Hashable, Sendable {\n            /// Indicates that the caller should produce more elements.\n            case produceMore\n            /// Indicates that the caller should stop producing elements.\n            case stopProducing\n            /// Indicates that the yielded elements have been dropped because the sequence already terminated.\n            case dropped\n        }\n\n        /// Yields a sequence of new elements to the ``NIOThrowingAsyncSequenceProducer``.\n        ///\n        /// If there is an ``NIOThrowingAsyncSequenceProducer/AsyncIterator`` awaiting the next element, it will get resumed right away.\n        /// Otherwise, the element will get buffered.\n        ///\n        /// If the ``NIOThrowingAsyncSequenceProducer`` is terminated this will drop the elements\n        /// and return ``YieldResult/dropped``.\n        ///\n        /// This can be called more than once and returns to the caller immediately\n        /// without blocking for any awaiting consumption from the iteration.\n        ///\n        /// - Parameter sequence: The sequence to yield.\n        /// - Returns: A ``NIOThrowingAsyncSequenceProducer/Source/YieldResult`` that indicates if the yield was successful\n        /// and if more elements should be produced.\n        @inlinable\n        public func yield<S: Sequence>(contentsOf sequence: S) -> YieldResult where S.Element == Element {\n            self._storage.yield(sequence)\n        }\n\n        /// Yields a new elements to the ``NIOThrowingAsyncSequenceProducer``.\n        ///\n        /// If there is an ``NIOThrowingAsyncSequenceProducer/AsyncIterator`` awaiting the next element, it will get resumed right away.\n        /// Otherwise, the element will get buffered.\n        ///\n        /// If the ``NIOThrowingAsyncSequenceProducer`` is terminated this will drop the elements\n        /// and return ``YieldResult/dropped``.\n        ///\n        /// This can be called more than once and returns to the caller immediately\n        /// without blocking for any awaiting consumption from the iteration.\n        ///\n        /// - Parameter element: The element to yield.\n        /// - Returns: A ``NIOThrowingAsyncSequenceProducer/Source/YieldResult`` that indicates if the yield was successful\n        /// and if more elements should be produced.\n        @inlinable\n        public func yield(_ element: Element) -> YieldResult {\n            self.yield(contentsOf: CollectionOfOne(element))\n        }\n\n        /// Finishes the sequence.\n        ///\n        /// Calling this function signals the sequence that there won't be any subsequent elements yielded.\n        ///\n        /// If there are still buffered elements and there is an ``NIOThrowingAsyncSequenceProducer/AsyncIterator`` consuming the sequence,\n        /// then termination of the sequence only happens once all elements have been consumed by the ``NIOThrowingAsyncSequenceProducer/AsyncIterator``.\n        /// Otherwise, the buffered elements will be dropped.\n        ///\n        /// - Note: Calling this function more than once has no effect.\n        @inlinable\n        public func finish() {\n            self._storage.finish(nil)\n        }\n\n        /// Finishes the sequence with the given `Failure`.\n        ///\n        /// Calling this function signals the sequence that there won't be any subsequent elements yielded.\n        ///\n        /// If there are still buffered elements and there is an ``NIOThrowingAsyncSequenceProducer/AsyncIterator`` consuming the sequence,\n        /// then termination of the sequence only happens once all elements have been consumed by the ``NIOThrowingAsyncSequenceProducer/AsyncIterator``.\n        /// Otherwise, the buffered elements will be dropped.\n        ///\n        /// - Note: Calling this function more than once has no effect.\n        /// - Parameter failure: The failure why the sequence finished.\n        @inlinable\n        public func finish(_ failure: Failure) {\n            self._storage.finish(failure)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOThrowingAsyncSequenceProducer {\n    /// This is the underlying storage of the sequence. The goal of this is to synchronize the access to all state.\n    @usableFromInline\n    internal struct Storage: Sendable {\n        @usableFromInline\n        struct State: Sendable {\n            @usableFromInline\n            var stateMachine: StateMachine\n            @usableFromInline\n            var delegate: Delegate?\n            @usableFromInline\n            var didSuspend: (@Sendable () -> Void)?\n\n            @inlinable\n            init(\n                stateMachine: StateMachine,\n                delegate: Delegate? = nil,\n                didSuspend: (@Sendable () -> Void)? = nil\n            ) {\n                self.stateMachine = stateMachine\n                self.delegate = delegate\n                self.didSuspend = didSuspend\n            }\n        }\n\n        @usableFromInline\n        internal let _state: NIOLockedValueBox<State>\n\n        @inlinable\n        internal func _setDidSuspend(_ didSuspend: (@Sendable () -> Void)?) {\n            self._state.withLockedValue {\n                $0.didSuspend = didSuspend\n            }\n        }\n\n        @inlinable\n        var isFinished: Bool {\n            self._state.withLockedValue { $0.stateMachine.isFinished }\n        }\n\n        @inlinable\n        internal init(\n            backPressureStrategy: Strategy,\n            delegate: Delegate\n        ) {\n            let state = State(\n                stateMachine: .init(backPressureStrategy: backPressureStrategy),\n                delegate: delegate\n            )\n            self._state = NIOLockedValueBox(state)\n        }\n\n        @inlinable\n        internal func sequenceDeinitialized() {\n            let delegate: Delegate? = self._state.withLockedValue {\n                let action = $0.stateMachine.sequenceDeinitialized()\n\n                switch action {\n                case .callDidTerminate:\n                    let delegate = $0.delegate\n                    $0.delegate = nil\n                    return delegate\n\n                case .none:\n                    return nil\n                }\n            }\n\n            delegate?.didTerminate()\n        }\n\n        @inlinable\n        internal func iteratorInitialized() {\n            self._state.withLockedValue {\n                $0.stateMachine.iteratorInitialized()\n            }\n        }\n\n        @inlinable\n        internal func iteratorDeinitialized() {\n            let delegate: Delegate? = self._state.withLockedValue {\n                let action = $0.stateMachine.iteratorDeinitialized()\n\n                switch action {\n                case .callDidTerminate:\n                    let delegate = $0.delegate\n                    $0.delegate = nil\n\n                    return delegate\n\n                case .none:\n                    return nil\n                }\n            }\n\n            delegate?.didTerminate()\n        }\n\n        @inlinable\n        internal func yield<S: Sequence>(_ sequence: S) -> Source.YieldResult\n        where S.Element == Element {\n            // We must not resume the continuation while holding the lock\n            // because it can deadlock in combination with the underlying ulock\n            // in cases where we race with a cancellation handler\n            let action = self._state.withLockedValue {\n                $0.stateMachine.yield(sequence)\n            }\n\n            switch action {\n            case .returnProduceMore:\n                return .produceMore\n\n            case .returnStopProducing:\n                return .stopProducing\n\n            case .returnDropped:\n                return .dropped\n\n            case .resumeContinuationAndReturnProduceMore(let continuation, let element):\n                continuation.resume(returning: element)\n\n                return .produceMore\n\n            case .resumeContinuationAndReturnStopProducing(let continuation, let element):\n                continuation.resume(returning: element)\n\n                return .stopProducing\n            }\n        }\n\n        @inlinable\n        internal func finish(_ failure: Failure?) {\n            // We must not resume the continuation while holding the lock\n            // because it can deadlock in combination with the underlying ulock\n            // in cases where we race with a cancellation handler\n            let (delegate, action): (Delegate?, NIOThrowingAsyncSequenceProducer.StateMachine.FinishAction) = self\n                ._state.withLockedValue {\n                    let action = $0.stateMachine.finish(failure)\n\n                    switch action {\n                    case .resumeContinuationWithFailureAndCallDidTerminate:\n                        let delegate = $0.delegate\n                        $0.delegate = nil\n                        return (delegate, action)\n\n                    case .none:\n                        return (nil, action)\n                    }\n                }\n\n            switch action {\n            case .resumeContinuationWithFailureAndCallDidTerminate(let continuation, let failure):\n                switch failure {\n                case .some(let error):\n                    continuation.resume(throwing: error)\n                case .none:\n                    continuation.resume(returning: nil)\n                }\n\n            case .none:\n                break\n            }\n\n            delegate?.didTerminate()\n        }\n\n        @inlinable\n        internal func next() async throws -> Element? {\n            try await withTaskCancellationHandler { () async throws -> Element? in\n                let (action, delegate) = self._state.withLockedValue { state -> (StateMachine.NextAction, Delegate?) in\n                    let action = state.stateMachine.next(continuation: nil)\n                    switch action {\n                    case .returnElement, .returnCancellationError, .returnNil, .suspendTask_withoutContinuationOnly:\n                        return (action, nil)\n                    case .returnElementAndCallProduceMore:\n                        return (action, state.delegate)\n                    case .returnFailureAndCallDidTerminate:\n                        let delegate = state.delegate\n                        state.delegate = nil\n                        return (action, delegate)\n                    case .produceMore_withContinuationOnly, .doNothing_withContinuationOnly:\n                        // Can't be returned when 'next(continuation:)' is called with no\n                        // continuation.\n                        fatalError()\n                    }\n                }\n\n                switch action {\n                case .returnElement(let element):\n                    return element\n\n                case .returnElementAndCallProduceMore(let element):\n                    delegate?.produceMore()\n                    return element\n\n                case .returnFailureAndCallDidTerminate(let failure):\n                    delegate?.didTerminate()\n\n                    switch failure {\n                    case .some(let error):\n                        throw error\n\n                    case .none:\n                        return nil\n                    }\n\n                case .returnCancellationError:\n                    // We have deprecated the generic Failure type in the public API and Failure should\n                    // now be `Swift.Error`. However, if users have not migrated to the new API they could\n                    // still use a custom generic Error type and this cast might fail.\n                    // In addition, we use `NIOThrowingAsyncSequenceProducer` in the implementation of the\n                    // non-throwing variant `NIOAsyncSequenceProducer` where `Failure` will be `Never` and\n                    // this cast will fail as well.\n                    // Everything is marked @inlinable and the Failure type is known at compile time,\n                    // therefore this cast should be optimised away in release build.\n                    if let error = CancellationError() as? Failure {\n                        throw error\n                    }\n                    return nil\n\n                case .returnNil:\n                    return nil\n\n                case .produceMore_withContinuationOnly, .doNothing_withContinuationOnly:\n                    // Can't be returned when 'next(continuation:)' is called with no\n                    // continuation.\n                    fatalError()\n\n                case .suspendTask_withoutContinuationOnly:\n                    // Holding the lock here *should* be safe but because of a bug in the runtime\n                    // it isn't, so drop the lock, create the continuation and then try again.\n                    //\n                    // See https://github.com/swiftlang/swift/issues/85668\n                    //\n                    // We switched to using NIOUnsafeContinuation after running with\n                    // CheckedContinuation for more than a year. Now we use NIOUnsafeContinuation\n                    // to reduce runtime costs.\n                    return try await withNIOUnsafeThrowingContinuation {\n                        (continuation: NIOUnsafeContinuation<Element?, any Error>) in\n                        let (action, delegate, didSuspend) = self._state.withLockedValue { state in\n                            let action = state.stateMachine.next(continuation: continuation)\n                            let delegate = state.delegate\n                            return (action, delegate, state.didSuspend)\n                        }\n\n                        switch action {\n                        case .returnElement(let element):\n                            continuation.resume(returning: element)\n\n                        case .returnElementAndCallProduceMore(let element):\n                            delegate?.produceMore()\n                            continuation.resume(returning: element)\n\n                        case .returnFailureAndCallDidTerminate(let failure):\n                            delegate?.didTerminate()\n                            switch failure {\n                            case .some(let error):\n                                continuation.resume(throwing: error)\n                            case .none:\n                                continuation.resume(returning: nil)\n                            }\n\n                        case .returnCancellationError:\n                            // We have deprecated the generic Failure type in the public API and Failure should\n                            // now be `Swift.Error`. However, if users have not migrated to the new API they could\n                            // still use a custom generic Error type and this cast might fail.\n                            // In addition, we use `NIOThrowingAsyncSequenceProducer` in the implementation of the\n                            // non-throwing variant `NIOAsyncSequenceProducer` where `Failure` will be `Never` and\n                            // this cast will fail as well.\n                            // Everything is marked @inlinable and the Failure type is known at compile time,\n                            // therefore this cast should be optimised away in release build.\n                            if let error = CancellationError() as? Failure {\n                                continuation.resume(throwing: error)\n                            } else {\n                                continuation.resume(returning: nil)\n                            }\n\n                        case .returnNil:\n                            continuation.resume(returning: nil)\n\n                        case .produceMore_withContinuationOnly:\n                            delegate?.produceMore()\n\n                        case .doNothing_withContinuationOnly:\n                            ()\n\n                        case .suspendTask_withoutContinuationOnly:\n                            // Can't be returned when 'next(continuation:)' is called with a\n                            // continuation.\n                            fatalError()\n                        }\n\n                        didSuspend?()\n                    }\n                }\n            } onCancel: {\n                // We must not resume the continuation while holding the lock\n                // because it can deadlock in combination with the underlying unlock\n                // in cases where we race with a cancellation handler\n                let (delegate, action): (Delegate?, NIOThrowingAsyncSequenceProducer.StateMachine.CancelledAction) =\n                    self._state.withLockedValue {\n                        let action = $0.stateMachine.cancelled()\n\n                        switch action {\n                        case .callDidTerminate:\n                            let delegate = $0.delegate\n                            $0.delegate = nil\n\n                            return (delegate, action)\n\n                        case .resumeContinuationWithCancellationErrorAndCallDidTerminate:\n                            let delegate = $0.delegate\n                            $0.delegate = nil\n\n                            return (delegate, action)\n\n                        case .none:\n                            return (nil, action)\n                        }\n                    }\n\n                switch action {\n                case .callDidTerminate:\n                    break\n\n                case .resumeContinuationWithCancellationErrorAndCallDidTerminate(let continuation):\n                    // We have deprecated the generic Failure type in the public API and Failure should\n                    // now be `Swift.Error`. However, if users have not migrated to the new API they could\n                    // still use a custom generic Error type and this cast might fail.\n                    // In addition, we use `NIOThrowingAsyncSequenceProducer` in the implementation of the\n                    // non-throwing variant `NIOAsyncSequenceProducer` where `Failure` will be `Never` and\n                    // this cast will fail as well.\n                    // Everything is marked @inlinable and the Failure type is known at compile time,\n                    // therefore this cast should be optimised away in release build.\n                    if let failure = CancellationError() as? Failure {\n                        continuation.resume(throwing: failure)\n                    } else {\n                        continuation.resume(returning: nil)\n                    }\n\n                case .none:\n                    break\n                }\n\n                delegate?.didTerminate()\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOThrowingAsyncSequenceProducer {\n    @usableFromInline\n    internal struct StateMachine: Sendable {\n        @usableFromInline\n        internal enum State: Sendable {\n            /// The initial state before either a call to `yield()` or a call to `next()` happened\n            case initial(\n                backPressureStrategy: Strategy,\n                iteratorInitialized: Bool\n            )\n\n            /// The state once either any element was yielded or `next()` was called.\n            case streaming(\n                backPressureStrategy: Strategy,\n                buffer: Deque<Element>,\n                continuation: NIOUnsafeContinuation<Element?, Error>?,\n                hasOutstandingDemand: Bool,\n                iteratorInitialized: Bool\n            )\n\n            /// The state once the underlying source signalled that it is finished.\n            case sourceFinished(\n                buffer: Deque<Element>,\n                iteratorInitialized: Bool,\n                failure: Failure?\n            )\n\n            /// The state once a call to next has been cancelled. Cancel the source when entering this state.\n            case cancelled(iteratorInitialized: Bool)\n\n            /// The state once there can be no outstanding demand. This can happen if:\n            /// 1. The ``NIOThrowingAsyncSequenceProducer/AsyncIterator`` was deinited\n            /// 2. The underlying source finished and all buffered elements have been consumed\n            case finished(iteratorInitialized: Bool)\n\n            /// Internal state to avoid CoW.\n            case modifying\n        }\n\n        /// The state machine's current state.\n        @usableFromInline\n        internal var _state: State\n\n        @inlinable\n        var isFinished: Bool {\n            switch self._state {\n            case .initial, .streaming:\n                return false\n            case .cancelled, .sourceFinished, .finished:\n                return true\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Initializes a new `StateMachine`.\n        ///\n        /// We are passing and holding the back-pressure strategy here because\n        /// it is a customizable extension of the state machine.\n        ///\n        /// - Parameter backPressureStrategy: The back-pressure strategy.\n        @inlinable\n        init(backPressureStrategy: Strategy) {\n            self._state = .initial(\n                backPressureStrategy: backPressureStrategy,\n                iteratorInitialized: false\n            )\n        }\n\n        /// Actions returned by `sequenceDeinitialized()`.\n        @usableFromInline\n        enum SequenceDeinitializedAction: Sendable {\n            /// Indicates that ``NIOAsyncSequenceProducerDelegate/didTerminate()`` should be called.\n            case callDidTerminate\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        mutating func sequenceDeinitialized() -> SequenceDeinitializedAction {\n            switch self._state {\n            case .initial(_, iteratorInitialized: false),\n                .streaming(_, _, _, _, iteratorInitialized: false),\n                .sourceFinished(_, iteratorInitialized: false, _),\n                .cancelled(iteratorInitialized: false):\n                // No iterator was created so we can transition to finished right away.\n                self._state = .finished(iteratorInitialized: false)\n\n                return .callDidTerminate\n\n            case .initial(_, iteratorInitialized: true),\n                .streaming(_, _, _, _, iteratorInitialized: true),\n                .sourceFinished(_, iteratorInitialized: true, _),\n                .cancelled(iteratorInitialized: true):\n                // An iterator was created and we deinited the sequence.\n                // This is an expected pattern and we just continue on normal.\n                return .none\n\n            case .finished:\n                // We are already finished so there is nothing left to clean up.\n                // This is just the references dropping afterwards.\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        @inlinable\n        mutating func iteratorInitialized() {\n            switch self._state {\n            case .initial(_, iteratorInitialized: true),\n                .streaming(_, _, _, _, iteratorInitialized: true),\n                .sourceFinished(_, iteratorInitialized: true, _),\n                .cancelled(iteratorInitialized: true),\n                .finished(iteratorInitialized: true):\n                // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                fatalError(\"NIOThrowingAsyncSequenceProducer allows only a single AsyncIterator to be created\")\n\n            case .initial(let backPressureStrategy, iteratorInitialized: false):\n                // The first and only iterator was initialized.\n                self._state = .initial(\n                    backPressureStrategy: backPressureStrategy,\n                    iteratorInitialized: true\n                )\n\n            case .streaming(let backPressureStrategy, let buffer, let continuation, let hasOutstandingDemand, false):\n                // The first and only iterator was initialized.\n                self._state = .streaming(\n                    backPressureStrategy: backPressureStrategy,\n                    buffer: buffer,\n                    continuation: continuation,\n                    hasOutstandingDemand: hasOutstandingDemand,\n                    iteratorInitialized: true\n                )\n\n            case .cancelled(iteratorInitialized: false):\n                // An iterator needs to be initialized before we can be cancelled.\n                preconditionFailure(\"Internal inconsistency\")\n\n            case .sourceFinished(let buffer, false, let failure):\n                // The first and only iterator was initialized.\n                self._state = .sourceFinished(\n                    buffer: buffer,\n                    iteratorInitialized: true,\n                    failure: failure\n                )\n\n            case .finished(iteratorInitialized: false):\n                // It is strange that an iterator is created after we are finished\n                // but it can definitely happen, e.g.\n                // Sequence.init -> source.finish -> sequence.makeAsyncIterator\n                self._state = .finished(iteratorInitialized: true)\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `iteratorDeinitialized()`.\n        @usableFromInline\n        enum IteratorDeinitializedAction: Sendable {\n            /// Indicates that ``NIOAsyncSequenceProducerDelegate/didTerminate()`` should be called.\n            case callDidTerminate\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        mutating func iteratorDeinitialized() -> IteratorDeinitializedAction {\n            switch self._state {\n            case .initial(_, iteratorInitialized: false),\n                .streaming(_, _, _, _, iteratorInitialized: false),\n                .sourceFinished(_, iteratorInitialized: false, _),\n                .cancelled(iteratorInitialized: false):\n                // An iterator needs to be initialized before it can be deinitialized.\n                preconditionFailure(\"Internal inconsistency\")\n\n            case .initial(_, iteratorInitialized: true),\n                .streaming(_, _, _, _, iteratorInitialized: true),\n                .sourceFinished(_, iteratorInitialized: true, _),\n                .cancelled(iteratorInitialized: true):\n                // An iterator was created and deinited. Since we only support\n                // a single iterator we can now transition to finish and inform the delegate.\n                self._state = .finished(iteratorInitialized: true)\n\n                return .callDidTerminate\n\n            case .finished:\n                // We are already finished so there is nothing left to clean up.\n                // This is just the references dropping afterwards.\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `yield()`.\n        @usableFromInline\n        enum YieldAction: Sendable {\n            /// Indicates that ``NIOThrowingAsyncSequenceProducer/Source/YieldResult/produceMore`` should be returned.\n            case returnProduceMore\n            /// Indicates that ``NIOThrowingAsyncSequenceProducer/Source/YieldResult/stopProducing`` should be returned.\n            case returnStopProducing\n            /// Indicates that the continuation should be resumed and\n            /// ``NIOThrowingAsyncSequenceProducer/Source/YieldResult/produceMore`` should be returned.\n            case resumeContinuationAndReturnProduceMore(\n                continuation: NIOUnsafeContinuation<Element?, Error>,\n                element: Element\n            )\n            /// Indicates that the continuation should be resumed and\n            /// ``NIOThrowingAsyncSequenceProducer/Source/YieldResult/stopProducing`` should be returned.\n            case resumeContinuationAndReturnStopProducing(\n                continuation: NIOUnsafeContinuation<Element?, Error>,\n                element: Element\n            )\n            /// Indicates that the yielded elements have been dropped.\n            case returnDropped\n\n            @inlinable\n            init(\n                shouldProduceMore: Bool,\n                continuationAndElement: (NIOUnsafeContinuation<Element?, Error>, Element)? = nil\n            ) {\n                switch (shouldProduceMore, continuationAndElement) {\n                case (true, .none):\n                    self = .returnProduceMore\n\n                case (false, .none):\n                    self = .returnStopProducing\n\n                case (true, .some((let continuation, let element))):\n                    self = .resumeContinuationAndReturnProduceMore(\n                        continuation: continuation,\n                        element: element\n                    )\n\n                case (false, .some((let continuation, let element))):\n                    self = .resumeContinuationAndReturnStopProducing(\n                        continuation: continuation,\n                        element: element\n                    )\n                }\n            }\n        }\n\n        @inlinable\n        mutating func yield<S: Sequence>(_ sequence: S) -> YieldAction where S.Element == Element {\n            switch self._state {\n            case .initial(var backPressureStrategy, let iteratorInitialized):\n                let buffer = Deque<Element>(sequence)\n                let shouldProduceMore = backPressureStrategy.didYield(bufferDepth: buffer.count)\n\n                self._state = .streaming(\n                    backPressureStrategy: backPressureStrategy,\n                    buffer: buffer,\n                    continuation: nil,\n                    hasOutstandingDemand: shouldProduceMore,\n                    iteratorInitialized: iteratorInitialized\n                )\n\n                return .init(shouldProduceMore: shouldProduceMore)\n\n            case .streaming(\n                var backPressureStrategy,\n                var buffer,\n                .some(let continuation),\n                let hasOutstandingDemand,\n                let iteratorInitialized\n            ):\n                // The buffer should always be empty if we hold a continuation\n                precondition(buffer.isEmpty, \"Expected an empty buffer\")\n\n                self._state = .modifying\n\n                buffer.append(contentsOf: sequence)\n\n                guard let element = buffer.popFirst() else {\n                    self._state = .streaming(\n                        backPressureStrategy: backPressureStrategy,\n                        buffer: buffer,\n                        continuation: continuation,\n                        hasOutstandingDemand: hasOutstandingDemand,\n                        iteratorInitialized: iteratorInitialized\n                    )\n                    return .init(shouldProduceMore: hasOutstandingDemand)\n                }\n\n                // We have an element and can resume the continuation\n\n                let shouldProduceMore = backPressureStrategy.didYield(bufferDepth: buffer.count)\n                self._state = .streaming(\n                    backPressureStrategy: backPressureStrategy,\n                    buffer: buffer,\n                    continuation: nil,  // Setting this to nil since we are resuming the continuation\n                    hasOutstandingDemand: shouldProduceMore,\n                    iteratorInitialized: iteratorInitialized\n                )\n\n                return .init(shouldProduceMore: shouldProduceMore, continuationAndElement: (continuation, element))\n\n            case .streaming(var backPressureStrategy, var buffer, continuation: .none, _, let iteratorInitialized):\n                self._state = .modifying\n\n                buffer.append(contentsOf: sequence)\n                let shouldProduceMore = backPressureStrategy.didYield(bufferDepth: buffer.count)\n\n                self._state = .streaming(\n                    backPressureStrategy: backPressureStrategy,\n                    buffer: buffer,\n                    continuation: nil,\n                    hasOutstandingDemand: shouldProduceMore,\n                    iteratorInitialized: iteratorInitialized\n                )\n\n                return .init(shouldProduceMore: shouldProduceMore)\n\n            case .cancelled, .sourceFinished, .finished:\n                // If the source has finished we are dropping the elements.\n                return .returnDropped\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `finish()`.\n        @usableFromInline\n        enum FinishAction: Sendable {\n            /// Indicates that the continuation should be resumed with `nil` and\n            /// that ``NIOAsyncSequenceProducerDelegate/didTerminate()`` should be called.\n            case resumeContinuationWithFailureAndCallDidTerminate(NIOUnsafeContinuation<Element?, Error>, Failure?)\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        mutating func finish(_ failure: Failure?) -> FinishAction {\n            switch self._state {\n            case .initial(_, let iteratorInitialized):\n                // Nothing was yielded nor did anybody call next\n                // This means we can transition to sourceFinished and store the failure\n                self._state = .sourceFinished(\n                    buffer: .init(),\n                    iteratorInitialized: iteratorInitialized,\n                    failure: failure\n                )\n\n                return .none\n\n            case .streaming(_, let buffer, .some(let continuation), _, let iteratorInitialized):\n                // We have a continuation, this means our buffer must be empty\n                // Furthermore, we can now transition to finished\n                // and resume the continuation with the failure\n                precondition(buffer.isEmpty, \"Expected an empty buffer\")\n\n                self._state = .finished(iteratorInitialized: iteratorInitialized)\n\n                return .resumeContinuationWithFailureAndCallDidTerminate(continuation, failure)\n\n            case .streaming(_, let buffer, continuation: .none, _, let iteratorInitialized):\n                self._state = .sourceFinished(\n                    buffer: buffer,\n                    iteratorInitialized: iteratorInitialized,\n                    failure: failure\n                )\n\n                return .none\n\n            case .cancelled, .sourceFinished, .finished:\n                // If the source has finished, finishing again has no effect.\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `cancelled()`.\n        @usableFromInline\n        enum CancelledAction: Sendable {\n            /// Indicates that ``NIOAsyncSequenceProducerDelegate/didTerminate()`` should be called.\n            case callDidTerminate\n            /// Indicates that the continuation should be resumed with a `CancellationError` and\n            /// that ``NIOAsyncSequenceProducerDelegate/didTerminate()`` should be called.\n            case resumeContinuationWithCancellationErrorAndCallDidTerminate(NIOUnsafeContinuation<Element?, Error>)\n            /// Indicates that nothing should be done.\n            case none\n        }\n\n        @inlinable\n        mutating func cancelled() -> CancelledAction {\n            switch self._state {\n            case .initial(_, let iteratorInitialized):\n                // This can happen if the `Task` that calls `next()` is already cancelled.\n\n                // We have deprecated the generic Failure type in the public API and Failure should\n                // now be `Swift.Error`. However, if users have not migrated to the new API they could\n                // still use a custom generic Error type and this cast might fail.\n                // In addition, we use `NIOThrowingAsyncSequenceProducer` in the implementation of the\n                // non-throwing variant `NIOAsyncSequenceProducer` where `Failure` will be `Never` and\n                // this cast will fail as well.\n                // Everything is marked @inlinable and the Failure type is known at compile time,\n                // therefore this cast should be optimised away in release build.\n                if let failure = CancellationError() as? Failure {\n                    self._state = .sourceFinished(\n                        buffer: .init(),\n                        iteratorInitialized: iteratorInitialized,\n                        failure: failure\n                    )\n                } else {\n                    self._state = .finished(iteratorInitialized: iteratorInitialized)\n                }\n\n                return .none\n\n            case .streaming(_, _, .some(let continuation), _, let iteratorInitialized):\n                // We have an outstanding continuation that needs to resumed\n                // and we can transition to finished here and inform the delegate\n                self._state = .finished(iteratorInitialized: iteratorInitialized)\n\n                return .resumeContinuationWithCancellationErrorAndCallDidTerminate(continuation)\n\n            case .streaming(_, _, continuation: .none, _, let iteratorInitialized):\n                // We may have elements in the buffer, which is why we have no continuation\n                // waiting. We must store the cancellation error to hand it out on the next\n                // next() call.\n                self._state = .cancelled(iteratorInitialized: iteratorInitialized)\n\n                return .callDidTerminate\n\n            case .cancelled, .sourceFinished, .finished:\n                // If the source has finished, finishing again has no effect.\n                return .none\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n\n        /// Actions returned by `next()`.\n        @usableFromInline\n        enum NextAction: Sendable {\n            /// Indicates that the element should be returned to the caller.\n            case returnElement(Element)\n            /// Indicates that the element should be returned to the caller and\n            /// that ``NIOAsyncSequenceProducerDelegate/produceMore()`` should be called.\n            case returnElementAndCallProduceMore(Element)\n            /// Indicates that the `Failure` should be returned to the caller and\n            /// that ``NIOAsyncSequenceProducerDelegate/didTerminate()`` should be called.\n            case returnFailureAndCallDidTerminate(Failure?)\n            /// Indicates that the next call to AsyncSequence got cancelled\n            case returnCancellationError\n            /// Indicates that the `nil` should be returned to the caller.\n            case returnNil\n\n            /// Indicates that the `Task` of the caller should be suspended. Only returned when\n            /// `next(continuation:)` is called with a non-nil continuation.\n            case suspendTask_withoutContinuationOnly\n\n            /// Indicates that caller should produce more values. Only returned when\n            /// `next(continuation:)` is called with `nil`.\n            case produceMore_withContinuationOnly\n            /// Indicates that caller shouldn't do anything. Only returned\n            /// when `next(continuation:)` is called with `nil`.\n            case doNothing_withContinuationOnly\n        }\n\n        @inlinable\n        mutating func next(continuation: NIOUnsafeContinuation<Element?, Error>?) -> NextAction {\n            switch self._state {\n            case .initial(let backPressureStrategy, let iteratorInitialized):\n                precondition(continuation == nil)\n\n                // We are not interacting with the back-pressure strategy here because\n                // we are doing this inside `next(:)`\n                self._state = .streaming(\n                    backPressureStrategy: backPressureStrategy,\n                    buffer: Deque<Element>(),\n                    continuation: nil,\n                    hasOutstandingDemand: false,\n                    iteratorInitialized: iteratorInitialized\n                )\n\n                return .suspendTask_withoutContinuationOnly\n\n            case .streaming(_, _, .some, _, _):\n                // We have multiple AsyncIterators iterating the sequence\n                preconditionFailure(\"This should never happen since we only allow a single Iterator to be created\")\n\n            case .streaming(\n                var backPressureStrategy,\n                var buffer,\n                .none,\n                let hasOutstandingDemand,\n                let iteratorInitialized\n            ):\n                self._state = .modifying\n\n                if let element = buffer.popFirst() {\n                    // We have an element to fulfil the demand right away.\n                    let shouldProduceMore = backPressureStrategy.didConsume(bufferDepth: buffer.count)\n\n                    self._state = .streaming(\n                        backPressureStrategy: backPressureStrategy,\n                        buffer: buffer,\n                        continuation: nil,\n                        hasOutstandingDemand: shouldProduceMore,\n                        iteratorInitialized: iteratorInitialized\n                    )\n\n                    if shouldProduceMore && !hasOutstandingDemand {\n                        // We didn't have any demand but now we do, so we need to inform the delegate.\n                        return .returnElementAndCallProduceMore(element)\n                    } else {\n                        // We don't have any new demand, so we can just return the element.\n                        return .returnElement(element)\n                    }\n                } else if let continuation = continuation {\n                    let shouldProduceMore = backPressureStrategy.didConsume(bufferDepth: buffer.count)\n                    self._state = .streaming(\n                        backPressureStrategy: backPressureStrategy,\n                        buffer: buffer,\n                        continuation: continuation,\n                        hasOutstandingDemand: shouldProduceMore,\n                        iteratorInitialized: iteratorInitialized\n                    )\n\n                    if shouldProduceMore && !hasOutstandingDemand {\n                        return .produceMore_withContinuationOnly\n                    } else {\n                        return .doNothing_withContinuationOnly\n                    }\n                } else {\n                    // This function is first called without a continuation (i.e. this branch), if\n                    // the buffer is empty the caller needs to re-call this function with a\n                    // continuation (the branch above) so defer checking the backpressure strategy\n                    // until then to minimise unnecessary delegate calls.\n\n                    self._state = .streaming(\n                        backPressureStrategy: backPressureStrategy,\n                        buffer: buffer,\n                        continuation: nil,\n                        hasOutstandingDemand: hasOutstandingDemand,\n                        iteratorInitialized: iteratorInitialized\n                    )\n\n                    return .suspendTask_withoutContinuationOnly\n                }\n\n            case .sourceFinished(var buffer, let iteratorInitialized, let failure):\n                self._state = .modifying\n\n                // Check if we have an element left in the buffer and return it\n                if let element = buffer.popFirst() {\n                    self._state = .sourceFinished(\n                        buffer: buffer,\n                        iteratorInitialized: iteratorInitialized,\n                        failure: failure\n                    )\n\n                    return .returnElement(element)\n                } else {\n                    // We are returning the queued failure now and can transition to finished\n                    self._state = .finished(iteratorInitialized: iteratorInitialized)\n\n                    return .returnFailureAndCallDidTerminate(failure)\n                }\n\n            case .cancelled(let iteratorInitialized):\n                self._state = .finished(iteratorInitialized: iteratorInitialized)\n                return .returnCancellationError\n\n            case .finished:\n                return .returnNil\n\n            case .modifying:\n                preconditionFailure(\"Invalid state\")\n            }\n        }\n    }\n}\n\n/// The ``NIOThrowingAsyncSequenceProducer/AsyncIterator`` MUST NOT be shared across `Task`s. With marking this as\n/// unavailable we are explicitly declaring this.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@available(*, unavailable)\nextension NIOThrowingAsyncSequenceProducer.AsyncIterator: Sendable {}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOThrowingAsyncSequenceProducer.Source: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/BSDSocketAPI.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if os(Windows)\nimport ucrt\n\nimport let WinSDK.IPPROTO_IP\nimport let WinSDK.IPPROTO_IPV6\nimport let WinSDK.IPPROTO_TCP\nimport let WinSDK.IPPROTO_UDP\n\nimport let WinSDK.IP_ADD_MEMBERSHIP\nimport let WinSDK.IP_DROP_MEMBERSHIP\nimport let WinSDK.IP_HDRINCL\nimport let WinSDK.IP_MULTICAST_IF\nimport let WinSDK.IP_MULTICAST_LOOP\nimport let WinSDK.IP_MULTICAST_TTL\nimport let WinSDK.IPV6_JOIN_GROUP\nimport let WinSDK.IPV6_LEAVE_GROUP\nimport let WinSDK.IPV6_MULTICAST_HOPS\nimport let WinSDK.IPV6_MULTICAST_IF\nimport let WinSDK.IPV6_MULTICAST_LOOP\nimport let WinSDK.IPV6_V6ONLY\n\nimport let WinSDK.AF_INET\nimport let WinSDK.AF_INET6\nimport let WinSDK.AF_UNIX\n\nimport let WinSDK.PF_INET\nimport let WinSDK.PF_INET6\nimport let WinSDK.PF_UNIX\n\nimport let WinSDK.SO_BROADCAST\nimport let WinSDK.SO_ERROR\nimport let WinSDK.SO_KEEPALIVE\nimport let WinSDK.SO_LINGER\nimport let WinSDK.SO_RCVBUF\nimport let WinSDK.SO_RCVTIMEO\nimport let WinSDK.SO_REUSEADDR\nimport let WinSDK.SO_SNDBUF\n\nimport let WinSDK.SOL_SOCKET\n\nimport let WinSDK.TCP_NODELAY\n\nimport struct WinSDK.SOCKET\n\nimport func WinSDK.inet_ntop\nimport func WinSDK.inet_pton\n\nimport func WinSDK.GetLastError\nimport func WinSDK.WSAGetLastError\n\ninternal typealias socklen_t = ucrt.size_t\n#elseif os(Linux) || os(Android)\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\nimport CNIOLinux\n\n#if os(Android)\nprivate let sysInet_ntop:\n    @convention(c) (CInt, UnsafeRawPointer, UnsafeMutablePointer<CChar>, socklen_t) -> UnsafePointer<CChar>? = inet_ntop\nprivate let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>, UnsafeMutableRawPointer) -> CInt = inet_pton\n#else\nprivate let sysInet_ntop:\n    @convention(c) (CInt, UnsafeRawPointer?, UnsafeMutablePointer<CChar>?, socklen_t) -> UnsafePointer<CChar>? =\n        inet_ntop\nprivate let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> CInt = inet_pton\n#endif\n#elseif os(OpenBSD)\n@preconcurrency import Glibc\nimport CNIOOpenBSD\n\nprivate let sysInet_ntop:\n    @convention(c) (CInt, UnsafeRawPointer?, UnsafeMutablePointer<CChar>?, socklen_t) -> UnsafePointer<CChar>? =\n        inet_ntop\nprivate let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> CInt = inet_pton\n#elseif canImport(Darwin)\nimport Darwin\n\nprivate let sysInet_ntop:\n    @convention(c) (CInt, UnsafeRawPointer?, UnsafeMutablePointer<CChar>?, socklen_t) -> UnsafePointer<CChar>? =\n        inet_ntop\nprivate let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> CInt = inet_pton\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n\nprivate let sysInet_ntop:\n    @convention(c) (CInt, UnsafeRawPointer?, UnsafeMutablePointer<CChar>?, socklen_t) -> UnsafePointer<CChar>? =\n        inet_ntop\nprivate let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> CInt = inet_pton\n#else\n#error(\"The BSD Socket module was unable to identify your C library.\")\n#endif\n\n#if os(Android)\n@usableFromInline let IFF_BROADCAST: CUnsignedInt = numericCast(Android.IFF_BROADCAST.rawValue)\n@usableFromInline let IFF_POINTOPOINT: CUnsignedInt = numericCast(Android.IFF_POINTOPOINT.rawValue)\n@usableFromInline let IFF_MULTICAST: CUnsignedInt = numericCast(Android.IFF_MULTICAST.rawValue)\n#if arch(arm)\n@usableFromInline let SO_RCVTIMEO = SO_RCVTIMEO_OLD\n@usableFromInline let SO_TIMESTAMP = SO_TIMESTAMP_OLD\n#endif\n#elseif os(Linux)\n// Work around SO_TIMESTAMP/SO_RCVTIMEO being awkwardly defined in glibc.\n@usableFromInline let SO_TIMESTAMP = CNIOLinux_SO_TIMESTAMP\n@usableFromInline let SO_RCVTIMEO = CNIOLinux_SO_RCVTIMEO\n#endif\n\npublic enum NIOBSDSocket: Sendable {\n    #if os(Windows)\n    public typealias Handle = SOCKET\n    #else\n    public typealias Handle = CInt\n    #endif\n    public struct PipeHandle {\n        public var input: Handle\n        public var output: Handle\n\n        @inlinable\n        public init(input: Handle, output: Handle) {\n            self.input = input\n            self.output = output\n        }\n    }\n}\n\nextension NIOBSDSocket {\n    /// Specifies the addressing scheme that the socket can use.\n    public struct AddressFamily: RawRepresentable, Sendable {\n        public typealias RawValue = CInt\n        public var rawValue: RawValue\n\n        @inlinable\n        public init(rawValue: RawValue) {\n            self.rawValue = rawValue\n        }\n    }\n}\n\nextension NIOBSDSocket.AddressFamily: Equatable {\n}\n\nextension NIOBSDSocket.AddressFamily: Hashable {\n}\n\nextension NIOBSDSocket {\n    /// Specifies the type of protocol that the socket can use.\n    public struct ProtocolFamily: RawRepresentable, Sendable {\n        public typealias RawValue = CInt\n        public var rawValue: RawValue\n\n        @inlinable\n        public init(rawValue: RawValue) {\n            self.rawValue = rawValue\n        }\n    }\n}\n\nextension NIOBSDSocket.ProtocolFamily: Equatable {\n}\n\nextension NIOBSDSocket.ProtocolFamily: Hashable {\n}\n\nextension NIOBSDSocket {\n    /// Defines socket option levels.\n    public struct OptionLevel: RawRepresentable, Sendable {\n        public typealias RawValue = CInt\n        public var rawValue: RawValue\n\n        @inlinable\n        public init(rawValue: RawValue) {\n            self.rawValue = rawValue\n        }\n    }\n}\n\nextension NIOBSDSocket.OptionLevel: Equatable {\n}\n\nextension NIOBSDSocket.OptionLevel: Hashable {\n}\n\nextension NIOBSDSocket {\n    /// Defines configuration option names.\n    public struct Option: RawRepresentable, Sendable {\n        public typealias RawValue = CInt\n        public var rawValue: RawValue\n\n        @inlinable\n        public init(rawValue: RawValue) {\n            self.rawValue = rawValue\n        }\n    }\n}\n\nextension NIOBSDSocket.Option: Equatable {\n}\n\nextension NIOBSDSocket.Option: Hashable {\n}\n\n// Address Family\nextension NIOBSDSocket.AddressFamily {\n    /// Address for IP version 4.\n    @inlinable\n    public static var inet: NIOBSDSocket.AddressFamily {\n        NIOBSDSocket.AddressFamily(rawValue: AF_INET)\n    }\n\n    /// Address for IP version 6.\n    @inlinable\n    public static var inet6: NIOBSDSocket.AddressFamily {\n        NIOBSDSocket.AddressFamily(rawValue: AF_INET6)\n    }\n\n    /// Unix local to host address.\n    @inlinable\n    public static var unix: NIOBSDSocket.AddressFamily {\n        NIOBSDSocket.AddressFamily(rawValue: AF_UNIX)\n    }\n}\n\n// Protocol Family\nextension NIOBSDSocket.ProtocolFamily {\n    /// IP network 4 protocol.\n    @inlinable\n    public static var inet: NIOBSDSocket.ProtocolFamily {\n        NIOBSDSocket.ProtocolFamily(rawValue: PF_INET)\n    }\n\n    /// IP network 6 protocol.\n    @inlinable\n    public static var inet6: NIOBSDSocket.ProtocolFamily {\n        NIOBSDSocket.ProtocolFamily(rawValue: PF_INET6)\n    }\n\n    #if !os(WASI)\n    /// UNIX local to the host.\n    @inlinable\n    public static var unix: NIOBSDSocket.ProtocolFamily {\n        NIOBSDSocket.ProtocolFamily(rawValue: PF_UNIX)\n    }\n    #endif\n}\n\n#if !os(Windows) && !os(WASI)\nextension NIOBSDSocket.ProtocolFamily {\n    /// UNIX local to the host, alias for `PF_UNIX` (`.unix`)\n    @inlinable\n    public static var local: NIOBSDSocket.ProtocolFamily {\n        NIOBSDSocket.ProtocolFamily(rawValue: PF_LOCAL)\n    }\n}\n#endif\n\n// Option Level\nextension NIOBSDSocket.OptionLevel {\n    /// Socket options that apply only to IP sockets.\n    #if os(Linux) || os(Android)\n    @inlinable\n    public static var ip: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: CInt(IPPROTO_IP))\n    }\n    #else\n    @inlinable\n    public static var ip: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_IP)\n    }\n    #endif\n\n    /// Socket options that apply only to IPv6 sockets.\n    #if os(Linux) || os(Android)\n    @inlinable\n    public static var ipv6: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: CInt(IPPROTO_IPV6))\n    }\n    #elseif os(Windows)\n    @inlinable\n    public static var ipv6: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_IPV6.rawValue)\n    }\n    #else\n    @inlinable\n    public static var ipv6: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_IPV6)\n    }\n    #endif\n\n    /// Socket options that apply only to TCP sockets.\n    #if os(Linux) || os(Android)\n    @inlinable\n    public static var tcp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: CInt(IPPROTO_TCP))\n    }\n    #elseif os(Windows)\n    @inlinable\n    public static var tcp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_TCP.rawValue)\n    }\n    #else\n    @inlinable\n    public static var tcp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_TCP)\n    }\n    #endif\n\n    /// Socket options that apply to MPTCP sockets.\n    ///\n    /// These only work on Linux currently.\n    @inlinable\n    public static var mptcp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: 284)\n    }\n\n    /// Socket options that apply to all sockets.\n    @inlinable\n    public static var socket: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: SOL_SOCKET)\n    }\n\n    /// Socket options that apply only to UDP sockets.\n    #if os(Linux) || os(Android)\n    @inlinable\n    public static var udp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: CInt(IPPROTO_UDP))\n    }\n    #elseif os(Windows)\n    @inlinable\n    public static var udp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_UDP.rawValue)\n    }\n    #else\n    @inlinable\n    public static var udp: NIOBSDSocket.OptionLevel {\n        NIOBSDSocket.OptionLevel(rawValue: IPPROTO_UDP)\n    }\n    #endif\n}\n\n// IPv4 Options\nextension NIOBSDSocket.Option {\n    /// Add a multicast group membership.\n    @inlinable\n    public static var ip_add_membership: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IP_ADD_MEMBERSHIP)\n    }\n\n    /// Drop a multicast group membership.\n    @inlinable\n    public static var ip_drop_membership: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IP_DROP_MEMBERSHIP)\n    }\n\n    /// Set the interface for outgoing multicast packets.\n    @inlinable\n    public static var ip_multicast_if: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IP_MULTICAST_IF)\n    }\n\n    /// Control multicast loopback.\n    @inlinable\n    public static var ip_multicast_loop: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IP_MULTICAST_LOOP)\n    }\n\n    /// Control multicast time-to-live.\n    @inlinable\n    public static var ip_multicast_ttl: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IP_MULTICAST_TTL)\n    }\n\n    /// The IPv4 layer generates an IP header when sending a packet\n    /// unless the ``ip_hdrincl`` socket option is enabled on the socket.\n    /// When it is enabled, the packet must contain an IP header.  For\n    /// receiving, the IP header is always included in the packet.\n    @inlinable\n    public static var ip_hdrincl: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IP_HDRINCL)\n    }\n}\n\n// IPv6 Options\nextension NIOBSDSocket.Option {\n    /// Add an IPv6 group membership.\n    @inlinable\n    public static var ipv6_join_group: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IPV6_JOIN_GROUP)\n    }\n\n    /// Drop an IPv6 group membership.\n    @inlinable\n    public static var ipv6_leave_group: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IPV6_LEAVE_GROUP)\n    }\n\n    /// Specify the maximum number of router hops for an IPv6 packet.\n    @inlinable\n    public static var ipv6_multicast_hops: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IPV6_MULTICAST_HOPS)\n    }\n\n    /// Set the interface for outgoing multicast packets.\n    @inlinable\n    public static var ipv6_multicast_if: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IPV6_MULTICAST_IF)\n    }\n\n    /// Control multicast loopback.\n    @inlinable\n    public static var ipv6_multicast_loop: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IPV6_MULTICAST_LOOP)\n    }\n\n    /// Indicates if a socket created for the `AF_INET6` address family is\n    /// restricted to IPv6 only.\n    @inlinable\n    public static var ipv6_v6only: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: IPV6_V6ONLY)\n    }\n}\n\n// TCP Options\nextension NIOBSDSocket.Option {\n    /// Disables the Nagle algorithm for send coalescing.\n    @inlinable\n    public static var tcp_nodelay: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: TCP_NODELAY)\n    }\n}\n\n#if os(Linux) || os(FreeBSD) || os(Android)\nextension NIOBSDSocket.Option {\n    /// Get information about the TCP connection.\n    @inlinable\n    public static var tcp_info: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: TCP_INFO)\n    }\n}\n#endif\n\n#if canImport(Darwin)\nextension NIOBSDSocket.Option {\n    /// Get information about the TCP connection.\n    @inlinable\n    public static var tcp_connection_info: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: TCP_CONNECTION_INFO)\n    }\n}\n#endif\n\n#if os(Linux)\nextension NIOBSDSocket.Option {\n    // Note: UDP_SEGMENT and UDP_GRO are not available on all Linux platforms so values are\n    // hardcoded.\n\n    /// Use UDP segmentation offload (UDP_SEGMENT, or 'GSO'). Only available on Linux.\n    @inlinable\n    public static var udp_segment: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: 103)\n    }\n\n    /// Use UDP generic receive offload (GRO). Only available on Linux.\n    @inlinable\n    public static var udp_gro: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: 104)\n    }\n}\n#endif\n\n// MPTCP options\n//\n// These values are hardcoded as they're fairly new, and not available in all\n// header files yet.\nextension NIOBSDSocket.Option {\n    /// Get info about an MPTCP connection\n    @inlinable\n    public static var mptcp_info: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: 1)\n    }\n}\n\n#if !os(WASI)\n// Socket Options\nextension NIOBSDSocket.Option {\n    /// Get the error status and clear.\n    @inlinable\n    public static var so_error: NIOBSDSocket.Option {\n        Self(rawValue: SO_ERROR)\n    }\n\n    /// Use keep-alives.\n    @inlinable\n    public static var so_keepalive: NIOBSDSocket.Option {\n        Self(rawValue: SO_KEEPALIVE)\n    }\n\n    /// Linger on close if unsent data is present.\n    @inlinable\n    public static var so_linger: NIOBSDSocket.Option {\n        Self(rawValue: SO_LINGER)\n    }\n\n    /// Specifies the total per-socket buffer space reserved for receives.\n    @inlinable\n    public static var so_rcvbuf: NIOBSDSocket.Option {\n        Self(rawValue: SO_RCVBUF)\n    }\n\n    /// Specifies the total per-socket buffer space reserved for sends.\n    @inlinable\n    public static var so_sndbuf: NIOBSDSocket.Option {\n        Self(rawValue: SO_SNDBUF)\n    }\n\n    /// Specifies the receive timeout.\n    @inlinable\n    public static var so_rcvtimeo: NIOBSDSocket.Option {\n        Self(rawValue: SO_RCVTIMEO)\n    }\n\n    /// Allows the socket to be bound to an address that is already in use.\n    @inlinable\n    public static var so_reuseaddr: NIOBSDSocket.Option {\n        Self(rawValue: SO_REUSEADDR)\n    }\n\n    /// Allows the socket to send broadcast messages.\n    @inlinable\n    public static var so_broadcast: NIOBSDSocket.Option {\n        Self(rawValue: SO_BROADCAST)\n    }\n}\n#endif\n\n#if !os(Windows) && !os(WASI)\nextension NIOBSDSocket.Option {\n    /// Indicate when to generate timestamps.\n    @inlinable\n    public static var so_timestamp: NIOBSDSocket.Option {\n        NIOBSDSocket.Option(rawValue: SO_TIMESTAMP)\n    }\n}\n#endif\n\nextension NIOBSDSocket {\n    // Sadly this was defined on BSDSocket, and we need it for SocketAddress.\n    @inline(never)\n    internal static func inet_pton(\n        addressFamily: NIOBSDSocket.AddressFamily,\n        addressDescription: UnsafePointer<CChar>,\n        address: UnsafeMutableRawPointer\n    ) throws {\n        #if os(Windows)\n        // TODO(compnerd) use `InetPtonW` to ensure that we handle unicode properly\n        switch WinSDK.inet_pton(addressFamily.rawValue, addressDescription, address) {\n        case 0: throw IOError(errnoCode: EINVAL, reason: \"inet_pton\")\n        case 1: return\n        default: throw IOError(winsock: WSAGetLastError(), reason: \"inet_pton\")\n        }\n        #else\n        switch sysInet_pton(CInt(addressFamily.rawValue), addressDescription, address) {\n        case 0: throw IOError(errnoCode: EINVAL, reason: #function)\n        case 1: return\n        default: throw IOError(errnoCode: errno, reason: #function)\n        }\n        #endif\n    }\n\n    @discardableResult\n    @inline(never)\n    internal static func inet_ntop(\n        addressFamily: NIOBSDSocket.AddressFamily,\n        addressBytes: UnsafeRawPointer,\n        addressDescription: UnsafeMutablePointer<CChar>,\n        addressDescriptionLength: socklen_t\n    ) throws -> UnsafePointer<CChar> {\n        #if os(Windows)\n        // TODO(compnerd) use `InetNtopW` to ensure that we handle unicode properly\n        guard\n            let result = WinSDK.inet_ntop(\n                addressFamily.rawValue,\n                addressBytes,\n                addressDescription,\n                Int(addressDescriptionLength)\n            )\n        else {\n            throw IOError(windows: GetLastError(), reason: \"inet_ntop\")\n        }\n        return result\n        #else\n        switch sysInet_ntop(CInt(addressFamily.rawValue), addressBytes, addressDescription, addressDescriptionLength) {\n        case .none: throw IOError(errnoCode: errno, reason: #function)\n        case .some(let ptr): return ptr\n        }\n        #endif\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-aux.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport _NIOBase64\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\nextension ByteBuffer {\n\n    // MARK: Bytes ([UInt8]) APIs\n\n    /// Get `length` bytes starting at `index` and return the result as `[UInt8]`. This will not change the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes of interest into the `ByteBuffer`.\n    ///   - length: The number of bytes of interest.\n    /// - Returns: A `[UInt8]` value containing the bytes of interest or `nil` if the bytes `ByteBuffer` are not readable.\n    @inlinable\n    public func getBytes(at index: Int, length: Int) -> [UInt8]? {\n        guard let range = self.rangeWithinReadableBytes(index: index, length: length) else {\n            return nil\n        }\n\n        return self.withUnsafeReadableBytes { ptr in\n            // this is not technically correct because we shouldn't just bind\n            // the memory to `UInt8` but it's not a real issue either and we\n            // need to work around https://bugs.swift.org/browse/SR-9604\n            [UInt8](UnsafeRawBufferPointer(rebasing: ptr[range]).bindMemory(to: UInt8.self))\n        }\n    }\n\n    /// Read `length` bytes off this `ByteBuffer`, move the reader index forward by `length` bytes and return the result\n    /// as `[UInt8]`.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes to be read from this `ByteBuffer`.\n    /// - Returns: A `[UInt8]` value containing `length` bytes or `nil` if there aren't at least `length` bytes readable.\n    @inlinable\n    public mutating func readBytes(length: Int) -> [UInt8]? {\n        guard let result = self.getBytes(at: self.readerIndex, length: length) else {\n            return nil\n        }\n        self._moveReaderIndex(forwardBy: length)\n        return result\n    }\n\n    #if compiler(>=6.2)\n    @inlinable\n    @available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *)\n    public mutating func readInlineArray<\n        let count: Int,\n        IntegerType: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: InlineArray<count, IntegerType>.Type = InlineArray<count, IntegerType>.self\n    ) -> InlineArray<count, IntegerType>? {\n        // use stride to account for padding bytes\n        let stride = MemoryLayout<IntegerType>.stride\n        let bytesRequired = stride * count\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        let inlineArray = InlineArray<count, IntegerType> { (outputSpan: inout OutputSpan<IntegerType>) in\n            for index in 0..<count {\n                // already made sure of 'self.readableBytes >= bytesRequired' above,\n                // so this is safe to force-unwrap as it's guaranteed to exist\n                let integer = self.getInteger(\n                    // this is less than 'bytesRequired' so is safe to multiply\n                    at: stride &* index,\n                    endianness: endianness,\n                    as: IntegerType.self\n                )!\n                outputSpan.append(integer)\n            }\n        }\n        // already made sure of 'self.readableBytes >= bytesRequired' above\n        self._moveReaderIndex(forwardBy: bytesRequired)\n        return inlineArray\n    }\n    #endif\n\n    /// Returns the Bytes at the current reader index without advancing it.\n    ///\n    /// This method is equivalent to calling `getBytes(at: readerIndex, ...)`\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes of interest.\n    /// - Returns: A `[UInt8]` value containing the bytes of interest or `nil` if the bytes `ByteBuffer` are not readable.\n    @inlinable\n    public func peekBytes(length: Int) -> [UInt8]? {\n        self.getBytes(at: self.readerIndex, length: length)\n    }\n\n    // MARK: StaticString APIs\n\n    /// Write the static `string` into this `ByteBuffer` using UTF-8 encoding, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeStaticString(_ string: StaticString) -> Int {\n        let written = self.setStaticString(string, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write the static `string` into this `ByteBuffer` at `index` using UTF-8 encoding, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    ///   - index: The index for the first serialized byte.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    public mutating func setStaticString(_ string: StaticString, at index: Int) -> Int {\n        // please do not replace the code below with code that uses `string.withUTF8Buffer { ... }` (see SR-7541)\n        self.setBytes(\n            UnsafeRawBufferPointer(\n                start: string.utf8Start,\n                count: string.utf8CodeUnitCount\n            ),\n            at: index\n        )\n    }\n\n    // MARK: Hex encoded string APIs\n    /// Write ASCII hexadecimal `string` into this `ByteBuffer` as raw bytes, decoding the hexadecimal & moving the writer index forward appropriately.\n    /// This method will throw if the string input is not of the \"plain\" hex encoded format.\n    /// - Parameters:\n    ///   - plainHexEncodedBytes: The hex encoded string to write. Plain hex dump format is hex bytes optionally separated by spaces, i.e. `48 65 6c 6c 6f` or `48656c6c6f` for `Hello`.\n    ///     This format is compatible with `xxd` CLI utility.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writePlainHexEncodedBytes(_ plainHexEncodedBytes: String) throws -> Int {\n        var slice = plainHexEncodedBytes.utf8[...]\n        let initialWriterIndex = self.writerIndex\n\n        do {\n            while let nextByte = try slice.popNextHexByte() {\n                self.writeInteger(nextByte)\n            }\n            return self.writerIndex - initialWriterIndex\n        } catch {\n            self.moveWriterIndex(to: initialWriterIndex)\n            throw error\n        }\n    }\n\n    // MARK: String APIs\n    /// Write `string` into this `ByteBuffer` using UTF-8 encoding, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeString(_ string: String) -> Int {\n        let written = self.setString(string, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `string` into this `ByteBuffer` null terminated using UTF-8 encoding, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeNullTerminatedString(_ string: String) -> Int {\n        let written = self.setNullTerminatedString(string, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    @inline(never)\n    @inlinable\n    mutating func _setStringSlowpath(_ string: String, at index: Int) -> Int {\n        // slow path, let's try to force the string to be native\n        if let written = (string + \"\").utf8.withContiguousStorageIfAvailable({ utf8Bytes in\n            self.setBytes(utf8Bytes, at: index)\n        }) {\n            return written\n        } else {\n            return self.setBytes(string.utf8, at: index)\n        }\n    }\n\n    /// Write `string` into this `ByteBuffer` at `index` using UTF-8 encoding. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    ///   - index: The index for the first serialized byte.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func setString(_ string: String, at index: Int) -> Int {\n        // Do not implement setString via setSubstring. Before Swift version 5.3,\n        // Substring.UTF8View did not implement withContiguousStorageIfAvailable\n        // and therefore had no fast access to the backing storage.\n        if let written = string.utf8.withContiguousStorageIfAvailable({ utf8Bytes in\n            self.setBytes(utf8Bytes, at: index)\n        }) {\n            // fast path, directly available\n            return written\n        } else {\n            return self._setStringSlowpath(string, at: index)\n        }\n    }\n\n    /// Write `string` null terminated into this `ByteBuffer` at `index` using UTF-8 encoding. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    ///   - index: The index for the first serialized byte.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    public mutating func setNullTerminatedString(_ string: String, at index: Int) -> Int {\n        let length = self.setString(string, at: index)\n        self.setInteger(UInt8(0), at: index &+ length)\n        return length &+ 1\n    }\n\n    /// Get the string at `index` from this `ByteBuffer` decoding using the UTF-8 encoding. Does not move the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index into `ByteBuffer` containing the string of interest.\n    ///   - length: The number of bytes making up the string.\n    /// - Returns: A `String` value containing the UTF-8 decoded selected bytes from this `ByteBuffer` or `nil` if\n    ///            the requested bytes are not readable.\n    @inlinable\n    public func getString(at index: Int, length: Int) -> String? {\n        guard let range = self.rangeWithinReadableBytes(index: index, length: length) else {\n            return nil\n        }\n        return self.withUnsafeReadableBytes { pointer in\n            assert(range.lowerBound >= 0 && (range.upperBound - range.lowerBound) <= pointer.count)\n            return String(\n                decoding: UnsafeRawBufferPointer(rebasing: pointer[range]),\n                as: Unicode.UTF8.self\n            )\n        }\n    }\n\n    /// Get the string at `index` from this `ByteBuffer` decoding using the UTF-8 encoding. Does not move the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index into `ByteBuffer` containing the null terminated string of interest.\n    /// - Returns: A `String` value deserialized from this `ByteBuffer` or `nil` if there isn't a complete null-terminated string,\n    ///            including null-terminator, in the readable bytes after `index` in the buffer\n    @inlinable\n    public func getNullTerminatedString(at index: Int) -> String? {\n        guard let stringLength = self._getNullTerminatedStringLength(at: index) else {\n            return nil\n        }\n        return self.getString(at: index, length: stringLength)\n    }\n\n    @inlinable\n    func _getNullTerminatedStringLength(at index: Int) -> Int? {\n        guard self.readerIndex <= index && index < self.writerIndex else {\n            return nil\n        }\n        guard let endIndex = self.readableBytesView[index...].firstIndex(of: 0) else {\n            return nil\n        }\n        return endIndex &- index\n    }\n\n    /// Read `length` bytes off this `ByteBuffer`, decoding it as `String` using the UTF-8 encoding. Move the reader index forward by `length`.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes making up the string.\n    /// - Returns: A `String` value deserialized from this `ByteBuffer` or `nil` if there aren't at least `length` bytes readable.\n    @inlinable\n    public mutating func readString(length: Int) -> String? {\n        guard let result = self.getString(at: self.readerIndex, length: length) else {\n            return nil\n        }\n        self._moveReaderIndex(forwardBy: length)\n        return result\n    }\n\n    /// Read a null terminated string off this `ByteBuffer`, decoding it as `String` using the UTF-8 encoding. Move the reader index\n    /// forward by the string's length and its null terminator.\n    ///\n    /// - Returns: A `String` value deserialized from this `ByteBuffer` or `nil` if there isn't a complete null-terminated string,\n    ///            including null-terminator, in the readable bytes of the buffer\n    @inlinable\n    public mutating func readNullTerminatedString() -> String? {\n        guard let stringLength = self._getNullTerminatedStringLength(at: self.readerIndex) else {\n            return nil\n        }\n        let result = self.readString(length: stringLength)\n        self.moveReaderIndex(forwardBy: 1)  // move forward by null terminator\n        return result\n    }\n\n    // MARK: Substring APIs\n    /// Write `substring` into this `ByteBuffer` using UTF-8 encoding, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - substring: The substring to write.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeSubstring(_ substring: Substring) -> Int {\n        let written = self.setSubstring(substring, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `substring` into this `ByteBuffer` at `index` using UTF-8 encoding. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - substring: The substring to write.\n    ///   - index: The index for the first serialized byte.\n    /// - Returns: The number of bytes written\n    @discardableResult\n    @inlinable\n    public mutating func setSubstring(_ substring: Substring, at index: Int) -> Int {\n        // Substring.UTF8View implements withContiguousStorageIfAvailable starting with\n        // Swift version 5.3.\n        if let written = substring.utf8.withContiguousStorageIfAvailable({ utf8Bytes in\n            self.setBytes(utf8Bytes, at: index)\n        }) {\n            // fast path, directly available\n            return written\n        } else {\n            // slow path, convert to string\n            return self.setString(String(substring), at: index)\n        }\n    }\n\n    /// Return a String decoded from the bytes at the current reader index using UTF-8 encoding.\n    ///\n    /// This is equivalent to calling `getString(at: readerIndex, length: ...)` and does not advance the reader index.\n    ///\n    /// - Parameter length: The number of bytes making up the string.\n    /// - Returns: A String containing the decoded bytes, or `nil` if the requested bytes are not readable.\n    @inlinable\n    public func peekString(length: Int) -> String? {\n        self.getString(at: self.readerIndex, length: length)\n    }\n\n    /// Return a null-terminated String starting at the current reader index.\n    ///\n    /// This is equivalent to calling `getNullTerminatedString(at: readerIndex)` and does not advance the reader index.\n    ///\n    /// - Returns: A String decoded from the null-terminated bytes, or `nil` if a complete null-terminated string is not available.\n    @inlinable\n    public func peekNullTerminatedString() -> String? {\n        self.getNullTerminatedString(at: self.readerIndex)\n    }\n\n    #if canImport(Dispatch)\n    // MARK: DispatchData APIs\n    /// Write `dispatchData` into this `ByteBuffer`, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - dispatchData: The `DispatchData` instance to write to the `ByteBuffer`.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeDispatchData(_ dispatchData: DispatchData) -> Int {\n        let written = self.setDispatchData(dispatchData, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `dispatchData` into this `ByteBuffer` at `index`. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - dispatchData: The `DispatchData` to write.\n    ///   - index: The index for the first serialized byte.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func setDispatchData(_ dispatchData: DispatchData, at index: Int) -> Int {\n        let allBytesCount = dispatchData.count\n        self.reserveCapacity(index + allBytesCount)\n        self.withVeryUnsafeMutableBytes { destCompleteStorage in\n            assert(destCompleteStorage.count >= index + allBytesCount)\n            let dest = destCompleteStorage[index..<index + allBytesCount]\n            dispatchData.copyBytes(to: .init(rebasing: dest), count: dest.count)\n        }\n        return allBytesCount\n    }\n\n    /// Get the bytes at `index` from this `ByteBuffer` as a `DispatchData`. Does not move the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index into `ByteBuffer` containing the string of interest.\n    ///   - length: The number of bytes.\n    /// - Returns: A `DispatchData` value deserialized from this `ByteBuffer` or `nil` if the requested bytes\n    ///            are not readable.\n    @inlinable\n    public func getDispatchData(at index: Int, length: Int) -> DispatchData? {\n        guard let range = self.rangeWithinReadableBytes(index: index, length: length) else {\n            return nil\n        }\n        return self.withUnsafeReadableBytes { pointer in\n            DispatchData(bytes: UnsafeRawBufferPointer(rebasing: pointer[range]))\n        }\n    }\n\n    /// Read `length` bytes off this `ByteBuffer` and return them as a `DispatchData`. Move the reader index forward by `length`.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes.\n    /// - Returns: A `DispatchData` value containing the bytes from this `ByteBuffer` or `nil` if there aren't at least `length` bytes readable.\n    @inlinable\n    public mutating func readDispatchData(length: Int) -> DispatchData? {\n        guard let result = self.getDispatchData(at: self.readerIndex, length: length) else {\n            return nil\n        }\n        self._moveReaderIndex(forwardBy: length)\n        return result\n    }\n\n    /// Return a DispatchData object containing the bytes at the current reader index.\n    ///\n    /// This is equivalent to calling `getDispatchData(at: readerIndex, length: ...)` and does not advance the reader index.\n    ///\n    /// - Parameter length: The number of bytes to be retrieved.\n    /// - Returns: A DispatchData object, or `nil` if the requested bytes are not readable.\n    @inlinable\n    public func peekDispatchData(length: Int) -> DispatchData? {\n        self.getDispatchData(at: self.readerIndex, length: length)\n    }\n    #endif\n\n    // MARK: Other APIs\n\n    /// Yields an immutable buffer pointer containing this `ByteBuffer`'s readable bytes. Will move the reader index\n    /// by the number of bytes returned by `body`.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes and returns the number of bytes it processed.\n    /// - Returns: The number of bytes read.\n    @discardableResult\n    @inlinable\n    public mutating func readWithUnsafeReadableBytes<ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer) throws(ErrorType) -> Int\n    ) throws(ErrorType) -> Int {\n        let bytesRead = try self.withUnsafeReadableBytes({ (ptr: UnsafeRawBufferPointer) throws(ErrorType) -> Int in\n            try body(ptr)\n        })\n        self._moveReaderIndex(forwardBy: bytesRead)\n        return bytesRead\n    }\n\n    /// Yields a mutable buffer pointer containing this `ByteBuffer`'s readable bytes. You may modify the yielded bytes.\n    /// Will move the reader index by the number of bytes returned by `body` but leave writer index as it was.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes and returns the number of bytes it processed.\n    /// - Returns: The number of bytes read.\n    @discardableResult\n    @inlinable\n    public mutating func readWithUnsafeMutableReadableBytes<ErrorType: Error>(\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int\n    ) throws(ErrorType) -> Int {\n        let bytesRead = try self.withUnsafeMutableReadableBytes({\n            (ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int in try body(ptr)\n        })\n        self._moveReaderIndex(forwardBy: bytesRead)\n        return bytesRead\n    }\n\n    /// Copy `buffer`'s readable bytes into this `ByteBuffer` starting at `index`. Does not move any of the reader or writer indices.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` to copy.\n    ///   - index: The index for the first byte.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @available(*, deprecated, renamed: \"setBuffer(_:at:)\")\n    public mutating func set(buffer: ByteBuffer, at index: Int) -> Int {\n        self.setBuffer(buffer, at: index)\n    }\n\n    /// Copy `buffer`'s readable bytes into this `ByteBuffer` starting at `index`. Does not move any of the reader or writer indices.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` to copy.\n    ///   - index: The index for the first byte.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func setBuffer(_ buffer: ByteBuffer, at index: Int) -> Int {\n        buffer.withUnsafeReadableBytes { p in\n            self.setBytes(p, at: index)\n        }\n    }\n\n    /// Write `buffer`'s readable bytes into this `ByteBuffer` starting at `writerIndex`. This will move both this\n    /// `ByteBuffer`'s writer index as well as `buffer`'s reader index by the number of bytes readable in `buffer`.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` to write.\n    /// - Returns: The number of bytes written to this `ByteBuffer` which is equal to the number of bytes read from `buffer`.\n    @discardableResult\n    @inlinable\n    public mutating func writeBuffer(_ buffer: inout ByteBuffer) -> Int {\n        let written = self.setBuffer(buffer, at: writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        buffer._moveReaderIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `bytes`, a `Sequence` of `UInt8` into this `ByteBuffer`. Moves the writer index forward by the number of bytes written.\n    ///\n    /// - Parameters:\n    ///   - bytes: A `Collection` of `UInt8` to be written.\n    /// - Returns: The number of bytes written or `bytes.count`.\n    @discardableResult\n    @inlinable\n    public mutating func writeBytes<Bytes: Sequence>(_ bytes: Bytes) -> Int where Bytes.Element == UInt8 {\n        let written = self.setBytes(bytes, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `bytes` into this `ByteBuffer`. Moves the writer index forward by the number of bytes written.\n    ///\n    /// - Parameters:\n    ///   - bytes: An `UnsafeRawBufferPointer`\n    /// - Returns: The number of bytes written or `bytes.count`.\n    @discardableResult\n    @inlinable\n    public mutating func writeBytes(_ bytes: UnsafeRawBufferPointer) -> Int {\n        let written = self.setBytes(bytes, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    #if compiler(>=6.2)\n    /// Write `bytes` into this `ByteBuffer`. Moves the writer index forward by the number of bytes written.\n    ///\n    /// - Parameters:\n    ///   - bytes: A `RawSpan`\n    /// - Returns: The number of bytes written or `bytes.byteCount`.\n    @discardableResult\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public mutating func writeBytes(_ bytes: RawSpan) -> Int {\n        let written = self.setBytes(bytes, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n    #endif\n\n    /// Writes `byte` `count` times. Moves the writer index forward by the number of bytes written.\n    ///\n    /// - Parameters:\n    ///   - byte: The `UInt8` byte to repeat.\n    ///   - count: How many times to repeat the given `byte`\n    /// - Returns: How many bytes were written.\n    @discardableResult\n    @inlinable\n    public mutating func writeRepeatingByte(_ byte: UInt8, count: Int) -> Int {\n        let written = self.setRepeatingByte(byte, count: count, at: self.writerIndex)\n        self._moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Sets the given `byte` `count` times at the given `index`. Will reserve more memory if necessary. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - byte: The `UInt8` byte to repeat.\n    ///   - count: How many times to repeat the given `byte`\n    ///   - index: The starting index of the bytes into the `ByteBuffer`.\n    /// - Returns: How many bytes were written.\n    @discardableResult\n    @inlinable\n    public mutating func setRepeatingByte(_ byte: UInt8, count: Int, at index: Int) -> Int {\n        precondition(count >= 0, \"Can't write fewer than 0 bytes\")\n        self.reserveCapacity(index + count)\n        self.withVeryUnsafeMutableBytes { pointer in\n            let dest = UnsafeMutableRawBufferPointer(rebasing: pointer[index..<index + count])\n            _ = dest.initializeMemory(as: UInt8.self, repeating: byte)\n        }\n        return count\n    }\n\n    /// Slice the readable bytes off this `ByteBuffer` without modifying the reader index. This method will return a\n    /// `ByteBuffer` sharing the underlying storage with the `ByteBuffer` the method was invoked on. The returned\n    /// `ByteBuffer` will contain the bytes in the range `readerIndex..<writerIndex` of the original `ByteBuffer`.\n    ///\n    /// - Note: Because `ByteBuffer` implements copy-on-write a copy of the storage will be automatically triggered when either of the `ByteBuffer`s sharing storage is written to.\n    ///\n    /// - Returns: A `ByteBuffer` sharing storage containing the readable bytes only.\n    @inlinable\n    public func slice() -> ByteBuffer {\n        // must work, bytes definitely in the buffer// must work, bytes definitely in the buffer\n        self.getSlice(at: self.readerIndex, length: self.readableBytes)!\n    }\n\n    /// Slice `length` bytes off this `ByteBuffer` and move the reader index forward by `length`.\n    /// If enough bytes are readable the `ByteBuffer` returned by this method will share the underlying storage with\n    /// the `ByteBuffer` the method was invoked on.\n    /// The returned `ByteBuffer` will contain the bytes in the range `readerIndex..<(readerIndex + length)` of the\n    /// original `ByteBuffer`.\n    /// The `readerIndex` of the returned `ByteBuffer` will be `0`, the `writerIndex` will be `length`.\n    ///\n    /// - Note: Because `ByteBuffer` implements copy-on-write a copy of the storage will be automatically triggered when either of the `ByteBuffer`s sharing storage is written to.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes to slice off.\n    /// - Returns: A `ByteBuffer` sharing storage containing `length` bytes or `nil` if the not enough bytes were readable.\n    @inlinable\n    public mutating func readSlice(length: Int) -> ByteBuffer? {\n        guard let result = self.getSlice_inlineAlways(at: self.readerIndex, length: length) else {\n            return nil\n        }\n        self._moveReaderIndex(forwardBy: length)\n        return result\n    }\n\n    @discardableResult\n    @inlinable\n    public mutating func writeImmutableBuffer(_ buffer: ByteBuffer) -> Int {\n        var mutable = buffer\n        return self.writeBuffer(&mutable)\n    }\n}\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\nextension ByteBuffer {\n    /// Yields a mutable buffer pointer containing this `ByteBuffer`'s readable bytes. You may modify the yielded bytes.\n    /// Will move the reader index by the number of bytes `body` returns in the first tuple component but leave writer index as it was.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes and returns the number of bytes it processed along with some other value.\n    /// - Returns: The value `body` returned in the second tuple component.\n    @inlinable\n    public mutating func readWithUnsafeMutableReadableBytes<T, ErrorType: Error>(\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> (Int, T)\n    ) throws(ErrorType) -> T {\n        let (bytesRead, ret) = try self.withUnsafeMutableReadableBytes({\n            (ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> (Int, T) in try body(ptr)\n        })\n        self._moveReaderIndex(forwardBy: bytesRead)\n        return ret\n    }\n\n    /// Yields an immutable buffer pointer containing this `ByteBuffer`'s readable bytes. Will move the reader index\n    /// by the number of bytes `body` returns in the first tuple component.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes and returns the number of bytes it processed along with some other value.\n    /// - Returns: The value `body` returned in the second tuple component.\n    @inlinable\n    public mutating func readWithUnsafeReadableBytes<T, ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer) throws(ErrorType) -> (Int, T)\n    ) throws(ErrorType) -> T {\n        let (bytesRead, ret) = try self.withUnsafeReadableBytes({\n            (ptr: UnsafeRawBufferPointer) throws(ErrorType) -> (Int, T) in try body(ptr)\n        })\n        self._moveReaderIndex(forwardBy: bytesRead)\n        return ret\n    }\n}\n\nextension ByteBuffer {\n    /// Return an empty `ByteBuffer` allocated with `ByteBufferAllocator()`.\n    ///\n    /// Calling this constructor will not allocate because it will return a `ByteBuffer` that wraps a shared storage\n    /// object. As soon as you write to the constructed buffer however, you will incur an allocation because a\n    /// copy-on-write will happen.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` it is\n    ///         recommended using `channel.allocator.buffer(capacity: 0)`. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init() {\n        self = ByteBufferAllocator.zeroCapacityWithDefaultAllocator\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the `string` encoded as UTF-8.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `string` and potentially some extra space using\n    /// the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(string:)`. Or if you want to write multiple items into the\n    ///         buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeString` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init(string: String) {\n        self = ByteBufferAllocator().buffer(string: string)\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the `string` encoded as UTF-8.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `string` and potentially some extra space using\n    /// the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(substring:)`. Or if you want to write multiple items into\n    ///         the buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeSubstring` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init(substring string: Substring) {\n        self = ByteBufferAllocator().buffer(substring: string)\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the `string` encoded as UTF-8.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `string` and potentially some extra space using\n    /// the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(staticString:)`. Or if you want to write multiple items into\n    ///         the buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeStaticString` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init(staticString string: StaticString) {\n        self = ByteBufferAllocator().buffer(staticString: string)\n    }\n\n    /// Create a fresh `ByteBuffer` containing the `bytes`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `bytes` and potentially some extra space using\n    /// the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(bytes:)`. Or if you want to write multiple items into the\n    ///         buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeBytes` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init<Bytes: Sequence>(bytes: Bytes) where Bytes.Element == UInt8 {\n        self = ByteBufferAllocator().buffer(bytes: bytes)\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the byte representation in the given `endianness` of\n    /// `integer`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `integer` and potentially some extra space using\n    /// the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(integer:)`. Or if you want to write multiple items into the\n    ///         buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeInteger` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init<I: FixedWidthInteger>(integer: I, endianness: Endianness = .big, as: I.Type = I.self) {\n        self = ByteBufferAllocator().buffer(integer: integer, endianness: endianness, as: `as`)\n    }\n\n    /// Create a fresh `ByteBuffer` containing `count` repetitions of `byte`.\n    ///\n    /// This will allocate a new `ByteBuffer` with at least `count` bytes.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(repeating:count:)`. Or if you want to write multiple items\n    ///         into the buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeRepeatingByte` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init(repeating byte: UInt8, count: Int) {\n        self = ByteBufferAllocator().buffer(repeating: byte, count: count)\n    }\n\n    /// Create a fresh `ByteBuffer` containing the readable bytes of `buffer`.\n    ///\n    /// This may allocate a new `ByteBuffer` with enough space to fit `buffer` and potentially some extra space using\n    /// the default allocator.\n    ///\n    /// - Note: Use this method only if you deliberately want to reallocate a potentially smaller `ByteBuffer` than the\n    ///         one you already have. Given that `ByteBuffer` is a value type, defensive copies are not necessary. If\n    ///         you have a `ByteBuffer` but would like the `readerIndex` to start at `0`, consider `readSlice` instead.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(buffer:)`. Or if you want to write multiple items into the\n    ///         buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeImmutableBuffer` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init(buffer: ByteBuffer) {\n        self = ByteBufferAllocator().buffer(buffer: buffer)\n    }\n\n    #if canImport(Dispatch)\n    /// Create a fresh `ByteBuffer` containing the bytes contained in the given `DispatchData`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit the bytes of the `DispatchData` and potentially\n    /// some extra space using the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(dispatchData:)`. Or if you want to write multiple items into\n    ///         the buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeDispatchData` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    @inlinable\n    public init(dispatchData: DispatchData) {\n        self = ByteBufferAllocator().buffer(dispatchData: dispatchData)\n    }\n    #endif\n\n    #if compiler(>=6.2)\n    /// Create a fresh ``ByteBuffer`` with a minimum size, and initializing it safely via an `OutputSpan`.\n    ///\n    /// This will allocate a new ``ByteBuffer`` with at least `capacity` bytes of storage, and then calls\n    /// `initializer` with an `OutputSpan` over the entire allocated storage. This is a convenient method\n    /// to initialize a buffer directly and safely in a single allocation, including from C code.\n    ///\n    /// Once this call returns, the buffer will have its ``ByteBuffer/writerIndex`` appropriately advanced to encompass\n    /// any memory initialized by the `initializer`. Uninitialized memory will be after the ``ByteBuffer/writerIndex``,\n    /// available for subsequent use.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(capacity:initializingWith:)`. Or if you want to write multiple items into\n    ///         the buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `write(minimumWritableBytes:initializingWith:)` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    ///\n    /// - parameters:\n    ///     - capacity: The minimum initial space to allocate for the buffer.\n    ///     - initializer: The initializer that will be invoked to initialize the allocated memory.\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public init<ErrorType: Error>(\n        initialCapacity capacity: Int,\n        initializingWith initializer: (_ span: inout OutputRawSpan) throws(ErrorType) -> Void\n    ) throws(ErrorType) {\n        self = try ByteBufferAllocator().buffer(capacity: capacity, initializingWith: initializer)\n    }\n    #endif\n}\n\nextension ByteBuffer: Codable {\n\n    /// Creates a ByteByffer by decoding from a Base64 encoded single value container.\n    public init(from decoder: Decoder) throws {\n        let container = try decoder.singleValueContainer()\n        let base64String = try container.decode(String.self)\n        self = try ByteBuffer(bytes: base64String._base64Decoded())\n    }\n\n    /// Encodes this buffer as a base64 string in a single value container.\n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        let base64String = String(_base64Encoding: self.readableBytesView)\n        try container.encode(base64String)\n    }\n}\n\nextension ByteBufferAllocator {\n    /// Create a fresh `ByteBuffer` containing the bytes of the `string` encoded as UTF-8.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `string` and potentially some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(string: String) -> ByteBuffer {\n        var buffer = self.buffer(capacity: string.utf8.count)\n        buffer.writeString(string)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the `string` encoded as UTF-8.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `string` and potentially some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(substring string: Substring) -> ByteBuffer {\n        var buffer = self.buffer(capacity: string.utf8.count)\n        buffer.writeSubstring(string)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the `string` encoded as UTF-8.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `string` and potentially some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(staticString string: StaticString) -> ByteBuffer {\n        var buffer = self.buffer(capacity: string.utf8CodeUnitCount)\n        buffer.writeStaticString(string)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing the `bytes`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `bytes` and potentially some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer<Bytes: Sequence>(bytes: Bytes) -> ByteBuffer where Bytes.Element == UInt8 {\n        var buffer = self.buffer(capacity: bytes.underestimatedCount)\n        buffer.writeBytes(bytes)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing the `bytes` decoded from the ASCII `plainHexEncodedBytes` string .\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `bytes` and potentially some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(plainHexEncodedBytes string: String) throws -> ByteBuffer {\n        var buffer = self.buffer(capacity: string.utf8.count / 2)\n        try buffer.writePlainHexEncodedBytes(string)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing the bytes of the byte representation in the given `endianness` of\n    /// `integer`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit `integer` and potentially some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer<I: FixedWidthInteger>(\n        integer: I,\n        endianness: Endianness = .big,\n        as: I.Type = I.self\n    ) -> ByteBuffer {\n        var buffer = self.buffer(capacity: MemoryLayout<I>.size)\n        buffer.writeInteger(integer, endianness: endianness, as: `as`)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing `count` repetitions of `byte`.\n    ///\n    /// This will allocate a new `ByteBuffer` with at least `count` bytes.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(repeating byte: UInt8, count: Int) -> ByteBuffer {\n        var buffer = self.buffer(capacity: count)\n        buffer.writeRepeatingByte(byte, count: count)\n        return buffer\n    }\n\n    /// Create a fresh `ByteBuffer` containing the readable bytes of `buffer`.\n    ///\n    /// This may allocate a new `ByteBuffer` with enough space to fit `buffer` and potentially some extra space.\n    ///\n    /// - Note: Use this method only if you deliberately want to reallocate a potentially smaller `ByteBuffer` than the\n    ///         one you already have. Given that `ByteBuffer` is a value type, defensive copies are not necessary. If\n    ///         you have a `ByteBuffer` but would like the `readerIndex` to start at `0`, consider `readSlice` instead.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(buffer: ByteBuffer) -> ByteBuffer {\n        var newBuffer = self.buffer(capacity: buffer.readableBytes)\n        newBuffer.writeImmutableBuffer(buffer)\n        return newBuffer\n    }\n\n    #if canImport(Dispatch)\n    /// Create a fresh `ByteBuffer` containing the bytes contained in the given `DispatchData`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit the bytes of the `DispatchData` and potentially\n    /// some extra space.\n    ///\n    /// - Returns: The `ByteBuffer` containing the written bytes.\n    @inlinable\n    public func buffer(dispatchData: DispatchData) -> ByteBuffer {\n        var buffer = self.buffer(capacity: dispatchData.count)\n        buffer.writeDispatchData(dispatchData)\n        return buffer\n    }\n    #endif\n\n    #if compiler(>=6.2)\n    /// Create a fresh ``ByteBuffer`` with a minimum size, and initializing it safely via an `OutputSpan`.\n    ///\n    /// This will allocate a new ``ByteBuffer`` with at least `capacity` bytes of storage, and then calls\n    /// `initializer` with an `OutputSpan` over the entire allocated storage. This is a convenient method\n    /// to initialize a buffer directly and safely in a single allocation, including from C code.\n    ///\n    /// Once this call returns, the buffer will have its ``ByteBuffer/writerIndex`` appropriately advanced to encompass\n    /// any memory initialized by the `initializer`. Uninitialized memory will be after the ``ByteBuffer/writerIndex``,\n    /// available for subsequent use.\n    ///\n    /// - parameters:\n    ///     - capacity: The minimum initial space to allocate for the buffer.\n    ///     - initializer: The initializer that will be invoked to initialize the allocated memory.\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public func buffer<ErrorType: Error>(\n        capacity: Int,\n        initializingWith initializer: (_ span: inout OutputRawSpan) throws(ErrorType) -> Void\n    ) throws(ErrorType) -> ByteBuffer {\n        var buffer = self.buffer(capacity: capacity)\n        try buffer.writeWithOutputRawSpan(minimumWritableBytes: capacity, initializingWith: initializer)\n        return buffer\n    }\n    #endif\n}\n\nextension Optional where Wrapped == ByteBuffer {\n    /// If `nil`, replace `self` with `.some(buffer)`. If non-`nil`, write `buffer`'s readable bytes into the\n    /// `ByteBuffer` starting at `writerIndex`.\n    ///\n    ///  This method will not modify `buffer`, meaning its `readerIndex` and `writerIndex` stays intact.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` to write.\n    /// - Returns: The number of bytes written to this `ByteBuffer` which is equal to the number of `readableBytes` in\n    ///            `buffer`.\n    @discardableResult\n    @inlinable\n    public mutating func setOrWriteImmutableBuffer(_ buffer: ByteBuffer) -> Int {\n        var mutable = buffer\n        return self.setOrWriteBuffer(&mutable)\n    }\n\n    /// If `nil`, replace `self` with `.some(buffer)`. If non-`nil`, write `buffer`'s readable bytes into the\n    /// `ByteBuffer` starting at `writerIndex`.\n    ///\n    /// This will move both this `ByteBuffer`'s writer index as well as `buffer`'s reader index by the number of bytes\n    /// readable in `buffer`.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` to write.\n    /// - Returns: The number of bytes written to this `ByteBuffer` which is equal to the number of bytes read from `buffer`.\n    @discardableResult\n    @inlinable\n    public mutating func setOrWriteBuffer(_ buffer: inout ByteBuffer) -> Int {\n        if self == nil {\n            let readableBytes = buffer.readableBytes\n            self = buffer\n            buffer.moveReaderIndex(to: buffer.writerIndex)\n            return readableBytes\n        } else {\n            return self!.writeBuffer(&buffer)\n        }\n    }\n}\n\nextension ByteBuffer {\n    /// Get the string at `index` from this `ByteBuffer` decoding using the UTF-8 encoding. Does not move the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// This is an alternative to `ByteBuffer.getString(at:length:)` which ensures the returned string is valid UTF8. If the\n    /// string is not valid UTF8 then a `ReadUTF8ValidationError` error is thrown.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index into `ByteBuffer` containing the string of interest.\n    ///   - length: The number of bytes making up the string.\n    /// - Returns: A `String` value containing the UTF-8 decoded selected bytes from this `ByteBuffer` or `nil` if\n    ///            the requested bytes are not readable.\n    @inlinable\n    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *)\n    public func getUTF8ValidatedString(at index: Int, length: Int) throws -> String? {\n        guard let slice = self.getSlice(at: index, length: length) else {\n            return nil\n        }\n        guard\n            let string = String(\n                validating: slice.readableBytesView,\n                as: Unicode.UTF8.self\n            )\n        else {\n            throw ReadUTF8ValidationError.invalidUTF8\n        }\n        return string\n    }\n\n    /// Read `length` bytes off this `ByteBuffer`, decoding it as `String` using the UTF-8 encoding. Move the reader index\n    /// forward by `length`.\n    ///\n    /// This is an alternative to `ByteBuffer.readString(length:)` which ensures the returned string is valid UTF8. If the\n    /// string is not valid UTF8 then a `ReadUTF8ValidationError` error is thrown and the reader index is not advanced.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes making up the string.\n    /// - Returns: A `String` value deserialized from this `ByteBuffer` or `nil` if there aren't at least `length` bytes readable.\n    @inlinable\n    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *)\n    public mutating func readUTF8ValidatedString(length: Int) throws -> String? {\n        guard let result = try self.getUTF8ValidatedString(at: self.readerIndex, length: length) else {\n            return nil\n        }\n        self.moveReaderIndex(forwardBy: length)\n        return result\n    }\n\n    /// Errors thrown when calling `readUTF8ValidatedString` or `getUTF8ValidatedString`.\n    public struct ReadUTF8ValidationError: Error, Equatable {\n        private enum BaseError: Hashable {\n            case invalidUTF8\n        }\n\n        private var baseError: BaseError\n\n        /// The length of the bytes to copy was negative.\n        public static let invalidUTF8: ReadUTF8ValidationError = .init(baseError: .invalidUTF8)\n    }\n\n    /// Return a UTF-8 validated String decoded from the bytes at the current reader index.\n    ///\n    /// This is equivalent to calling `getUTF8ValidatedString(at: readerIndex, length: ...)` and does not advance the reader index.\n    ///\n    /// - Parameter length: The number of bytes making up the string.\n    /// - Returns: A validated String, or `nil` if the requested bytes are not readable.\n    /// - Throws: `ReadUTF8ValidationError.invalidUTF8` if the bytes are not valid UTF8.\n    @inlinable\n    @available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *)\n    public func peekUTF8ValidatedString(length: Int) throws -> String? {\n        try self.getUTF8ValidatedString(at: self.readerIndex, length: length)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-binaryEncodedLengthPrefix.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Describes a way to encode and decode an integer as bytes.\n/// For more information, see <doc:ByteBuffer-lengthPrefix>\n///\npublic protocol NIOBinaryIntegerEncodingStrategy {\n    /// Read an integer from a buffer.\n    /// If there are not enough bytes to read an integer of this encoding, return nil, and do not move the reader index.\n    /// If the the full integer can be read, move the reader index to after the integer, and return the integer.\n    /// - Parameters:\n    ///   - as: The type of integer to be read.\n    ///   - buffer: The buffer to read from.\n    /// - Returns: The integer that was read, or nil if it was not possible to read it.\n    func readInteger<IntegerType: FixedWidthInteger>(\n        as: IntegerType.Type,\n        from buffer: inout ByteBuffer\n    ) -> IntegerType?\n\n    /// Write an integer to a buffer. Move the writer index to after the written integer.\n    /// - Parameters:\n    ///    - integer: The integer to write.\n    ///    - buffer: The buffer to write to.\n    /// - Returns: The number of bytes used to write the integer.\n    func writeInteger<IntegerType: FixedWidthInteger>(\n        _ integer: IntegerType,\n        to buffer: inout ByteBuffer\n    ) -> Int\n\n    /// An estimate of the number of bytes required to write integers using this strategy.\n    /// Callers may use this to reserve bytes before writing the integer.\n    /// If the actual bytes used by the write function is more or less than this, it may be necessary to shuffle bytes.\n    /// Therefore, an accurate prediction here will improve performance.\n    /// This function will be called from ``ByteBuffer/writeLengthPrefixed(strategy:writeData:)``\n    var requiredBytesHint: Int { get }\n\n    /// Write an integer to a buffer. Move the writer index to after the written integer.\n    /// This function will be called when an integer needs to be written, and some capacity has already been reserved for it.\n    /// Implementers should consider using a less efficient encoding, if possible, to fit exactly within the reserved capacity.\n    /// Otherwise, the caller will need to shift bytes to reconcile the difference.\n    /// It is up to the implementer to find the balance between performance and size.\n    /// - Parameters:\n    ///   - integer: The integer to write\n    ///   - reservedCapacity: The capacity already reserved for writing this integer\n    ///   - buffer: The buffer to write into.\n    /// - Returns: The number of bytes used to write the integer.\n    func writeInteger(\n        _ integer: Int,\n        reservedCapacity: Int,\n        to buffer: inout ByteBuffer\n    ) -> Int\n}\n\nextension NIOBinaryIntegerEncodingStrategy {\n    @inlinable\n    public var requiredBytesHint: Int { 1 }\n\n    @inlinable\n    public func writeInteger<IntegerType: FixedWidthInteger>(\n        _ integer: IntegerType,\n        reservedCapacity: Int,\n        to buffer: inout ByteBuffer\n    ) -> Int {\n        self.writeInteger(integer, to: &buffer)\n    }\n}\n\nextension ByteBuffer {\n    /// Read a binary encoded integer, moving the `readerIndex` appropriately.\n    /// If there are not enough bytes, nil is returned.\n    @inlinable\n    public mutating func readEncodedInteger<Strategy: NIOBinaryIntegerEncodingStrategy, Integer: FixedWidthInteger>(\n        as: Integer.Type = Integer.self,\n        strategy: Strategy\n    ) -> Integer? {\n        strategy.readInteger(as: Integer.self, from: &self)\n    }\n\n    /// Write a binary encoded integer.\n    ///\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeEncodedInteger<\n        Integer: FixedWidthInteger,\n        Strategy: NIOBinaryIntegerEncodingStrategy\n    >(\n        _ value: Integer,\n        strategy: Strategy\n    ) -> Int {\n        strategy.writeInteger(value, to: &self)\n    }\n\n    /// Prefixes bytes written by `writeData` with the number of bytes written.\n    /// The number of bytes written is encoded using `strategy`.\n    ///\n    /// - Note: This function works by reserving the number of bytes suggested by `strategy` before the data.\n    /// It then writes the data, and then goes back to write the length.\n    /// If the reserved capacity turns out to be too little or too much, then the data will be shifted.\n    /// Therefore, this function is most performant if the strategy is able to use the same number of bytes that it reserved.\n    ///\n    /// - Parameters:\n    ///   - strategy: The strategy to use for encoding the length.\n    ///   - writeData: A closure that takes a buffer, writes some data to it, and returns the number of bytes written.\n    /// - Returns: Number of total bytes written. This is the length of the written data + the number of bytes used to write the length before it.\n    @discardableResult\n    @inlinable\n    public mutating func writeLengthPrefixed<Strategy: NIOBinaryIntegerEncodingStrategy, ErrorType: Error>(\n        strategy: Strategy,\n        writeData: (_ buffer: inout ByteBuffer) throws(ErrorType) -> Int\n    ) throws(ErrorType) -> Int {\n        /// The index at which we write the length\n        let lengthPrefixIndex = self.writerIndex\n        /// The space which we reserve for writing the length\n        let reservedCapacity = strategy.requiredBytesHint\n        self.writeRepeatingByte(0, count: reservedCapacity)\n\n        /// The index at which we start writing the data originally. We may later move the data if the reserved space for the length wasn't right\n        let originalDataStartIndex = self.writerIndex\n        /// The length of the data written\n        let dataLength: Int\n        do {\n            dataLength = try writeData(&self)\n        } catch {\n            // Clean up our write so that it as if we never did it.\n            self.moveWriterIndex(to: lengthPrefixIndex)\n            throw error\n        }\n        /// The index at the end of the written data originally. We may later move the data if the reserved space for the length wasn't right\n        let originalDataEndIndex = self.writerIndex\n\n        // Quick check to make sure the user didn't do something silly\n        precondition(\n            originalDataEndIndex - originalDataStartIndex == dataLength,\n            \"writeData returned \\(dataLength) bytes, but actually \\(originalDataEndIndex - originalDataStartIndex) bytes were written. They must be the same.\"\n        )\n\n        // We write the length after the data to begin with. We will move it later\n\n        /// The actual number of bytes used to write the length written. The user may write more or fewer bytes than what we reserved\n        let actualIntegerLength = strategy.writeInteger(\n            dataLength,\n            reservedCapacity: reservedCapacity,\n            to: &self\n        )\n\n        switch actualIntegerLength {\n        case reservedCapacity:\n            // Good, exact match, swap the values and then \"delete\" the trailing bytes by moving the index back\n            self._moveBytes(from: originalDataEndIndex, to: lengthPrefixIndex, size: actualIntegerLength)\n            self.moveWriterIndex(to: originalDataEndIndex)\n        case ..<reservedCapacity:\n            // We wrote fewer bytes. We now have to move the length bytes from the end, and\n            // _then_ shrink the rest of the buffer onto it.\n            self._moveBytes(from: originalDataEndIndex, to: lengthPrefixIndex, size: actualIntegerLength)\n            let newDataStartIndex = lengthPrefixIndex + actualIntegerLength\n            self._moveBytes(\n                from: originalDataStartIndex,\n                to: newDataStartIndex,\n                size: dataLength\n            )\n            self.moveWriterIndex(to: newDataStartIndex + dataLength)\n        case reservedCapacity...:\n            // We wrote more bytes. We now have to create enough space. Once we do, we have the same\n            // implementation as the matching case.\n            let extraSpaceNeeded = actualIntegerLength - reservedCapacity\n            self._createSpace(before: lengthPrefixIndex, requiredSpace: extraSpaceNeeded)\n\n            // Clean up the indices.\n            let newDataEndIndex = originalDataEndIndex + extraSpaceNeeded\n            // We wrote the length after the data, so we have to move those bytes to the space at the front\n            self._moveBytes(from: newDataEndIndex, to: lengthPrefixIndex, size: actualIntegerLength)\n            self.moveWriterIndex(to: newDataEndIndex)\n        default:\n            fatalError(\"Unreachable\")\n        }\n\n        let totalBytesWritten = self.writerIndex - lengthPrefixIndex\n        return totalBytesWritten\n    }\n\n    /// Reads a slice which is prefixed with a length. The length will be read using `strategy`, and then that many bytes will be read to create a slice.\n    /// - Returns: The slice, if there are enough bytes to read it fully. In this case, the readerIndex will move to after the slice.\n    /// If there are not enough bytes to read the full slice, the readerIndex will stay unchanged.\n    @inlinable\n    public mutating func readLengthPrefixedSlice<Strategy: NIOBinaryIntegerEncodingStrategy>(\n        strategy: Strategy\n    ) -> ByteBuffer? {\n        let originalReaderIndex = self.readerIndex\n        guard let length = strategy.readInteger(as: Int.self, from: &self), let slice = self.readSlice(length: length)\n        else {\n            self.moveReaderIndex(to: originalReaderIndex)\n            return nil\n        }\n        return slice\n    }\n}\n\n// MARK: - Helpers for writing length-prefixed things\n\nextension ByteBuffer {\n    /// Write the length of `buffer` using `strategy`. Then write the buffer.\n    /// - Parameters:\n    ///   - buffer: The buffer to be written.\n    ///   - strategy: The encoding strategy to use.\n    /// - Returns: The total bytes written. This is the bytes needed to write the length, plus the length of the buffer itself.\n    @discardableResult\n    @inlinable\n    public mutating func writeLengthPrefixedBuffer<\n        Strategy: NIOBinaryIntegerEncodingStrategy\n    >(\n        _ buffer: ByteBuffer,\n        strategy: Strategy\n    ) -> Int {\n        self.reserveCapacity(minimumWritableBytes: buffer.readableBytes + strategy.requiredBytesHint)\n        var written = 0\n        written += self.writeEncodedInteger(buffer.readableBytes, strategy: strategy)\n        written += self.writeImmutableBuffer(buffer)\n        return written\n    }\n\n    /// Write the length of `string` using `strategy`. Then write the string.\n    /// - Parameters:\n    ///  - string: The string to be written.\n    ///  - strategy: The encoding strategy to use.\n    /// - Returns: The total bytes written. This is the bytes needed to write the length, plus the length of the string itself.\n    @discardableResult\n    @inlinable\n    public mutating func writeLengthPrefixedString<\n        Strategy: NIOBinaryIntegerEncodingStrategy\n    >(\n        _ string: String,\n        strategy: Strategy\n    ) -> Int {\n        // writeString always writes the String as UTF8 bytes, without a null-terminator\n        // So the length will be the utf8 count\n        self.reserveCapacity(minimumWritableBytes: string.utf8.count + strategy.requiredBytesHint)\n        var written = 0\n        written += self.writeEncodedInteger(string.utf8.count, strategy: strategy)\n        written += self.writeString(string)\n        return written\n    }\n\n    /// Write the length of `bytes` using `strategy`. Then write the bytes.\n    /// - Parameters:\n    ///  - bytes: The bytes to be written.\n    ///  - strategy: The encoding strategy to use.\n    /// - Returns: The total bytes written. This is the bytes needed to write the length, plus the length of the bytes themselves.\n    @discardableResult\n    @inlinable\n    public mutating func writeLengthPrefixedBytes<\n        Bytes: Sequence,\n        Strategy: NIOBinaryIntegerEncodingStrategy\n    >(\n        _ bytes: Bytes,\n        strategy: Strategy\n    ) -> Int\n    where Bytes.Element == UInt8 {\n        let numberOfBytes = bytes.withContiguousStorageIfAvailable { b in\n            UnsafeRawBufferPointer(b).count\n        }\n        if let numberOfBytes {\n            self.reserveCapacity(minimumWritableBytes: numberOfBytes + strategy.requiredBytesHint)\n            var written = 0\n            written += self.writeEncodedInteger(numberOfBytes, strategy: strategy)\n            written += self.writeBytes(bytes)\n            return written\n        } else {\n            return self.writeLengthPrefixed(strategy: strategy) { buffer in\n                buffer.writeBytes(bytes)\n            }\n        }\n    }\n}\n\nextension ByteBuffer {\n    /// Creates `requiredSpace` bytes of free space immediately before `index`.\n    /// e.g. given [a, b, c, d, e, f, g, h, i, j] and calling this function with (before: 4, requiredSpace: 2) would result in\n    /// [a, b, c, d, 0, 0, e, f, g, h, i, j]\n    /// 2 extra bytes of space were created before index 4 (the letter e).\n    /// The total bytes written will be equal to `requiredSpace`, and the writer index will be moved accordingly.\n    @usableFromInline\n    mutating func _createSpace(before index: Int, requiredSpace: Int) {\n        precondition(index >= self.readerIndex)\n        let bytesToMove = self.writerIndex - index\n\n        // Add the required number of bytes to the end first\n        self.writeRepeatingByte(0, count: requiredSpace)\n        // Move the data forward by that many bytes, to make space at the front\n        // The precondition above makes this safe: our indices are in the valid range, so we can safely use them here\n        try! self.copyBytes(at: index, to: index + requiredSpace, length: bytesToMove)\n    }\n\n    /// Move the `size` bytes starting from `source` to `destination`.\n    /// `source` and `destination` must both be within the writable range.\n    @usableFromInline\n    mutating func _moveBytes(from source: Int, to destination: Int, size: Int) {\n        precondition(source >= self.readerIndex && destination < self.writerIndex && source >= destination)\n        precondition(source + size <= self.writerIndex)\n\n        // The precondition above makes this safe: our indices are in the valid range, so we can safely use them here\n        try! self.copyBytes(at: source, to: destination, length: size)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-conversions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\nextension Array where Element == UInt8 {\n\n    /// Creates a `[UInt8]` from the given buffer. The entire readable portion of the buffer will be read.\n    /// - Parameter buffer: The buffer to read.\n    @inlinable\n    public init(buffer: ByteBuffer) {\n        var buffer = buffer\n        self = buffer.readBytes(length: buffer.readableBytes)!\n    }\n\n}\n\nextension String {\n\n    /// Creates a `String` from a given `ByteBuffer`. The entire readable portion of the buffer will be read.\n    ///\n    /// This initializer always succeeds. If the buffer contains bytes that are not valid UTF-8, they will be\n    /// replaced with the Unicode replacement character (U+FFFD).\n    ///\n    /// If you need to validate that the buffer contains valid UTF-8, use ``ByteBuffer/readUTF8ValidatedString(length:)``\n    /// instead, which throws an error for invalid UTF-8.\n    ///\n    /// - Parameter buffer: The buffer to read.\n    @inlinable\n    public init(buffer: ByteBuffer) {\n        var buffer = buffer\n        self = buffer.readString(length: buffer.readableBytes)!\n    }\n\n    /// Creates a `String` from a given `Int` with a given base (`radix`), padded with zeroes to the provided `padding` size.\n    ///\n    /// - Parameters:\n    ///   - radix: radix base to use for conversion.\n    ///   - padding: the desired length of the resulting string.\n    @inlinable\n    internal init<Value>(_ value: Value, radix: Int, padding: Int) where Value: BinaryInteger {\n        let formatted = String(value, radix: radix)\n        self = String(repeating: \"0\", count: padding - formatted.count) + formatted\n    }\n}\n\n#if canImport(Dispatch)\nextension DispatchData {\n\n    /// Creates a `DispatchData` from a given `ByteBuffer`. The entire readable portion of the buffer will be read.\n    /// - Parameter buffer: The buffer to read.\n    @inlinable\n    public init(buffer: ByteBuffer) {\n        var buffer = buffer\n        self = buffer.readDispatchData(length: buffer.readableBytes)!\n    }\n\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-core.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if os(Windows)\nimport ucrt\n#elseif canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"The Byte Buffer module was unable to identify your C library.\")\n#endif\n\n@usableFromInline let sysMalloc: @convention(c) (size_t) -> UnsafeMutableRawPointer? = malloc\n@usableFromInline let sysRealloc: @convention(c) (UnsafeMutableRawPointer?, size_t) -> UnsafeMutableRawPointer? =\n    realloc\n@inlinable\nfunc sysFree(_ ptr: UnsafeMutableRawPointer) {\n    free(ptr)\n}\n\nextension _ByteBufferSlice: Equatable {}\n\n/// The slice of a `ByteBuffer`, it's different from `Range<UInt32>` because the lower bound is actually only\n/// 24 bits (the upper bound is still 32). Before constructing, you need to make sure the lower bound actually\n/// fits within 24 bits, otherwise the behaviour is undefined.\n@usableFromInline\nstruct _ByteBufferSlice: Sendable {\n    @usableFromInline private(set) var upperBound: ByteBuffer._Index\n    @usableFromInline private(set) var _begin: _UInt24\n    @inlinable var lowerBound: ByteBuffer._Index {\n        UInt32(self._begin)\n    }\n    @inlinable var count: Int {\n        // Safe: the only constructors that set this enforce that upperBound > lowerBound, so\n        // this cannot underflow.\n        Int(self.upperBound &- self.lowerBound)\n    }\n    @inlinable init() {\n        self._begin = .init(0)\n        self.upperBound = .init(0)\n    }\n    @inlinable static var maxSupportedLowerBound: ByteBuffer._Index {\n        ByteBuffer._Index(_UInt24.max)\n    }\n}\n\nextension _ByteBufferSlice {\n    @inlinable init(_ range: Range<UInt32>) {\n        self._begin = _UInt24(range.lowerBound)\n        self.upperBound = range.upperBound\n    }\n}\n\nextension _ByteBufferSlice: CustomStringConvertible {\n    @usableFromInline\n    var description: String {\n        \"_ByteBufferSlice { \\(self.lowerBound)..<\\(self.upperBound) }\"\n    }\n}\n\n/// The preferred allocator for `ByteBuffer` values. The allocation strategy is opaque but is currently libc's\n/// `malloc`, `realloc` and `free`.\n///\n/// - Note: `ByteBufferAllocator` is thread-safe.\npublic struct ByteBufferAllocator: Sendable {\n\n    /// Create a fresh `ByteBufferAllocator`. In the future the allocator might use for example allocation pools and\n    /// therefore it's recommended to reuse `ByteBufferAllocators` where possible instead of creating fresh ones in\n    /// many places.\n    public init() {\n        self.init {\n            sysMalloc($0)\n        } reallocate: { ptr, _, newSize in\n            sysRealloc(ptr, newSize)\n        } deallocate: {\n            sysFree($0)\n        } copy: {\n            $0.copyMemory(from: $1, byteCount: $2)\n        }\n    }\n\n    /// Creates a `ByteBufferAllocator` with custom memory allocation functions.\n    ///\n    /// This allows `ByteBuffer` to work with memory from external allocation systems.\n    /// All memory operations on buffers created with this allocator will use the provided functions.\n    ///\n    /// ## Example: Integrating with External Buffer System\n    ///\n    /// ```swift\n    /// let allocator = ByteBufferAllocator { size in\n    ///     externalSystem.allocate(Int(size))\n    /// } reallocate: { ptr, oldSize, newSize in\n    ///     externalSystem.reallocate(ptr, Int(oldSize), Int(newSize))\n    /// } deallocate: { ptr in\n    ///     externalSystem.deallocate(ptr)\n    /// } copy: { dst, src, count in\n    ///     dst.copyMemory(from: src, byteCount: Int(count))\n    /// }\n    /// ```\n    ///\n    /// - Warning: This is an advanced API. The provided functions must:\n    ///   - Be thread-safe if the allocator will be used from multiple threads\n    ///   - Handle the same pointer across allocate/reallocate/deallocate calls\n    ///   - Not throw or trap (C calling convention)\n    ///\n    /// - Parameters:\n    ///   - allocate: Allocate new memory of given size. Must not return nil.\n    ///   - reallocate: Reallocate existing memory. Takes pointer, old capacity, and new capacity. Must not return nil.\n    ///   - deallocate: Deallocate memory previously allocated by allocate.\n    ///   - copy: Copy bytes between memory regions.\n    @_spi(CustomByteBufferAllocator)\n    @inlinable\n    public init(\n        allocate: @escaping @convention(c) (_ size: size_t) -> UnsafeMutableRawPointer?,\n        reallocate:\n            @escaping @convention(c) (_ ptr: UnsafeMutableRawPointer?, _ oldSize: size_t, _ newSize: size_t) ->\n            UnsafeMutableRawPointer?,\n        deallocate: @escaping @convention(c) (_ ptr: UnsafeMutableRawPointer) -> Void,\n        copy:\n            @escaping @convention(c) (_ dst: UnsafeMutableRawPointer, _ src: UnsafeRawPointer, _ count: size_t) -> Void\n    ) {\n        self.allocate = allocate\n        self.reallocate = reallocate\n        self.deallocate = deallocate\n        self.copy = copy\n    }\n\n    /// Request a freshly allocated `ByteBuffer` of size `capacity` or larger.\n    ///\n    /// - Note: The passed `capacity` is the `ByteBuffer`'s initial capacity, it will grow automatically if necessary.\n    ///\n    /// - Note: If `capacity` is `0`, this function will not allocate. If you want to trigger an allocation immediately,\n    ///         also call `.clear()`.\n    ///\n    /// - Parameters:\n    ///   - capacity: The initial capacity of the returned `ByteBuffer`.\n    @inlinable\n    public func buffer(capacity: Int) -> ByteBuffer {\n        precondition(capacity >= 0, \"ByteBuffer capacity must be positive.\")\n        guard capacity > 0 else {\n            return ByteBufferAllocator.zeroCapacityWithDefaultAllocator\n        }\n        return ByteBuffer(allocator: self, startingCapacity: capacity)\n    }\n\n    @usableFromInline\n    internal static let zeroCapacityWithDefaultAllocator = ByteBuffer(\n        allocator: ByteBufferAllocator(),\n        startingCapacity: 0\n    )\n\n    @usableFromInline internal let allocate: @convention(c) (size_t) -> UnsafeMutableRawPointer?\n    @usableFromInline internal let reallocate:\n        @convention(c) (UnsafeMutableRawPointer?, size_t, size_t) -> UnsafeMutableRawPointer?\n    @usableFromInline internal let deallocate: @convention(c) (UnsafeMutableRawPointer) -> Void\n    @usableFromInline internal let copy: @convention(c) (UnsafeMutableRawPointer, UnsafeRawPointer, size_t) -> Void\n}\n\n@inlinable func _toCapacity(_ value: Int) -> ByteBuffer._Capacity {\n    ByteBuffer._Capacity(truncatingIfNeeded: value)\n}\n\n@inlinable func _toIndex(_ value: Int) -> ByteBuffer._Index {\n    ByteBuffer._Index(truncatingIfNeeded: value)\n}\n\n/// `ByteBuffer` stores contiguously allocated raw bytes. It is a random and sequential accessible sequence of zero or\n/// more bytes (octets).\n///\n/// ### Allocation\n/// Use `allocator.buffer(capacity: desiredCapacity)` to allocate a new `ByteBuffer`.\n///\n/// ### Basic usage\n/// A variety of types can be read/written from/to a `ByteBuffer`. Using Swift's `extension` mechanism you can easily\n/// create `ByteBuffer` support for your own data types. Out of the box, `ByteBuffer` supports for example the following\n/// types (non-exhaustive list):\n///\n///  - `String`/`StaticString`\n///  - Swift's various (unsigned) integer types\n///  - `Foundation`'s `Data`\n///  - `[UInt8]` and generally any `Collection` of `UInt8`\n///\n/// The best and easiest way to read and convert ``ByteBuffer`` into a `String`,  `Array<UInt8>`, or `Data` is by\n/// passing the buffer to an initializer.\n///\n/// Example:\n///\n///     let buf = ...\n///     let myString = String(buffer: buf)\n///\n/// `ByteBuffer` provides APIs for reading its contents either sequentially (`read*` methods) or randomly (`get*`\n/// methods). All `ByteBuffer` methods that don't contain the word 'unsafe' will only allow you to access the readable\n/// bytes of the buffer, i.e. `readerIndex ..< writerIndex`.\n///\n/// If you need to loop over all the bytes in the buffer, you can use the `Collection` conformance with ``readableBytesView``:\n///\n///     for byte in buffer.readableBytesView {\n///         print(byte)\n///     }\n///\n/// If you need to process the whole buffer front to back, it's recommended that you use sequential `read*` methods:\n///\n///     while buffer.readableBytes > 0 {\n///         if let chunk = buffer.readBytes(length: min(chunkSize, buffer.readableBytes) {\n///             // work with the chunk of data\n///         } else {\n///             // fallback in case of buffer read error.\n///         }\n///     }\n///\n/// ### Random Access\n/// For every supported type `ByteBuffer` usually contains two methods for random access:\n///\n///  1. `get<Type>(at: Int, length: Int)` where `<type>` is for example `String`, `Data`, `Bytes` (for `[UInt8]`)\n///  2. `set<Type>(at: Int)`\n///\n/// Example:\n///\n///     var buf = ...\n///     buf.setString(\"Hello World\", at: 0)\n///     buf.moveWriterIndex(to: 11)\n///     let helloWorld = buf.getString(at: 0, length: 11)\n///\n///     let written = buf.setInteger(17 as Int, at: 11)\n///     buf.moveWriterIndex(forwardBy: written)\n///     let seventeen: Int? = buf.getInteger(at: 11)\n///\n/// If needed, `ByteBuffer` will automatically resize its storage to accommodate your `set` request.\n///\n/// - Note: If you need to access the contents of a `ByteBuffer` with `get*(at: index)` methods, make sure that the\n/// `index` you're passing in is within the readable bytes range. If you try to access an index outside\n/// `readerIndex ..< writerIndex` range, `get*` methods will return `nil`. For most applications, initializing\n/// the desired type with the contents of the buffer, or using one of the `read*` is a better approach.\n///\n/// ### Sequential Access\n/// `ByteBuffer` provides two properties which are indices into the `ByteBuffer` to support sequential access:\n///  - `readerIndex`, the index of the next readable byte\n///  - `writerIndex`, the index of the next byte to write\n///\n/// For every supported type `ByteBuffer` usually contains two methods for sequential access:\n///\n///  1. `read<Type>(length: Int)` to read `length` bytes from the current `readerIndex` (and then advance the reader\n///     index by `length` bytes)\n///  2. `write<Type>(Type)` to write, advancing the `writerIndex` by the appropriate amount\n///\n/// Example:\n///\n///      var buf = ...\n///      buf.writeString(\"Hello World\")\n///      buf.writeInteger(17 as Int)\n///      let helloWorld = buf.readString(length: 11)\n///      let seventeen: Int = buf.readInteger()\n///\n/// ### Layout\n///     +-------------------+------------------+------------------+\n///     | discardable bytes |  readable bytes  |  writable bytes  |\n///     |                   |     (CONTENT)    |                  |\n///     +-------------------+------------------+------------------+\n///     |                   |                  |                  |\n///     0      <=      readerIndex   <=   writerIndex    <=    capacity\n///\n/// The 'discardable bytes' are usually bytes that have already been read, they can however still be accessed using\n/// the random access methods. 'Readable bytes' are the bytes currently available to be read using the sequential\n/// access interface (`read<Type>`/`write<Type>`). Getting `writableBytes` (bytes beyond the writer index) is undefined\n/// behaviour and might yield arbitrary bytes (_not_ `0` initialised).\n///\n/// ### Slicing\n/// `ByteBuffer` supports slicing a `ByteBuffer` without copying the underlying storage.\n///\n/// Example:\n///\n///     var buf = ...\n///     let dataBytes: [UInt8] = [0xca, 0xfe, 0xba, 0xbe]\n///     let dataBytesLength = UInt32(dataBytes.count)\n///     buf.writeInteger(dataBytesLength) /* the header */\n///     buf.writeBytes(dataBytes) /* the data */\n///     let bufDataBytesOnly = buf.getSlice(at: 4, length: dataBytes.count)\n///     /* `bufDataByteOnly` and `buf` will share their storage */\n///\npublic struct ByteBuffer {\n    @usableFromInline typealias Slice = _ByteBufferSlice\n    @usableFromInline typealias Allocator = ByteBufferAllocator\n    // these two type aliases should be made `@usableFromInline internal` for\n    // the 2.0 release when we can drop Swift 4.0 & 4.1 support. The reason they\n    // must be public is because Swift 4.0 and 4.1 don't support attributes for\n    // typealiases and Swift 4.2 warns if those attributes aren't present and\n    // the type is internal.\n    public typealias _Index = UInt32\n    public typealias _Capacity = UInt32\n\n    @usableFromInline var _storage: _Storage\n    @usableFromInline var _readerIndex: _Index\n    @usableFromInline var _writerIndex: _Index\n    @usableFromInline var _slice: Slice\n\n    // MARK: Internal _Storage for CoW\n    /// Note: This class is **not** thread-safe\n    @usableFromInline final class _Storage {\n        @usableFromInline private(set) var capacity: _Capacity\n        @usableFromInline private(set) var bytes: UnsafeMutableRawPointer\n        @usableFromInline let allocator: ByteBufferAllocator\n\n        @inlinable\n        init(bytesNoCopy: UnsafeMutableRawPointer, capacity: _Capacity, allocator: ByteBufferAllocator) {\n            self.bytes = bytesNoCopy\n            self.capacity = capacity\n            self.allocator = allocator\n        }\n\n        deinit {\n            self.deallocate()\n        }\n\n        @inlinable\n        var fullSlice: _ByteBufferSlice {\n            _ByteBufferSlice(0..<self.capacity)\n        }\n\n        @inlinable\n        static func _allocateAndPrepareRawMemory(bytes: _Capacity, allocator: Allocator) -> UnsafeMutableRawPointer {\n            let ptr = allocator.allocate(size_t(bytes))!\n            // bind the memory so we can assume it elsewhere to be bound to UInt8\n            ptr.bindMemory(to: UInt8.self, capacity: Int(bytes))\n            return ptr\n        }\n\n        @inlinable\n        func allocateStorage() -> _Storage {\n            self.allocateStorage(capacity: self.capacity)\n        }\n\n        @inlinable\n        func allocateStorage(capacity: _Capacity) -> _Storage {\n            let newCapacity = capacity == 0 ? 0 : capacity.nextPowerOf2ClampedToMax()\n            return _Storage(\n                bytesNoCopy: _Storage._allocateAndPrepareRawMemory(bytes: newCapacity, allocator: self.allocator),\n                capacity: newCapacity,\n                allocator: self.allocator\n            )\n        }\n\n        @inlinable\n        func reallocSlice(_ slice: Range<ByteBuffer._Index>, capacity: _Capacity) -> _Storage {\n            assert(slice.count <= capacity)\n            let new = self.allocateStorage(capacity: capacity)\n            self.allocator.copy(new.bytes, self.bytes.advanced(by: Int(slice.lowerBound)), size_t(slice.count))\n            return new\n        }\n\n        @inlinable\n        func reallocStorage(capacity minimumNeededCapacity: _Capacity) {\n            let newCapacity = minimumNeededCapacity.nextPowerOf2ClampedToMax()\n            let ptr = self.allocator.reallocate(self.bytes, size_t(self.capacity), size_t(newCapacity))!\n            // bind the memory so we can assume it elsewhere to be bound to UInt8\n            ptr.bindMemory(to: UInt8.self, capacity: Int(newCapacity))\n            self.bytes = ptr\n            self.capacity = newCapacity\n        }\n\n        private func deallocate() {\n            self.allocator.deallocate(self.bytes)\n        }\n\n        @inlinable\n        static func reallocated(minimumCapacity: _Capacity, allocator: Allocator) -> _Storage {\n            let newCapacity = minimumCapacity == 0 ? 0 : minimumCapacity.nextPowerOf2ClampedToMax()\n            // TODO: Use realloc if possible\n            return _Storage(\n                bytesNoCopy: _Storage._allocateAndPrepareRawMemory(bytes: newCapacity, allocator: allocator),\n                capacity: newCapacity,\n                allocator: allocator\n            )\n        }\n\n        func dumpBytes(slice: Slice, offset: Int, length: Int) -> String {\n            var desc = \"[\"\n            let bytes = UnsafeRawBufferPointer(start: self.bytes, count: Int(self.capacity))\n            for byte in bytes[Int(slice.lowerBound) + offset..<Int(slice.lowerBound) + offset + length] {\n                let hexByte = String(byte, radix: 16)\n                desc += \" \\(hexByte.count == 1 ? \"0\" : \"\")\\(hexByte)\"\n            }\n            desc += \" ]\"\n            return desc\n        }\n    }\n\n    @inlinable\n    @inline(never)\n    mutating func _copyStorageAndRebase(capacity: _Capacity, resetIndices: Bool = false) {\n        // This math has to be very careful, because we already know that in some call paths _readerIndex exceeds 1 << 24, and lots of this math\n        // is in UInt32 space. It's not hard for us to trip some of these conditions.\n        // As a result, I've heavily commented this function to explain the math.\n\n        // Step 1: If we are resetting the indices, we need to slide the allocation by at least the current value of _readerIndex, so the new\n        // value of _readerIndex will be 0. Otherwise we can leave them as they are.\n        // Resetting the indices will also ensure that leading unwritten bytes are not copied.\n        let indexRebaseAmount = resetIndices ? self._readerIndex : 0\n\n        // Step 2: We also want to only copy the bytes within the slice, and move them to index 0. As a result, we have this\n        // state space after the copy-and-rebase:\n        //\n        // +--------------+------------------------+-------------------+\n        // | resetIndices | self._slice.lowerBound | self._readerIndex |\n        // +--------------+------------------------+-------------------+\n        // |     true     | 0                      | 0                 |\n        // |     false    | 0                      | self._readerIndex |\n        // +--------------+------------------------+-------------------+\n        //\n        // The maximum value of _readerIndex (and so indexRebaseAmount) is UInt32.max, but that can only happen if the lower bound\n        // of the slice is 0, when this addition would be safe. Recall that _readerIndex is an index _into_ the slice, and the upper bound of\n        // the slice must be stored into a UInt32, so the capacity can never be more than UInt32.max. As _slice.lowerBound advances, _readerIndex\n        // must shrink. In the worst case, _readerIndex == _slice.count == (_slice.upperBound - _slice.lowerBound), so it is always safe to add\n        // _slice.lowerBound to _readerIndex. This cannot overflow.\n        //\n        // This value ends up storing the lower bound of the bytes we want to copy.\n        let storageRebaseAmount = self._slice.lowerBound + indexRebaseAmount\n\n        // Step 3: Here we need to find out the range within the slice that defines the upper bound of the range of bytes we want to copy.\n        // This will be the smallest of:\n        //\n        // 1. The target requested capacity, in bytes, as a UInt32 (the argument `capacity`), added to the lower bound. The resulting size of\n        //     the slice is equal to the argument `capacity`.\n        // 2. The upper bound of the current slice. This will be smaller than (1) if there are fewer bytes in the current buffer than the size of\n        //     the requested capacity.\n        //\n        // This math is checked on purpose: we should not pass a value of capacity that is larger than the size of the buffer, and if resetIndices is\n        // true then we shouldn't pass a value that is larger than readable bytes. If we do, that's an error.\n        let storageUpperBound = min(self._slice.upperBound, storageRebaseAmount + capacity)\n\n        // Step 4: Allocate the new buffer and copy the slice of bytes we want to keep.\n        let newSlice = storageRebaseAmount..<storageUpperBound\n        self._storage = self._storage.reallocSlice(newSlice, capacity: capacity)\n\n        // Step 5: Fixup the indices. These should never trap, but we're going to leave them checked because this method is fiddly.\n        self._moveReaderIndex(to: self._readerIndex - indexRebaseAmount)\n        self._moveWriterIndex(to: self._writerIndex - indexRebaseAmount)\n\n        // Step 6: As we've reallocated the buffer, we can now use the entire new buffer as our slice.\n        self._slice = self._storage.fullSlice\n    }\n\n    @inlinable\n    @inline(never)\n    mutating func _copyStorageAndRebase(extraCapacity: _Capacity = 0, resetIndices: Bool = false) {\n        self._copyStorageAndRebase(capacity: _toCapacity(self._slice.count) + extraCapacity, resetIndices: resetIndices)\n    }\n\n    @inlinable\n    @inline(never)\n    mutating func _ensureAvailableCapacity(_ capacity: _Capacity, at index: _Index) {\n        assert(isKnownUniquelyReferenced(&self._storage))\n\n        let totalNeededCapacityWhenKeepingSlice = self._slice.lowerBound + index + capacity\n        if totalNeededCapacityWhenKeepingSlice > self._slice.upperBound {\n            // we need to at least adjust the slice's upper bound which we can do as we're the unique owner of the storage,\n            // let's see if adjusting the slice's upper bound buys us enough storage\n            if totalNeededCapacityWhenKeepingSlice > self._storage.capacity {\n                let newStorageMinCapacity = index + capacity\n                // nope, we need to actually re-allocate again. If our slice does not start at 0, let's also rebase\n                if self._slice.lowerBound == 0 {\n                    self._storage.reallocStorage(capacity: newStorageMinCapacity)\n                } else {\n                    self._storage = self._storage.reallocSlice(\n                        self._slice.lowerBound..<self._slice.upperBound,\n                        capacity: newStorageMinCapacity\n                    )\n                }\n                self._slice = self._storage.fullSlice\n            } else {\n                // yes, let's just extend the slice until the end of the buffer\n                self._slice = _ByteBufferSlice(_slice.lowerBound..<self._storage.capacity)\n            }\n        }\n        assert(self._slice.lowerBound + index + capacity <= self._slice.upperBound)\n        assert(self._slice.lowerBound >= 0, \"illegal slice: negative lower bound: \\(self._slice.lowerBound)\")\n        assert(\n            self._slice.upperBound <= self._storage.capacity,\n            \"illegal slice: upper bound (\\(self._slice.upperBound)) exceeds capacity: \\(self._storage.capacity)\"\n        )\n    }\n\n    // MARK: Internal API\n\n    @inlinable\n    mutating func _moveReaderIndex(to newIndex: _Index) {\n        assert(newIndex >= 0 && newIndex <= writerIndex)\n        self._readerIndex = newIndex\n    }\n\n    @inlinable\n    mutating func _moveReaderIndex(forwardBy offset: Int) {\n        let newIndex = self._readerIndex + _toIndex(offset)\n        self._moveReaderIndex(to: newIndex)\n    }\n\n    @inlinable\n    mutating func _moveWriterIndex(to newIndex: _Index) {\n        assert(newIndex >= 0 && newIndex <= _toCapacity(self._slice.count))\n        self._writerIndex = newIndex\n    }\n\n    @inlinable\n    mutating func _moveWriterIndex(forwardBy offset: Int) {\n        let newIndex = self._writerIndex + _toIndex(offset)\n        self._moveWriterIndex(to: newIndex)\n    }\n\n    @inlinable\n    mutating func _setBytes(_ bytes: UnsafeRawBufferPointer, at index: _Index) -> _Capacity {\n        let bytesCount = bytes.count\n        let newEndIndex: _Index = index + _toIndex(bytesCount)\n        if !isKnownUniquelyReferenced(&self._storage) {\n            let extraCapacity = newEndIndex > self._slice.upperBound ? newEndIndex - self._slice.upperBound : 0\n            self._copyStorageAndRebase(extraCapacity: extraCapacity)\n        }\n        self._ensureAvailableCapacity(_Capacity(bytesCount), at: index)\n        self._setBytesAssumingUniqueBufferAccess(bytes, at: index)\n        return _toCapacity(bytesCount)\n    }\n\n    @inlinable\n    mutating func _setBytesAssumingUniqueBufferAccess(_ bytes: UnsafeRawBufferPointer, at index: _Index) {\n        let targetPtr = UnsafeMutableRawBufferPointer(\n            rebasing: self._slicedStorageBuffer.dropFirst(Int(index))\n        )\n        targetPtr.copyMemory(from: bytes)\n    }\n\n    #if compiler(>=6.2)\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    mutating func _setBytes(_ bytes: RawSpan, at index: _Index) -> _Capacity {\n        let bytesCount = bytes.byteCount\n        let newEndIndex: _Index = index + _toIndex(bytesCount)\n        if !isKnownUniquelyReferenced(&self._storage) {\n            let extraCapacity = newEndIndex > self._slice.upperBound ? newEndIndex - self._slice.upperBound : 0\n            self._copyStorageAndRebase(extraCapacity: extraCapacity)\n        }\n        self._ensureAvailableCapacity(_Capacity(bytesCount), at: index)\n        self._setBytesAssumingUniqueBufferAccess(bytes, at: index)\n        return _toCapacity(bytesCount)\n    }\n\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    mutating func _setBytesAssumingUniqueBufferAccess(_ bytes: RawSpan, at index: _Index) {\n        let targetPtr = UnsafeMutableRawBufferPointer(\n            rebasing: self._slicedStorageBuffer.dropFirst(Int(index))\n        )\n\n        bytes.withUnsafeBytes {\n            targetPtr.copyMemory(from: $0)\n        }\n    }\n    #endif\n\n    @inline(never)\n    @inlinable\n    @_specialize(where Bytes == CircularBuffer<UInt8>)\n    mutating func _setSlowPath<Bytes: Sequence>(bytes: Bytes, at index: _Index) -> _Capacity\n    where Bytes.Element == UInt8 {\n        func ensureCapacityAndReturnStorageBase(capacity: Int) -> UnsafeMutablePointer<UInt8> {\n            self._ensureAvailableCapacity(_Capacity(capacity), at: index)\n            let newBytesPtr = UnsafeMutableRawBufferPointer(\n                rebasing: self._slicedStorageBuffer[Int(index)..<Int(index) + Int(capacity)]\n            )\n            return newBytesPtr.bindMemory(to: UInt8.self).baseAddress!\n        }\n        let underestimatedByteCount = bytes.underestimatedCount\n        let newPastEndIndex: _Index = index + _toIndex(underestimatedByteCount)\n        if !isKnownUniquelyReferenced(&self._storage) {\n            let extraCapacity = newPastEndIndex > self._slice.upperBound ? newPastEndIndex - self._slice.upperBound : 0\n            self._copyStorageAndRebase(extraCapacity: extraCapacity)\n        }\n\n        var base = ensureCapacityAndReturnStorageBase(capacity: underestimatedByteCount)\n        var (iterator, idx) = UnsafeMutableBufferPointer(start: base, count: underestimatedByteCount).initialize(\n            from: bytes\n        )\n        assert(idx == underestimatedByteCount)\n        while let b = iterator.next() {\n            base = ensureCapacityAndReturnStorageBase(capacity: idx + 1)\n            base[idx] = b\n            idx += 1\n        }\n        return _toCapacity(idx)\n    }\n\n    @inlinable\n    mutating func _setBytes<Bytes: Sequence>(_ bytes: Bytes, at index: _Index) -> _Capacity\n    where Bytes.Element == UInt8 {\n        if let written = bytes.withContiguousStorageIfAvailable({ bytes in\n            self._setBytes(UnsafeRawBufferPointer(bytes), at: index)\n        }) {\n            // fast path, we've got access to the contiguous bytes\n            return written\n        } else {\n            return self._setSlowPath(bytes: bytes, at: index)\n        }\n    }\n\n    // MARK: Public Core API\n\n    @inlinable init(allocator: ByteBufferAllocator, startingCapacity: Int) {\n        let startingCapacity = _toCapacity(startingCapacity)\n        self._readerIndex = 0\n        self._writerIndex = 0\n        self._storage = _Storage.reallocated(minimumCapacity: startingCapacity, allocator: allocator)\n        self._slice = self._storage.fullSlice\n    }\n\n    /// Creates a `ByteBuffer` taking ownership of existing memory.\n    ///\n    /// The `ByteBuffer` takes ownership of the memory in `buffer` and will manage it\n    /// using the provided `allocator`. When the `ByteBuffer` needs to free, grow, or\n    /// copy the memory, it will use the allocator's functions.\n    ///\n    /// ## Example\n    ///\n    /// ```swift\n    /// // Get memory from external system\n    /// let buffer = externalSystem.extractBuffer()\n    ///\n    /// // Create allocator with external system's functions\n    /// let allocator = ByteBufferAllocator { size in\n    ///     externalSystem.allocate(Int(size))\n    /// } reallocate: { ptr, oldSize, newSize in\n    ///     externalSystem.reallocate(ptr, Int(oldSize), Int(newSize))\n    /// } deallocate: { ptr in\n    ///     externalSystem.deallocate(ptr)\n    /// } copy: { dst, src, count in\n    ///     dst.copyMemory(from: src, byteCount: Int(count))\n    /// }\n    ///\n    /// // Take ownership of the memory\n    /// let byteBuffer = ByteBuffer(\n    ///     takingOwnershipOf: buffer,\n    ///     allocator: allocator\n    /// )\n    /// ```\n    ///\n    /// - Warning: The caller must ensure:\n    ///   - The buffer was allocated in a manner compatible with `allocator.deallocate`\n    ///   - The buffer will not be accessed or freed by any other code after this call\n    ///   - The memory region is valid and accessible\n    ///\n    /// - Parameters:\n    ///   - buffer: The buffer whose memory to take ownership of. Must have a non-nil baseAddress.\n    ///   - allocator: The allocator to use for managing this memory\n    ///   - readerIndex: Initial reader index (default: 0)\n    ///   - writerIndex: Initial writer index (default: buffer.count, making all bytes readable)\n    @_spi(CustomByteBufferAllocator)\n    @inlinable\n    public init(\n        takingOwnershipOf buffer: UnsafeMutableRawBufferPointer,\n        allocator: ByteBufferAllocator,\n        readerIndex: Int = 0,\n        writerIndex: Int? = nil\n    ) {\n        precondition(buffer.baseAddress != nil, \"Cannot take ownership of buffer with nil baseAddress\")\n\n        let capacity = buffer.count\n        let writerIndex = writerIndex ?? capacity\n\n        precondition(capacity >= 0, \"ByteBuffer capacity must be non-negative\")\n        precondition(readerIndex >= 0 && readerIndex <= capacity, \"readerIndex out of bounds\")\n        precondition(writerIndex >= readerIndex && writerIndex <= capacity, \"writerIndex out of bounds\")\n\n        let bytes = buffer.baseAddress!\n        bytes.bindMemory(to: UInt8.self, capacity: capacity)\n\n        let storage = _Storage(\n            bytesNoCopy: bytes,\n            capacity: _toCapacity(capacity),\n            allocator: allocator\n        )\n\n        self._storage = storage\n        self._readerIndex = _toIndex(readerIndex)\n        self._writerIndex = _toIndex(writerIndex)\n        self._slice = storage.fullSlice\n    }\n\n    /// The number of bytes writable until `ByteBuffer` will need to grow its underlying storage which will likely\n    /// trigger a copy of the bytes.\n    @inlinable public var writableBytes: Int {\n        // this cannot over/overflow because both values are positive and writerIndex<=slice.count, checked on ingestion\n        Int(_toCapacity(self._slice.count) &- self._writerIndex)\n    }\n\n    /// The number of bytes readable (`readableBytes` = `writerIndex` - `readerIndex`).\n    @inlinable public var readableBytes: Int {\n        // this cannot under/overflow because both are positive and writer >= reader (checked on ingestion of bytes).\n        Int(self._writerIndex &- self._readerIndex)\n    }\n\n    /// The current capacity of the storage of this `ByteBuffer`, this is not constant and does _not_ signify the number\n    /// of bytes that have been written to this `ByteBuffer`.\n    @inlinable\n    public var capacity: Int {\n        self._slice.count\n    }\n\n    /// The current capacity of the underlying storage of this `ByteBuffer`.\n    /// A COW slice of the buffer (e.g. readSlice(length: x)) will posses the same storageCapacity as the original\n    /// buffer until new data is written.\n    @inlinable\n    public var storageCapacity: Int {\n        self._storage.fullSlice.count\n    }\n\n    /// Reserves enough space to store the specified number of bytes.\n    ///\n    /// This method will ensure that the buffer has space for at least as many bytes as requested.\n    /// This includes any bytes already stored, and completely disregards the reader/writer indices.\n    /// If the buffer already has space to store the requested number of bytes, this method will be\n    /// a no-op.\n    ///\n    /// - Parameters:\n    ///   - minimumCapacity: The minimum number of bytes this buffer must be able to store.\n    @inlinable\n    public mutating func reserveCapacity(_ minimumCapacity: Int) {\n        guard minimumCapacity > self.capacity else {\n            return\n        }\n        let targetCapacity = _toCapacity(minimumCapacity)\n\n        if isKnownUniquelyReferenced(&self._storage) {\n            // We have the unique reference. If we have the full slice, we can realloc. Otherwise\n            // we have to copy memory anyway.\n            self._ensureAvailableCapacity(targetCapacity, at: 0)\n        } else {\n            // We don't have a unique reference here, so we need to allocate and copy, no\n            // optimisations available.\n            self._copyStorageAndRebase(capacity: targetCapacity)\n        }\n    }\n\n    /// Reserves enough space to write at least the specified number of bytes.\n    ///\n    /// This method will ensure that the buffer has enough writable space for at least as many bytes\n    /// as requested. If the buffer already has space to write the requested number of bytes, this\n    /// method will be a no-op.\n    ///\n    /// - Parameter minimumWritableBytes: The minimum number of writable bytes this buffer must have.\n    @inlinable\n    public mutating func reserveCapacity(minimumWritableBytes: Int) {\n        self.reserveCapacity(self.writerIndex + minimumWritableBytes)\n    }\n\n    @inlinable\n    @inline(never)\n    mutating func _copyStorageAndRebaseIfNeeded() {\n        if !isKnownUniquelyReferenced(&self._storage) {\n            self._copyStorageAndRebase()\n        }\n    }\n\n    @inlinable\n    var _slicedStorageBuffer: UnsafeMutableRawBufferPointer {\n        UnsafeMutableRawBufferPointer(\n            start: self._storage.bytes.advanced(by: Int(self._slice.lowerBound)),\n            count: self._slice.count\n        )\n    }\n\n    /// Yields a mutable buffer pointer containing this `ByteBuffer`'s readable bytes. You may modify those bytes.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes.\n    /// - Returns: The value returned by `body`.\n    @inlinable\n    public mutating func withUnsafeMutableReadableBytes<T, ErrorType: Error>(\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        self._copyStorageAndRebaseIfNeeded()\n        // this is safe because we always know that readerIndex >= writerIndex\n        let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))\n        return try body(.init(rebasing: self._slicedStorageBuffer[range]))\n    }\n\n    #if compiler(>=6.2)\n    /// Provides safe high-performance read-only access to the readable bytes of this buffer.\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public var readableBytesSpan: RawSpan {\n        @_lifetime(borrow self)\n        borrowing get {\n            let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))\n            return _overrideLifetime(RawSpan(_unsafeBytes: self._slicedStorageBuffer[range]), borrowing: self)\n        }\n    }\n\n    /// Provides mutable access to the readable bytes of this buffer.\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public var mutableReadableBytesSpan: MutableRawSpan {\n        @_lifetime(&self)\n        mutating get {\n            self._copyStorageAndRebaseIfNeeded()\n            let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))\n            return _overrideLifetime(MutableRawSpan(_unsafeBytes: self._slicedStorageBuffer[range]), mutating: &self)\n        }\n    }\n\n    /// Provides safe high-performance read-only access to the readable bytes of this buffer.\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public var readableBytesUInt8Span: Span<UInt8> {\n        @_lifetime(borrow self)\n        borrowing get {\n            let span = self.readableBytesSpan._unsafeView(as: UInt8.self)\n            return _overrideLifetime(span, borrowing: self)\n        }\n    }\n\n    /// Provides mutable access to the readable bytes of this buffer.\n    /// Currently this doesn't compile due to a Faulty exclusivity check\n    /// see https://github.com/swiftlang/swift/issues/81218\n    #if false\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public var mutableReadableBytesUInt8Span: MutableSpan<UInt8> {\n        @_lifetime(&self)\n        mutating get {\n            var bytes = self.mutableReadableBytesSpan\n            let span = bytes._unsafeMutableView(as: UInt8.self)\n            return _overrideLifetime(span, mutating: &self)\n        }\n    }\n    #endif\n\n    /// Enables high-performance low-level appending into the writable section of this buffer.\n    ///\n    /// The writer index will be advanced by the number of bytes written into the\n    /// `OutputRawSpan`.\n    ///\n    /// - parameters:\n    ///     - minimumWritableBytes: The minimum initial space to allocate for the buffer.\n    ///     - initializer: The initializer that will be invoked to initialize the allocated memory.\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public mutating func writeWithOutputRawSpan<ErrorType: Error>(\n        minimumWritableBytes: Int,\n        initializingWith initializer: (_ span: inout OutputRawSpan) throws(ErrorType) -> Void\n    ) throws(ErrorType) {\n        try self.writeWithUnsafeMutableBytes(minimumWritableBytes: minimumWritableBytes) { ptr throws(ErrorType) in\n            var span = OutputRawSpan(buffer: ptr, initializedCount: 0)\n            try initializer(&span)\n            return span.byteCount\n        }\n    }\n    #endif\n\n    /// Yields the bytes currently writable (`bytesWritable` = `capacity` - `writerIndex`). Before reading those bytes you must first\n    /// write to them otherwise you will trigger undefined behaviour. The writer index will remain unchanged.\n    ///\n    /// - Note: In almost all cases you should use `writeWithUnsafeMutableBytes` which will move the write pointer instead of this method\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes and return the number of bytes written.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    public mutating func withUnsafeMutableWritableBytes<T, ErrorType: Error>(\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        self._copyStorageAndRebaseIfNeeded()\n        return try body(.init(rebasing: self._slicedStorageBuffer.dropFirst(self.writerIndex)))\n    }\n\n    /// This vends a pointer of the `ByteBuffer` at the `writerIndex` after ensuring that the buffer has at least `minimumWritableBytes` of writable bytes available.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - minimumWritableBytes: The number of writable bytes to reserve capacity for before vending the `ByteBuffer` pointer to `body`.\n    ///   - body: The closure that will accept the yielded bytes and return the number of bytes written.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeWithUnsafeMutableBytes<ErrorType: Error>(\n        minimumWritableBytes: Int,\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int\n    ) throws(ErrorType) -> Int {\n        if minimumWritableBytes > 0 {\n            self.reserveCapacity(minimumWritableBytes: minimumWritableBytes)\n        }\n        let bytesWritten = try self.withUnsafeMutableWritableBytes({\n            (ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int in try body(ptr)\n        })\n        self._moveWriterIndex(to: self._writerIndex + _toIndex(bytesWritten))\n        return bytesWritten\n    }\n\n    @available(\n        *,\n        deprecated,\n        message:\n            \"please use writeWithUnsafeMutableBytes(minimumWritableBytes:_:) instead to ensure sufficient write capacity.\"\n    )\n    @discardableResult\n    @inlinable\n    public mutating func writeWithUnsafeMutableBytes<ErrorType: Error>(\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int\n    ) throws(ErrorType) -> Int {\n        try self.writeWithUnsafeMutableBytes(\n            minimumWritableBytes: 0,\n            { (ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int in try body(ptr) }\n        )\n    }\n\n    /// This vends a pointer to the storage of the `ByteBuffer`. It's marked as _very unsafe_ because it might contain\n    /// uninitialised memory and it's undefined behaviour to read it. In most cases you should use `withUnsafeReadableBytes`.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    @inlinable\n    public func withVeryUnsafeBytes<T, ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        try body(.init(self._slicedStorageBuffer))\n    }\n\n    /// This vends a pointer to the storage of the `ByteBuffer`. It's marked as _very unsafe_ because it might contain\n    /// uninitialised memory and it's undefined behaviour to read it. In most cases you should use `withUnsafeMutableWritableBytes`.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    @inlinable\n    public mutating func withVeryUnsafeMutableBytes<T, ErrorType: Error>(\n        _ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        self._copyStorageAndRebaseIfNeeded()  // this will trigger a CoW if necessary\n        return try body(.init(self._slicedStorageBuffer))\n    }\n\n    /// Yields a buffer pointer containing this `ByteBuffer`'s readable bytes.\n    ///\n    /// - warning: Do not escape the pointer from the closure for later use.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes.\n    /// - Returns: The value returned by `body`.\n    @inlinable\n    public func withUnsafeReadableBytes<T, ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        // This is safe, writerIndex >= readerIndex\n        let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))\n        return try body(.init(rebasing: self._slicedStorageBuffer[range]))\n    }\n\n    /// Yields a buffer pointer containing this `ByteBuffer`'s readable bytes. You may hold a pointer to those bytes\n    /// even after the closure returned iff you model the lifetime of those bytes correctly using the `Unmanaged`\n    /// instance. If you don't require the pointer after the closure returns, use `withUnsafeReadableBytes`.\n    ///\n    /// If you escape the pointer from the closure, you _must_ call `storageManagement.retain()` to get ownership to\n    /// the bytes and you also must call `storageManagement.release()` if you no longer require those bytes. Calls to\n    /// `retain` and `release` must be balanced.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded bytes and the `storageManagement`.\n    /// - Returns: The value returned by `body`.\n    @inlinable\n    public func withUnsafeReadableBytesWithStorageManagement<T, ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer, Unmanaged<AnyObject>) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        let storageReference: Unmanaged<AnyObject> = Unmanaged.passUnretained(self._storage)\n        // This is safe, writerIndex >= readerIndex\n        let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))\n        return try body(.init(rebasing: self._slicedStorageBuffer[range]), storageReference)\n    }\n\n    /// See `withUnsafeReadableBytesWithStorageManagement` and `withVeryUnsafeBytes`.\n    @inlinable\n    public func withVeryUnsafeBytesWithStorageManagement<T, ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer, Unmanaged<AnyObject>) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T {\n        let storageReference: Unmanaged<AnyObject> = Unmanaged.passUnretained(self._storage)\n        return try body(.init(self._slicedStorageBuffer), storageReference)\n    }\n\n    /// Yields a mutable buffer pointer to this `ByteBuffer`'s storage along with a storage management handle.\n    /// It's marked as _very unsafe_ because it might contain uninitialised memory and it's undefined behaviour to read it.\n    ///\n    /// This method provides mutable access to the full buffer storage (not just readable bytes)\n    /// along with an `Unmanaged` reference to the storage owner for lifetime management.\n    /// If you don't require the pointer after the closure returns, use `withVeryUnsafeMutableBytes`.\n    ///\n    /// If you escape the pointer from the closure, you _must_ call `storageManagement.retain()` to get ownership to\n    /// the bytes and you also must call `storageManagement.release()` if you no longer require those bytes. Calls to\n    /// `retain` and `release` must be balanced.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the mutable buffer pointer and storage management.\n    /// - Returns: The value returned by `body`.\n    @_spi(CustomByteBufferAllocator)\n    @inlinable\n    public mutating func withVeryUnsafeMutableBytesWithStorageManagement<T, ErrorType: Error>(\n        _ body: (_ bytes: UnsafeMutableRawBufferPointer, _ storageManagement: Unmanaged<AnyObject>) throws(ErrorType) ->\n            T\n    ) throws(ErrorType) -> T {\n        self._copyStorageAndRebaseIfNeeded()\n        let storageReference: Unmanaged<AnyObject> = Unmanaged.passUnretained(self._storage)\n        return try body(.init(self._slicedStorageBuffer), storageReference)\n    }\n\n    @inlinable\n    @inline(never)\n    func _copyIntoByteBufferWithSliceIndex0_slowPath(index: _Index, length: _Capacity) -> ByteBuffer {\n        var new = self\n        new._moveWriterIndex(to: index + length)\n        new._moveReaderIndex(to: index)\n        new._copyStorageAndRebase(capacity: length, resetIndices: true)\n        return new\n    }\n\n    /// Returns a slice of size `length` bytes, starting at `index`. The `ByteBuffer` this is invoked on and the\n    /// `ByteBuffer` returned will share the same underlying storage. However, the byte at `index` in this `ByteBuffer`\n    /// will correspond to index `0` in the returned `ByteBuffer`.\n    /// The `readerIndex` of the returned `ByteBuffer` will be `0`, the `writerIndex` will be `length`.\n    ///\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The index the requested slice starts at.\n    ///   - length: The length of the requested slice.\n    /// - Returns: A `ByteBuffer` containing the selected bytes as readable bytes or `nil` if the selected bytes were\n    ///            not readable in the initial `ByteBuffer`.\n    @inlinable\n    public func getSlice(at index: Int, length: Int) -> ByteBuffer? {\n        self.getSlice_inlineAlways(at: index, length: length)\n    }\n\n    @inline(__always)\n    @inlinable\n    internal func getSlice_inlineAlways(at index: Int, length: Int) -> ByteBuffer? {\n        guard\n            index >= 0 && length >= 0 && index >= self.readerIndex && length <= self.writerIndex\n                && index <= self.writerIndex &- length\n        else {\n            return nil\n        }\n        let index = _toIndex(index)\n        let length = _toCapacity(length)\n\n        // The arithmetic below is safe because:\n        // 1. maximum `writerIndex` <= self._slice.count (see `_moveWriterIndex`)\n        // 2. `self._slice.lowerBound + self._slice.count` is always safe (because it's `self._slice.upperBound`)\n        // 3. `index` is inside the range `self.readerIndex ... self.writerIndex` (the `guard` above)\n        //\n        // This means that the largest number that `index` could have is equal to\n        // `self._slice_.upperBound = self._slice.lowerBound + self._slice.count` and that\n        // is guaranteed to be expressible as a `UInt32` (because it's actually stored as such).\n        let sliceStartIndex: UInt32 = self._slice.lowerBound + index\n\n        guard sliceStartIndex <= ByteBuffer.Slice.maxSupportedLowerBound else {\n            // the slice's begin is past the maximum supported slice begin value (16 MiB) so the only option we have\n            // is copy the slice into a fresh buffer. The slice begin will then be at index 0.\n            return self._copyIntoByteBufferWithSliceIndex0_slowPath(index: index, length: length)\n        }\n        var new = self\n        assert(sliceStartIndex == self._slice.lowerBound &+ index)\n\n        // - The arithmetic below is safe because\n        //   1. `writerIndex` <= `self._slice.count` (see `_moveWriterIndex`)\n        //   2. `length` <= `self.writerIndex` (see `guard`s)\n        //   3. `sliceStartIndex` + `self._slice.count` is always safe (because that's `self._slice.upperBound`.\n        // - The range construction is safe because `length` >= 0 (see `guard` at the beginning of the function).\n        new._slice = _ByteBufferSlice(\n            Range(\n                uncheckedBounds: (\n                    lower: sliceStartIndex,\n                    upper: sliceStartIndex &+ length\n                )\n            )\n        )\n        new._moveReaderIndex(to: 0)\n        new._moveWriterIndex(to: length)\n        return new\n    }\n\n    /// Returns a slice of size `length` bytes, starting at the current `readerIndex`. The `ByteBuffer` this is invoked on\n    /// and the `ByteBuffer` returned will share the same underlying storage. However, the byte at `readerIndex` in this\n    /// `ByteBuffer` will correspond to index `0` in the returned `ByteBuffer`.\n    /// The `readerIndex` of the returned `ByteBuffer` will be `0`, the `writerIndex` will be `length`.\n    ///\n    /// This method is equivalent to calling `getSlice(at: readerIndex, length: length)`.\n    ///\n    /// - Parameter length: The length of the requested slice.\n    /// - Returns: A `ByteBuffer` containing the selected bytes as readable bytes or `nil` if the selected bytes were not\n    ///            readable in the initial `ByteBuffer`.\n    @inlinable\n    public func peekSlice(length: Int) -> ByteBuffer? {\n        self.getSlice(at: self.readerIndex, length: length)\n    }\n\n    /// Discard the bytes before the reader index. The byte at index `readerIndex` before calling this method will be\n    /// at index `0` after the call returns.\n    ///\n    /// - Returns: `true` if one or more bytes have been discarded, `false` if there are no bytes to discard.\n    @inlinable\n    @discardableResult public mutating func discardReadBytes() -> Bool {\n        guard self._readerIndex > 0 else {\n            return false\n        }\n\n        if self._readerIndex == self._writerIndex {\n            // If the whole buffer was consumed we can just reset the readerIndex and writerIndex to 0 and move on.\n            self._moveWriterIndex(to: 0)\n            self._moveReaderIndex(to: 0)\n            return true\n        }\n\n        if isKnownUniquelyReferenced(&self._storage) {\n            self._storage.bytes.advanced(by: Int(self._slice.lowerBound))\n                .copyMemory(\n                    from: self._storage.bytes.advanced(by: Int(self._slice.lowerBound + self._readerIndex)),\n                    byteCount: self.readableBytes\n                )\n            let indexShift = self._readerIndex\n            self._moveReaderIndex(to: 0)\n            self._moveWriterIndex(to: self._writerIndex - indexShift)\n        } else {\n            self._copyStorageAndRebase(extraCapacity: 0, resetIndices: true)\n        }\n        return true\n    }\n\n    /// The `ByteBuffer` will successfully be shrunk if the requested capacity is less than the current capacity,\n    /// and the requested capacity is greater than or equal to the number of readable bytes in the buffer.\n    /// If either condition is not true, the buffer will not be shrunk.\n    ///\n    /// - Parameter desiredCapacity: The desired capacity for the buffers capacity to be shrunken to\n    /// - Returns: Bool indicating whether the buffer capacity has been shrunk to the desiredCapacity.\n    @inlinable\n    @discardableResult public mutating func shrinkBufferCapacity(to desiredCapacity: Int) -> Bool {\n        let desiredCapacity = ByteBuffer.roundUpToUsableCapacity(_toCapacity(desiredCapacity))\n        guard desiredCapacity < self.capacity, desiredCapacity >= self.readableBytes else {\n            return false\n        }\n        self._copyStorageAndRebase(capacity: desiredCapacity, resetIndices: true)\n        return true\n    }\n\n    /// Returns size of capacity with optimal padding\n    /// - Parameter initialCapacity: Capacity that needs expansion with padding\n    /// - Returns: Capacity with calculated padding\n    @inlinable\n    static func roundUpToUsableCapacity(_ initialCapacity: UInt32) -> UInt32 {\n        initialCapacity == 0 ? 0 : initialCapacity.nextPowerOf2ClampedToMax()\n    }\n\n    /// The reader index or the number of bytes previously read from this `ByteBuffer`. `readerIndex` is `0` for a\n    /// newly allocated `ByteBuffer`.\n    @inlinable\n    public var readerIndex: Int {\n        Int(self._readerIndex)\n    }\n\n    /// The write index or the number of bytes previously written to this `ByteBuffer`. `writerIndex` is `0` for a\n    /// newly allocated `ByteBuffer`.\n    @inlinable\n    public var writerIndex: Int {\n        Int(self._writerIndex)\n    }\n\n    /// Set both reader index and writer index to `0`. This will reset the state of this `ByteBuffer` to the state\n    /// of a freshly allocated one, if possible without allocations. This is the cheapest way to recycle a `ByteBuffer`\n    /// for a new use-case.\n    ///\n    /// - Note: This method will allocate if the underlying storage is referenced by another `ByteBuffer`. Even if an\n    ///         allocation is necessary this will be cheaper as the copy of the storage is elided.\n    @inlinable\n    public mutating func clear() {\n        if !isKnownUniquelyReferenced(&self._storage) {\n            self._storage = self._storage.allocateStorage()\n        }\n        self._slice = self._storage.fullSlice\n        self._moveWriterIndex(to: 0)\n        self._moveReaderIndex(to: 0)\n    }\n\n    /// Set both reader index and writer index to `0`. This will reset the state of this `ByteBuffer` to the state\n    /// of a freshly allocated one, if possible without allocations. This is the cheapest way to recycle a `ByteBuffer`\n    /// for a new use-case.\n    ///\n    /// - Note: This method will allocate if the underlying storage is referenced by another `ByteBuffer`. Even if an\n    ///         allocation is necessary this will be cheaper as the copy of the storage is elided.\n    ///\n    /// - Parameters:\n    ///   - minimumCapacity: The minimum capacity that will be (re)allocated for this buffer\n    @available(*, deprecated, message: \"Use an `Int` as the argument\")\n    public mutating func clear(minimumCapacity: UInt32) {\n        self.clear(minimumCapacity: Int(minimumCapacity))\n    }\n\n    /// Set both reader index and writer index to `0`. This will reset the state of this `ByteBuffer` to the state\n    /// of a freshly allocated one, if possible without allocations. This is the cheapest way to recycle a `ByteBuffer`\n    /// for a new use-case.\n    ///\n    /// - Note: This method will allocate if the underlying storage is referenced by another `ByteBuffer`. Even if an\n    ///         allocation is necessary this will be cheaper as the copy of the storage is elided.\n    ///\n    /// - Parameters:\n    ///   - minimumCapacity: The minimum capacity that will be (re)allocated for this buffer\n    @inlinable\n    public mutating func clear(minimumCapacity: Int) {\n        precondition(minimumCapacity >= 0, \"Cannot have a minimum capacity < 0\")\n        precondition(minimumCapacity <= _Capacity.max, \"Minimum capacity must be <= \\(_Capacity.max)\")\n\n        let minimumCapacity = _Capacity(minimumCapacity)\n        if !isKnownUniquelyReferenced(&self._storage) {\n            self._storage = self._storage.allocateStorage(capacity: minimumCapacity)\n        } else if minimumCapacity > self._storage.capacity {\n            self._storage.reallocStorage(capacity: minimumCapacity)\n        }\n        self._slice = self._storage.fullSlice\n\n        self._moveWriterIndex(to: 0)\n        self._moveReaderIndex(to: 0)\n    }\n}\n\nextension ByteBuffer: CustomStringConvertible, CustomDebugStringConvertible {\n    /// A `String` describing this `ByteBuffer` including length and the bytes it contains (partially).\n    ///\n    /// For a `ByteBuffer` initialised with `hello world` the description would be the following:\n    ///\n    ///     [68656c6c6f20776f726c64](11 bytes)\n    ///\n    /// Buffers larger that 64 bytes will get truncated when printing out.\n    /// The format of the description is not API.\n    ///\n    /// - Returns: A description of this `ByteBuffer`.\n    public var description: String {\n        \"[\\(self.hexDump(format: .compact(maxBytes: 64)))](\\(self.readableBytes) bytes)\"\n    }\n\n    public var debugDescription: String {\n        String(describing: self)\n    }\n}\n\n// change types to the user visible `Int`\nextension ByteBuffer {\n    /// Copy the collection of `bytes` into the `ByteBuffer` at `index`. Does not move the writer index.\n    @discardableResult\n    @inlinable\n    public mutating func setBytes<Bytes: Sequence>(_ bytes: Bytes, at index: Int) -> Int where Bytes.Element == UInt8 {\n        Int(self._setBytes(bytes, at: _toIndex(index)))\n    }\n\n    /// Copy `bytes` into the `ByteBuffer` at `index`. Does not move the writer index.\n    @discardableResult\n    @inlinable\n    public mutating func setBytes(_ bytes: UnsafeRawBufferPointer, at index: Int) -> Int {\n        Int(self._setBytes(bytes, at: _toIndex(index)))\n    }\n\n    #if compiler(>=6.2)\n    /// Copy `bytes` from a `RawSpan` into the `ByteBuffer` at `index`. Does not move the writer index.\n    @discardableResult\n    @inlinable\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    public mutating func setBytes(_ bytes: RawSpan, at index: Int) -> Int {\n        Int(self._setBytes(bytes, at: _toIndex(index)))\n    }\n    #endif\n\n    /// Move the reader index forward by `offset` bytes.\n    ///\n    /// - warning: By contract the bytes between (including) `readerIndex` and (excluding) `writerIndex` must be\n    ///            initialised, ie. have been written before. Also the `readerIndex` must always be less than or equal\n    ///            to the `writerIndex`. Failing to meet either of these requirements leads to undefined behaviour.\n    /// - Parameters:\n    ///   - offset: The number of bytes to move the reader index forward by.\n    @inlinable\n    public mutating func moveReaderIndex(forwardBy offset: Int) {\n        let newIndex = self._readerIndex + _toIndex(offset)\n        precondition(\n            newIndex >= 0 && newIndex <= writerIndex,\n            \"new readerIndex: \\(newIndex), expected: range(0, \\(writerIndex))\"\n        )\n        self._moveReaderIndex(to: newIndex)\n    }\n\n    /// Set the reader index to `offset`.\n    ///\n    /// - warning: By contract the bytes between (including) `readerIndex` and (excluding) `writerIndex` must be\n    ///            initialised, ie. have been written before. Also the `readerIndex` must always be less than or equal\n    ///            to the `writerIndex`. Failing to meet either of these requirements leads to undefined behaviour.\n    /// - Parameters:\n    ///   - offset: The offset in bytes to set the reader index to.\n    @inlinable\n    public mutating func moveReaderIndex(to offset: Int) {\n        let newIndex = _toIndex(offset)\n        precondition(\n            newIndex >= 0 && newIndex <= writerIndex,\n            \"new readerIndex: \\(newIndex), expected: range(0, \\(writerIndex))\"\n        )\n        self._moveReaderIndex(to: newIndex)\n    }\n\n    /// Move the writer index forward by `offset` bytes.\n    ///\n    /// - warning: By contract the bytes between (including) `readerIndex` and (excluding) `writerIndex` must be\n    ///            initialised, ie. have been written before. Also the `readerIndex` must always be less than or equal\n    ///            to the `writerIndex`. Failing to meet either of these requirements leads to undefined behaviour.\n    /// - Parameters:\n    ///   - offset: The number of bytes to move the writer index forward by.\n    @inlinable\n    public mutating func moveWriterIndex(forwardBy offset: Int) {\n        let newIndex = self._writerIndex + _toIndex(offset)\n        precondition(\n            newIndex >= 0 && newIndex <= _toCapacity(self._slice.count),\n            \"new writerIndex: \\(newIndex), expected: range(0, \\(_toCapacity(self._slice.count)))\"\n        )\n        self._moveWriterIndex(to: newIndex)\n    }\n\n    /// Set the writer index to `offset`.\n    ///\n    /// - warning: By contract the bytes between (including) `readerIndex` and (excluding) `writerIndex` must be\n    ///            initialised, ie. have been written before. Also the `readerIndex` must always be less than or equal\n    ///            to the `writerIndex`. Failing to meet either of these requirements leads to undefined behaviour.\n    /// - Parameters:\n    ///   - offset: The offset in bytes to set the reader index to.\n    @inlinable\n    public mutating func moveWriterIndex(to offset: Int) {\n        let newIndex = _toIndex(offset)\n        precondition(\n            newIndex >= 0 && newIndex <= _toCapacity(self._slice.count),\n            \"new writerIndex: \\(newIndex), expected: range(0, \\(_toCapacity(self._slice.count)))\"\n        )\n        self._moveWriterIndex(to: newIndex)\n    }\n}\n\nextension ByteBuffer {\n    /// Copies `length` `bytes` starting at the `fromIndex` to `toIndex`. Does not move the writer index.\n    ///\n    /// - Note: Overlapping ranges, for example `copyBytes(at: 1, to: 2, length: 5)` are allowed.\n    /// - Precondition: The range represented by `fromIndex` and `length` must be readable bytes,\n    ///     that is: `fromIndex >= readerIndex` and `fromIndex + length <= writerIndex`.\n    /// - Parameter fromIndex: The index of the first byte to copy.\n    /// - Parameter toIndex: The index into to which the first byte will be copied.\n    /// - Parameter length: The number of bytes which should be copied.\n    @discardableResult\n    @inlinable\n    public mutating func copyBytes(at fromIndex: Int, to toIndex: Int, length: Int) throws -> Int {\n        switch length {\n        case ..<0:\n            throw CopyBytesError.negativeLength\n        case 0:\n            return 0\n        default:\n            ()\n        }\n        guard self.readerIndex <= fromIndex && fromIndex + length <= self.writerIndex else {\n            throw CopyBytesError.unreadableSourceBytes\n        }\n\n        if !isKnownUniquelyReferenced(&self._storage) {\n            let newEndIndex = max(self._writerIndex, _toIndex(toIndex + length))\n            self._copyStorageAndRebase(capacity: newEndIndex)\n        }\n\n        self._ensureAvailableCapacity(_Capacity(length), at: _toIndex(toIndex))\n        self.withVeryUnsafeMutableBytes { ptr in\n            let srcPtr = UnsafeRawBufferPointer(start: ptr.baseAddress!.advanced(by: fromIndex), count: length)\n            let targetPtr = UnsafeMutableRawBufferPointer(rebasing: ptr.dropFirst(toIndex))\n            targetPtr.copyMemory(from: srcPtr)\n        }\n\n        return length\n    }\n\n    /// Errors thrown when calling `copyBytes`.\n    public struct CopyBytesError: Error {\n        private enum BaseError: Hashable {\n            case negativeLength\n            case unreadableSourceBytes\n        }\n\n        private var baseError: BaseError\n\n        /// The length of the bytes to copy was negative.\n        public static let negativeLength: CopyBytesError = .init(baseError: .negativeLength)\n\n        /// The bytes to copy are not readable.\n        public static let unreadableSourceBytes: CopyBytesError = .init(baseError: .unreadableSourceBytes)\n    }\n}\n\nextension ByteBuffer.CopyBytesError: Hashable {}\n\nextension ByteBuffer.CopyBytesError: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        String(describing: self.baseError)\n    }\n}\n\nextension ByteBuffer: Equatable {\n    // TODO: I don't think this makes sense. This should compare bytes 0..<writerIndex instead.\n\n    /// Compare two `ByteBuffer` values. Two `ByteBuffer` values are considered equal if the readable bytes are equal.\n    @inlinable\n    public static func == (lhs: ByteBuffer, rhs: ByteBuffer) -> Bool {\n        guard lhs.readableBytes == rhs.readableBytes else {\n            return false\n        }\n\n        if lhs._slice == rhs._slice && lhs._storage === rhs._storage {\n            return true\n        }\n\n        return lhs.withUnsafeReadableBytes { lPtr in\n            rhs.withUnsafeReadableBytes { rPtr in\n                // Shouldn't get here otherwise because of readableBytes check\n                assert(lPtr.count == rPtr.count)\n                return memcmp(lPtr.baseAddress!, rPtr.baseAddress!, lPtr.count) == 0\n            }\n        }\n    }\n}\n\nextension ByteBuffer: Hashable {\n    /// The hash value for the readable bytes.\n    @inlinable\n    public func hash(into hasher: inout Hasher) {\n        self.withUnsafeReadableBytes { ptr in\n            hasher.combine(bytes: ptr)\n        }\n    }\n}\n\nextension ByteBuffer: @unchecked Sendable {}\n\nextension ByteBuffer {\n    /// Modify this `ByteBuffer` if this `ByteBuffer` is known to uniquely own its storage.\n    ///\n    /// In some cases it is possible that code is holding a `ByteBuffer` that has been shared with other\n    /// parts of the code, and may want to mutate that `ByteBuffer`. In some cases it may be worth modifying\n    /// a `ByteBuffer` only if that `ByteBuffer` is guaranteed to not perform a copy-on-write operation to do\n    /// so, for example when a different buffer could be used or more cheaply allocated instead.\n    ///\n    /// This function will execute the provided block only if it is guaranteed to be able to avoid a copy-on-write\n    /// operation. If it cannot execute the block the returned value will be `nil`.\n    ///\n    /// - Parameters:\n    ///   - body: The modification operation to execute, with this `ByteBuffer` passed `inout` as an argument.\n    /// - Returns: The return value of `body`.\n    @inlinable\n    public mutating func modifyIfUniquelyOwned<T, ErrorType: Error>(\n        _ body: (inout ByteBuffer) throws(ErrorType) -> T\n    ) throws(ErrorType) -> T? {\n        if isKnownUniquelyReferenced(&self._storage) {\n            return try body(&self)\n        } else {\n            return nil\n        }\n    }\n}\n\nextension ByteBuffer {\n    @inlinable\n    func rangeWithinReadableBytes(index: Int, length: Int) -> Range<Int>? {\n        guard index >= self.readerIndex && length >= 0 else {\n            return nil\n        }\n\n        // both these &-s are safe, they can't underflow because both left & right side are >= 0 (and index >= readerIndex)\n        let indexFromReaderIndex = index &- self.readerIndex\n        assert(indexFromReaderIndex >= 0)\n        guard indexFromReaderIndex <= self.readableBytes &- length else {\n            return nil\n        }\n\n        let upperBound = indexFromReaderIndex &+ length  // safe, can't overflow, we checked it above.\n\n        // uncheckedBounds is safe because `length` is >= 0, so the lower bound will always be lower/equal to upper\n        return Range<Int>(uncheckedBounds: (lower: indexFromReaderIndex, upper: upperBound))\n    }\n}\n\n@available(*, unavailable)\nextension ByteBuffer._Storage: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-hex.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension ByteBuffer {\n\n    /// Create a fresh `ByteBuffer` containing the `bytes` decoded from the string representation of `plainHexEncodedBytes`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit the hex decoded `bytes` and potentially some extra space\n    /// using the default allocator.\n    ///\n    /// - info: If you have access to a `Channel`, `ChannelHandlerContext`, or `ByteBufferAllocator` we\n    ///         recommend using `channel.allocator.buffer(integer:)`. Or if you want to write multiple items into the\n    ///         buffer use `channel.allocator.buffer(capacity: ...)` to allocate a `ByteBuffer` of the right\n    ///         size followed by a `writeHexEncodedBytes` instead of using this method. This allows SwiftNIO to do\n    ///         accounting and optimisations of resources acquired for operations on a given `Channel` in the future.\n    public init(plainHexEncodedBytes string: String) throws {\n        self = try ByteBufferAllocator().buffer(plainHexEncodedBytes: string)\n    }\n\n    /// Describes a ByteBuffer hexDump format.\n    /// Can be either xxd output compatible, or hexdump compatible.\n    public struct HexDumpFormat: Hashable, Sendable {\n\n        @usableFromInline\n        enum Value: Hashable, Sendable {\n            case plain(maxBytes: Int? = nil)\n            case detailed(maxBytes: Int? = nil)\n            case compact(maxBytes: Int? = nil)\n        }\n\n        @usableFromInline\n        let value: Value\n\n        @inlinable\n        init(_ value: Value) { self.value = value }\n\n        /// A plain hex dump format compatible with `xxd` CLI utility.\n        @inlinable\n        public static var plain: HexDumpFormat { Self(.plain(maxBytes: nil)) }\n\n        /// A hex dump format compatible with `hexdump` command line utility.\n        @inlinable\n        public static var detailed: HexDumpFormat { Self(.detailed(maxBytes: nil)) }\n\n        /// A hex dump analog to `plain` format  but without whitespaces.\n        public static var compact: HexDumpFormat { Self(.compact(maxBytes: nil)) }\n\n        /// A detailed hex dump format compatible with `xxd`, clipped to `maxBytes` bytes dumped.\n        /// This format will dump first `maxBytes / 2` bytes, and the last `maxBytes / 2` bytes, replacing the rest with \" ... \".\n        public static func plain(maxBytes: Int) -> Self {\n            Self(.plain(maxBytes: maxBytes))\n        }\n\n        /// A hex dump format compatible with `hexdump` command line tool.\n        /// This format will dump first `maxBytes / 2` bytes, and the last `maxBytes / 2` bytes, with a placeholder in between.\n        public static func detailed(maxBytes: Int) -> Self {\n            Self(.detailed(maxBytes: maxBytes))\n        }\n\n        /// A hex dump analog to `plain`format  but without whitespaces.\n        /// This format will dump first `maxBytes / 2` bytes, and the last `maxBytes / 2` bytes, with a placeholder in between.\n        public static func compact(maxBytes: Int) -> Self {\n            Self(.compact(maxBytes: maxBytes))\n        }\n    }\n\n    /// Shared logic for `hexDumpPlain` and `hexDumpCompact`.\n    /// Returns a `String` of hexadecimals digits of the readable bytes in the buffer.\n    /// - Parameter\n    ///   - separateWithWhitespace: Controls whether the hex deump will be separated by whitespaces.\n    private func _hexDump(separateWithWhitespace: Bool) -> String {\n        var hexString = \"\"\n        var capacity: Int\n\n        if separateWithWhitespace {\n            capacity = self.readableBytes * 3\n        } else {\n            capacity = self.readableBytes * 2\n        }\n\n        hexString.reserveCapacity(capacity)\n\n        for byte in self.readableBytesView {\n            hexString += String(byte, radix: 16, padding: 2)\n            if separateWithWhitespace {\n                hexString += \" \"\n            }\n        }\n\n        if separateWithWhitespace {\n            return String(hexString.dropLast())\n        }\n\n        return hexString\n    }\n\n    /// Shared logic for `hexDumpPlain(maxBytes: Int)` and `hexDumpCompact(maxBytes: Int)`.\n    ///\n    /// - Parameters:\n    ///   - maxBytes: The maximum amount of bytes presented in the dump.\n    ///   - separateWithWhitespace: Controls whether the dump will be separated by whitespaces.\n    private func _hexDump(maxBytes: Int, separateWithWhitespace: Bool) -> String {\n        // If the buffer length fits in the max bytes limit in the hex dump, just dump the whole thing.\n        if self.readableBytes <= maxBytes {\n            return self._hexDump(separateWithWhitespace: separateWithWhitespace)\n        }\n\n        var buffer = self\n\n        // Safe to force-unwrap because we just checked readableBytes is > maxBytes above.\n        let front = buffer.readSlice(length: maxBytes / 2)!\n        buffer.moveReaderIndex(to: buffer.writerIndex - maxBytes / 2)\n        let back = buffer.readSlice(length: buffer.readableBytes)!\n\n        let startHex = front._hexDump(separateWithWhitespace: separateWithWhitespace)\n        let endHex = back._hexDump(separateWithWhitespace: separateWithWhitespace)\n\n        var dots: String\n        if separateWithWhitespace {\n            dots = \" ... \"\n        } else {\n            dots = \"...\"\n        }\n\n        return startHex + dots + endHex\n    }\n\n    /// Return a `String` of space separated hexadecimal digits of the readable bytes in the buffer,\n    /// in a format that's compatible with `xxd -r -p`.\n    /// `hexDumpPlain()` always dumps all readable bytes, i.e. from `readerIndex` to `writerIndex`,\n    /// so you should set those indices to desired location to get the offset and length that you need to dump.\n    private func hexDumpPlain() -> String {\n        self._hexDump(separateWithWhitespace: true)\n    }\n\n    /// Return a `String` of space delimited hexadecimal digits of the readable bytes in the buffer,\n    /// in a format that's compatible with `xxd -r -p`, but clips the output to the max length of `maxBytes` bytes.\n    /// If the dump contains more than the `maxBytes` bytes, this function will return the first `maxBytes/2`\n    /// and the last `maxBytes/2` of that, replacing the rest with `...`, i.e. `01 02 03 ... 09 11 12`.\n    ///\n    /// - Parameters:\n    ///   - maxBytes: The maximum amount of bytes presented in the dump.\n    private func hexDumpPlain(maxBytes: Int) -> String {\n        self._hexDump(maxBytes: maxBytes, separateWithWhitespace: true)\n    }\n\n    /// Return a `String` of  hexadecimal digits of the readable bytes in the buffer,\n    /// analog to `.plain` format but without whitespaces. This format guarantees not to emit whitespaces.\n    /// `hexDumpCompact()` always dumps all readable bytes, i.e. from `readerIndex` to `writerIndex`,\n    /// so you should set those indices to desired location to get the offset and length that you need to dump.\n    private func hexDumpCompact() -> String {\n        self._hexDump(separateWithWhitespace: false)\n    }\n\n    /// Return a `String` of  hexadecimal digits of the readable bytes in the buffer,\n    /// analog to `.plain` format but without whitespaces and clips the output to the max length of `maxBytes` bytes.\n    /// This format guarantees not to emmit whitespaces.\n    /// If the dump contains more than the `maxBytes` bytes, this function will return the first `maxBytes/2`\n    /// and the last `maxBytes/2` of that, replacing the rest with `...`, i.e. `010203...091112`.\n    ///\n    /// - Parameters:\n    ///   - maxBytes: The maximum amount of bytes presented in the dump.\n    private func hexDumpCompact(maxBytes: Int) -> String {\n        self._hexDump(maxBytes: maxBytes, separateWithWhitespace: false)\n    }\n\n    /// Returns a `String` containing a detailed hex dump of this buffer.\n    /// Intended to be used internally in ``hexDump(format:)``\n    /// - Parameters:\n    ///   - lineOffset: an offset from the beginning of the outer buffer that is being dumped. It's used to print the line offset in hexdump -C format.\n    ///   - paddingBefore: the amount of space to pad before the first byte dumped on this line, used in center and right columns.\n    ///   - paddingAfter: the amount of sapce to pad after the last byte on this line, used in center and right columns.\n    private func _hexDumpLine(lineOffset: Int, paddingBefore: Int = 0, paddingAfter: Int = 0) -> String {\n        // Each line takes 78 visible characters + \\n\n        var result = \"\"\n        result.reserveCapacity(79)\n\n        // Left column of the hex dump signifies the offset from the beginning of the dumped buffer\n        // and is separated from the next column with two spaces.\n        result += String(lineOffset, radix: 16, padding: 8)\n        result += \"  \"\n\n        // Center column consists of:\n        // - xxd-compatible dump of the first 8 bytes\n        // - space\n        // - xxd-compatible dump of the rest 8 bytes\n        // If there are not enough bytes to dump, the column is padded with space.\n\n        // If there's any padding on the left, apply that first.\n        result += String(repeating: \" \", count: paddingBefore * 3)\n\n        // Add the left side of the central column\n        let bytesInLeftColumn = max(8 - paddingBefore, 0)\n        for byte in self.readableBytesView.prefix(bytesInLeftColumn) {\n            result += String(byte, radix: 16, padding: 2)\n            result += \" \"\n        }\n\n        // Add an extra space for the centre column.\n        result += \" \"\n\n        // Add the right side of the central column.\n        for byte in self.readableBytesView.dropFirst(bytesInLeftColumn) {\n            result += String(byte, radix: 16, padding: 2)\n            result += \" \"\n        }\n\n        // Pad the resulting center column line to 60 characters.\n        result += String(repeating: \" \", count: 60 - result.count)\n\n        // Right column renders the 16 bytes line as ASCII characters, or \".\" if the character is not printable.\n        let printableRange = UInt8(ascii: \" \")..<UInt8(ascii: \"~\")\n        let printableBytes = self.readableBytesView.map {\n            printableRange.contains($0) ? $0 : UInt8(ascii: \".\")\n        }\n\n        result += \"|\"\n        result += String(repeating: \" \", count: paddingBefore)\n        result += String(decoding: printableBytes, as: UTF8.self)\n        result += String(repeating: \" \", count: paddingAfter)\n        result += \"|\\n\"\n        return result\n    }\n\n    /// Returns a `String` of hexadecimal digits of bytes in the Buffer,\n    /// with formatting compatible with output of `hexdump -C`.\n    private func hexdumpDetailed() -> String {\n        if self.readableBytes == 0 {\n            return \"\"\n        }\n\n        var result = \"\"\n        result.reserveCapacity(self.readableBytes / 16 * 79 + 8)\n\n        var buffer = self\n\n        var lineOffset = 0\n        while buffer.readableBytes > 0 {\n            // Safe to force-unwrap because we're in a loop that guarantees there's at least one byte to read.\n            let slice = buffer.readSlice(length: min(16, buffer.readableBytes))!\n            result += slice._hexDumpLine(lineOffset: lineOffset)\n            lineOffset += slice.readableBytes\n        }\n\n        result += String(self.readableBytes, radix: 16, padding: 8)\n        return result\n    }\n\n    /// Returns a `String` of hexadecimal digits of bytes in this ByteBuffer\n    /// with formatting sort of compatible with `hexdump -C`, but clipped on length.\n    /// Dumps limit/2 first and limit/2 last bytes, with a separator line in between.\n    ///\n    /// - Parameters:\n    ///   - maxBytes: Max bytes to dump.\n    private func hexDumpDetailed(maxBytes: Int) -> String {\n        if self.readableBytes <= maxBytes {\n            return self.hexdumpDetailed()\n        }\n\n        let separator = \"........  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  ..................\\n\"\n\n        // reserve capacity for the maxBytes dumped, plus the separator line, and buffer length line.\n        var result = \"\"\n        result.reserveCapacity(maxBytes / 16 * 79 + 79 + 8)\n\n        var buffer = self\n\n        // Dump the front part of the buffer first, up to maxBytes/2 bytes.\n        // Safe to force-unwrap because we know the buffer has more readable bytes than maxBytes.\n        var front = buffer.readSlice(length: maxBytes / 2)!\n        var bufferOffset = 0\n        while front.readableBytes > 0 {\n            // Safe to force-unwrap because buffer is guaranteed to have at least one byte in it.\n            let slice = front.readSlice(length: min(16, front.readableBytes))!\n\n            // This will only be non-zero on the last line of this loop\n            let paddingAfter = 16 - slice.readableBytes\n            result += slice._hexDumpLine(lineOffset: bufferOffset, paddingAfter: paddingAfter)\n            bufferOffset += slice.readableBytes\n        }\n\n        result += separator\n\n        // Dump the back maxBytes/2 bytes.\n        bufferOffset = buffer.writerIndex - maxBytes / 2\n        buffer.moveReaderIndex(to: bufferOffset)\n        var back = buffer.readSlice(length: buffer.readableBytes)!\n\n        // On the first line of the back part, we might want less than 16 bytes, with padding on the left.\n        // But if this is also the last line, than take whatever is left.\n        let lineLength = min(16 - bufferOffset % 16, back.readableBytes)\n\n        // Line offset is the offset of the first byte of this line in a full buffer hex dump.\n        // It may not match `bufferOffset` in the first line of the `back` part.\n        let lineOffset = bufferOffset - bufferOffset % 16\n\n        // Safe to force-unwrap because `back` is guaranteed to have at least one byte.\n        let slice = back.readSlice(length: lineLength)!\n\n        // paddingBefore is going to be applied both in the center column and the right column of the line.\n        result += slice._hexDumpLine(lineOffset: lineOffset, paddingBefore: 16 - lineLength)\n        bufferOffset += lineLength\n\n        // Now dump the rest of the back part of the buffer.\n        while back.readableBytes > 0 {\n            let slice = back.readSlice(length: min(16, back.readableBytes))!\n            result += slice._hexDumpLine(lineOffset: bufferOffset)\n            bufferOffset += slice.readableBytes\n        }\n\n        // Last line of the dump, just the index of the last byte in the buffer.\n        result += String(self.readableBytes, radix: 16, padding: 8)\n        return result\n    }\n\n    /// Returns a hex dump of  this `ByteBuffer` in a preferred `HexDumpFormat`.\n    ///\n    /// `hexDump` provides several formats:\n    ///   - `.plain` — plain hex dump format with hex bytes separated by spaces, i.e. `48 65 6c 6c 6f` for `Hello`. This format is compatible with `xxd -r`.\n    ///   - `.plain(maxBytes: Int)` — like `.plain`, but clipped to maximum bytes dumped.\n    ///   - `.compact` — plain hexd dump without whitespaces.\n    ///   - `.compact(maxBytes: Int)` — like `.compact`, but  clipped to maximum bytes dumped.\n    ///   - `.detailed` — detailed hex dump format with both hex, and ASCII representation of the bytes. This format is compatible with what `hexdump -C` outputs.\n    ///   - `.detailed(maxBytes: Int)` — like `.detailed`, but  clipped to maximum bytes dumped.\n    ///\n    /// - Parameters:\n    ///   - format: ``HexDumpFormat`` to use for the dump.\n    public func hexDump(format: HexDumpFormat) -> String {\n        switch format.value {\n        case .plain(let maxBytes):\n            if let maxBytes = maxBytes {\n                return self.hexDumpPlain(maxBytes: maxBytes)\n            } else {\n                return self.hexDumpPlain()\n            }\n\n        case .compact(let maxBytes):\n            if let maxBytes = maxBytes {\n                return self.hexDumpCompact(maxBytes: maxBytes)\n            } else {\n                return self.hexDumpCompact()\n            }\n\n        case .detailed(let maxBytes):\n            if let maxBytes = maxBytes {\n                return self.hexDumpDetailed(maxBytes: maxBytes)\n            } else {\n                return self.hexdumpDetailed()\n            }\n        }\n    }\n\n    /// An error that is thrown when an invalid hex encoded string was attempted to be written to a ByteBuffer.\n    public struct HexDecodingError: Error, Equatable {\n        private let kind: HexDecodingErrorKind\n\n        private enum HexDecodingErrorKind {\n            /// The hex encoded string was not of the expected even length.\n            case invalidHexLength\n            /// An invalid hex character was found in the hex encoded string.\n            case invalidCharacter\n        }\n\n        public static let invalidHexLength = HexDecodingError(kind: .invalidHexLength)\n        public static let invalidCharacter = HexDecodingError(kind: .invalidCharacter)\n    }\n}\n\nextension UInt8 {\n    fileprivate var isASCIIWhitespace: Bool {\n        [UInt8(ascii: \"\\n\"), UInt8(ascii: \"\\t\"), UInt8(ascii: \"\\r\"), UInt8(ascii: \" \")].contains(\n            self\n        )\n    }\n\n    fileprivate var asciiHexNibble: UInt8 {\n        get throws {\n            switch self {\n            case UInt8(ascii: \"0\")...UInt8(ascii: \"9\"):\n                return self - UInt8(ascii: \"0\")\n            case UInt8(ascii: \"a\")...UInt8(ascii: \"f\"):\n                return self - UInt8(ascii: \"a\") + 10\n            case UInt8(ascii: \"A\")...UInt8(ascii: \"F\"):\n                return self - UInt8(ascii: \"A\") + 10\n            default:\n                throw ByteBuffer.HexDecodingError.invalidCharacter\n            }\n        }\n    }\n}\n\nextension Substring.UTF8View {\n    @usableFromInline\n    mutating func popNextHexByte() throws -> UInt8? {\n        while let nextByte = self.first, nextByte.isASCIIWhitespace {\n            self = self.dropFirst()\n        }\n\n        guard let firstHex = try self.popFirst()?.asciiHexNibble else {\n            return nil  // No next byte to pop\n        }\n\n        guard let secondHex = try self.popFirst()?.asciiHexNibble else {\n            throw ByteBuffer.HexDecodingError.invalidHexLength\n        }\n\n        return (firstHex << 4) | secondHex\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-int.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension ByteBuffer {\n    @inlinable\n    func _toEndianness<T: FixedWidthInteger>(value: T, endianness: Endianness) -> T {\n        switch endianness {\n        case .little:\n            return value.littleEndian\n        case .big:\n            return value.bigEndian\n        }\n    }\n\n    /// Read an integer off this `ByteBuffer`, move the reader index forward by the integer's byte size and return the result.\n    ///\n    /// - Parameters:\n    ///   - endianness: The endianness of the integer in this `ByteBuffer` (defaults to big endian).\n    ///   - as: the desired `FixedWidthInteger` type (optional parameter)\n    /// - Returns: An integer value deserialized from this `ByteBuffer` or `nil` if there aren't enough bytes readable.\n    @inlinable\n    public mutating func readInteger<T: FixedWidthInteger>(endianness: Endianness = .big, as: T.Type = T.self) -> T? {\n        guard let result = self.getInteger(at: self.readerIndex, endianness: endianness, as: T.self) else {\n            return nil\n        }\n        self._moveReaderIndex(forwardBy: MemoryLayout<T>.size)\n        return result\n    }\n\n    /// Get the integer at `index` from this `ByteBuffer`. Does not move the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes for the integer into the `ByteBuffer`.\n    ///   - endianness: The endianness of the integer in this `ByteBuffer` (defaults to big endian).\n    ///   - as: the desired `FixedWidthInteger` type (optional parameter)\n    /// - Returns: An integer value deserialized from this `ByteBuffer` or `nil` if the bytes of interest are not\n    ///            readable.\n    @inlinable\n    public func getInteger<T: FixedWidthInteger>(\n        at index: Int,\n        endianness: Endianness = Endianness.big,\n        as: T.Type = T.self\n    ) -> T? {\n        guard let range = self.rangeWithinReadableBytes(index: index, length: MemoryLayout<T>.size) else {\n            return nil\n        }\n\n        if T.self == UInt8.self {\n            assert(range.count == 1)\n            return self.withUnsafeReadableBytes { ptr in\n                ptr[range.startIndex] as! T\n            }\n        }\n\n        return self.withUnsafeReadableBytes { ptr in\n            var value: T = 0\n            withUnsafeMutableBytes(of: &value) { valuePtr in\n                valuePtr.copyMemory(from: UnsafeRawBufferPointer(rebasing: ptr[range]))\n            }\n            return _toEndianness(value: value, endianness: endianness)\n        }\n    }\n\n    /// Write `integer` into this `ByteBuffer`, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - integer: The integer to serialize.\n    ///   - endianness: The endianness to use, defaults to big endian.\n    ///   - as: the desired `FixedWidthInteger` type (optional parameter)\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func writeInteger<T: FixedWidthInteger>(\n        _ integer: T,\n        endianness: Endianness = .big,\n        as: T.Type = T.self\n    ) -> Int {\n        let bytesWritten = self.setInteger(integer, at: self.writerIndex, endianness: endianness)\n        self._moveWriterIndex(forwardBy: bytesWritten)\n        return Int(bytesWritten)\n    }\n\n    /// Write `integer` into this `ByteBuffer` starting at `index`. This does not alter the writer index.\n    ///\n    /// - Parameters:\n    ///   - integer: The integer to serialize.\n    ///   - index: The index of the first byte to write.\n    ///   - endianness: The endianness to use, defaults to big endian.\n    ///   - as: the desired `FixedWidthInteger` type (optional parameter)\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    @inlinable\n    public mutating func setInteger<T: FixedWidthInteger>(\n        _ integer: T,\n        at index: Int,\n        endianness: Endianness = .big,\n        as: T.Type = T.self\n    ) -> Int {\n        var value = _toEndianness(value: integer, endianness: endianness)\n        return Swift.withUnsafeBytes(of: &value) { ptr in\n            self.setBytes(ptr, at: index)\n        }\n    }\n\n    /// Returns the integer at the current reader index without advancing it.\n    ///\n    /// This method is equivalent to calling `getInteger(at: readerIndex, ...)`\n    ///\n    /// - Parameters:\n    ///   - endianness: The endianness of the integer (defaults to big endian).\n    ///   - as: The desired `FixedWidthInteger` type (optional parameter).\n    /// - Returns: An integer value deserialized from this `ByteBuffer` or `nil` if the bytes are not readable.\n    @inlinable\n    public func peekInteger<T: FixedWidthInteger>(\n        endianness: Endianness = .big,\n        as: T.Type = T.self\n    ) -> T? {\n        self.getInteger(at: self.readerIndex, endianness: endianness, as: `as`)\n    }\n}\n\nextension FixedWidthInteger {\n\n    /// Returns the next power of two.\n    @inlinable\n    func nextPowerOf2() -> Self {\n        guard self != 0 else {\n            return 1\n        }\n        return 1 << (Self.bitWidth - (self - 1).leadingZeroBitCount)\n    }\n\n    /// Returns the previous power of 2, or self if it already is.\n    @inlinable\n    func previousPowerOf2() -> Self {\n        guard self != 0 else {\n            return 0\n        }\n\n        return 1 << ((Self.bitWidth - 1) - self.leadingZeroBitCount)\n    }\n\n    /// Initialize an integer from a byte buffer of exactly the right size.\n    /// The bytes will be read using the host system's endianness.\n    ///\n    /// - Parameters:\n    ///   - buffer: The ByteBuffer to read from\n    ///   - endianness: The endianness to use when reading the integer, defaults to the host system's endianness.\n    @inlinable\n    public init?(buffer: ByteBuffer, endianness: Endianness = .host) {\n        var buffer = buffer\n        guard let value = buffer.readInteger(endianness: endianness, as: Self.self), buffer.readableBytes == 0 else {\n            return nil\n        }\n        self = value\n    }\n}\n\nextension UInt32 {\n    /// Returns the next power of two unless that would overflow, in which case UInt32.max (on 64-bit systems) or\n    /// Int32.max (on 32-bit systems) is returned. The returned value is always safe to be cast to Int and passed\n    /// to malloc on all platforms.\n    @inlinable\n    func nextPowerOf2ClampedToMax() -> UInt32 {\n        guard self > 0 else {\n            return 1\n        }\n\n        var n = self\n\n        #if arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n        // on 32-bit platforms we can't make use of a whole UInt32.max (as it doesn't fit in an Int)\n        let max = UInt32(Int.max)\n        #else\n        // on 64-bit platforms we're good\n        let max = UInt32.max\n        #endif\n\n        n -= 1\n        n |= n >> 1\n        n |= n >> 2\n        n |= n >> 4\n        n |= n >> 8\n        n |= n >> 16\n        if n != max {\n            n += 1\n        }\n\n        return n\n    }\n}\n\n/// Endianness refers to the sequential order in which bytes are arranged into larger numerical values when stored in\n/// memory or when transmitted over digital links.\npublic enum Endianness: Sendable {\n    /// The endianness of the machine running this program.\n    public static let host: Endianness = hostEndianness0()\n\n    private static func hostEndianness0() -> Endianness {\n        let number: UInt32 = 0x1234_5678\n        return number == number.bigEndian ? .big : .little\n    }\n\n    /// big endian, the most significant byte (MSB) is at the lowest address\n    case big\n\n    /// little endian, the least significant byte (LSB) is at the lowest address\n    case little\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-lengthPrefix.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension ByteBuffer {\n    public struct LengthPrefixError: Swift.Error {\n        private enum BaseError {\n            case messageLengthDoesNotFitExactlyIntoRequiredIntegerFormat\n            case messageCouldNotBeReadSuccessfully\n        }\n        private var baseError: BaseError\n\n        public static let messageLengthDoesNotFitExactlyIntoRequiredIntegerFormat: LengthPrefixError = .init(\n            baseError: .messageLengthDoesNotFitExactlyIntoRequiredIntegerFormat\n        )\n        public static let messageCouldNotBeReadSuccessfully: LengthPrefixError = .init(\n            baseError: .messageCouldNotBeReadSuccessfully\n        )\n    }\n}\n\nextension ByteBuffer {\n    /// Prefixes a message written by `writeMessage` with the number of bytes written as an `Integer`.\n    /// - Parameters:\n    ///   - endianness: The endianness of the length prefix `Integer` in this `ByteBuffer` (defaults to big endian).\n    ///   - integer: the desired `Integer` type used to write the length prefix\n    ///   - writeMessage: A closure that takes a buffer, writes a message to it and returns the number of bytes written\n    /// - Throws: If the number of bytes written during `writeMessage` can not be exactly represented as the given `Integer` i.e. if the number of bytes written is greater than `Integer.max`\n    /// - Returns: Number of total bytes written\n    @discardableResult\n    @inlinable\n    public mutating func writeLengthPrefixed<Integer>(\n        endianness: Endianness = .big,\n        as integer: Integer.Type,\n        writeMessage: (inout ByteBuffer) throws -> Int\n    ) throws -> Int where Integer: FixedWidthInteger {\n        var totalBytesWritten = 0\n\n        let lengthPrefixIndex = self.writerIndex\n        // Write a zero as a placeholder which will later be overwritten by the actual number of bytes written\n        totalBytesWritten += self.writeInteger(.zero, endianness: endianness, as: Integer.self)\n\n        let startWriterIndex = self.writerIndex\n        let messageLength = try writeMessage(&self)\n        let endWriterIndex = self.writerIndex\n\n        totalBytesWritten += messageLength\n\n        let actualBytesWritten = endWriterIndex - startWriterIndex\n        assert(\n            actualBytesWritten == messageLength,\n            \"writeMessage returned \\(messageLength) bytes, but actually \\(actualBytesWritten) bytes were written, but they should be the same\"\n        )\n\n        guard let lengthPrefix = Integer(exactly: messageLength) else {\n            throw LengthPrefixError.messageLengthDoesNotFitExactlyIntoRequiredIntegerFormat\n        }\n\n        self.setInteger(lengthPrefix, at: lengthPrefixIndex, endianness: endianness, as: Integer.self)\n\n        return totalBytesWritten\n    }\n}\n\nextension ByteBuffer {\n    /// Reads an `Integer` from `self`, reads a slice of that length and passes it to `readMessage`.\n    /// It is checked that `readMessage` returns a non-nil value.\n    ///\n    /// The `readerIndex` is **not** moved forward if the length prefix could not be read or `self` does not contain enough bytes. Otherwise `readerIndex` is moved forward even if `readMessage` throws or returns nil.\n    /// - Parameters:\n    ///   - endianness: The endianness of the length prefix `Integer` in this `ByteBuffer` (defaults to big endian).\n    ///   - integer: the desired `Integer` type used to read the length prefix\n    ///   - readMessage: A closure that takes a `ByteBuffer` slice which contains the message after the length prefix\n    /// - Throws: if `readMessage` returns nil\n    /// - Returns: `nil` if the length prefix could not be read,\n    ///            the length prefix is negative or\n    ///            the buffer does not contain enough bytes to read a message of this length.\n    ///            Otherwise the result of `readMessage`.\n    @inlinable\n    public mutating func readLengthPrefixed<Integer, Result>(\n        endianness: Endianness = .big,\n        as integer: Integer.Type,\n        readMessage: (ByteBuffer) throws -> Result?\n    ) throws -> Result? where Integer: FixedWidthInteger {\n        guard let buffer = self.readLengthPrefixedSlice(endianness: endianness, as: Integer.self) else {\n            return nil\n        }\n        guard let result = try readMessage(buffer) else {\n            throw LengthPrefixError.messageCouldNotBeReadSuccessfully\n        }\n        return result\n    }\n\n    /// Reads an `Integer` from `self` and reads a slice of that length from `self` and returns it.\n    ///\n    /// If nil is returned, `readerIndex` is **not** moved forward.\n    /// - Parameters:\n    ///   - endianness: The endianness of the length prefix `Integer` in this `ByteBuffer` (defaults to big endian).\n    ///   - integer: the desired `Integer` type used to read the length prefix\n    /// - Returns: `nil` if the length prefix could not be read,\n    ///            the length prefix is negative or\n    ///            the buffer does not contain enough bytes to read a message of this length.\n    ///            Otherwise the message after the length prefix.\n    @inlinable\n    public mutating func readLengthPrefixedSlice<Integer>(\n        endianness: Endianness = .big,\n        as integer: Integer.Type\n    ) -> ByteBuffer? where Integer: FixedWidthInteger {\n        guard let result = self.getLengthPrefixedSlice(at: self.readerIndex, endianness: endianness, as: Integer.self)\n        else {\n            return nil\n        }\n        self._moveReaderIndex(forwardBy: MemoryLayout<Integer>.size + result.readableBytes)\n        return result\n    }\n\n    /// Gets an `Integer` from `self` and gets a slice of that length from `self` and returns it.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes for the slice into the `ByteBuffer`.\n    ///   - endianness: The endianness of the length prefix `Integer` in this `ByteBuffer` (defaults to big endian).\n    ///   - integer: the desired `Integer` type used to get the length prefix\n    /// - Returns: `nil` if the length prefix could not be read,\n    ///            the length prefix is negative or\n    ///            the buffer does not contain enough bytes to read a message of this length.\n    ///            Otherwise the message after the length prefix.\n    @inlinable\n    public func getLengthPrefixedSlice<Integer>(\n        at index: Int,\n        endianness: Endianness = .big,\n        as integer: Integer.Type\n    ) -> ByteBuffer? where Integer: FixedWidthInteger {\n        guard let lengthPrefix = self.getInteger(at: index, endianness: endianness, as: Integer.self),\n            let messageLength = Int(exactly: lengthPrefix),\n            let messageBuffer = self.getSlice(at: index + MemoryLayout<Integer>.size, length: messageLength)\n        else {\n            return nil\n        }\n\n        return messageBuffer\n    }\n\n    /// Reads an integer length prefix at the current `readerIndex`, then returns a `ByteBuffer` slice of that length\n    /// without advancing the reader index.\n    ///\n    /// This method is equivalent to calling `getLengthPrefixedSlice(at: readerIndex, ...)`.\n    ///\n    /// - Parameters:\n    ///   - endianness: The endianness of the length prefix (defaults to big endian).\n    ///   - integer: The `FixedWidthInteger` type for the length prefix.\n    /// - Returns: `nil` if the length prefix could not be read, the length prefix is negative, or if there aren't enough\n    ///            bytes for the message after the prefix. Otherwise, a slice of the requested length.\n    @inlinable\n    public func peekLengthPrefixedSlice<Integer>(\n        endianness: Endianness = .big,\n        as integer: Integer.Type\n    ) -> ByteBuffer? where Integer: FixedWidthInteger {\n        self.getLengthPrefixedSlice(at: self.readerIndex, endianness: endianness, as: integer)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-multi-int.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// NOTE: THIS FILE IS AUTO-GENERATED BY dev/generate-bytebuffer-multi-int.sh\n\nextension ByteBuffer {\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger>(\n        endianness: Endianness = .big,\n        as: (T1, T2).Type = (T1, T2).self\n    ) -> (T1, T2)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (T1(bigEndian: v1), T2(bigEndian: v2))\n        case .little:\n            return (T1(littleEndian: v1), T2(littleEndian: v2))\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger>(\n        endianness: Endianness = .big,\n        as: (T1, T2).Type = (T1, T2).self\n    ) -> (T1, T2)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger>(\n        _ value1: T1,\n        _ value2: T2,\n        endianness: Endianness = .big,\n        as: (T1, T2).Type = (T1, T2).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger, T3: FixedWidthInteger>(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3).Type = (T1, T2, T3).self\n    ) -> (T1, T2, T3)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3))\n        case .little:\n            return (T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3))\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger, T3: FixedWidthInteger>(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3).Type = (T1, T2, T3).self\n    ) -> (T1, T2, T3)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger, T3: FixedWidthInteger>(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3).Type = (T1, T2, T3).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger\n    >(endianness: Endianness = .big, as: (T1, T2, T3, T4).Type = (T1, T2, T3, T4).self) -> (T1, T2, T3, T4)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4))\n        case .little:\n            return (T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4))\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger\n    >(endianness: Endianness = .big, as: (T1, T2, T3, T4).Type = (T1, T2, T3, T4).self) -> (T1, T2, T3, T4)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4).Type = (T1, T2, T3, T4).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger\n    >(endianness: Endianness = .big, as: (T1, T2, T3, T4, T5).Type = (T1, T2, T3, T4, T5).self) -> (T1, T2, T3, T4, T5)?\n    {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5))\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger\n    >(endianness: Endianness = .big, as: (T1, T2, T3, T4, T5).Type = (T1, T2, T3, T4, T5).self) -> (T1, T2, T3, T4, T5)?\n    {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5).Type = (T1, T2, T3, T4, T5).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6).Type = (T1, T2, T3, T4, T5, T6).self\n    ) -> (T1, T2, T3, T4, T5, T6)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6).Type = (T1, T2, T3, T4, T5, T6).self\n    ) -> (T1, T2, T3, T4, T5, T6)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6).Type = (T1, T2, T3, T4, T5, T6).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7).Type = (T1, T2, T3, T4, T5, T6, T7).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7).Type = (T1, T2, T3, T4, T5, T6, T7).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7).Type = (T1, T2, T3, T4, T5, T6, T7).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8).Type = (T1, T2, T3, T4, T5, T6, T7, T8).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8).Type = (T1, T2, T3, T4, T5, T6, T7, T8).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8).Type = (T1, T2, T3, T4, T5, T6, T7, T8).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n        bytesRequired &+= MemoryLayout<T10>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var v10: T10 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            withUnsafeMutableBytes(of: &v10) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)\n            }\n            offset = offset &+ MemoryLayout<T10>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9), T10(littleEndian: v10)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        _ value10: T10,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        var v10: T10\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n            v10 = value10.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n            v10 = value10.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n        spaceNeeded &+= MemoryLayout<T10>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)\n            offset = offset &+ MemoryLayout<T10>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n        bytesRequired &+= MemoryLayout<T10>.size\n        bytesRequired &+= MemoryLayout<T11>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var v10: T10 = 0\n        var v11: T11 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            withUnsafeMutableBytes(of: &v10) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)\n            }\n            offset = offset &+ MemoryLayout<T10>.size\n            withUnsafeMutableBytes(of: &v11) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)\n            }\n            offset = offset &+ MemoryLayout<T11>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),\n                T11(bigEndian: v11)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        _ value10: T10,\n        _ value11: T11,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        var v10: T10\n        var v11: T11\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n            v10 = value10.bigEndian\n            v11 = value11.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n            v10 = value10.littleEndian\n            v11 = value11.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n        spaceNeeded &+= MemoryLayout<T10>.size\n        spaceNeeded &+= MemoryLayout<T11>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)\n            offset = offset &+ MemoryLayout<T10>.size\n            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)\n            offset = offset &+ MemoryLayout<T11>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n        bytesRequired &+= MemoryLayout<T10>.size\n        bytesRequired &+= MemoryLayout<T11>.size\n        bytesRequired &+= MemoryLayout<T12>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var v10: T10 = 0\n        var v11: T11 = 0\n        var v12: T12 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            withUnsafeMutableBytes(of: &v10) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)\n            }\n            offset = offset &+ MemoryLayout<T10>.size\n            withUnsafeMutableBytes(of: &v11) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)\n            }\n            offset = offset &+ MemoryLayout<T11>.size\n            withUnsafeMutableBytes(of: &v12) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)\n            }\n            offset = offset &+ MemoryLayout<T12>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),\n                T11(bigEndian: v11), T12(bigEndian: v12)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        _ value10: T10,\n        _ value11: T11,\n        _ value12: T12,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12\n        ).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        var v10: T10\n        var v11: T11\n        var v12: T12\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n            v10 = value10.bigEndian\n            v11 = value11.bigEndian\n            v12 = value12.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n            v10 = value10.littleEndian\n            v11 = value11.littleEndian\n            v12 = value12.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n        spaceNeeded &+= MemoryLayout<T10>.size\n        spaceNeeded &+= MemoryLayout<T11>.size\n        spaceNeeded &+= MemoryLayout<T12>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)\n            offset = offset &+ MemoryLayout<T10>.size\n            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)\n            offset = offset &+ MemoryLayout<T11>.size\n            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)\n            offset = offset &+ MemoryLayout<T12>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n        bytesRequired &+= MemoryLayout<T10>.size\n        bytesRequired &+= MemoryLayout<T11>.size\n        bytesRequired &+= MemoryLayout<T12>.size\n        bytesRequired &+= MemoryLayout<T13>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var v10: T10 = 0\n        var v11: T11 = 0\n        var v12: T12 = 0\n        var v13: T13 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            withUnsafeMutableBytes(of: &v10) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)\n            }\n            offset = offset &+ MemoryLayout<T10>.size\n            withUnsafeMutableBytes(of: &v11) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)\n            }\n            offset = offset &+ MemoryLayout<T11>.size\n            withUnsafeMutableBytes(of: &v12) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)\n            }\n            offset = offset &+ MemoryLayout<T12>.size\n            withUnsafeMutableBytes(of: &v13) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T13>.size)\n            }\n            offset = offset &+ MemoryLayout<T13>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),\n                T11(bigEndian: v11), T12(bigEndian: v12), T13(bigEndian: v13)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12),\n                T13(littleEndian: v13)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        _ value10: T10,\n        _ value11: T11,\n        _ value12: T12,\n        _ value13: T13,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13\n        ).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        var v10: T10\n        var v11: T11\n        var v12: T12\n        var v13: T13\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n            v10 = value10.bigEndian\n            v11 = value11.bigEndian\n            v12 = value12.bigEndian\n            v13 = value13.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n            v10 = value10.littleEndian\n            v11 = value11.littleEndian\n            v12 = value12.littleEndian\n            v13 = value13.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n        spaceNeeded &+= MemoryLayout<T10>.size\n        spaceNeeded &+= MemoryLayout<T11>.size\n        spaceNeeded &+= MemoryLayout<T12>.size\n        spaceNeeded &+= MemoryLayout<T13>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)\n            offset = offset &+ MemoryLayout<T10>.size\n            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)\n            offset = offset &+ MemoryLayout<T11>.size\n            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)\n            offset = offset &+ MemoryLayout<T12>.size\n            (basePtr + offset).copyMemory(from: &v13, byteCount: MemoryLayout<T13>.size)\n            offset = offset &+ MemoryLayout<T13>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger,\n        T14: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n        bytesRequired &+= MemoryLayout<T10>.size\n        bytesRequired &+= MemoryLayout<T11>.size\n        bytesRequired &+= MemoryLayout<T12>.size\n        bytesRequired &+= MemoryLayout<T13>.size\n        bytesRequired &+= MemoryLayout<T14>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var v10: T10 = 0\n        var v11: T11 = 0\n        var v12: T12 = 0\n        var v13: T13 = 0\n        var v14: T14 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            withUnsafeMutableBytes(of: &v10) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)\n            }\n            offset = offset &+ MemoryLayout<T10>.size\n            withUnsafeMutableBytes(of: &v11) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)\n            }\n            offset = offset &+ MemoryLayout<T11>.size\n            withUnsafeMutableBytes(of: &v12) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)\n            }\n            offset = offset &+ MemoryLayout<T12>.size\n            withUnsafeMutableBytes(of: &v13) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T13>.size)\n            }\n            offset = offset &+ MemoryLayout<T13>.size\n            withUnsafeMutableBytes(of: &v14) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T14>.size)\n            }\n            offset = offset &+ MemoryLayout<T14>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),\n                T11(bigEndian: v11), T12(bigEndian: v12), T13(bigEndian: v13), T14(bigEndian: v14)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12),\n                T13(littleEndian: v13), T14(littleEndian: v14)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger,\n        T14: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger,\n        T14: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        _ value10: T10,\n        _ value11: T11,\n        _ value12: T12,\n        _ value13: T13,\n        _ value14: T14,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14\n        ).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        var v10: T10\n        var v11: T11\n        var v12: T12\n        var v13: T13\n        var v14: T14\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n            v10 = value10.bigEndian\n            v11 = value11.bigEndian\n            v12 = value12.bigEndian\n            v13 = value13.bigEndian\n            v14 = value14.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n            v10 = value10.littleEndian\n            v11 = value11.littleEndian\n            v12 = value12.littleEndian\n            v13 = value13.littleEndian\n            v14 = value14.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n        spaceNeeded &+= MemoryLayout<T10>.size\n        spaceNeeded &+= MemoryLayout<T11>.size\n        spaceNeeded &+= MemoryLayout<T12>.size\n        spaceNeeded &+= MemoryLayout<T13>.size\n        spaceNeeded &+= MemoryLayout<T14>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)\n            offset = offset &+ MemoryLayout<T10>.size\n            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)\n            offset = offset &+ MemoryLayout<T11>.size\n            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)\n            offset = offset &+ MemoryLayout<T12>.size\n            (basePtr + offset).copyMemory(from: &v13, byteCount: MemoryLayout<T13>.size)\n            offset = offset &+ MemoryLayout<T13>.size\n            (basePtr + offset).copyMemory(from: &v14, byteCount: MemoryLayout<T14>.size)\n            offset = offset &+ MemoryLayout<T14>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public mutating func readMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger,\n        T14: FixedWidthInteger,\n        T15: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)? {\n        var bytesRequired: Int = MemoryLayout<T1>.size\n        bytesRequired &+= MemoryLayout<T2>.size\n        bytesRequired &+= MemoryLayout<T3>.size\n        bytesRequired &+= MemoryLayout<T4>.size\n        bytesRequired &+= MemoryLayout<T5>.size\n        bytesRequired &+= MemoryLayout<T6>.size\n        bytesRequired &+= MemoryLayout<T7>.size\n        bytesRequired &+= MemoryLayout<T8>.size\n        bytesRequired &+= MemoryLayout<T9>.size\n        bytesRequired &+= MemoryLayout<T10>.size\n        bytesRequired &+= MemoryLayout<T11>.size\n        bytesRequired &+= MemoryLayout<T12>.size\n        bytesRequired &+= MemoryLayout<T13>.size\n        bytesRequired &+= MemoryLayout<T14>.size\n        bytesRequired &+= MemoryLayout<T15>.size\n\n        guard self.readableBytes >= bytesRequired else {\n            return nil\n        }\n\n        var v1: T1 = 0\n        var v2: T2 = 0\n        var v3: T3 = 0\n        var v4: T4 = 0\n        var v5: T5 = 0\n        var v6: T6 = 0\n        var v7: T7 = 0\n        var v8: T8 = 0\n        var v9: T9 = 0\n        var v10: T10 = 0\n        var v11: T11 = 0\n        var v12: T12 = 0\n        var v13: T13 = 0\n        var v14: T14 = 0\n        var v15: T15 = 0\n        var offset = 0\n        self.readWithUnsafeReadableBytes { ptr -> Int in\n            assert(ptr.count >= bytesRequired)\n            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty\n            withUnsafeMutableBytes(of: &v1) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)\n            }\n            offset = offset &+ MemoryLayout<T1>.size\n            withUnsafeMutableBytes(of: &v2) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)\n            }\n            offset = offset &+ MemoryLayout<T2>.size\n            withUnsafeMutableBytes(of: &v3) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)\n            }\n            offset = offset &+ MemoryLayout<T3>.size\n            withUnsafeMutableBytes(of: &v4) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)\n            }\n            offset = offset &+ MemoryLayout<T4>.size\n            withUnsafeMutableBytes(of: &v5) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)\n            }\n            offset = offset &+ MemoryLayout<T5>.size\n            withUnsafeMutableBytes(of: &v6) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)\n            }\n            offset = offset &+ MemoryLayout<T6>.size\n            withUnsafeMutableBytes(of: &v7) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)\n            }\n            offset = offset &+ MemoryLayout<T7>.size\n            withUnsafeMutableBytes(of: &v8) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)\n            }\n            offset = offset &+ MemoryLayout<T8>.size\n            withUnsafeMutableBytes(of: &v9) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)\n            }\n            offset = offset &+ MemoryLayout<T9>.size\n            withUnsafeMutableBytes(of: &v10) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)\n            }\n            offset = offset &+ MemoryLayout<T10>.size\n            withUnsafeMutableBytes(of: &v11) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)\n            }\n            offset = offset &+ MemoryLayout<T11>.size\n            withUnsafeMutableBytes(of: &v12) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)\n            }\n            offset = offset &+ MemoryLayout<T12>.size\n            withUnsafeMutableBytes(of: &v13) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T13>.size)\n            }\n            offset = offset &+ MemoryLayout<T13>.size\n            withUnsafeMutableBytes(of: &v14) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T14>.size)\n            }\n            offset = offset &+ MemoryLayout<T14>.size\n            withUnsafeMutableBytes(of: &v15) { destPtr in\n                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T15>.size)\n            }\n            offset = offset &+ MemoryLayout<T15>.size\n            assert(offset == bytesRequired)\n            return offset\n        }\n        switch endianness {\n        case .big:\n            return (\n                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),\n                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),\n                T11(bigEndian: v11), T12(bigEndian: v12), T13(bigEndian: v13), T14(bigEndian: v14), T15(bigEndian: v15)\n            )\n        case .little:\n            return (\n                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),\n                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),\n                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12),\n                T13(littleEndian: v13), T14(littleEndian: v14), T15(littleEndian: v15)\n            )\n        }\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    public func peekMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger,\n        T14: FixedWidthInteger,\n        T15: FixedWidthInteger\n    >(\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15\n        ).self\n    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)? {\n        var copy = self\n        return copy.readMultipleIntegers(endianness: endianness, as: `as`)\n    }\n\n    @inlinable\n    @_alwaysEmitIntoClient\n    @discardableResult\n    public mutating func writeMultipleIntegers<\n        T1: FixedWidthInteger,\n        T2: FixedWidthInteger,\n        T3: FixedWidthInteger,\n        T4: FixedWidthInteger,\n        T5: FixedWidthInteger,\n        T6: FixedWidthInteger,\n        T7: FixedWidthInteger,\n        T8: FixedWidthInteger,\n        T9: FixedWidthInteger,\n        T10: FixedWidthInteger,\n        T11: FixedWidthInteger,\n        T12: FixedWidthInteger,\n        T13: FixedWidthInteger,\n        T14: FixedWidthInteger,\n        T15: FixedWidthInteger\n    >(\n        _ value1: T1,\n        _ value2: T2,\n        _ value3: T3,\n        _ value4: T4,\n        _ value5: T5,\n        _ value6: T6,\n        _ value7: T7,\n        _ value8: T8,\n        _ value9: T9,\n        _ value10: T10,\n        _ value11: T11,\n        _ value12: T12,\n        _ value13: T13,\n        _ value14: T14,\n        _ value15: T15,\n        endianness: Endianness = .big,\n        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15).Type = (\n            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15\n        ).self\n    ) -> Int {\n        var v1: T1\n        var v2: T2\n        var v3: T3\n        var v4: T4\n        var v5: T5\n        var v6: T6\n        var v7: T7\n        var v8: T8\n        var v9: T9\n        var v10: T10\n        var v11: T11\n        var v12: T12\n        var v13: T13\n        var v14: T14\n        var v15: T15\n        switch endianness {\n        case .big:\n            v1 = value1.bigEndian\n            v2 = value2.bigEndian\n            v3 = value3.bigEndian\n            v4 = value4.bigEndian\n            v5 = value5.bigEndian\n            v6 = value6.bigEndian\n            v7 = value7.bigEndian\n            v8 = value8.bigEndian\n            v9 = value9.bigEndian\n            v10 = value10.bigEndian\n            v11 = value11.bigEndian\n            v12 = value12.bigEndian\n            v13 = value13.bigEndian\n            v14 = value14.bigEndian\n            v15 = value15.bigEndian\n        case .little:\n            v1 = value1.littleEndian\n            v2 = value2.littleEndian\n            v3 = value3.littleEndian\n            v4 = value4.littleEndian\n            v5 = value5.littleEndian\n            v6 = value6.littleEndian\n            v7 = value7.littleEndian\n            v8 = value8.littleEndian\n            v9 = value9.littleEndian\n            v10 = value10.littleEndian\n            v11 = value11.littleEndian\n            v12 = value12.littleEndian\n            v13 = value13.littleEndian\n            v14 = value14.littleEndian\n            v15 = value15.littleEndian\n        }\n\n        var spaceNeeded: Int = MemoryLayout<T1>.size\n        spaceNeeded &+= MemoryLayout<T2>.size\n        spaceNeeded &+= MemoryLayout<T3>.size\n        spaceNeeded &+= MemoryLayout<T4>.size\n        spaceNeeded &+= MemoryLayout<T5>.size\n        spaceNeeded &+= MemoryLayout<T6>.size\n        spaceNeeded &+= MemoryLayout<T7>.size\n        spaceNeeded &+= MemoryLayout<T8>.size\n        spaceNeeded &+= MemoryLayout<T9>.size\n        spaceNeeded &+= MemoryLayout<T10>.size\n        spaceNeeded &+= MemoryLayout<T11>.size\n        spaceNeeded &+= MemoryLayout<T12>.size\n        spaceNeeded &+= MemoryLayout<T13>.size\n        spaceNeeded &+= MemoryLayout<T14>.size\n        spaceNeeded &+= MemoryLayout<T15>.size\n\n        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\n            assert(ptr.count >= spaceNeeded)\n            var offset = 0\n            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length\n            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)\n            offset = offset &+ MemoryLayout<T1>.size\n            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)\n            offset = offset &+ MemoryLayout<T2>.size\n            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)\n            offset = offset &+ MemoryLayout<T3>.size\n            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)\n            offset = offset &+ MemoryLayout<T4>.size\n            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)\n            offset = offset &+ MemoryLayout<T5>.size\n            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)\n            offset = offset &+ MemoryLayout<T6>.size\n            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)\n            offset = offset &+ MemoryLayout<T7>.size\n            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)\n            offset = offset &+ MemoryLayout<T8>.size\n            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)\n            offset = offset &+ MemoryLayout<T9>.size\n            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)\n            offset = offset &+ MemoryLayout<T10>.size\n            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)\n            offset = offset &+ MemoryLayout<T11>.size\n            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)\n            offset = offset &+ MemoryLayout<T12>.size\n            (basePtr + offset).copyMemory(from: &v13, byteCount: MemoryLayout<T13>.size)\n            offset = offset &+ MemoryLayout<T13>.size\n            (basePtr + offset).copyMemory(from: &v14, byteCount: MemoryLayout<T14>.size)\n            offset = offset &+ MemoryLayout<T14>.size\n            (basePtr + offset).copyMemory(from: &v15, byteCount: MemoryLayout<T15>.size)\n            offset = offset &+ MemoryLayout<T15>.size\n            assert(offset == spaceNeeded)\n            return offset\n        }\n    }\n\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-quicBinaryEncodingStrategy.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension ByteBuffer {\n    /// A ``NIOBinaryIntegerEncodingStrategy`` which encodes bytes as defined in RFC 9000 § 16\n    public struct QUICBinaryEncodingStrategy: NIOBinaryIntegerEncodingStrategy, Sendable {\n        /// All possible values for how many bytes a QUIC encoded integer can be\n        public enum IntegerLength: Int, Sendable {\n            case one = 1\n            case two = 2\n            case four = 4\n            case eight = 8\n        }\n        /// An estimate of the bytes required to write integers using this strategy\n        public var requiredBytesHint: Int\n\n        /// Note: Prefer to use the APIs directly on ByteBuffer such as ``ByteBuffer/writeEncodedInteger(_:strategy:)`` and pass `.quic` rather than directly initialising an instance of this strategy\n        /// - Parameter requiredBytesHint: An estimate of the bytes required to write integers using this strategy. This parameter is only relevant if calling ``ByteBuffer/writeLengthPrefixed(strategy:writeData:)``\n        @inlinable\n        public init(requiredBytesHint: IntegerLength) {\n            self.requiredBytesHint = requiredBytesHint.rawValue\n        }\n\n        @inlinable\n        public func readInteger<IntegerType: FixedWidthInteger>(\n            as: IntegerType.Type,\n            from buffer: inout ByteBuffer\n        ) -> IntegerType? {\n            guard let firstByte = buffer.getInteger(at: buffer.readerIndex, as: UInt8.self) else {\n                return nil\n            }\n\n            // Look at the first two bits to work out the length, then read that, mask off the top two bits, and\n            // extend to integer.\n            switch firstByte & 0xC0 {\n            case 0x00:\n                // Easy case.\n                buffer.moveReaderIndex(forwardBy: 1)\n                return IntegerType(firstByte & ~0xC0)\n            case 0x40:\n                // Length is two bytes long, read the next one.\n                return buffer.readInteger(as: UInt16.self).map { IntegerType($0 & ~(0xC0 << 8)) }\n            case 0x80:\n                // Length is 4 bytes long.\n                return buffer.readInteger(as: UInt32.self).map { IntegerType($0 & ~(0xC0 << 24)) }\n            case 0xC0:\n                // Length is 8 bytes long.\n                return buffer.readInteger(as: UInt64.self).map { IntegerType($0 & ~(0xC0 << 56)) }\n            default:\n                fatalError(\"Unreachable\")\n            }\n        }\n\n        /// Calculates the minimum number of bytes needed to encode an integer using this strategy\n        /// - Parameter integer: The integer to be encoded\n        /// - Returns: The number of bytes needed to encode it\n        public static func bytesNeededForInteger<IntegerType: FixedWidthInteger>(_ integer: IntegerType) -> Int {\n            // We must cast the integer to UInt64 here\n            // Otherwise, an integer can fall through to the default case\n            // E.g., if someone calls this function with UInt8.max (which is 255), they would not hit the first case (0..<63)\n            // The second case cannot be represented at all in UInt8, because 16383 is too big\n            // Swift will end up creating the 16383 literal as 0, and thus we will fall all the way through to the default\n            switch UInt64(integer) {\n            case 0..<63:\n                return 1\n            case 0..<16383:\n                return 2\n            case 0..<1_073_741_823:\n                return 4\n            case 0..<4_611_686_018_427_387_903:\n                return 8\n            default:\n                fatalError(\"QUIC variable-length integer outside of valid range\")\n            }\n        }\n\n        @inlinable\n        public func writeInteger<IntegerType: FixedWidthInteger>(\n            _ integer: IntegerType,\n            to buffer: inout ByteBuffer\n        ) -> Int {\n            self.writeInteger(integer, reservedCapacity: 0, to: &buffer)\n        }\n\n        @inlinable\n        public func writeInteger<IntegerType: FixedWidthInteger>(\n            _ integer: IntegerType,\n            reservedCapacity: Int,\n            to buffer: inout ByteBuffer\n        ) -> Int {\n            if reservedCapacity > 8 {\n                fatalError(\"Reserved space for QUIC encoded integer must be at most 8 bytes\")\n            }\n            // Use more space than necessary in order to fill the reserved space\n            // This will avoid a memmove\n            // If the needed space is more than the reserved, we can't avoid the move\n            switch max(reservedCapacity, Self.bytesNeededForInteger(integer)) {\n            case 1:\n                // Easy, store the value. The top two bits are 0 so we don't need to do any masking.\n                return buffer.writeInteger(UInt8(truncatingIfNeeded: integer))\n            case 2:\n                // Set the top two bit mask, then write the value.\n                let value = UInt16(truncatingIfNeeded: integer) | (0x40 << 8)\n                return buffer.writeInteger(value)\n            case 4:\n                // Set the top two bit mask, then write the value.\n                let value = UInt32(truncatingIfNeeded: integer) | (0x80 << 24)\n                return buffer.writeInteger(value)\n            case 8:\n                // Set the top two bit mask, then write the value.\n                let value = UInt64(truncatingIfNeeded: integer) | (0xC0 << 56)\n                return buffer.writeInteger(value)\n            default:\n                fatalError(\"Unreachable\")\n            }\n        }\n    }\n}\n\nextension NIOBinaryIntegerEncodingStrategy where Self == ByteBuffer.QUICBinaryEncodingStrategy {\n    @inlinable\n    /// Encodes bytes as defined in RFC 9000 § 16\n    /// - Parameter requiredBytesHint: An estimate of the bytes required to write integers using this strategy. This parameter is only relevant if calling ``ByteBuffer/writeLengthPrefixed(strategy:writeData:)``\n    /// - Returns: An instance of ``ByteBuffer/QUICBinaryEncodingStrategy``\n    public static func quic(\n        requiredBytesHint: ByteBuffer.QUICBinaryEncodingStrategy.IntegerLength\n    ) -> ByteBuffer.QUICBinaryEncodingStrategy {\n        ByteBuffer.QUICBinaryEncodingStrategy(requiredBytesHint: requiredBytesHint)\n    }\n\n    @inlinable\n    /// Encodes bytes as defined in RFC 9000 § 16\n    public static var quic: ByteBuffer.QUICBinaryEncodingStrategy { .quic(requiredBytesHint: .four) }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ByteBuffer-views.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A view into a portion of a `ByteBuffer`.\n///\n/// A `ByteBufferView` is useful whenever a `Collection where Element == UInt8` representing a portion of a\n/// `ByteBuffer` is needed.\npublic struct ByteBufferView: RandomAccessCollection, Sendable {\n    public typealias Element = UInt8\n    public typealias Index = Int\n    public typealias SubSequence = ByteBufferView\n\n    @usableFromInline var _buffer: ByteBuffer\n    @usableFromInline var _range: Range<Index>\n\n    @inlinable\n    internal init(buffer: ByteBuffer, range: Range<Index>) {\n        precondition(range.lowerBound >= 0 && range.upperBound <= buffer.capacity)\n        self._buffer = buffer\n        self._range = range\n    }\n\n    /// Creates a `ByteBufferView` from the readable bytes of the given `buffer`.\n    @inlinable\n    public init(_ buffer: ByteBuffer) {\n        self = ByteBufferView(buffer: buffer, range: buffer.readerIndex..<buffer.writerIndex)\n    }\n\n    @inlinable\n    public func withUnsafeBytes<R, ErrorType: Error>(\n        _ body: (UnsafeRawBufferPointer) throws(ErrorType) -> R\n    ) throws(ErrorType) -> R {\n        try self._buffer.withVeryUnsafeBytes { (ptr: UnsafeRawBufferPointer) throws(ErrorType) -> R in\n            try body(\n                UnsafeRawBufferPointer(\n                    start: ptr.baseAddress!.advanced(by: self._range.lowerBound),\n                    count: self._range.count\n                )\n            )\n        }\n    }\n\n    @inlinable\n    public var startIndex: Index {\n        self._range.lowerBound\n    }\n\n    @inlinable\n    public var endIndex: Index {\n        self._range.upperBound\n    }\n\n    @inlinable\n    public func index(after i: Index) -> Index {\n        i + 1\n    }\n\n    @inlinable\n    public var count: Int {\n        // Unchecked is safe here: Range enforces that upperBound is strictly greater than\n        // lower bound, and we guarantee that _range.lowerBound >= 0.\n        self._range.upperBound &- self._range.lowerBound\n    }\n\n    @inlinable\n    public subscript(position: Index) -> UInt8 {\n        get {\n            guard position >= self._range.lowerBound && position < self._range.upperBound else {\n                preconditionFailure(\"index \\(position) out of range\")\n            }\n            return self._buffer.getInteger(at: position)!  // range check above\n        }\n        set {\n            guard position >= self._range.lowerBound && position < self._range.upperBound else {\n                preconditionFailure(\"index \\(position) out of range\")\n            }\n            self._buffer.setInteger(newValue, at: position)\n        }\n    }\n\n    @inlinable\n    public subscript(range: Range<Index>) -> ByteBufferView {\n        get {\n            ByteBufferView(buffer: self._buffer, range: range)\n        }\n        set {\n            self.replaceSubrange(range, with: newValue)\n        }\n    }\n\n    @inlinable\n    public func withContiguousStorageIfAvailable<R, ErrorType: Error>(\n        _ body: (UnsafeBufferPointer<UInt8>) throws(ErrorType) -> R\n    ) throws(ErrorType) -> R? {\n        try self.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) throws(ErrorType) -> R in\n            try body(bytes.bindMemory(to: UInt8.self))\n        }\n    }\n\n    @inlinable\n    public func _customIndexOfEquatableElement(_ element: Element) -> Index?? {\n        .some(\n            self.withUnsafeBytes { ptr -> Index? in\n                ptr.firstIndex(of: element).map { $0 + self._range.lowerBound }\n            }\n        )\n    }\n\n    @inlinable\n    public func _customLastIndexOfEquatableElement(_ element: Element) -> Index?? {\n        .some(\n            self.withUnsafeBytes { ptr -> Index? in\n                ptr.lastIndex(of: element).map { $0 + self._range.lowerBound }\n            }\n        )\n    }\n\n    @inlinable\n    public func _customContainsEquatableElement(_ element: Element) -> Bool? {\n        .some(\n            self.withUnsafeBytes { ptr -> Bool in\n                ptr.contains(element)\n            }\n        )\n    }\n\n    @inlinable\n    public func _copyContents(\n        initializing ptr: UnsafeMutableBufferPointer<UInt8>\n    ) -> (Iterator, UnsafeMutableBufferPointer<UInt8>.Index) {\n        precondition(ptr.count >= self.count)\n\n        let bytesToWrite = self.count\n\n        let endIndex = self.withContiguousStorageIfAvailable { ourBytes in\n            ptr.initialize(from: ourBytes).1\n        }\n        precondition(endIndex == bytesToWrite)\n\n        let iterator = self[self.endIndex..<self.endIndex].makeIterator()\n        return (iterator, bytesToWrite)\n    }\n\n    // These are implemented as no-ops for performance reasons.\n    @inlinable\n    public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {}\n\n    @inlinable\n    public func _failEarlyRangeCheck(_ index: Index, bounds: ClosedRange<Index>) {}\n\n    @inlinable\n    public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {}\n}\n\nextension ByteBufferView: MutableCollection {}\n\nextension ByteBufferView: RangeReplaceableCollection {\n    // required by `RangeReplaceableCollection`\n    @inlinable\n    public init() {\n        self = ByteBufferView(ByteBuffer())\n    }\n\n    /// Reserves enough space in the underlying `ByteBuffer` such that this view can\n    /// store the specified number of bytes without reallocation.\n    ///\n    /// See the documentation for ``ByteBuffer/reserveCapacity(_:)`` for more details.\n    @inlinable\n    public mutating func reserveCapacity(_ minimumCapacity: Int) {\n        let additionalCapacity = minimumCapacity - self.count\n        if additionalCapacity > 0 {\n            self._buffer.reserveCapacity(self._buffer.capacity + additionalCapacity)\n        }\n    }\n\n    /// Writes a single byte to the underlying `ByteBuffer`.\n    @inlinable\n    public mutating func append(_ byte: UInt8) {\n        // ``CollectionOfOne`` has no witness for\n        // ``Sequence.withContiguousStorageIfAvailable(_:)``. so we do this instead:\n        self._buffer.setInteger(byte, at: self._range.upperBound)\n        self._range = self._range.lowerBound..<self._range.upperBound.advanced(by: 1)\n        self._buffer.moveWriterIndex(to: self._range.upperBound)\n    }\n\n    /// Writes a sequence of bytes to the underlying `ByteBuffer`.\n    @inlinable\n    public mutating func append<Bytes: Sequence>(contentsOf bytes: Bytes) where Bytes.Element == UInt8 {\n        let written = self._buffer.setBytes(bytes, at: self._range.upperBound)\n        self._range = self._range.lowerBound..<self._range.upperBound.advanced(by: written)\n        self._buffer.moveWriterIndex(to: self._range.upperBound)\n    }\n\n    @inlinable\n    public mutating func replaceSubrange<C: Collection>(_ subrange: Range<Index>, with newElements: C)\n    where ByteBufferView.Element == C.Element {\n        precondition(\n            subrange.startIndex >= self.startIndex && subrange.endIndex <= self.endIndex,\n            \"subrange out of bounds\"\n        )\n\n        if newElements.count == subrange.count {\n            self._buffer.setBytes(newElements, at: subrange.startIndex)\n        } else if newElements.count < subrange.count {\n            // Replace the subrange.\n            self._buffer.setBytes(newElements, at: subrange.startIndex)\n\n            // Remove the unwanted bytes between the newly copied bytes and the end of the subrange.\n            // try! is fine here: the copied range is within the view and the length can't be negative.\n            try! self._buffer.copyBytes(\n                at: subrange.endIndex,\n                to: subrange.startIndex.advanced(by: newElements.count),\n                length: subrange.endIndex.distance(to: self._buffer.writerIndex)\n            )\n\n            // Shorten the range.\n            let removedBytes = subrange.count - newElements.count\n            self._buffer.moveWriterIndex(to: self._buffer.writerIndex - removedBytes)\n            self._range = self._range.dropLast(removedBytes)\n        } else {\n            // Make space for the new elements.\n            // try! is fine here: the copied range is within the view and the length can't be negative.\n            try! self._buffer.copyBytes(\n                at: subrange.endIndex,\n                to: subrange.startIndex.advanced(by: newElements.count),\n                length: subrange.endIndex.distance(to: self._buffer.writerIndex)\n            )\n\n            // Replace the bytes.\n            self._buffer.setBytes(newElements, at: subrange.startIndex)\n\n            // Widen the range.\n            let additionalByteCount = newElements.count - subrange.count\n            self._buffer.moveWriterIndex(forwardBy: additionalByteCount)\n            self._range = self._range.startIndex..<self._range.endIndex.advanced(by: additionalByteCount)\n        }\n    }\n\n    /// Returns the first index in which a byte satisfies the given predicate.\n    ///\n    /// - Parameter predicate: A closure that takes a byte as its argument\n    ///   and returns a Boolean value that indicates whether the passed byte\n    ///   represents a match.\n    /// - Returns: The index of the first byte for which `predicate` returns\n    ///   `true`. If no bytes in the collection satisfy the given predicate,\n    ///   returns `nil`.\n    ///\n    /// - Complexity: O(*n*), where *n* is the length of the collection.\n    @inlinable\n    public func firstIndex(where predicate: (UInt8) throws -> Bool) rethrows -> Index? {\n        try self.withUnsafeBytes { ptr in\n            try ptr.firstIndex(where: predicate).map { $0 + self._range.lowerBound }\n        }\n    }\n\n    /// Returns the index of the last byte that matches the given predicate.\n    ///\n    /// - Parameter predicate: A closure that takes a byte as its argument\n    ///   and returns a Boolean value that indicates whether the passed byte\n    ///   represents a match.\n    /// - Returns: The index of the last byte in the collection that matches\n    ///   `predicate`, or `nil` if no bytes match.\n    ///\n    /// - Complexity: O(*n*), where *n* is the length of the collection.\n    @inlinable\n    public func lastIndex(where predicate: (UInt8) throws -> Bool) rethrows -> Index? {\n        try self.withUnsafeBytes { ptr in\n            try ptr.lastIndex(where: predicate).map { $0 + self._range.lowerBound }\n        }\n    }\n}\n\nextension ByteBuffer {\n    /// A view into the readable bytes of the `ByteBuffer`.\n    @inlinable\n    public var readableBytesView: ByteBufferView {\n        ByteBufferView(self)\n    }\n\n    /// Returns a view into some portion of the readable bytes of a `ByteBuffer`.\n    ///\n    /// - Parameters:\n    ///   - index: The index the view should start at\n    ///   - length: The length of the view (in bytes)\n    /// - Returns: A view into a portion of a `ByteBuffer` or `nil` if the requested bytes were not readable.\n    @inlinable\n    public func viewBytes(at index: Int, length: Int) -> ByteBufferView? {\n        guard length >= 0 && index >= self.readerIndex && index <= self.writerIndex - length else {\n            return nil\n        }\n\n        return ByteBufferView(buffer: self, range: index..<(index + length))\n    }\n\n    /// Create a `ByteBuffer` from the given `ByteBufferView`s range.\n    ///\n    /// - Parameter view: The `ByteBufferView` which you want to get a `ByteBuffer` from.\n    @inlinable\n    public init(_ view: ByteBufferView) {\n        self = view._buffer.getSlice(at: view.startIndex, length: view.count)!\n    }\n}\n\nextension ByteBufferView: Equatable {\n    /// required by `Equatable`\n    @inlinable\n    public static func == (lhs: ByteBufferView, rhs: ByteBufferView) -> Bool {\n\n        guard lhs._range.count == rhs._range.count else {\n            return false\n        }\n\n        // A well-formed ByteBufferView can never have a range that is out-of-bounds of the backing ByteBuffer.\n        // As a result, these getSlice calls can never fail, and we'd like to know it if they do.\n        let leftBufferSlice = lhs._buffer.getSlice(at: lhs._range.startIndex, length: lhs._range.count)!\n        let rightBufferSlice = rhs._buffer.getSlice(at: rhs._range.startIndex, length: rhs._range.count)!\n\n        return leftBufferSlice == rightBufferSlice\n    }\n}\n\nextension ByteBufferView: Hashable {\n    /// required by `Hashable`\n    @inlinable\n    public func hash(into hasher: inout Hasher) {\n        // A well-formed ByteBufferView can never have a range that is out-of-bounds of the backing ByteBuffer.\n        // As a result, this getSlice call can never fail, and we'd like to know it if it does.\n        hasher.combine(self._buffer.getSlice(at: self._range.startIndex, length: self._range.count)!)\n    }\n}\n\nextension ByteBufferView: ExpressibleByArrayLiteral {\n    /// required by `ExpressibleByArrayLiteral`\n    @inlinable\n    public init(arrayLiteral elements: Element...) {\n        self.init(elements)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/Channel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\n\n/// The core `Channel` methods that are for internal use of the `Channel` implementation only.\n///\n/// - warning: If you are not implementing a custom `Channel` type, you should never call any of these.\n///\n/// - Note: All methods must be called from the `EventLoop` thread.\npublic protocol ChannelCore: AnyObject {\n    /// Returns the local bound `SocketAddress`.\n    func localAddress0() throws -> SocketAddress\n\n    /// Return the connected `SocketAddress`.\n    func remoteAddress0() throws -> SocketAddress\n\n    /// Register with the `EventLoop` to receive I/O notifications.\n    ///\n    /// - Parameters:\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func register0(promise: EventLoopPromise<Void>?)\n\n    /// Register channel as already connected or bound socket.\n    /// - Parameters:\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func registerAlreadyConfigured0(promise: EventLoopPromise<Void>?)\n\n    /// Bind to a `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - to: The `SocketAddress` to which we should bind the `Channel`.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func bind0(to: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    /// Connect to a `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - to: The `SocketAddress` to which we should connect the `Channel`.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func connect0(to: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    /// Write the given data to the outbound buffer.\n    ///\n    /// - Parameters:\n    ///   - data: The data to write, wrapped in a `NIOAny`.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func write0(_ data: NIOAny, promise: EventLoopPromise<Void>?)\n\n    /// Try to flush out all previous written messages that are pending.\n    func flush0()\n\n    /// Request that the `Channel` perform a read when data is ready.\n    func read0()\n\n    /// Close the `Channel`.\n    ///\n    /// - Parameters:\n    ///   - error: The `Error` which will be used to fail any pending writes.\n    ///   - mode: The `CloseMode` to apply.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func close0(error: Error, mode: CloseMode, promise: EventLoopPromise<Void>?)\n\n    /// Trigger an outbound event.\n    ///\n    /// - Parameters:\n    ///   - event: The triggered event.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?)\n\n    /// Called when data was read from the `Channel` but it was not consumed by any `ChannelInboundHandler` in the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - data: The data that was read, wrapped in a `NIOAny`.\n    func channelRead0(_ data: NIOAny)\n\n    /// Called when an inbound error was encountered but was not consumed by any `ChannelInboundHandler` in the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - error: The `Error` that was encountered.\n    func errorCaught0(error: Error)\n}\n\n/// A `Channel` is easiest thought of as a network socket. But it can be anything that is capable of I/O operations such\n/// as read, write, connect, and bind.\n///\n/// - Note: All operations on `Channel` are thread-safe.\n///\n/// In SwiftNIO, all I/O operations are asynchronous and hence all operations on `Channel` are asynchronous too. This means\n/// that all I/O operations will return immediately, usually before the work has been completed. The `EventLoopPromise`s\n/// passed to or returned by the operations are used to retrieve the result of an operation after it has completed.\n///\n/// A `Channel` owns its `ChannelPipeline` which handles all I/O events and requests associated with the `Channel`.\npublic protocol Channel: AnyObject, ChannelOutboundInvoker, _NIOPreconcurrencySendable {\n    /// The `Channel`'s `ByteBuffer` allocator. This is _the only_ supported way of allocating `ByteBuffer`s to be used with this `Channel`.\n    var allocator: ByteBufferAllocator { get }\n\n    /// The `closeFuture` will fire when the `Channel` has been closed.\n    ///\n    /// - Important: This future should never be failed: it signals when the channel has been closed, and this action should not fail,\n    ///              regardless of whether the close happenned cleanly or not.\n    ///              If you are interested in any errors thrown during `close` to diagnose any unclean channel closures, you\n    ///              should instead use the future returned from ``ChannelOutboundInvoker/close(mode:file:line:)-7hlgf``\n    ///              or pass a promise via ``ChannelOutboundInvoker/close(mode:promise:)``.\n    var closeFuture: EventLoopFuture<Void> { get }\n\n    /// The `ChannelPipeline` which handles all I/O events and requests associated with this `Channel`.\n    var pipeline: ChannelPipeline { get }\n\n    /// The local `SocketAddress`.\n    var localAddress: SocketAddress? { get }\n\n    /// The remote peer's `SocketAddress`.\n    ///\n    /// If we end up accepting an already-closed connection, the kernel can end up in a place\n    /// where it has no remote address to give us. In this situation, `remoteAddress` will be\n    /// `nil`. It can also be `nil` in cases where it isn't representable in SocketAddress, e.g. if\n    /// we're talking over a vsock.\n    var remoteAddress: SocketAddress? { get }\n\n    /// `Channel`s are hierarchical and might have a parent `Channel`. `Channel` hierarchies are in use for certain\n    /// protocols such as HTTP/2.\n    var parent: Channel? { get }\n\n    /// Set `option` to `value` on this `Channel`.\n    func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void>\n\n    /// Get the value of `option` for this `Channel`.\n    func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value>\n\n    /// Returns if this `Channel` is currently writable.\n    var isWritable: Bool { get }\n\n    /// Returns if this `Channel` is currently active. Active is defined as the period of time after the\n    /// `channelActive` and before `channelInactive` has fired. The main use for this is to know if `channelActive`\n    /// or `channelInactive` can be expected next when `handlerAdded` was received.\n    var isActive: Bool { get }\n\n    /// Reach out to the `_ChannelCore`.\n    ///\n    /// - warning: Unsafe, this is for use in NIO's core only.\n    var _channelCore: ChannelCore { get }\n\n    /// Returns a view of the `Channel` exposing synchronous versions of `setOption` and `getOption`.\n    /// The default implementation returns `nil`, and `Channel` implementations must opt in to\n    /// support this behavior.\n    var syncOptions: NIOSynchronousChannelOptions? { get }\n\n    /// Write data into the `Channel`, automatically wrapping with `NIOAny`.\n    ///\n    /// - seealso: `ChannelOutboundInvoker.write`.\n    @preconcurrency\n    func write<T: Sendable>(_ any: T) -> EventLoopFuture<Void>\n\n    /// Write data into the `Channel`, automatically wrapping with `NIOAny`.\n    ///\n    /// - seealso: `ChannelOutboundInvoker.write`.\n    @preconcurrency\n    func write<T: Sendable>(_ any: T, promise: EventLoopPromise<Void>?)\n\n    /// Write and flush data into the `Channel`, automatically wrapping with `NIOAny`.\n    ///\n    /// - seealso: `ChannelOutboundInvoker.writeAndFlush`.\n    @preconcurrency\n    func writeAndFlush<T: Sendable>(_ any: T) -> EventLoopFuture<Void>\n\n    /// Write and flush data into the `Channel`, automatically wrapping with `NIOAny`.\n    ///\n    /// - seealso: `ChannelOutboundInvoker.writeAndFlush`.\n    @preconcurrency\n    func writeAndFlush<T: Sendable>(_ any: T, promise: EventLoopPromise<Void>?)\n}\n\nextension Channel {\n    /// Default implementation: `NIOSynchronousChannelOptions` are not supported.\n    public var syncOptions: NIOSynchronousChannelOptions? {\n        nil\n    }\n}\n\npublic protocol NIOSynchronousChannelOptions {\n    /// Set `option` to `value` on this `Channel`.\n    ///\n    /// - Important: Must be called on the `EventLoop` the `Channel` is running on.\n    func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) throws\n\n    /// Get the value of `option` for this `Channel`.\n    ///\n    /// - Important: Must be called on the `EventLoop` the `Channel` is running on.\n    func getOption<Option: ChannelOption>(_ option: Option) throws -> Option.Value\n}\n\n/// Default implementations which will start on the head of the `ChannelPipeline`.\nextension Channel {\n\n    public func bind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        pipeline.bind(to: address, promise: promise)\n    }\n\n    public func connect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        pipeline.connect(to: address, promise: promise)\n    }\n\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func write(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        pipeline.write(data, promise: promise)\n    }\n\n    public func write<T: Sendable>(_ data: T, promise: EventLoopPromise<Void>?) {\n        pipeline.write(data, promise: promise)\n    }\n\n    public func flush() {\n        pipeline.flush()\n    }\n\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func writeAndFlush(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        pipeline.writeAndFlush(data, promise: promise)\n    }\n\n    public func writeAndFlush<T: Sendable>(_ data: T, promise: EventLoopPromise<Void>?) {\n        pipeline.writeAndFlush(data, promise: promise)\n    }\n\n    public func read() {\n        pipeline.read()\n    }\n\n    public func close(mode: CloseMode = .all, promise: EventLoopPromise<Void>?) {\n        pipeline.close(mode: mode, promise: promise)\n    }\n\n    public func register(promise: EventLoopPromise<Void>?) {\n        pipeline.register(promise: promise)\n    }\n\n    public func registerAlreadyConfigured0(promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._operationUnsupported)\n    }\n\n    @preconcurrency\n    public func triggerUserOutboundEvent(_ event: Any & Sendable, promise: EventLoopPromise<Void>?) {\n        pipeline.triggerUserOutboundEvent(event, promise: promise)\n    }\n}\n\n/// Provides special extension to make writing data to the `Channel` easier by removing the need to wrap data in `NIOAny` manually.\nextension Channel {\n\n    /// Write data into the `Channel`.\n    ///\n    /// - seealso: `ChannelOutboundInvoker.write`.\n    @preconcurrency\n    public func write<T: Sendable>(_ any: T) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.write(any, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Write and flush data into the `Channel`.\n    ///\n    /// - seealso: `ChannelOutboundInvoker.writeAndFlush`.\n    @preconcurrency\n    public func writeAndFlush<T: Sendable>(_ any: T) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.writeAndFlush(any, promise: promise)\n        return promise.futureResult\n    }\n}\n\nextension ChannelCore {\n    /// Unwraps the given `NIOAny` as a specific concrete type.\n    ///\n    /// This method is intended for use when writing custom `ChannelCore` implementations.\n    /// This can safely be called in methods like `write0` to extract data from the `NIOAny`\n    /// provided in those cases.\n    ///\n    /// Note that if the unwrap fails, this will cause a runtime trap. `ChannelCore`\n    /// implementations should be concrete about what types they support writing. If multiple\n    /// types are supported, consider using a tagged union to store the type information like\n    /// NIO's own `IOData`, which will minimise the amount of runtime type checking.\n    ///\n    /// - Parameters:\n    ///   - data: The `NIOAny` to unwrap.\n    ///   - as: The type to extract from the `NIOAny`.\n    /// - Returns: The content of the `NIOAny`.\n    @inlinable\n    public func unwrapData<T>(_ data: NIOAny, as: T.Type = T.self) -> T {\n        data.forceAs()\n    }\n\n    /// Attempts to unwrap the given `NIOAny` as a specific concrete type.\n    ///\n    /// This method is intended for use when writing custom `ChannelCore` implementations.\n    /// This can safely be called in methods like `write0` to extract data from the `NIOAny`\n    /// provided in those cases.\n    ///\n    /// If the unwrap fails, this will return `nil`. `ChannelCore` implementations should almost\n    /// always support only one runtime type, so in general they should avoid using this and prefer\n    /// using `unwrapData` instead. This method exists for rare use-cases where tolerating type\n    /// mismatches is acceptable.\n    ///\n    /// - Parameters:\n    ///   - data: The `NIOAny` to unwrap.\n    ///   - as: The type to extract from the `NIOAny`.\n    /// - Returns: The content of the `NIOAny`, or `nil` if the type is incorrect.\n    /// - warning: If you are implementing a `ChannelCore`, you should use `unwrapData` unless you\n    ///     are doing something _extremely_ unusual.\n    @inlinable\n    public func tryUnwrapData<T>(_ data: NIOAny, as: T.Type = T.self) -> T? {\n        data.tryAs()\n    }\n\n    /// Removes the `ChannelHandler`s from the `ChannelPipeline` belonging to `channel`, and\n    /// closes that `ChannelPipeline`.\n    ///\n    /// This method is intended for use when writing custom `ChannelCore` implementations.\n    /// This can be called from `close0` to tear down the `ChannelPipeline` when closure is\n    /// complete.\n    ///\n    /// - Parameters:\n    ///   - channel: The `Channel` whose `ChannelPipeline` will be closed.\n    @available(*, deprecated, renamed: \"removeHandlers(pipeline:)\")\n    public func removeHandlers(channel: Channel) {\n        self.removeHandlers(pipeline: channel.pipeline)\n    }\n\n    /// Removes the `ChannelHandler`s from the `ChannelPipeline` `pipeline`, and\n    /// closes that `ChannelPipeline`.\n    ///\n    /// This method is intended for use when writing custom `ChannelCore` implementations.\n    /// This can be called from `close0` to tear down the `ChannelPipeline` when closure is\n    /// complete.\n    ///\n    /// - Parameters:\n    ///   - pipeline: The `ChannelPipline` to be closed.\n    public func removeHandlers(pipeline: ChannelPipeline) {\n        pipeline.removeHandlers()\n    }\n}\n\n/// An error that can occur on `Channel` operations.\npublic enum ChannelError: Error {\n    /// Tried to connect on a `Channel` that is already connecting.\n    case connectPending\n\n    /// Connect operation timed out\n    case connectTimeout(TimeAmount)\n\n    /// Unsupported operation triggered on a `Channel`. For example `connect` on a `ServerSocketChannel`.\n    case operationUnsupported\n\n    /// An I/O operation (e.g. read/write/flush) called on a channel that is already closed.\n    case ioOnClosedChannel\n\n    /// Close was called on a channel that is already closed.\n    case alreadyClosed\n\n    /// Output-side of the channel is closed.\n    case outputClosed\n\n    /// Input-side of the channel is closed.\n    case inputClosed\n\n    /// A read operation reached end-of-file. This usually means the remote peer closed the socket but it's still\n    /// open locally.\n    case eof\n\n    /// A `DatagramChannel` `write` was made with a buffer that is larger than the MTU for the connection, and so the\n    /// datagram was not written. Either shorten the datagram or manually fragment, and then try again.\n    case writeMessageTooLarge\n\n    /// A `DatagramChannel` `write` was made with an address that was not reachable and so could not be delivered.\n    case writeHostUnreachable\n\n    /// The local address of the `Channel` could not be determined.\n    case unknownLocalAddress\n\n    /// The address family of the multicast group was not valid for this `Channel`.\n    case badMulticastGroupAddressFamily\n\n    /// The address family of the provided multicast group join is not valid for this `Channel`.\n    case badInterfaceAddressFamily\n\n    /// An attempt was made to join a multicast group that does not correspond to a multicast\n    /// address.\n    case illegalMulticastAddress(SocketAddress)\n\n    #if !os(WASI)\n    /// Multicast is not supported on Interface\n    @available(*, deprecated, renamed: \"NIOMulticastNotSupportedError\")\n    case multicastNotSupported(NIONetworkInterface)\n    #endif\n\n    /// An operation that was inappropriate given the current `Channel` state was attempted.\n    case inappropriateOperationForState\n\n    /// An attempt was made to remove a ChannelHandler that is not removable.\n    case unremovableHandler\n}\n\nextension ChannelError {\n    // 'any Error' is unconditionally boxed, avoid allocating per use by statically boxing them.\n    static let _alreadyClosed: any Error = ChannelError.alreadyClosed\n    static let _inputClosed: any Error = ChannelError.inputClosed\n    @usableFromInline\n    static let _ioOnClosedChannel: any Error = ChannelError.ioOnClosedChannel\n    static let _operationUnsupported: any Error = ChannelError.operationUnsupported\n    static let _outputClosed: any Error = ChannelError.outputClosed\n    static let _unremovableHandler: any Error = ChannelError.unremovableHandler\n}\n\nextension ChannelError: Equatable {}\n\nextension ChannelError: CustomStringConvertible {\n    public var description: String {\n        switch self {\n        case .connectPending:\n            \"Connect pending\"\n        case let .connectTimeout(value):\n            \"Connect timeout (\\(value))\"\n        case .operationUnsupported:\n            \"Operation unsupported\"\n        case .ioOnClosedChannel:\n            \"I/O on closed channel\"\n        case .alreadyClosed:\n            \"Already closed\"\n        case .outputClosed:\n            \"Output closed\"\n        case .inputClosed:\n            \"Input closed\"\n        case .eof:\n            \"End of file\"\n        case .writeMessageTooLarge:\n            \"Write message too large\"\n        case .writeHostUnreachable:\n            \"Write host unreachable\"\n        case .unknownLocalAddress:\n            \"Unknown local address\"\n        case .badMulticastGroupAddressFamily:\n            \"Bad multicast group address family\"\n        case .badInterfaceAddressFamily:\n            \"Bad interface address family\"\n        case let .illegalMulticastAddress(address):\n            \"Illegal multicast address \\(address)\"\n        #if !os(WASI)\n        case let .multicastNotSupported(interface):\n            \"Multicast not supported on interface \\(interface)\"\n        #endif\n        case .inappropriateOperationForState:\n            \"Inappropriate operation for state\"\n        case .unremovableHandler:\n            \"Unremovable handler\"\n        }\n    }\n}\n\n/// The removal of a `ChannelHandler` using `ChannelPipeline.removeHandler` has been attempted more than once.\npublic struct NIOAttemptedToRemoveHandlerMultipleTimesError: Error {}\n\npublic enum DatagramChannelError: Sendable {\n    public struct WriteOnUnconnectedSocketWithoutAddress: Error {\n        public init() {}\n    }\n\n    public struct WriteOnConnectedSocketWithInvalidAddress: Error {\n        let envelopeRemoteAddress: SocketAddress\n        let connectedRemoteAddress: SocketAddress\n\n        public init(\n            envelopeRemoteAddress: SocketAddress,\n            connectedRemoteAddress: SocketAddress\n        ) {\n            self.envelopeRemoteAddress = envelopeRemoteAddress\n            self.connectedRemoteAddress = connectedRemoteAddress\n        }\n    }\n}\n\n/// An `Channel` related event that is passed through the `ChannelPipeline` to notify the user.\npublic enum ChannelEvent: Equatable, Sendable {\n    /// `ChannelOptions.allowRemoteHalfClosure` is `true` and input portion of the `Channel` was closed.\n    case inputClosed\n    /// Output portion of the `Channel` was closed.\n    case outputClosed\n}\n\n/// A `Channel` user event that is sent when the `Channel` has been asked to quiesce.\n///\n/// The action(s) that should be taken after receiving this event are both application and protocol dependent. If the\n/// protocol supports a notion of requests and responses, it might make sense to stop accepting new requests but finish\n/// processing the request currently in flight.\npublic struct ChannelShouldQuiesceEvent: Sendable {\n    public init() {\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ChannelHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Base protocol for handlers that handle I/O events or intercept an I/O operation.\n///\n/// All methods are called from within the `EventLoop` that is assigned to the `Channel` itself.\n///\n/// You should _never_ implement this protocol directly. Please implement one of its sub-protocols.\npublic protocol ChannelHandler: AnyObject {\n    /// Called when this `ChannelHandler` is added to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func handlerAdded(context: ChannelHandlerContext)\n\n    /// Called when this `ChannelHandler` is removed from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func handlerRemoved(context: ChannelHandlerContext)\n}\n\n/// Untyped `ChannelHandler` which handles outbound I/O events or intercept an outbound I/O operation.\n///\n/// Despite the fact that `write` is one of the methods on this protocol, you should avoid assuming that \"outbound\" events are to do with\n/// writing to channel sources. Instead, \"outbound\" events are events that are passed *to* the channel source (e.g. a socket): that is, things you tell\n/// the channel source to do. That includes `write` (\"write this data to the channel source\"), but it also includes `read` (\"please begin attempting to read from\n/// the channel source\") and `bind` (\"please bind the following address\"), which have nothing to do with sending data.\n///\n/// We _strongly_ advise against implementing this protocol directly. Please implement `ChannelOutboundHandler`.\npublic protocol _ChannelOutboundHandler: ChannelHandler {\n\n    /// Called to request that the `Channel` register itself for I/O events with its `EventLoop`.\n    /// This should call `context.register` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?)\n\n    /// Called to request that the `Channel` bind to a specific `SocketAddress`.\n    ///\n    /// This should call `context.bind` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - to: The `SocketAddress` to which this `Channel` should bind.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func bind(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    /// Called to request that the `Channel` connect to a given `SocketAddress`.\n    ///\n    /// This should call `context.connect` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - to: The `SocketAddress` to which the the `Channel` should connect.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func connect(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    /// Called to request a write operation. The write operation will write the messages through the\n    /// `ChannelPipeline`. Those are then ready to be flushed to the actual `Channel` when\n    /// `Channel.flush` or `ChannelHandlerContext.flush` is called.\n    ///\n    /// This should call `context.write` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - data: The data to write through the `Channel`, wrapped in a `NIOAny`.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?)\n\n    /// Called to request that the `Channel` flush all pending writes. The flush operation will try to flush out all previous written messages\n    /// that are pending.\n    ///\n    /// This should call `context.flush` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or just\n    /// discard it if the flush should be suppressed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func flush(context: ChannelHandlerContext)\n\n    /// Called to request that the `Channel` perform a read when data is ready. The read operation will signal that we are ready to read more data.\n    ///\n    /// This should call `context.read` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or just\n    /// discard it if the read should be suppressed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func read(context: ChannelHandlerContext)\n\n    /// Called to request that the `Channel` close itself down.\n    ///\n    /// This should call `context.close` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - mode: The `CloseMode` to apply\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?)\n\n    /// Called when an user outbound event is triggered.\n    ///\n    /// This should call `context.triggerUserOutboundEvent` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - event: The triggered event.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?)\n}\n\n/// Untyped `ChannelHandler` which handles inbound I/O events.\n///\n/// Despite the fact that `channelRead` is one of the methods on this protocol, you should avoid assuming that \"inbound\" events are to do with\n/// reading from channel sources. Instead, \"inbound\" events are events that originate *from* the channel source (e.g. the socket): that is, events that the\n/// channel source tells you about. This includes things like `channelRead` (\"there is some data to read\"), but it also includes things like\n/// `channelWritabilityChanged` (\"this source is no longer marked writable\").\n///\n/// We _strongly_ advise against implementing this protocol directly. Please implement `ChannelInboundHandler`.\npublic protocol _ChannelInboundHandler: ChannelHandler {\n\n    /// Called when the `Channel` has successfully registered with its `EventLoop` to handle I/O.\n    ///\n    /// This should call `context.fireChannelRegistered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func channelRegistered(context: ChannelHandlerContext)\n\n    /// Called when the `Channel` has unregistered from its `EventLoop`, and so will no longer be receiving I/O events.\n    ///\n    /// This should call `context.fireChannelUnregistered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func channelUnregistered(context: ChannelHandlerContext)\n\n    /// Called when the `Channel` has become active, and is able to send and receive data.\n    ///\n    /// This should call `context.fireChannelActive` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func channelActive(context: ChannelHandlerContext)\n\n    /// Called when the `Channel` has become inactive and is no longer able to send and receive data.\n    ///\n    /// This should call `context.fireChannelInactive` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func channelInactive(context: ChannelHandlerContext)\n\n    /// Called when some data has been read from the remote peer.\n    ///\n    /// This should call `context.fireChannelRead` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - data: The data read from the remote peer, wrapped in a `NIOAny`.\n    func channelRead(context: ChannelHandlerContext, data: NIOAny)\n\n    /// Called when the `Channel` has completed its current read loop, either because no more data is available to read from the transport at this time, or because the `Channel` needs to yield to the event loop to process other I/O events for other `Channel`s.\n    /// If `ChannelOptions.autoRead` is `false` no further read attempt will be made until `ChannelHandlerContext.read` or `Channel.read` is explicitly called.\n    ///\n    /// This should call `context.fireChannelReadComplete` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func channelReadComplete(context: ChannelHandlerContext)\n\n    /// The writability state of the `Channel` has changed, either because it has buffered more data than the writability high water mark, or because the amount of buffered data has dropped below the writability low water mark.\n    /// You can check the state with `Channel.isWritable`.\n    ///\n    /// This should call `context.fireChannelWritabilityChanged` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    func channelWritabilityChanged(context: ChannelHandlerContext)\n\n    /// Called when a user inbound event has been triggered.\n    ///\n    /// This should call `context.fireUserInboundEventTriggered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - event: The event.\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any)\n\n    /// An error was encountered earlier in the inbound `ChannelPipeline`.\n    ///\n    /// This should call `context.fireErrorCaught` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the error.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - error: The `Error` that was encountered.\n    func errorCaught(context: ChannelHandlerContext, error: Error)\n}\n\n// Default implementations for the ChannelHandler protocol\nextension ChannelHandler {\n\n    /// Do nothing by default.\n    public func handlerAdded(context: ChannelHandlerContext) {\n    }\n\n    /// Do nothing by default.\n    public func handlerRemoved(context: ChannelHandlerContext) {\n    }\n}\n\n/// Provides default implementations for all methods defined by `_ChannelOutboundHandler`.\n///\n/// These default implementations will just call `context.methodName` to forward to the next `_ChannelOutboundHandler` in\n/// the `ChannelPipeline` until the operation is handled by the `Channel` itself.\nextension _ChannelOutboundHandler {\n\n    public func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        context.register(promise: promise)\n    }\n\n    public func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        context.bind(to: address, promise: promise)\n    }\n\n    public func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        context.connect(to: address, promise: promise)\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        context.write(data, promise: promise)\n    }\n\n    public func flush(context: ChannelHandlerContext) {\n        context.flush()\n    }\n\n    public func read(context: ChannelHandlerContext) {\n        context.read()\n    }\n\n    public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        context.close(mode: mode, promise: promise)\n    }\n\n    public func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {\n        context.triggerUserOutboundEvent(event, promise: promise)\n    }\n}\n\n/// Provides default implementations for all methods defined by `_ChannelInboundHandler`.\n///\n/// These default implementations will just `context.fire*` to forward to the next `_ChannelInboundHandler` in\n/// the `ChannelPipeline` until the operation is handled by the `Channel` itself.\nextension _ChannelInboundHandler {\n\n    public func channelRegistered(context: ChannelHandlerContext) {\n        context.fireChannelRegistered()\n    }\n\n    public func channelUnregistered(context: ChannelHandlerContext) {\n        context.fireChannelUnregistered()\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n        context.fireChannelActive()\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        context.fireChannelInactive()\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.fireChannelRead(data)\n    }\n\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        context.fireChannelReadComplete()\n    }\n\n    public func channelWritabilityChanged(context: ChannelHandlerContext) {\n        context.fireChannelWritabilityChanged()\n    }\n\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        context.fireErrorCaught(error)\n    }\n}\n\n/// A `RemovableChannelHandler` is a `ChannelHandler` that can be dynamically removed from a `ChannelPipeline` whilst\n/// the `Channel` is operating normally.\n/// A `RemovableChannelHandler` is required to remove itself from the `ChannelPipeline` (using\n/// `ChannelHandlerContext.leavePipeline`) as soon as possible.\n///\n/// - Note: When a `Channel` gets torn down, every `ChannelHandler` in the `Channel`'s `ChannelPipeline` will be\n///         removed from the `ChannelPipeline`. Those removals however happen synchronously and are not going through\n///         the methods of this protocol.\npublic protocol RemovableChannelHandler: ChannelHandler {\n    /// Ask the receiving `RemovableChannelHandler` to remove itself from the `ChannelPipeline` as soon as possible.\n    /// The receiving `RemovableChannelHandler` may elect to remove itself sometime after this method call, rather than\n    /// immediately, but if it does so it must take the necessary precautions to handle events arriving between the\n    /// invocation of this method and the call to `ChannelHandlerContext.leavePipeline` that triggers the actual\n    /// removal.\n    ///\n    /// - Note: Like the other `ChannelHandler` methods, this method should not be invoked by the user directly. To\n    ///         remove a `RemovableChannelHandler` from the `ChannelPipeline`, use `ChannelPipeline.removeHandler`.\n    ///\n    /// - Parameters:\n    ///    - context: The `ChannelHandlerContext` of the `RemovableChannelHandler` to be removed from the `ChannelPipeline`.\n    ///    - removalToken: The removal token to hand to `ChannelHandlerContext.leavePipeline` to trigger the actual\n    ///                    removal from the `ChannelPipeline`.\n    func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken)\n}\n\nextension RemovableChannelHandler {\n    /// Implements the default behaviour which is to synchronously remove the handler from the pipeline. Thanks to this,\n    /// stateless `ChannelHandler`s can just use `RemovableChannelHandler` as a marker-protocol and declare themselves\n    /// as removable without writing any extra code.\n    public func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n        precondition(context.handler === self)\n        context.leavePipeline(removalToken: removalToken)\n    }\n}\n\n/// A `NIOOutboundByteBufferingChannelHandler` is a `ChannelHandler` that\n/// reports the number of bytes buffered for outbound direction.\npublic protocol NIOOutboundByteBufferingChannelHandler {\n    /// The number of bytes buffered in the channel handler, which are queued to be sent to\n    /// the next outbound channel handler.\n    var outboundBufferedBytes: Int { get }\n}\n\n/// A `NIOInboundByteBufferingChannelHandler` is a `ChannelHandler` that\n/// reports the number of bytes buffered for inbound direction.\npublic protocol NIOInboundByteBufferingChannelHandler {\n    /// The number of bytes buffered in the channel handler, which are queued to be sent to\n    /// the next inbound channel handler.\n    var inboundBufferedBytes: Int { get }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ChannelHandlers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//  Contains ChannelHandler implementations which are generic and can be re-used easily.\n//\n//\n\n/// A `ChannelHandler` that implements a backoff for a `ServerChannel` when accept produces an `IOError`.\n/// These errors are often recoverable by reducing the rate at which we call accept.\npublic final class AcceptBackoffHandler: ChannelDuplexHandler, RemovableChannelHandler {\n    public typealias InboundIn = Channel\n    public typealias OutboundIn = Channel\n\n    private var nextReadDeadlineNS: Optional<NIODeadline>\n    private let backoffProvider: (IOError) -> TimeAmount?\n    private let shouldForwardIOErrorCaught: Bool\n    private var scheduledRead: Optional<Scheduled<Void>>\n\n    /// Default implementation used as `backoffProvider` which delays accept by 1 second.\n    public static func defaultBackoffProvider(error: IOError) -> TimeAmount? {\n        .seconds(1)\n    }\n\n    /// Create a new instance\n    ///\n    /// - Parameters:\n    ///   - backoffProvider: returns a `TimeAmount` which will be the amount of time to wait before attempting another `read`.\n    public init(backoffProvider: @escaping (IOError) -> TimeAmount? = AcceptBackoffHandler.defaultBackoffProvider) {\n        self.backoffProvider = backoffProvider\n        self.nextReadDeadlineNS = nil\n        self.scheduledRead = nil\n        self.shouldForwardIOErrorCaught = true\n    }\n\n    /// Create a new instance\n    ///\n    /// - Parameters:\n    ///   - shouldForwardIOErrorCaught: A boolean indicating if a caught IOError should be forwarded.\n    ///   - backoffProvider: returns a `TimeAmount` which will be the amount of time to wait before attempting another `read`.\n    public init(\n        shouldForwardIOErrorCaught: Bool,\n        backoffProvider: @escaping (IOError) -> TimeAmount? = AcceptBackoffHandler.defaultBackoffProvider\n    ) {\n        self.backoffProvider = backoffProvider\n        self.nextReadDeadlineNS = nil\n        self.scheduledRead = nil\n        self.shouldForwardIOErrorCaught = shouldForwardIOErrorCaught\n    }\n\n    public func read(context: ChannelHandlerContext) {\n        // If we already have a read scheduled there is no need to schedule another one.\n        guard scheduledRead == nil else { return }\n\n        if let deadline = self.nextReadDeadlineNS {\n            let now = NIODeadline.now()\n            if now >= deadline {\n                // The backoff already expired, just do a read.\n                doRead(context)\n            } else {\n                // Schedule the read to be executed after the backoff time elapsed.\n                scheduleRead(at: deadline, context: context)\n            }\n        } else {\n            context.read()\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        guard let ioError = error as? IOError else {\n            context.fireErrorCaught(error)\n            return\n        }\n\n        if let amount = backoffProvider(ioError) {\n            self.nextReadDeadlineNS = .now() + amount\n            if let scheduled = self.scheduledRead {\n                scheduled.cancel()\n                scheduleRead(at: self.nextReadDeadlineNS!, context: context)\n            }\n        }\n\n        if self.shouldForwardIOErrorCaught {\n            context.fireErrorCaught(error)\n        }\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        if let scheduled = self.scheduledRead {\n            scheduled.cancel()\n            self.scheduledRead = nil\n        }\n        self.nextReadDeadlineNS = nil\n        context.fireChannelInactive()\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        if let scheduled = self.scheduledRead {\n            // Cancel the previous scheduled read and trigger a read directly. This is needed as otherwise we may never read again.\n            scheduled.cancel()\n            self.scheduledRead = nil\n            context.read()\n        }\n        self.nextReadDeadlineNS = nil\n    }\n\n    private func scheduleRead(at: NIODeadline, context: ChannelHandlerContext) {\n        self.scheduledRead = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(deadline: at) {\n            self.doRead(context)\n        }\n    }\n\n    private func doRead(_ context: ChannelHandlerContext) {\n        // Reset the backoff time and read.\n        self.nextReadDeadlineNS = nil\n        self.scheduledRead = nil\n        context.read()\n    }\n}\n\n@available(*, unavailable)\nextension AcceptBackoffHandler: Sendable {}\n\n/// ChannelHandler implementation which enforces back-pressure by stopping to read from the remote peer when it cannot write back fast enough.\n/// It will start reading again once pending data was written.\npublic final class BackPressureHandler: ChannelDuplexHandler, RemovableChannelHandler {\n    public typealias OutboundIn = NIOAny\n    public typealias InboundIn = ByteBuffer\n    public typealias InboundOut = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n\n    private var pendingRead = false\n    private var writable: Bool = true\n\n    public init() {}\n\n    public func read(context: ChannelHandlerContext) {\n        if writable {\n            context.read()\n        } else {\n            pendingRead = true\n        }\n    }\n\n    public func channelWritabilityChanged(context: ChannelHandlerContext) {\n        self.writable = context.channel.isWritable\n        if writable {\n            mayRead(context: context)\n        } else {\n            context.flush()\n        }\n\n        // Propagate the event as the user may still want to do something based on it.\n        context.fireChannelWritabilityChanged()\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        mayRead(context: context)\n    }\n\n    private func mayRead(context: ChannelHandlerContext) {\n        if pendingRead {\n            pendingRead = false\n            context.read()\n        }\n    }\n}\n\n@available(*, unavailable)\nextension BackPressureHandler: Sendable {}\n\n/// Triggers an IdleStateEvent when a Channel has not performed read, write, or both operation for a while.\npublic final class IdleStateHandler: ChannelDuplexHandler, RemovableChannelHandler {\n    public typealias InboundIn = NIOAny\n    public typealias InboundOut = NIOAny\n    public typealias OutboundIn = NIOAny\n    public typealias OutboundOut = NIOAny\n\n    ///A user event triggered by IdleStateHandler when a Channel is idle.\n    public enum IdleStateEvent: Sendable {\n        /// Will be triggered when no write was performed for the specified amount of time\n        case write\n        /// Will be triggered when no read was performed for the specified amount of time\n        case read\n        /// Will be triggered when neither read nor write was performed for the specified amount of time\n        case all\n    }\n\n    public let readTimeout: TimeAmount?\n    public let writeTimeout: TimeAmount?\n    public let allTimeout: TimeAmount?\n\n    private var reading = false\n    private var lastReadTime: NIODeadline = .distantPast\n    private var lastWriteCompleteTime: NIODeadline = .distantPast\n    private var scheduledReaderTask: Optional<Scheduled<Void>>\n    private var scheduledWriterTask: Optional<Scheduled<Void>>\n    private var scheduledAllTask: Optional<Scheduled<Void>>\n\n    public init(readTimeout: TimeAmount? = nil, writeTimeout: TimeAmount? = nil, allTimeout: TimeAmount? = nil) {\n        self.readTimeout = readTimeout\n        self.writeTimeout = writeTimeout\n        self.allTimeout = allTimeout\n        self.scheduledAllTask = nil\n        self.scheduledReaderTask = nil\n        self.scheduledWriterTask = nil\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        if context.channel.isActive {\n            initIdleTasks(context)\n        }\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        cancelIdleTasks(context)\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n        initIdleTasks(context)\n        context.fireChannelActive()\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        if readTimeout != nil || allTimeout != nil {\n            reading = true\n        }\n        context.fireChannelRead(data)\n    }\n\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        if (readTimeout != nil || allTimeout != nil) && reading {\n            lastReadTime = .now()\n            reading = false\n        }\n        context.fireChannelReadComplete()\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if writeTimeout == nil && allTimeout == nil {\n            context.write(data, promise: promise)\n            return\n        }\n\n        let writePromise = promise ?? context.eventLoop.makePromise()\n        writePromise.futureResult.hop(\n            to: context.eventLoop\n        ).assumeIsolatedUnsafeUnchecked().whenComplete { (_: Result<Void, Error>) in\n            self.lastWriteCompleteTime = .now()\n        }\n        context.write(data, promise: writePromise)\n    }\n\n    private func shouldReschedule(_ context: ChannelHandlerContext) -> Bool {\n        if context.channel.isActive {\n            return true\n        }\n        return false\n    }\n\n    private func makeReadTimeoutTask(_ context: ChannelHandlerContext, _ timeout: TimeAmount) -> (() -> Void) {\n        {\n            guard self.shouldReschedule(context) else {\n                return\n            }\n\n            if self.reading {\n                self.scheduledReaderTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    in: timeout,\n                    self.makeReadTimeoutTask(context, timeout)\n                )\n                return\n            }\n\n            let diff = .now() - self.lastReadTime\n            if diff >= timeout {\n                // Reader is idle - set a new timeout and trigger an event through the pipeline\n                self.scheduledReaderTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    in: timeout,\n                    self.makeReadTimeoutTask(context, timeout)\n                )\n\n                context.fireUserInboundEventTriggered(IdleStateEvent.read)\n            } else {\n                // Read occurred before the timeout - set a new timeout with shorter delay.\n                self.scheduledReaderTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    deadline: self.lastReadTime + timeout,\n                    self.makeReadTimeoutTask(context, timeout)\n                )\n            }\n        }\n    }\n\n    private func makeWriteTimeoutTask(_ context: ChannelHandlerContext, _ timeout: TimeAmount) -> (() -> Void) {\n        {\n            guard self.shouldReschedule(context) else {\n                return\n            }\n\n            let lastWriteTime = self.lastWriteCompleteTime\n            let diff = .now() - lastWriteTime\n\n            if diff >= timeout {\n                // Writer is idle - set a new timeout and notify the callback.\n                self.scheduledWriterTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    in: timeout,\n                    self.makeWriteTimeoutTask(context, timeout)\n                )\n\n                context.fireUserInboundEventTriggered(IdleStateEvent.write)\n            } else {\n                // Write occurred before the timeout - set a new timeout with shorter delay.\n                self.scheduledWriterTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    deadline: self.lastWriteCompleteTime + timeout,\n                    self.makeWriteTimeoutTask(context, timeout)\n                )\n            }\n        }\n    }\n\n    private func makeAllTimeoutTask(_ context: ChannelHandlerContext, _ timeout: TimeAmount) -> (() -> Void) {\n        {\n            guard self.shouldReschedule(context) else {\n                return\n            }\n\n            if self.reading {\n                self.scheduledReaderTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    in: timeout,\n                    self.makeAllTimeoutTask(context, timeout)\n                )\n                return\n            }\n            let lastRead = self.lastReadTime\n            let lastWrite = self.lastWriteCompleteTime\n            let latestLast = max(lastRead, lastWrite)\n\n            let diff = .now() - latestLast\n            if diff >= timeout {\n                // Reader is idle - set a new timeout and trigger an event through the pipeline\n                self.scheduledReaderTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    in: timeout,\n                    self.makeAllTimeoutTask(context, timeout)\n                )\n\n                context.fireUserInboundEventTriggered(IdleStateEvent.all)\n            } else {\n                // Read occurred before the timeout - set a new timeout with shorter delay.\n                self.scheduledReaderTask = context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(\n                    deadline: latestLast + timeout,\n                    self.makeAllTimeoutTask(context, timeout)\n                )\n            }\n        }\n    }\n\n    private func schedule(\n        _ context: ChannelHandlerContext,\n        _ amount: TimeAmount?,\n        _ body: @escaping (ChannelHandlerContext, TimeAmount) -> (() -> Void)\n    ) -> Scheduled<Void>? {\n        if let timeout = amount {\n            return context.eventLoop.assumeIsolatedUnsafeUnchecked().scheduleTask(in: timeout, body(context, timeout))\n        }\n        return nil\n    }\n\n    private func initIdleTasks(_ context: ChannelHandlerContext) {\n        let now = NIODeadline.now()\n        lastReadTime = now\n        lastWriteCompleteTime = now\n        scheduledReaderTask = schedule(context, readTimeout, makeReadTimeoutTask)\n        scheduledWriterTask = schedule(context, writeTimeout, makeWriteTimeoutTask)\n        scheduledAllTask = schedule(context, allTimeout, makeAllTimeoutTask)\n    }\n\n    private func cancelIdleTasks(_ context: ChannelHandlerContext) {\n        scheduledReaderTask?.cancel()\n        scheduledWriterTask?.cancel()\n        scheduledAllTask?.cancel()\n        scheduledReaderTask = nil\n        scheduledWriterTask = nil\n        scheduledAllTask = nil\n    }\n}\n\n@available(*, unavailable)\nextension IdleStateHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/ChannelInvoker.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n/// Allows users to invoke an \"outbound\" operation related to a `Channel` that will flow through the `ChannelPipeline` until\n/// it will finally be executed by the the `ChannelCore` implementation.\npublic protocol ChannelOutboundInvoker {\n\n    /// Register on an `EventLoop` and so have all its IO handled.\n    ///\n    /// - Parameters:\n    ///   - promise: the `EventLoopPromise` that will be notified once the operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    func register(promise: EventLoopPromise<Void>?)\n\n    /// Bind to a `SocketAddress`.\n    /// - Parameters:\n    ///   - to: the `SocketAddress` to which we should bind the `Channel`.\n    ///   - promise: the `EventLoopPromise` that will be notified once the operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    func bind(to: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    /// Connect to a `SocketAddress`.\n    /// - Parameters:\n    ///   - to: the `SocketAddress` to which we should connect the `Channel`.\n    ///   - promise: the `EventLoopPromise` that will be notified once the operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    func connect(to: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    /// Write data to the remote peer.\n    ///\n    /// Be aware that to be sure that data is really written to the remote peer you need to call `flush` or use `writeAndFlush`.\n    /// Calling `write` multiple times and then `flush` may allow the `Channel` to `write` multiple data objects to the remote peer with one syscall.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - promise: the `EventLoopPromise` that will be notified once the operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    func write(_ data: NIOAny, promise: EventLoopPromise<Void>?)\n\n    /// Flush data that was previously written via `write` to the remote peer.\n    func flush()\n\n    /// Shortcut for calling `write` and `flush`.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - promise: the `EventLoopPromise` that will be notified once the `write` operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    func writeAndFlush(_ data: NIOAny, promise: EventLoopPromise<Void>?)\n\n    /// Signal that we want to read from the `Channel` once there is data ready.\n    ///\n    /// If `ChannelOptions.autoRead` is set for a `Channel` (which is the default) this method is automatically invoked by the transport implementation,\n    /// otherwise it's the user's responsibility to call this method manually once new data should be read and processed.\n    ///\n    func read()\n\n    /// Close the `Channel` and so the connection if one exists.\n    ///\n    /// - Parameters:\n    ///   - mode: the `CloseMode` that is used\n    ///   - promise: the `EventLoopPromise` that will be notified once the operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    func close(mode: CloseMode, promise: EventLoopPromise<Void>?)\n\n    /// Trigger a custom user outbound event which will flow through the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - event: The event itself.\n    ///   - promise: the `EventLoopPromise` that will be notified once the operation completes,\n    ///                or `nil` if not interested in the outcome of the operation.\n    @preconcurrency\n    func triggerUserOutboundEvent(_ event: Any & Sendable, promise: EventLoopPromise<Void>?)\n\n    /// The `EventLoop` which is used by this `ChannelOutboundInvoker` for execution.\n    var eventLoop: EventLoop { get }\n}\n\n/// Extra `ChannelOutboundInvoker` methods. Each method that returns a `EventLoopFuture` will just do the following:\n///   - create a new `EventLoopPromise<Void>`\n///   - call the corresponding method that takes a `EventLoopPromise<Void>`\n///   - return `EventLoopPromise.futureResult`\nextension ChannelOutboundInvoker {\n\n    /// Register on an `EventLoop` and so have all its IO handled.\n    /// - Parameters:\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    public func register(file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Void> {\n        let promise = makePromise(file: file, line: line)\n        register(promise: promise)\n        return promise.futureResult\n    }\n\n    /// Bind to a `SocketAddress`.\n    /// - Parameters:\n    ///   - address: the `SocketAddress` to which we should bind the `Channel`.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    public func bind(\n        to address: SocketAddress,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<Void> {\n        let promise = makePromise(file: file, line: line)\n        bind(to: address, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Connect to a `SocketAddress`.\n    /// - Parameters:\n    ///   - address: the `SocketAddress` to which we should connect the `Channel`.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    public func connect(\n        to address: SocketAddress,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<Void> {\n        let promise = makePromise(file: file, line: line)\n        connect(to: address, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Write data to the remote peer.\n    ///\n    /// Be aware that to be sure that data is really written to the remote peer you need to call `flush` or use `writeAndFlush`.\n    /// Calling `write` multiple times and then `flush` may allow the `Channel` to `write` multiple data objects to the remote peer with one syscall.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func write(_ data: NIOAny, file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Void> {\n        let promise = makePromise(file: file, line: line)\n        write(data, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Shortcut for calling `write` and `flush`.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the `write` operation completes.\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func writeAndFlush(_ data: NIOAny, file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Void>\n    {\n        let promise = makePromise(file: file, line: line)\n        writeAndFlush(data, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Close the `Channel` and so the connection if one exists.\n    ///\n    /// - Parameters:\n    ///   - mode: the `CloseMode` that is used\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    public func close(mode: CloseMode = .all, file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Void>\n    {\n        let promise = makePromise(file: file, line: line)\n        self.close(mode: mode, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Trigger a custom user outbound event which will flow through the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - event: the event itself.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    @preconcurrency\n    public func triggerUserOutboundEvent(\n        _ event: Any & Sendable,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<Void> {\n        let promise = makePromise(file: file, line: line)\n        triggerUserOutboundEvent(event, promise: promise)\n        return promise.futureResult\n    }\n\n    private func makePromise(file: StaticString = #fileID, line: UInt = #line) -> EventLoopPromise<Void> {\n        eventLoop.makePromise(file: file, line: line)\n    }\n}\n\n/// Fire inbound events related to a `Channel` through the `ChannelPipeline` until its end is reached or it's consumed by a `ChannelHandler`.\npublic protocol ChannelInboundInvoker {\n\n    /// Called once a `Channel` was registered to its `EventLoop` and so IO will be processed.\n    func fireChannelRegistered()\n\n    /// Called once a `Channel` was unregistered from its `EventLoop` which means no IO will be handled for a `Channel` anymore.\n    func fireChannelUnregistered()\n\n    /// Called once a `Channel` becomes active.\n    ///\n    /// What active means depends on the `Channel` implementation and semantics.\n    /// For example for TCP it means the `Channel` is connected to the remote peer.\n    func fireChannelActive()\n\n    /// Called once a `Channel` becomes inactive.\n    ///\n    /// What inactive means depends on the `Channel` implementation and semantics.\n    /// For example for TCP it means the `Channel` was disconnected from the remote peer and closed.\n    func fireChannelInactive()\n\n    /// Called once there is some data read for a `Channel` that needs processing.\n    ///\n    /// - Parameters:\n    ///   - data: the data that was read and is ready to be processed.\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    func fireChannelRead(_ data: NIOAny)\n\n    /// Called once there is no more data to read immediately on a `Channel`. Any new data received will be handled later.\n    func fireChannelReadComplete()\n\n    /// Called when a `Channel`'s writable state changes.\n    ///\n    /// The writability state of a Channel depends on watermarks that can be set via `Channel.setOption` and how much data\n    /// is still waiting to be transferred to the remote peer.\n    /// You should take care to enforce some kind of backpressure if the channel becomes unwritable which means `Channel.isWritable`\n    /// will return `false` to ensure you do not consume too much memory due to queued writes. What exactly you should do here depends on the\n    /// protocol and other semantics. But for example you may want to stop writing to the `Channel` until `Channel.writable` becomes\n    /// `true` again or stop reading at all.\n    func fireChannelWritabilityChanged()\n\n    /// Called when an inbound operation `Error` was caught.\n    ///\n    /// Be aware that for inbound operations this method is called while for outbound operations defined in `ChannelOutboundInvoker`\n    /// the `EventLoopFuture` or `EventLoopPromise` will be notified.\n    ///\n    /// - Parameters:\n    ///   - error: the error we encountered.\n    func fireErrorCaught(_ error: Error)\n\n    /// Trigger a custom user inbound event which will flow through the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - event: the event itself.\n    @preconcurrency\n    func fireUserInboundEventTriggered(_ event: Any & Sendable)\n}\n\n/// A protocol that signals that outbound and inbound events are triggered by this invoker.\npublic protocol ChannelInvoker: ChannelOutboundInvoker, ChannelInboundInvoker {}\n\n/// Specify what kind of close operation is requested.\npublic enum CloseMode: Sendable {\n    /// Close the output (writing) side of the `Channel` without closing the actual file descriptor.\n    /// This is an optional mode which means it may not be supported by all `Channel` implementations.\n    case output\n\n    /// Close the input (reading) side of the `Channel` without closing the actual file descriptor.\n    /// This is an optional mode which means it may not be supported by all `Channel` implementations.\n    case input\n\n    /// Close the whole `Channel (file descriptor).\n    case all\n}\n"
  },
  {
    "path": "Sources/NIOCore/ChannelOption.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A configuration option that can be set on a `Channel` to configure different behaviour.\npublic protocol ChannelOption: Equatable, _NIOPreconcurrencySendable {\n    /// The type of the `ChannelOption`'s value.\n    associatedtype Value: Sendable\n}\n\npublic typealias SocketOptionName = Int32\n#if (os(Linux) || os(Android)) && !canImport(Musl)\npublic typealias SocketOptionLevel = Int\npublic typealias SocketOptionValue = Int\n#else\npublic typealias SocketOptionLevel = CInt\npublic typealias SocketOptionValue = CInt\n#endif\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.SocketOption\")\npublic typealias SocketOption = ChannelOptions.Types.SocketOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.AllocatorOption\")\npublic typealias AllocatorOption = ChannelOptions.Types.AllocatorOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.RecvAllocatorOption\")\npublic typealias RecvAllocatorOption = ChannelOptions.Types.RecvAllocatorOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.AutoReadOption\")\npublic typealias AutoReadOption = ChannelOptions.Types.AutoReadOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.WriteSpinOption\")\npublic typealias WriteSpinOption = ChannelOptions.Types.WriteSpinOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.MaxMessagesPerReadOption\")\npublic typealias MaxMessagesPerReadOption = ChannelOptions.Types.MaxMessagesPerReadOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.BacklogOption\")\npublic typealias BacklogOption = ChannelOptions.Types.BacklogOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.DatagramVectorReadMessageCountOption\")\npublic typealias DatagramVectorReadMessageCountOption = ChannelOptions.Types.DatagramVectorReadMessageCountOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.WriteBufferWaterMark\")\npublic typealias WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.WriteBufferWaterMarkOption\")\npublic typealias WriteBufferWaterMarkOption = ChannelOptions.Types.WriteBufferWaterMarkOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.ConnectTimeoutOption\")\npublic typealias ConnectTimeoutOption = ChannelOptions.Types.ConnectTimeoutOption\n\n@available(*, deprecated, renamed: \"ChannelOptions.Types.AllowRemoteHalfClosureOption\")\npublic typealias AllowRemoteHalfClosureOption = ChannelOptions.Types.AllowRemoteHalfClosureOption\n\nextension ChannelOptions {\n    public enum Types: Sendable {\n\n        /// `SocketOption` allows users to specify configuration settings that are directly applied to the underlying socket file descriptor.\n        ///\n        /// Valid options are typically found in the various man pages like `man 4 tcp`.\n        public struct SocketOption: ChannelOption, Equatable, Sendable {\n            public typealias Value = (SocketOptionValue)\n\n            public var optionLevel: NIOBSDSocket.OptionLevel\n            public var optionName: NIOBSDSocket.Option\n\n            public var level: SocketOptionLevel {\n                get {\n                    SocketOptionLevel(optionLevel.rawValue)\n                }\n                set {\n                    self.optionLevel = NIOBSDSocket.OptionLevel(rawValue: CInt(newValue))\n                }\n            }\n            public var name: SocketOptionName {\n                get {\n                    SocketOptionName(optionName.rawValue)\n                }\n                set {\n                    self.optionName = NIOBSDSocket.Option(rawValue: CInt(newValue))\n                }\n            }\n\n            #if !os(Windows)\n            /// Create a new `SocketOption`.\n            ///\n            /// - Parameters:\n            ///   - level: The level for the option as defined in `man setsockopt`, e.g. SO_SOCKET.\n            ///   - name: The name of the option as defined in `man setsockopt`, e.g. `SO_REUSEADDR`.\n            public init(level: SocketOptionLevel, name: SocketOptionName) {\n                self.optionLevel = NIOBSDSocket.OptionLevel(rawValue: CInt(level))\n                self.optionName = NIOBSDSocket.Option(rawValue: CInt(name))\n            }\n            #endif\n\n            /// Create a new `SocketOption`.\n            ///\n            /// - Parameters:\n            ///   - level: The level for the option as defined in `man setsockopt`, e.g. SO_SOCKET.\n            ///   - name: The name of the option as defined in `man setsockopt`, e.g. `SO_REUSEADDR`.\n            public init(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) {\n                self.optionLevel = level\n                self.optionName = name\n            }\n        }\n\n        /// `AllocatorOption` allows to specify the `ByteBufferAllocator` to use.\n        public struct AllocatorOption: ChannelOption, Sendable {\n            public typealias Value = ByteBufferAllocator\n\n            public init() {}\n        }\n\n        /// `RecvAllocatorOption` allows users to specify the `RecvByteBufferAllocator` to use.\n        public struct RecvAllocatorOption: ChannelOption, Sendable {\n            public typealias Value = RecvByteBufferAllocator\n\n            public init() {}\n        }\n\n        /// `AutoReadOption` allows users to configure if a `Channel` should automatically call `Channel.read` again once all data was read from the transport or\n        /// if the user is responsible to call `Channel.read` manually.\n        public struct AutoReadOption: ChannelOption, Sendable {\n            public typealias Value = Bool\n\n            public init() {}\n        }\n\n        /// `WriteSpinOption` allows users to configure the number of repetitions of a only partially successful write call before considering the `Channel` not writable.\n        /// Setting this option to `0` means that we only issue one write call and if that call does not write all the bytes,\n        /// we consider the `Channel` not writable.\n        public struct WriteSpinOption: ChannelOption, Sendable {\n            public typealias Value = UInt\n\n            public init() {}\n        }\n\n        /// `MaxMessagesPerReadOption` allows users to configure the maximum number of read calls to the underlying transport are performed before wait again until\n        /// there is more to read and be notified.\n        public struct MaxMessagesPerReadOption: ChannelOption, Sendable {\n            public typealias Value = UInt\n\n            public init() {}\n        }\n\n        /// `BacklogOption` allows users to configure the `backlog` value as specified in `man 2 listen`. This is only useful for `ServerSocketChannel`s.\n        public struct BacklogOption: ChannelOption, Sendable {\n            public typealias Value = Int32\n\n            public init() {}\n        }\n\n        /// `DatagramVectorReadMessageCountOption` allows users to configure the number of messages to attempt to read in a single syscall on a\n        /// datagram `Channel`.\n        ///\n        /// Some datagram `Channel`s have extremely high datagram throughput. This can occur when the single datagram socket is encapsulating\n        /// many logical \"connections\" (e.g. with QUIC) or when the datagram socket is simply serving an enormous number of consumers (e.g.\n        /// with a public-facing DNS server). In this case the overhead of one syscall per datagram is profoundly limiting. Using this\n        /// `ChannelOption` allows the `Channel` to read multiple datagrams at once.\n        ///\n        /// Note that simply increasing this number will not necessarily bring performance gains and may in fact cause data loss. Any increase\n        /// to this should be matched by increasing the size of the buffers allocated by the `Channel` `RecvByteBufferAllocator` (as set by\n        /// `ChannelOption.recvAllocator`) proportionally. For example, to receive 10 messages at a time, set the size of the buffers allocated\n        /// by the `RecvByteBufferAllocator` to at least 10x the size of the maximum datagram size you wish to receive.\n        ///\n        /// Naturally, this option is only valid on datagram channels.\n        ///\n        /// This option only works on the following platforms:\n        ///\n        /// - Linux\n        /// - FreeBSD\n        /// - Android\n        ///\n        /// On all other platforms, setting it has no effect.\n        ///\n        /// Set this option to 0 to disable vector reads and to use serial reads instead.\n        public struct DatagramVectorReadMessageCountOption: ChannelOption, Sendable {\n            public typealias Value = Int\n\n            public init() {}\n        }\n\n        /// ``DatagramSegmentSize`` controls the `UDP_SEGMENT` socket option (sometimes reffered to as 'GSO') which allows for\n        /// large writes to be sent via `sendmsg` and `sendmmsg` and segmented into separate datagrams by the kernel (or in some cases, the NIC).\n        /// The size of segments the large write is split into is controlled by the value of this option (note that writes do not need to be a\n        /// multiple of this option).\n        ///\n        /// This option is currently only supported on Linux (4.18 and newer). Support can be checked using ``System/supportsUDPSegmentationOffload``.\n        ///\n        /// Setting this option to zero disables segmentation offload.\n        public struct DatagramSegmentSize: ChannelOption, Sendable {\n            public typealias Value = CInt\n            public init() {}\n        }\n\n        /// ``DatagramReceiveOffload`` sets the `UDP_GRO` socket option which allows for datagrams to be accumulated\n        /// by the kernel (or in some cases, the NIC) and reduces traversals in the kernel's networking layer.\n        ///\n        /// This option is currently only supported on Linux (5.10 and newer). Support can be checked\n        /// using ``System/supportsUDPReceiveOffload``.\n        ///\n        /// - Note: users should ensure they use an appropriate receive buffer allocator when enabling this option.\n        ///   The default allocator for datagram channels uses fixed sized buffers of 2048 bytes.\n        public struct DatagramReceiveOffload: ChannelOption, Sendable {\n            public typealias Value = Bool\n            public init() {}\n        }\n\n        /// ``DatagramReceiveSegmentSize`` enables per-message GRO (Generic Receive Offload) segment size reporting.\n        /// When enabled, the kernel will provide the original segment size via control messages for aggregated datagrams,\n        /// which will be reported in `AddressedEnvelope.Metadata.segmentSize`.\n        ///\n        /// This option requires ``DatagramReceiveOffload`` to be enabled first and is only supported on Linux.\n        /// Support can be checked using ``System/supportsUDPReceiveOffload``.\n        ///\n        /// - Note: This provides the receive-side complement to per-message GSO (``AddressedEnvelope/Metadata/segmentSize``).\n        public struct DatagramReceiveSegmentSize: ChannelOption, Sendable {\n            public typealias Value = Bool\n            public init() {}\n        }\n\n        /// When set to true IP level ECN information will be reported through `AddressedEnvelope.Metadata`\n        public struct ExplicitCongestionNotificationsOption: ChannelOption, Sendable {\n            public typealias Value = Bool\n            public init() {}\n        }\n\n        /// The watermark used to detect when `Channel.isWritable` returns `true` or `false`.\n        public struct WriteBufferWaterMark: Sendable {\n            /// The low mark setting for a `Channel`.\n            ///\n            /// When the amount of buffered bytes in the `Channel`s outbound buffer drops below this value the `Channel` will be\n            /// marked as writable again (after it was non-writable).\n            public let low: Int\n\n            /// The high mark setting for a `Channel`.\n            ///\n            /// When the amount of buffered bytes in the `Channel`s outbound exceeds this value the `Channel` will be\n            /// marked as non-writable. It will be marked as writable again once the amount of buffered bytes drops below `low`.\n            public let high: Int\n\n            /// Create a new instance.\n            ///\n            /// Valid initialization is restricted to `1 <= low <= high`.\n            ///\n            /// - Parameters:\n            ///      - low: The low watermark.\n            ///      - high: The high watermark.\n            public init(low: Int, high: Int) {\n                precondition(low >= 1, \"low must be >= 1 but was \\(low)\")\n                precondition(high >= low, \"low must be <= high, but was low: \\(low) high: \\(high)\")\n                self.low = low\n                self.high = high\n            }\n        }\n\n        /// `WriteBufferWaterMarkOption` allows users to configure when a `Channel` should be marked as writable or not. Once the amount of bytes queued in a\n        /// `Channel`s outbound buffer is larger than `WriteBufferWaterMark.high` the channel will be marked as non-writable and so\n        /// `Channel.isWritable` will return `false`. Once we were able to write some data out of the outbound buffer and the amount of bytes queued\n        /// falls below `WriteBufferWaterMark.low` the `Channel` will become writable again. Once this happens `Channel.writable` will return\n        /// `true` again. These writability changes are also propagated through the `ChannelPipeline` and so can be intercepted via `ChannelInboundHandler.channelWritabilityChanged`.\n        public struct WriteBufferWaterMarkOption: ChannelOption, Sendable {\n            public typealias Value = WriteBufferWaterMark\n\n            public init() {}\n        }\n\n        /// `ConnectTimeoutOption` allows users to configure the `TimeAmount` after which a connect will fail if it was not established in the meantime. May be\n        /// `nil`, in which case the connection attempt will never time out.\n        public struct ConnectTimeoutOption: ChannelOption, Sendable {\n            public typealias Value = TimeAmount?\n\n            public init() {}\n        }\n\n        /// `AllowRemoteHalfClosureOption` allows users to configure whether the `Channel` will close itself when its remote\n        /// peer shuts down its send stream, or whether it will remain open. If set to `false` (the default), the `Channel`\n        /// will be closed automatically if the remote peer shuts down its send stream. If set to true, the `Channel` will\n        /// not be closed: instead, a `ChannelEvent.inboundClosed` user event will be sent on the `ChannelPipeline`,\n        /// and no more data will be received.\n        public struct AllowRemoteHalfClosureOption: ChannelOption, Sendable {\n            public typealias Value = Bool\n\n            public init() {}\n        }\n\n        /// When set to true IP level Packet Info information will be reported through `AddressedEnvelope.Metadata` for UDP packets.\n        public struct ReceivePacketInfo: ChannelOption, Sendable {\n            public typealias Value = Bool\n            public init() {}\n        }\n\n        /// `BufferedWritableBytesOption` allows users to know the number of writable bytes currently buffered in the `Channel`.\n        public struct BufferedWritableBytesOption: ChannelOption, Sendable {\n            public typealias Value = Int\n\n            public init() {}\n        }\n    }\n}\n\n/// Provides `ChannelOption`s to be used with a `Channel`, `Bootstrap` or `ServerBootstrap`.\npublic struct ChannelOptions: Sendable {\n    #if !os(Windows)\n    public static let socket: @Sendable (SocketOptionLevel, SocketOptionName) -> ChannelOptions.Types.SocketOption = {\n        (level: SocketOptionLevel, name: SocketOptionName) -> Types.SocketOption in\n        .init(level: NIOBSDSocket.OptionLevel(rawValue: CInt(level)), name: NIOBSDSocket.Option(rawValue: CInt(name)))\n    }\n    #endif\n\n    /// - seealso: `SocketOption`.\n    public static let socketOption: @Sendable (NIOBSDSocket.Option) -> ChannelOptions.Types.SocketOption = {\n        (name: NIOBSDSocket.Option) -> Types.SocketOption in\n        .init(level: .socket, name: name)\n    }\n\n    /// - seealso: `SocketOption`.\n    public static let ipOption: @Sendable (NIOBSDSocket.Option) -> ChannelOptions.Types.SocketOption = {\n        (name: NIOBSDSocket.Option) -> Types.SocketOption in\n        .init(level: .ip, name: name)\n    }\n\n    /// - seealso: `SocketOption`.\n    public static let tcpOption: @Sendable (NIOBSDSocket.Option) -> ChannelOptions.Types.SocketOption = {\n        (name: NIOBSDSocket.Option) -> Types.SocketOption in\n        .init(level: .tcp, name: name)\n    }\n\n    /// - seealso: `AllocatorOption`.\n    public static let allocator = Types.AllocatorOption()\n\n    /// - seealso: `RecvAllocatorOption`.\n    public static let recvAllocator = Types.RecvAllocatorOption()\n\n    /// - seealso: `AutoReadOption`.\n    public static let autoRead = Types.AutoReadOption()\n\n    /// - seealso: `MaxMessagesPerReadOption`.\n    public static let maxMessagesPerRead = Types.MaxMessagesPerReadOption()\n\n    /// - seealso: `BacklogOption`.\n    public static let backlog = Types.BacklogOption()\n\n    /// - seealso: `WriteSpinOption`.\n    public static let writeSpin = Types.WriteSpinOption()\n\n    /// - seealso: `WriteBufferWaterMarkOption`.\n    public static let writeBufferWaterMark = Types.WriteBufferWaterMarkOption()\n\n    /// - seealso: `ConnectTimeoutOption`.\n    public static let connectTimeout = Types.ConnectTimeoutOption()\n\n    /// - seealso: `AllowRemoteHalfClosureOption`.\n    public static let allowRemoteHalfClosure = Types.AllowRemoteHalfClosureOption()\n\n    /// - seealso: `DatagramVectorReadMessageCountOption`\n    public static let datagramVectorReadMessageCount = Types.DatagramVectorReadMessageCountOption()\n\n    /// - seealso: `DatagramSegmentSize`\n    public static let datagramSegmentSize = Types.DatagramSegmentSize()\n\n    /// - seealso: `DatagramReceiveOffload`\n    public static let datagramReceiveOffload = Types.DatagramReceiveOffload()\n\n    /// - seealso: `DatagramReceiveSegmentSize`\n    public static let datagramReceiveSegmentSize = Types.DatagramReceiveSegmentSize()\n\n    /// - seealso: `ExplicitCongestionNotificationsOption`\n    public static let explicitCongestionNotification = Types.ExplicitCongestionNotificationsOption()\n\n    /// - seealso: `ReceivePacketInfo`\n    public static let receivePacketInfo = Types.ReceivePacketInfo()\n\n    /// - seealso: `BufferedWritableBytesOption`\n    public static let bufferedWritableBytes = Types.BufferedWritableBytesOption()\n}\n\n/// - seealso: `SocketOption`.\nextension ChannelOption where Self == ChannelOptions.Types.SocketOption {\n    #if !(os(Windows))\n    public static func socket(_ level: SocketOptionLevel, _ name: SocketOptionName) -> Self {\n        .init(level: NIOBSDSocket.OptionLevel(rawValue: CInt(level)), name: NIOBSDSocket.Option(rawValue: CInt(name)))\n    }\n    #endif\n\n    public static func socketOption(_ name: NIOBSDSocket.Option) -> Self {\n        .init(level: .socket, name: name)\n    }\n\n    public static func ipOption(_ name: NIOBSDSocket.Option) -> Self {\n        .init(level: .ip, name: name)\n    }\n\n    public static func tcpOption(_ name: NIOBSDSocket.Option) -> Self {\n        .init(level: .tcp, name: name)\n    }\n}\n\n/// - seealso: `AllocatorOption`.\nextension ChannelOption where Self == ChannelOptions.Types.AllocatorOption {\n    public static var allocator: Self { .init() }\n}\n\n/// - seealso: `RecvAllocatorOption`.\nextension ChannelOption where Self == ChannelOptions.Types.RecvAllocatorOption {\n    public static var recvAllocator: Self { .init() }\n}\n\n/// - seealso: `AutoReadOption`.\nextension ChannelOption where Self == ChannelOptions.Types.AutoReadOption {\n    public static var autoRead: Self { .init() }\n}\n\n/// - seealso: `MaxMessagesPerReadOption`.\nextension ChannelOption where Self == ChannelOptions.Types.MaxMessagesPerReadOption {\n    public static var maxMessagesPerRead: Self { .init() }\n}\n\n/// - seealso: `BacklogOption`.\nextension ChannelOption where Self == ChannelOptions.Types.BacklogOption {\n    public static var backlog: Self { .init() }\n}\n\n/// - seealso: `WriteSpinOption`.\nextension ChannelOption where Self == ChannelOptions.Types.WriteSpinOption {\n    public static var writeSpin: Self { .init() }\n}\n\n/// - seealso: `WriteBufferWaterMarkOption`.\nextension ChannelOption where Self == ChannelOptions.Types.WriteBufferWaterMarkOption {\n    public static var writeBufferWaterMark: Self { .init() }\n}\n\n/// - seealso: `ConnectTimeoutOption`.\nextension ChannelOption where Self == ChannelOptions.Types.ConnectTimeoutOption {\n    public static var connectTimeout: Self { .init() }\n}\n\n/// - seealso: `AllowRemoteHalfClosureOption`.\nextension ChannelOption where Self == ChannelOptions.Types.AllowRemoteHalfClosureOption {\n    public static var allowRemoteHalfClosure: Self { .init() }\n}\n\n/// - seealso: `DatagramVectorReadMessageCountOption`.\nextension ChannelOption where Self == ChannelOptions.Types.DatagramVectorReadMessageCountOption {\n    public static var datagramVectorReadMessageCount: Self { .init() }\n}\n\n/// - seealso: `DatagramSegmentSize`.\nextension ChannelOption where Self == ChannelOptions.Types.DatagramSegmentSize {\n    public static var datagramSegmentSize: Self { .init() }\n}\n\n/// - seealso: `DatagramReceiveOffload`.\nextension ChannelOption where Self == ChannelOptions.Types.DatagramReceiveOffload {\n    public static var datagramReceiveOffload: Self { .init() }\n}\n\n/// - seealso: `DatagramReceiveSegmentSize`.\nextension ChannelOption where Self == ChannelOptions.Types.DatagramReceiveSegmentSize {\n    public static var datagramReceiveSegmentSize: Self { .init() }\n}\n\n/// - seealso: `ExplicitCongestionNotificationsOption`.\nextension ChannelOption where Self == ChannelOptions.Types.ExplicitCongestionNotificationsOption {\n    public static var explicitCongestionNotification: Self { .init() }\n}\n\n/// - seealso: `ReceivePacketInfo`.\nextension ChannelOption where Self == ChannelOptions.Types.ReceivePacketInfo {\n    public static var receivePacketInfo: Self { .init() }\n}\n\n/// - seealso: `BufferedWritableBytesOption`\nextension ChannelOption where Self == ChannelOptions.Types.BufferedWritableBytesOption {\n    public static var bufferedWritableBytes: Self { .init() }\n}\n\nextension ChannelOptions {\n    /// A type-safe storage facility for `ChannelOption`s. You will only ever need this if you implement your own\n    /// `Channel` that needs to store `ChannelOption`s.\n    public struct Storage: Sendable {\n        @usableFromInline\n        internal var _storage:\n            [(\n                any ChannelOption,\n                (any Sendable, @Sendable (Channel) -> (any ChannelOption, any Sendable) -> EventLoopFuture<Void>)\n            )]\n\n        public init() {\n            self._storage = []\n            self._storage.reserveCapacity(2)\n        }\n\n        /// Add `Options`, a `ChannelOption` to the `ChannelOptions.Storage`.\n        ///\n        /// - Parameters:\n        ///    - newKey: the key for the option\n        ///    - newValue: the value for the option\n        @inlinable\n        public mutating func append<Option: ChannelOption>(key newKey: Option, value newValue: Option.Value) {\n            @Sendable\n            func applier(_ t: Channel) -> (any ChannelOption, any Sendable) -> EventLoopFuture<Void> {\n                { (option, value) in\n                    t.setOption(option as! Option, value: value as! Option.Value)\n                }\n            }\n            var hasSet = false\n            self._storage = self._storage.map { currentKeyAndValue in\n                let (currentKey, _) = currentKeyAndValue\n                if let currentKey = currentKey as? Option, currentKey == newKey {\n                    hasSet = true\n                    return (currentKey, (newValue, applier))\n                } else {\n                    return currentKeyAndValue\n                }\n            }\n            if !hasSet {\n                self._storage.append((newKey, (newValue, applier)))\n            }\n        }\n\n        /// Apply all stored `ChannelOption`s to `Channel`.\n        ///\n        /// - Parameters:\n        ///    - channel: The `Channel` to apply the `ChannelOption`s to\n        /// - Returns:\n        ///    - An `EventLoopFuture` that is fulfilled when all `ChannelOption`s have been applied to the `Channel`.\n        public func applyAllChannelOptions(to channel: Channel) -> EventLoopFuture<Void> {\n            let applyPromise = channel.eventLoop.makePromise(of: Void.self)\n            let it = self._storage.makeIterator()\n\n            @Sendable\n            func applyNext(\n                iterator: IndexingIterator<\n                    [(\n                        any ChannelOption,\n                        (\n                            any Sendable,\n                            @Sendable (any Channel) -> (any ChannelOption, any Sendable) -> EventLoopFuture<Void>\n                        )\n                    )]\n                >\n            ) {\n                var iterator = iterator\n                guard let (key, (value, applier)) = iterator.next() else {\n                    // If we reached the end, everything is applied.\n                    applyPromise.succeed(())\n                    return\n                }\n                let it = iterator\n\n                applier(channel)(key, value).map {\n                    applyNext(\n                        iterator: it\n                    )\n                }.cascadeFailure(to: applyPromise)\n            }\n            applyNext(iterator: it)\n\n            return applyPromise.futureResult\n        }\n\n        /// Remove all options with the given `key`.\n        ///\n        /// Calling this function has the effect of removing all instances of a ``ChannelOption``\n        /// from the ``ChannelOptions/Storage``, as if none had been added. This is useful in rare\n        /// cases where a bootstrap knows that some configuration must purge options of a certain kind.\n        ///\n        /// - Parameters:\n        ///   - key: The ``ChannelOption`` to remove.\n        public mutating func remove<Option: ChannelOption>(key: Option) {\n            self._storage.removeAll(where: { existingKey, _ in\n                (existingKey as? Option) == key\n            })\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ChannelPipeline.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A list of `ChannelHandler`s that handle or intercept inbound events and outbound operations of a\n/// `Channel`. `ChannelPipeline` implements an advanced form of the Intercepting Filter pattern\n/// to give a user full control over how an event is handled and how the `ChannelHandler`s in a pipeline\n/// interact with each other.\n///\n/// # Creation of a pipeline\n///\n/// Each `Channel` has its own `ChannelPipeline` and it is created automatically when a new `Channel` is created.\n///\n/// # How an event flows in a pipeline\n///\n/// The following diagram describes how I/O events are typically processed by `ChannelHandler`s in a `ChannelPipeline`.\n/// An I/O event is handled by either a `ChannelInboundHandler` or a `ChannelOutboundHandler`\n/// and is forwarded to the next handler in the `ChannelPipeline` by calling the event propagation methods defined in\n/// `ChannelHandlerContext`, such as `ChannelHandlerContext.fireChannelRead` and\n/// `ChannelHandlerContext.write`.\n///\n/// ```\n///                                                    I/O Request\n///                                                    via `Channel` or\n///                                                    `ChannelHandlerContext`\n///                                                      |\n///  +---------------------------------------------------+---------------+\n///  |                           ChannelPipeline         |               |\n///  |                                TAIL              \\|/              |\n///  |    +---------------------+            +-----------+----------+    |\n///  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |              /|\\                                  |               |\n///  |               |                                  \\|/              |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |              /|\\                                  .               |\n///  |               .                                   .               |\n///  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|\n///  |        [ method call]                       [method call]         |\n///  |               .                                   .               |\n///  |               .                                  \\|/              |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |              /|\\                                  |               |\n///  |               |                                  \\|/              |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |              /|\\             HEAD                 |               |\n///  +---------------+-----------------------------------+---------------+\n///                  |                                  \\|/\n///  +---------------+-----------------------------------+---------------+\n///  |               |                                   |               |\n///  |       [ Socket.read ]                    [ Socket.write ]         |\n///  |                                                                   |\n///  |  SwiftNIO Internal I/O Threads (Transport Implementation)         |\n///  +-------------------------------------------------------------------+\n/// ```\n///\n/// An inbound event is handled by the inbound handlers in the head-to-tail direction as shown on the left side of the\n/// diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the\n/// diagram. The inbound data is often read from a remote peer via the actual input operation such as\n/// `Socket.read`. If an inbound event goes beyond the tail inbound handler, it is discarded\n/// silently, or logged if it needs your attention.\n///\n/// An outbound event is handled by the outbound handlers in the tail-to-head direction as shown on the right side of the\n/// diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests.\n/// If an outbound event goes beyond the head outbound handler, it is handled by an I/O thread associated with the\n/// `Channel`. The I/O thread often performs the actual output operation such as `Socket.write`.\n///\n///\n/// For example, let us assume that we created the following pipeline:\n///\n/// ```\n/// ChannelPipeline p = ...\n/// let future = p.add(name: \"1\", handler: InboundHandlerA()).flatMap {\n///   p.add(name: \"2\", handler: InboundHandlerB())\n/// }.flatMap {\n///   p.add(name: \"3\", handler: OutboundHandlerA())\n/// }.flatMap {\n///   p.add(name: \"4\", handler: OutboundHandlerB())\n/// }.flatMap {\n///   p.add(name: \"5\", handler: InboundOutboundHandlerX())\n/// }\n/// // Handle the future as well ....\n/// ```\n///\n/// In the example above, a class whose name starts with `Inbound` is an inbound handler.\n/// A class whose name starts with `Outbound` is an outbound handler.\n///\n/// In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound.\n/// When an event goes outbound, the order is 5, 4, 3, 2, 1.  On top of this principle, `ChannelPipeline` skips\n/// the evaluation of certain handlers to shorten the stack depth:\n///\n/// - 3 and 4 don't implement `ChannelInboundHandler`, and therefore the actual evaluation order of an inbound event will be: 1, 2, and 5.\n/// - 1 and 2 don't implement `ChannelOutboundHandler`, and therefore the actual evaluation order of a outbound event will be: 5, 4, and 3.\n/// - If 5 implements both `ChannelInboundHandler` and `ChannelOutboundHandler`, the evaluation order of an inbound and a outbound event could be 125 and 543 respectively.\n///\n/// - Note: Handlers may choose not to propagate messages down the pipeline immediately.  For example a handler may need to wait\n/// for additional data before sending a protocol event to the next handler in the pipeline.  Due to this you can't assume that later handlers\n/// in the pipeline will receive the same number of events as were sent, or that events of different types will arrive in the same order.\n/// For example - a user event could overtake a data event if a handler is aggregating data events before propagating but immediately\n/// propagating user events.\n///\n/// # Forwarding an event to the next handler\n///\n/// As you might noticed in the diagram above, a handler has to invoke the event propagation methods in\n/// `ChannelHandlerContext` to forward an event to its next handler.\n/// Those methods include:\n///\n/// - Inbound event propagation methods defined in `ChannelInboundInvoker`\n/// - Outbound event propagation methods defined in `ChannelOutboundInvoker`.\n///\n/// # Building a pipeline\n///\n/// A user is supposed to have one or more `ChannelHandler`s in a `ChannelPipeline` to receive I/O events (e.g. read) and\n/// to request I/O operations (e.g. write and close).  For example, a typical server will have the following handlers\n/// in each channel's pipeline, but your mileage may vary depending on the complexity and characteristics of the\n/// protocol and business logic:\n///\n/// - Protocol Decoder - translates binary data (e.g. `ByteBuffer`) into a struct / class\n/// - Protocol Encoder - translates a struct / class into binary data (e.g. `ByteBuffer`)\n/// - Business Logic Handler - performs the actual business logic (e.g. database access)\n///\n/// # Thread safety\n///\n/// A `ChannelHandler` can be added or removed at any time because a `ChannelPipeline` is thread safe.\npublic final class ChannelPipeline: ChannelInvoker {\n    private var head: Optional<ChannelHandlerContext>\n    private var tail: Optional<ChannelHandlerContext>\n\n    private var idx: Int = 0\n    internal private(set) var destroyed: Bool = false\n\n    /// The `EventLoop` that is used by the underlying `Channel`.\n    public let eventLoop: EventLoop\n\n    /// The `Channel` that this `ChannelPipeline` belongs to.\n    ///\n    /// - Note: This will be nil after the channel has closed\n    private var _channel: Optional<Channel>\n\n    /// The `Channel` that this `ChannelPipeline` belongs to.\n    @usableFromInline\n    internal var channel: Channel {\n        self.eventLoop.assertInEventLoop()\n        assert(self._channel != nil || self.destroyed)\n        return self._channel ?? DeadChannel(pipeline: self)\n    }\n\n    /// Add a `ChannelHandler` to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - name: the name to use for the `ChannelHandler` when it's added. If none is specified it will generate a name.\n    ///   - handler: the `ChannelHandler` to add\n    ///   - position: The position in the `ChannelPipeline` to add `handler`. Defaults to `.last`.\n    /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was added.\n    @preconcurrency\n    public func addHandler(\n        _ handler: ChannelHandler & Sendable,\n        name: String? = nil,\n        position: ChannelPipeline.Position = .last\n    ) -> EventLoopFuture<Void> {\n        let future: EventLoopFuture<Void>\n\n        if self.eventLoop.inEventLoop {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            future = self.eventLoop.makeCompletedFuture(\n                self.addHandlerSync(handler, name: name, position: syncPosition)\n            )\n        } else {\n            future = self.eventLoop.submit {\n                let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n                try self.addHandlerSync(handler, name: name, position: syncPosition).get()\n            }\n        }\n\n        return future\n    }\n\n    /// Synchronously add a `ChannelHandler` to the `ChannelPipeline`.\n    ///\n    /// May only be called from on the event loop.\n    ///\n    /// - Parameters:\n    ///   - handler: the `ChannelHandler` to add\n    ///   - name: the name to use for the `ChannelHandler` when it's added. If none is specified a name will be generated.\n    ///   - position: The position in the `ChannelPipeline` to add `handler`. Defaults to `.last`.\n    /// - Returns: the result of adding this handler - either success or failure with an error code if this could not be completed.\n    fileprivate func addHandlerSync(\n        _ handler: ChannelHandler,\n        name: String? = nil,\n        position: ChannelPipeline.SynchronousOperations.Position = .last\n    ) -> Result<Void, Error> {\n        self.eventLoop.assertInEventLoop()\n\n        if self.destroyed {\n            return .failure(ChannelError._ioOnClosedChannel)\n        }\n\n        switch position {\n        case .first:\n            return self.add0(\n                name: name,\n                handler: handler,\n                relativeContext: head!,\n                operation: self.add0(context:after:)\n            )\n        case .last:\n            return self.add0(\n                name: name,\n                handler: handler,\n                relativeContext: tail!,\n                operation: self.add0(context:before:)\n            )\n        case .before(let beforeHandler):\n            return self.add0(\n                name: name,\n                handler: handler,\n                relativeHandler: beforeHandler,\n                operation: self.add0(context:before:)\n            )\n        case .after(let afterHandler):\n            return self.add0(\n                name: name,\n                handler: handler,\n                relativeHandler: afterHandler,\n                operation: self.add0(context:after:)\n            )\n        }\n    }\n\n    /// Synchronously add a `ChannelHandler` to the pipeline, relative to another `ChannelHandler`,\n    /// where the insertion is done by a specific operation.\n    ///\n    /// May only be called from on the event loop.\n    ///\n    /// This will search the pipeline for `relativeHandler` and, if it cannot find it, will fail\n    /// `promise` with `ChannelPipelineError.notFound`.\n    ///\n    /// - Parameters:\n    ///   - name: The name to use for the `ChannelHandler` when its added. If none is specified, a name will be\n    ///         automatically generated.\n    ///   - handler: The `ChannelHandler` to add.\n    ///   - relativeHandler: The `ChannelHandler` already in the `ChannelPipeline` that `handler` will be\n    ///         inserted relative to.\n    ///   - operation: A callback that will insert `handler` relative to `relativeHandler`.\n    /// - Returns: the result of adding this handler - either success or failure with an error code if this could not be completed.\n    private func add0(\n        name: String?,\n        handler: ChannelHandler,\n        relativeHandler: ChannelHandler,\n        operation: (ChannelHandlerContext, ChannelHandlerContext) -> Void\n    ) -> Result<Void, Error> {\n        self.eventLoop.assertInEventLoop()\n        if self.destroyed {\n            return .failure(ChannelError._ioOnClosedChannel)\n        }\n\n        guard let context = self.contextForPredicate0({ $0.handler === relativeHandler }) else {\n            return .failure(ChannelPipelineError.notFound)\n        }\n\n        return self.add0(name: name, handler: handler, relativeContext: context, operation: operation)\n    }\n\n    /// Synchronously add a `ChannelHandler` to the pipeline, relative to a `ChannelHandlerContext`,\n    /// where the insertion is done by a specific operation.\n    ///\n    /// May only be called from on the event loop.\n    ///\n    /// This method is more efficient than the one that takes a `relativeHandler` as it does not need to\n    /// search the pipeline for the insertion point. It should be used whenever possible.\n    ///\n    /// - Parameters:\n    ///   - name: The name to use for the `ChannelHandler` when its added. If none is specified, a name will be\n    ///         automatically generated.\n    ///   - handler: The `ChannelHandler` to add.\n    ///   - relativeContext: The `ChannelHandlerContext` already in the `ChannelPipeline` that `handler` will be\n    ///         inserted relative to.\n    ///   - operation: A callback that will insert `handler` relative to `relativeHandler`.\n    /// - Returns: the result of adding this handler - either success or failure with an error code if this could not be completed.\n    private func add0(\n        name: String?,\n        handler: ChannelHandler,\n        relativeContext: ChannelHandlerContext,\n        operation: (ChannelHandlerContext, ChannelHandlerContext) -> Void\n    ) -> Result<Void, Error> {\n        self.eventLoop.assertInEventLoop()\n\n        if self.destroyed {\n            return .failure(ChannelError._ioOnClosedChannel)\n        }\n\n        let context = ChannelHandlerContext(name: name ?? nextName(), handler: handler, pipeline: self)\n        operation(context, relativeContext)\n\n        context.invokeHandlerAdded()\n        return .success(())\n    }\n\n    /// Synchronously add a single new `ChannelHandlerContext` after one that currently exists in the\n    /// pipeline.\n    ///\n    /// Must be called from within the event loop thread, as it synchronously manipulates the\n    /// `ChannelHandlerContext`s on the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - new: The `ChannelHandlerContext` to add to the pipeline.\n    ///   - existing: The `ChannelHandlerContext` that `new` will be added after.\n    private func add0(context new: ChannelHandlerContext, after existing: ChannelHandlerContext) {\n        self.eventLoop.assertInEventLoop()\n\n        let next = existing.next\n        new.prev = existing\n        new.next = next\n        existing.next = new\n        next?.prev = new\n    }\n\n    /// Synchronously add a single new `ChannelHandlerContext` before one that currently exists in the\n    /// pipeline.\n    ///\n    /// Must be called from within the event loop thread, as it synchronously manipulates the\n    /// `ChannelHandlerContext`s on the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - new: The `ChannelHandlerContext` to add to the pipeline.\n    ///   - existing: The `ChannelHandlerContext` that `new` will be added before.\n    private func add0(context new: ChannelHandlerContext, before existing: ChannelHandlerContext) {\n        self.eventLoop.assertInEventLoop()\n\n        let prev = existing.prev\n        new.prev = prev\n        new.next = existing\n        existing.prev = new\n        prev?.next = new\n    }\n\n    /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - handler: the `ChannelHandler` to remove.\n    /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was removed.\n    @preconcurrency\n    public func removeHandler(_ handler: RemovableChannelHandler & Sendable) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.removeHandler(handler, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - name: the name that was used to add the `ChannelHandler` to the `ChannelPipeline` before.\n    /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was removed.\n    public func removeHandler(name: String) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.removeHandler(name: name, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: the `ChannelHandlerContext` that belongs to `ChannelHandler` that should be removed.\n    /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was removed.\n    @available(\n        *,\n        deprecated,\n        message: \"Use .syncOperations.removeHandler(context:) instead, this method is not Sendable-safe.\"\n    )\n    public func removeHandler(context: ChannelHandlerContext) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.removeHandler(context: context, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - handler: the `ChannelHandler` to remove.\n    ///   - promise: An `EventLoopPromise` that will complete when the `ChannelHandler` is removed.\n    @preconcurrency\n    public func removeHandler(_ handler: RemovableChannelHandler & Sendable, promise: EventLoopPromise<Void>?) {\n        @Sendable\n        func removeHandler0() {\n            self.syncOperations.removeHandler(handler, promise: promise)\n        }\n\n        if self.eventLoop.inEventLoop {\n            removeHandler0()\n        } else {\n            self.eventLoop.execute {\n                removeHandler0()\n            }\n        }\n    }\n\n    /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - name: the name that was used to add the `ChannelHandler` to the `ChannelPipeline` before.\n    ///   - promise: An `EventLoopPromise` that will complete when the `ChannelHandler` is removed.\n    public func removeHandler(name: String, promise: EventLoopPromise<Void>?) {\n        @Sendable\n        func removeHandler0() {\n            self.syncOperations.removeHandler(name: name, promise: promise)\n        }\n\n        if self.eventLoop.inEventLoop {\n            removeHandler0()\n        } else {\n            self.eventLoop.execute {\n                removeHandler0()\n            }\n        }\n    }\n\n    /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: the `ChannelHandlerContext` that belongs to `ChannelHandler` that should be removed.\n    ///   - promise: An `EventLoopPromise` that will complete when the `ChannelHandler` is removed.\n    @available(\n        *,\n        deprecated,\n        message: \"Use .syncOperations.removeHandler(context:) instead, this method is not Sendable-safe.\"\n    )\n    public func removeHandler(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        let sendableView = context.sendableView\n\n        guard sendableView.channelHandlerIsRemovable else {\n            promise?.fail(ChannelError._unremovableHandler)\n            return\n        }\n\n        @Sendable\n        func removeHandler0() {\n            sendableView.wrappedValue.startUserTriggeredRemoval(promise: promise)\n        }\n\n        if self.eventLoop.inEventLoop {\n            removeHandler0()\n        } else {\n            self.eventLoop.execute {\n                removeHandler0()\n            }\n        }\n    }\n\n    /// Returns the `ChannelHandlerContext` that belongs to a `ChannelHandler`.\n    ///\n    /// - Parameters:\n    ///   - handler: the `ChannelHandler` for which the `ChannelHandlerContext` should be returned\n    /// - Returns: the `EventLoopFuture` which will be notified once the the operation completes.\n    @available(\n        *,\n        deprecated,\n        message: \"This method is not strict concurrency safe. Prefer .syncOperations.context(handler:)\"\n    )\n    @preconcurrency\n    public func context(handler: ChannelHandler & Sendable) -> EventLoopFuture<ChannelHandlerContext> {\n        let promise = self.eventLoop.makePromise(of: ChannelHandlerContext.self)\n\n        if self.eventLoop.inEventLoop {\n            promise.assumeIsolatedUnsafeUnchecked().completeWith(self.contextSync(handler: handler))\n        } else {\n            self.eventLoop.execute {\n                promise.assumeIsolatedUnsafeUnchecked().completeWith(self.contextSync(handler: handler))\n            }\n        }\n\n        return promise.futureResult\n    }\n\n    /// Synchronously returns the `ChannelHandlerContext` that belongs to a `ChannelHandler`.\n    ///\n    /// - Important: This must be called on the `EventLoop`.\n    /// - Parameters:\n    ///   - handler: the `ChannelHandler` for which the `ChannelHandlerContext` should be returned\n    /// - Returns: the `ChannelHandlerContext` that belongs to the `ChannelHandler`, if one exists.\n    fileprivate func contextSync(handler: ChannelHandler) -> Result<ChannelHandlerContext, Error> {\n        self._contextSync({ $0.handler === handler })\n    }\n\n    /// Returns the `ChannelHandlerContext` that belongs to a `ChannelHandler`.\n    ///\n    /// - Parameters:\n    ///   - name: the name that was used to add the `ChannelHandler` to the `ChannelPipeline` before.\n    /// - Returns: the `EventLoopFuture` which will be notified once the the operation completes.\n    public func context(name: String) -> EventLoopFuture<ChannelHandlerContext> {\n        let promise = self.eventLoop.makePromise(of: ChannelHandlerContext.self)\n\n        if self.eventLoop.inEventLoop {\n            promise.assumeIsolatedUnsafeUnchecked().completeWith(self.contextSync(name: name))\n        } else {\n            self.eventLoop.execute {\n                promise.assumeIsolatedUnsafeUnchecked().completeWith(self.contextSync(name: name))\n            }\n        }\n\n        return promise.futureResult\n    }\n\n    /// Synchronously finds and returns the `ChannelHandlerContext` that belongs to the\n    /// `ChannelHandler` with the given name.\n    ///\n    /// - Important: This must be called on the `EventLoop`.\n    /// - Parameter name: The name of the `ChannelHandler` to find.\n    /// - Returns: the `ChannelHandlerContext` that belongs to the `ChannelHandler`, if one exists.\n    fileprivate func contextSync(name: String) -> Result<ChannelHandlerContext, Error> {\n        self._contextSync({ $0.name == name })\n    }\n\n    /// Returns the `ChannelHandlerContext` that belongs to a `ChannelHandler` of the given type.\n    ///\n    /// If multiple channel handlers of the same type are present in the pipeline, returns the context\n    /// belonging to the first such handler.\n    ///\n    /// - Parameters:\n    ///   - handlerType: The type of the handler to search for.\n    /// - Returns: the `EventLoopFuture` which will be notified once the the operation completes.\n    @inlinable\n    @preconcurrency\n    public func context<Handler: ChannelHandler & _NIOCoreSendableMetatype>(\n        handlerType: Handler.Type\n    ) -> EventLoopFuture<ChannelHandlerContext> {\n        let promise = self.eventLoop.makePromise(of: ChannelHandlerContext.self)\n\n        if self.eventLoop.inEventLoop {\n            promise.assumeIsolatedUnsafeUnchecked().completeWith(self._contextSync(handlerType: handlerType))\n        } else {\n            self.eventLoop.execute {\n                promise.assumeIsolatedUnsafeUnchecked().completeWith(self._contextSync(handlerType: handlerType))\n            }\n        }\n\n        return promise.futureResult\n    }\n\n    /// Returns if the ``ChannelHandler`` of the given type is contained in the pipeline.\n    ///\n    /// - Parameters:\n    ///   - type: The type of the handler.\n    /// - Returns: An ``EventLoopFuture`` that is succeeded if a handler of the given type is contained in the pipeline. Otherwise\n    /// the future will be failed with an error.\n    @inlinable\n    @preconcurrency\n    public func containsHandler<Handler: ChannelHandler & _NIOCoreSendableMetatype>(\n        type: Handler.Type\n    ) -> EventLoopFuture<Void> {\n        self.handler(type: type).map { _ in () }\n    }\n\n    /// Returns if the ``ChannelHandler`` of the given type is contained in the pipeline.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the handler.\n    /// - Returns: An ``EventLoopFuture`` that is succeeded if a handler of the given type is contained in the pipeline. Otherwise\n    /// the future will be failed with an error.\n    @inlinable\n    public func containsHandler(name: String) -> EventLoopFuture<Void> {\n        self.context(name: name).map { _ in () }\n    }\n\n    /// Synchronously finds and returns the `ChannelHandlerContext` that belongs to the first\n    /// `ChannelHandler` of the given type.\n    ///\n    /// - Important: This must be called on the `EventLoop`.\n    /// - Parameter handlerType: The type of handler to search for.\n    /// - Returns: the `ChannelHandlerContext` that belongs to the `ChannelHandler`, if one exists.\n    @inlinable  // should be fileprivate\n    internal func _contextSync<Handler: ChannelHandler>(\n        handlerType: Handler.Type\n    ) -> Result<ChannelHandlerContext, Error> {\n        self._contextSync({ $0.handler is Handler })\n    }\n\n    /// Synchronously finds a `ChannelHandlerContext` in the `ChannelPipeline`.\n    /// - Important: This must be called on the `EventLoop`.\n    @usableFromInline  // should be fileprivate\n    internal func _contextSync(_ body: (ChannelHandlerContext) -> Bool) -> Result<ChannelHandlerContext, Error> {\n        self.eventLoop.assertInEventLoop()\n\n        if let context = self.contextForPredicate0(body) {\n            return .success(context)\n        } else {\n            return .failure(ChannelPipelineError.notFound)\n        }\n    }\n\n    /// Returns a `ChannelHandlerContext` which matches.\n    ///\n    /// This skips head and tail (as these are internal and should not be accessible by the user).\n    ///\n    /// - Parameters:\n    ///   - body: The predicate to execute per `ChannelHandlerContext` in the `ChannelPipeline`.\n    /// - Returns: The first `ChannelHandlerContext` that matches or `nil` if none did.\n    private func contextForPredicate0(_ body: (ChannelHandlerContext) -> Bool) -> ChannelHandlerContext? {\n        var curCtx: ChannelHandlerContext? = self.head?.next\n        while let context = curCtx, context !== self.tail {\n            if body(context) {\n                return context\n            }\n            curCtx = context.next\n        }\n\n        return nil\n    }\n\n    /// Remove a `ChannelHandlerContext` from the `ChannelPipeline` directly without going through the\n    /// `RemovableChannelHandler` API. This must only be used to clear the pipeline on `Channel` tear down and\n    /// as a result of the `leavePipeline` call in the `RemovableChannelHandler` API.\n    internal func removeHandlerFromPipeline(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        let nextCtx = context.next\n        let prevCtx = context.prev\n\n        if let prevCtx = prevCtx {\n            prevCtx.next = nextCtx\n        }\n        if let nextCtx = nextCtx {\n            nextCtx.prev = prevCtx\n        }\n\n        context.invokeHandlerRemoved()\n        promise?.succeed(())\n\n        // We need to keep the current node alive until after the callout in case the user uses the context.\n        context.next = nil\n        context.prev = nil\n    }\n\n    /// Returns the next name to use for a `ChannelHandler`.\n    private func nextName() -> String {\n        self.eventLoop.assertInEventLoop()\n\n        let name = \"handler\\(idx)\"\n        idx += 1\n        return name\n    }\n\n    /// Remove all the `ChannelHandler`s from the `ChannelPipeline` and destroy these.\n    ///\n    /// This method must only be called from within the `EventLoop`. It should only be called from a `ChannelCore`\n    /// implementation. Once called, the `ChannelPipeline` is no longer active and cannot be used again.\n    func removeHandlers() {\n        self.eventLoop.assertInEventLoop()\n\n        if let head = self.head {\n            while let context = head.next {\n                removeHandlerFromPipeline(context: context, promise: nil)\n            }\n            removeHandlerFromPipeline(context: self.head!, promise: nil)\n        }\n        self.head = nil\n        self.tail = nil\n\n        self.destroyed = true\n        self._channel = nil\n    }\n\n    // Just delegate to the head and tail context\n    public func fireChannelRegistered() {\n        if eventLoop.inEventLoop {\n            fireChannelRegistered0()\n        } else {\n            eventLoop.execute {\n                self.fireChannelRegistered0()\n            }\n        }\n    }\n\n    public func fireChannelUnregistered() {\n        if eventLoop.inEventLoop {\n            fireChannelUnregistered0()\n        } else {\n            eventLoop.execute {\n                self.fireChannelUnregistered0()\n            }\n        }\n    }\n\n    public func fireChannelInactive() {\n        if eventLoop.inEventLoop {\n            fireChannelInactive0()\n        } else {\n            eventLoop.execute {\n                self.fireChannelInactive0()\n            }\n        }\n    }\n\n    public func fireChannelActive() {\n        if eventLoop.inEventLoop {\n            fireChannelActive0()\n        } else {\n            eventLoop.execute {\n                self.fireChannelActive0()\n            }\n        }\n    }\n\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func fireChannelRead(_ data: NIOAny) {\n        if eventLoop.inEventLoop {\n            _fireChannelRead0(data)\n        } else {\n            // This is unsafe, but necessary.\n            let unsafeTransfer = UnsafeTransfer(data)\n            eventLoop.execute {\n                self._fireChannelRead0(unsafeTransfer.wrappedValue)\n            }\n        }\n    }\n\n    @inlinable\n    public func fireChannelRead<T: Sendable>(_ data: T) {\n        if eventLoop.inEventLoop {\n            _fireChannelRead0(NIOAny(data))\n        } else {\n            eventLoop.execute {\n                self._fireChannelRead0(NIOAny(data))\n            }\n        }\n    }\n\n    public func fireChannelReadComplete() {\n        if eventLoop.inEventLoop {\n            fireChannelReadComplete0()\n        } else {\n            eventLoop.execute {\n                self.fireChannelReadComplete0()\n            }\n        }\n    }\n\n    public func fireChannelWritabilityChanged() {\n        if eventLoop.inEventLoop {\n            fireChannelWritabilityChanged0()\n        } else {\n            eventLoop.execute {\n                self.fireChannelWritabilityChanged0()\n            }\n        }\n    }\n\n    @preconcurrency\n    public func fireUserInboundEventTriggered(_ event: Any & Sendable) {\n        if eventLoop.inEventLoop {\n            fireUserInboundEventTriggered0(event)\n        } else {\n            eventLoop.execute {\n                self.fireUserInboundEventTriggered0(event)\n            }\n        }\n    }\n\n    public func fireErrorCaught(_ error: Error) {\n        if eventLoop.inEventLoop {\n            fireErrorCaught0(error: error)\n        } else {\n            eventLoop.execute {\n                self.fireErrorCaught0(error: error)\n            }\n        }\n    }\n\n    public func close(mode: CloseMode = .all, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            close0(mode: mode, promise: promise)\n        } else {\n            eventLoop.execute {\n                self.close0(mode: mode, promise: promise)\n            }\n        }\n    }\n\n    public func flush() {\n        if eventLoop.inEventLoop {\n            flush0()\n        } else {\n            eventLoop.execute {\n                self.flush0()\n            }\n        }\n    }\n\n    public func read() {\n        if eventLoop.inEventLoop {\n            read0()\n        } else {\n            eventLoop.execute {\n                self.read0()\n            }\n        }\n    }\n\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func write(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            _write0(data, promise: promise)\n        } else {\n            // This is unsafe, but unavoidable.\n            let unsafeTransfer = UnsafeTransfer(data)\n            eventLoop.execute {\n                self._write0(unsafeTransfer.wrappedValue, promise: promise)\n            }\n        }\n    }\n\n    @inlinable\n    public func write<T: Sendable>(_ data: T, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            _write0(NIOAny(data), promise: promise)\n        } else {\n            eventLoop.execute {\n                self._write0(NIOAny(data), promise: promise)\n            }\n        }\n    }\n\n    @available(\n        *,\n        deprecated,\n        message: \"NIOAny is not Sendable. Avoid wrapping the value in NIOAny to silence this warning.\"\n    )\n    public func writeAndFlush(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            _writeAndFlush0(data, promise: promise)\n        } else {\n            // This is unsafe, but unavoidable.\n            let unsafeTransfer = UnsafeTransfer(data)\n            eventLoop.execute {\n                self._writeAndFlush0(unsafeTransfer.wrappedValue, promise: promise)\n            }\n        }\n    }\n\n    @inlinable\n    public func writeAndFlush<T: Sendable>(_ data: T, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            _writeAndFlush0(NIOAny(data), promise: promise)\n        } else {\n            eventLoop.execute {\n                self._writeAndFlush0(NIOAny(data), promise: promise)\n            }\n        }\n    }\n\n    public func bind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            bind0(to: address, promise: promise)\n        } else {\n            eventLoop.execute {\n                self.bind0(to: address, promise: promise)\n            }\n        }\n    }\n\n    public func connect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            connect0(to: address, promise: promise)\n        } else {\n            eventLoop.execute {\n                self.connect0(to: address, promise: promise)\n            }\n        }\n    }\n\n    public func register(promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            register0(promise: promise)\n        } else {\n            eventLoop.execute {\n                self.register0(promise: promise)\n            }\n        }\n    }\n\n    @preconcurrency\n    public func triggerUserOutboundEvent(_ event: Any & Sendable, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            triggerUserOutboundEvent0(event, promise: promise)\n        } else {\n            eventLoop.execute {\n                self.triggerUserOutboundEvent0(event, promise: promise)\n            }\n        }\n    }\n\n    // These methods are expected to only be called from within the EventLoop\n\n    private var firstOutboundCtx: ChannelHandlerContext? {\n        self.tail?.prev\n    }\n\n    private var firstInboundCtx: ChannelHandlerContext? {\n        self.head?.next\n    }\n\n    private func close0(mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeClose(mode: mode, promise: promise)\n        } else {\n            promise?.fail(ChannelError._alreadyClosed)\n        }\n    }\n\n    private func flush0() {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeFlush()\n        }\n    }\n\n    private func read0() {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeRead()\n        }\n    }\n\n    @usableFromInline func _write0(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeWrite(data, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    @usableFromInline func _writeAndFlush0(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeWriteAndFlush(data, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    private func bind0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeBind(to: address, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    private func connect0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeConnect(to: address, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    private func register0(promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeRegister(promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    private func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?) {\n        if let firstOutboundCtx = firstOutboundCtx {\n            firstOutboundCtx.invokeTriggerUserOutboundEvent(event, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    private func fireChannelRegistered0() {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelRegistered()\n        }\n    }\n\n    private func fireChannelUnregistered0() {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelUnregistered()\n        }\n    }\n\n    private func fireChannelInactive0() {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelInactive()\n        }\n    }\n\n    private func fireChannelActive0() {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelActive()\n        }\n    }\n\n    @usableFromInline func _fireChannelRead0(_ data: NIOAny) {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelRead(data)\n        }\n    }\n\n    private func fireChannelReadComplete0() {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelReadComplete()\n        }\n    }\n\n    private func fireChannelWritabilityChanged0() {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeChannelWritabilityChanged()\n        }\n    }\n\n    private func fireUserInboundEventTriggered0(_ event: Any) {\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeUserInboundEventTriggered(event)\n        }\n    }\n\n    private func fireErrorCaught0(error: Error) {\n        assert((error as? ChannelError).map { $0 != .eof } ?? true)\n        if let firstInboundCtx = firstInboundCtx {\n            firstInboundCtx.invokeErrorCaught(error)\n        }\n    }\n\n    private var inEventLoop: Bool {\n        eventLoop.inEventLoop\n    }\n\n    /// Create `ChannelPipeline` for a given `Channel`. This method should never be called by the end-user\n    /// directly: it is only intended for use with custom `Channel` implementations. Users should always use\n    /// `channel.pipeline` to access the `ChannelPipeline` for a `Channel`.\n    ///\n    /// - Parameters:\n    ///    - channel: The `Channel` this `ChannelPipeline` is created for.\n    public init(channel: Channel) {\n        self._channel = channel\n        self.eventLoop = channel.eventLoop\n        self.head = nil  // we need to initialise these to `nil` so we can use `self` in the lines below\n        self.tail = nil  // we need to initialise these to `nil` so we can use `self` in the lines below\n\n        self.head = ChannelHandlerContext(\n            name: HeadChannelHandler.name,\n            handler: HeadChannelHandler.sharedInstance,\n            pipeline: self\n        )\n        self.tail = ChannelHandlerContext(\n            name: TailChannelHandler.name,\n            handler: TailChannelHandler.sharedInstance,\n            pipeline: self\n        )\n        self.head?.next = self.tail\n        self.tail?.prev = self.head\n    }\n}\n\nextension ChannelPipeline: @unchecked Sendable {}\n\nextension ChannelPipeline {\n    /// Adds the provided channel handlers to the pipeline in the order given, taking account\n    /// of the behaviour of `ChannelHandler.add(first:)`.\n    ///\n    /// - Parameters:\n    ///   - handlers: The array of `ChannelHandler`s to be added.\n    ///   - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.\n    ///\n    /// - Returns: A future that will be completed when all of the supplied `ChannelHandler`s were added.\n    @preconcurrency\n    public func addHandlers(\n        _ handlers: [ChannelHandler & Sendable],\n        position: ChannelPipeline.Position = .last\n    ) -> EventLoopFuture<Void> {\n        let future: EventLoopFuture<Void>\n\n        if self.eventLoop.inEventLoop {\n            future = self.eventLoop.makeCompletedFuture(self.addHandlersSync(handlers, position: position))\n        } else {\n            future = self.eventLoop.submit {\n                try self.addHandlersSync(handlers, position: position).get()\n            }\n        }\n\n        return future\n    }\n\n    /// Adds the provided channel handlers to the pipeline in the order given, taking account\n    /// of the behaviour of `ChannelHandler.add(first:)`.\n    ///\n    /// - Parameters:\n    ///   - handlers: One or more `ChannelHandler`s to be added.\n    ///   - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.\n    ///\n    /// - Returns: A future that will be completed when all of the supplied `ChannelHandler`s were added.\n    @preconcurrency\n    public func addHandlers(\n        _ handlers: (ChannelHandler & Sendable)...,\n        position: ChannelPipeline.Position = .last\n    ) -> EventLoopFuture<Void> {\n        self.addHandlers(handlers, position: position)\n    }\n\n    /// Synchronously adds the provided `ChannelHandler`s to the pipeline in the order given, taking\n    /// account of the behaviour of `ChannelHandler.add(first:)`.\n    ///\n    /// - Important: Must be called on the `EventLoop`.\n    /// - Parameters:\n    ///   - handlers: The array of `ChannelHandler`s to add.\n    ///   - position: The position in the `ChannelPipeline` to add the handlers.\n    /// - Returns: A result representing whether the handlers were added or not.\n    fileprivate func addHandlersSync(\n        _ handlers: [ChannelHandler & Sendable],\n        position: ChannelPipeline.Position\n    ) -> Result<Void, Error> {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        switch syncPosition {\n        case .first, .after:\n            return self._addHandlersSync(handlers.reversed(), position: syncPosition)\n        case .last, .before:\n            return self._addHandlersSync(handlers, position: syncPosition)\n        }\n    }\n\n    /// Synchronously adds the provided `ChannelHandler`s to the pipeline in the order given, taking\n    /// account of the behaviour of `ChannelHandler.add(first:)`.\n    ///\n    /// This duplicate of the above method exists to avoid needing to rebox the array of existentials\n    /// from any (ChannelHandler & Sendable) to any ChannelHandler.\n    ///\n    /// - Important: Must be called on the `EventLoop`.\n    /// - Parameters:\n    ///   - handlers: The array of `ChannelHandler`s to add.\n    ///   - position: The position in the `ChannelPipeline` to add the handlers.\n    /// - Returns: A result representing whether the handlers were added or not.\n    fileprivate func addHandlersSyncNotSendable(\n        _ handlers: [ChannelHandler],\n        position: ChannelPipeline.SynchronousOperations.Position\n    ) -> Result<Void, Error> {\n        switch position {\n        case .first, .after:\n            return self._addHandlersSyncNotSendable(handlers.reversed(), position: position)\n        case .last, .before:\n            return self._addHandlersSyncNotSendable(handlers, position: position)\n        }\n    }\n\n    /// Synchronously adds a sequence of `ChannelHandlers` to the pipeline at the given position.\n    ///\n    /// - Important: Must be called on the `EventLoop`.\n    /// - Parameters:\n    ///   - handlers: A sequence of handlers to add.\n    ///   - position: The position in the `ChannelPipeline` to add the handlers.\n    /// - Returns: A result representing whether the handlers were added or not.\n    private func _addHandlersSync<Handlers: Sequence>(\n        _ handlers: Handlers,\n        position: ChannelPipeline.SynchronousOperations.Position\n    ) -> Result<Void, Error> where Handlers.Element == ChannelHandler & Sendable {\n        self.eventLoop.assertInEventLoop()\n\n        for handler in handlers {\n            let result = self.addHandlerSync(handler, position: position)\n            switch result {\n            case .success:\n                ()\n            case .failure:\n                return result\n            }\n        }\n\n        return .success(())\n    }\n\n    /// Synchronously adds a sequence of `ChannelHandlers` to the pipeline at the given position.\n    ///\n    /// This duplicate of the above method exists to avoid needing to rebox the array of existentials\n    /// from any (ChannelHandler & Sendable) to any ChannelHandler.\n    ///\n    /// - Important: Must be called on the `EventLoop`.\n    /// - Parameters:\n    ///   - handlers: A sequence of handlers to add.\n    ///   - position: The position in the `ChannelPipeline` to add the handlers.\n    /// - Returns: A result representing whether the handlers were added or not.\n    private func _addHandlersSyncNotSendable<Handlers: Sequence>(\n        _ handlers: Handlers,\n        position: ChannelPipeline.SynchronousOperations.Position\n    ) -> Result<Void, Error> where Handlers.Element == ChannelHandler {\n        self.eventLoop.assertInEventLoop()\n\n        for handler in handlers {\n            let result = self.addHandlerSync(handler, position: position)\n            switch result {\n            case .success:\n                ()\n            case .failure:\n                return result\n            }\n        }\n\n        return .success(())\n    }\n}\n\n// MARK: - Synchronous View\n\nextension ChannelPipeline {\n    /// A view of a `ChannelPipeline` which may be used to invoke synchronous operations.\n    ///\n    /// All functions **must** be called from the pipeline's event loop.\n    public struct SynchronousOperations {\n        @usableFromInline\n        internal let _pipeline: ChannelPipeline\n\n        fileprivate init(pipeline: ChannelPipeline) {\n            self._pipeline = pipeline\n        }\n\n        /// The `EventLoop` of the `Channel` this synchronous operations view corresponds to.\n        public var eventLoop: EventLoop {\n            self._pipeline.eventLoop\n        }\n\n        /// Add a handler to the pipeline.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameters:\n        ///   - handler: The handler to add.\n        ///   - name: The name to use for the `ChannelHandler` when it's added. If no name is specified the one will be generated.\n        ///   - position: The position in the `ChannelPipeline` to add `handler`. Defaults to `.last`.\n        public func addHandler(\n            _ handler: ChannelHandler,\n            name: String? = nil,\n            position: ChannelPipeline.SynchronousOperations.Position = .last\n        ) throws {\n            try self._pipeline.addHandlerSync(handler, name: name, position: position).get()\n        }\n\n        /// Add a handler to the pipeline.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameters:\n        ///   - handler: The handler to add.\n        ///   - name: The name to use for the `ChannelHandler` when it's added. If no name is specified the one will be generated.\n        ///   - position: The position in the `ChannelPipeline` to add `handler`. Defaults to `.last`.\n        @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n        @_disfavoredOverload\n        public func addHandler(\n            _ handler: ChannelHandler,\n            name: String? = nil,\n            position: ChannelPipeline.Position = .last\n        ) throws {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            try self._pipeline.addHandlerSync(handler, name: name, position: syncPosition).get()\n        }\n\n        /// Add an array of handlers to the pipeline.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameters:\n        ///   - handlers: The handlers to add.\n        ///   - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.\n        public func addHandlers(\n            _ handlers: [ChannelHandler],\n            position: ChannelPipeline.SynchronousOperations.Position = .last\n        ) throws {\n            try self._pipeline.addHandlersSyncNotSendable(handlers, position: position).get()\n        }\n\n        /// Add an array of handlers to the pipeline.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameters:\n        ///   - handlers: The handlers to add.\n        ///   - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.\n        @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n        @_disfavoredOverload\n        public func addHandlers(\n            _ handlers: [ChannelHandler],\n            position: ChannelPipeline.Position = .last\n        ) throws {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            try self._pipeline.addHandlersSyncNotSendable(handlers, position: syncPosition).get()\n        }\n\n        /// Add one or more handlers to the pipeline.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameters:\n        ///   - handlers: The handlers to add.\n        ///   - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.\n        public func addHandlers(\n            _ handlers: ChannelHandler...,\n            position: ChannelPipeline.SynchronousOperations.Position = .last\n        ) throws {\n            try self._pipeline.addHandlersSyncNotSendable(handlers, position: position).get()\n        }\n\n        /// Add one or more handlers to the pipeline.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameters:\n        ///   - handlers: The handlers to add.\n        ///   - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.\n        @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n        @_disfavoredOverload\n        public func addHandlers(\n            _ handlers: ChannelHandler...,\n            position: ChannelPipeline.Position = .last\n        ) throws {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            try self._pipeline.addHandlersSyncNotSendable(handlers, position: syncPosition).get()\n        }\n\n        /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n        ///\n        /// - Parameters:\n        ///   - handler: the `ChannelHandler` to remove.\n        /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was removed.\n        public func removeHandler(_ handler: RemovableChannelHandler) -> EventLoopFuture<Void> {\n            let promise = self.eventLoop.makePromise(of: Void.self)\n            self.removeHandler(handler, promise: promise)\n            return promise.futureResult\n        }\n\n        /// Remove a ``ChannelHandler`` from the ``ChannelPipeline``.\n        ///\n        /// - Parameters:\n        ///   - handler: the ``ChannelHandler`` to remove.\n        ///   - promise: an ``EventLoopPromise`` to notify when the ``ChannelHandler`` was removed.\n        public func removeHandler(_ handler: RemovableChannelHandler, promise: EventLoopPromise<Void>?) {\n            switch self._pipeline.contextSync(handler: handler) {\n            case .success(let context):\n                self.removeHandler(context: context, promise: promise)\n            case .failure(let error):\n                promise?.fail(error)\n            }\n        }\n\n        /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n        ///\n        /// - Parameters:\n        ///   - name: the name that was used to add the `ChannelHandler` to the `ChannelPipeline` before.\n        /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was removed.\n        public func removeHandler(name: String) -> EventLoopFuture<Void> {\n            let promise = self.eventLoop.makePromise(of: Void.self)\n            self.removeHandler(name: name, promise: promise)\n            return promise.futureResult\n        }\n\n        /// Remove a ``ChannelHandler`` from the ``ChannelPipeline``.\n        ///\n        /// - Parameters:\n        ///   - name: the name that was used to add the `ChannelHandler` to the `ChannelPipeline` before.\n        ///   - promise: an ``EventLoopPromise`` to notify when the ``ChannelHandler`` was removed.\n        public func removeHandler(name: String, promise: EventLoopPromise<Void>?) {\n            switch self._pipeline.contextSync(name: name) {\n            case .success(let context):\n                self.removeHandler(context: context, promise: promise)\n            case .failure(let error):\n                promise?.fail(error)\n            }\n        }\n\n        /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n        ///\n        /// - Parameters:\n        ///   - context: the `ChannelHandlerContext` that belongs to `ChannelHandler` that should be removed.\n        /// - Returns: the `EventLoopFuture` which will be notified once the `ChannelHandler` was removed.\n        public func removeHandler(context: ChannelHandlerContext) -> EventLoopFuture<Void> {\n            let promise = self.eventLoop.makePromise(of: Void.self)\n            self.removeHandler(context: context, promise: promise)\n            return promise.futureResult\n        }\n\n        /// Remove a `ChannelHandler` from the `ChannelPipeline`.\n        ///\n        /// - Parameters:\n        ///   - context: the `ChannelHandlerContext` that belongs to `ChannelHandler` that should be removed.\n        ///   - promise: an ``EventLoopPromise`` to notify when the ``ChannelHandler`` was removed.\n        public func removeHandler(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n            if context.handler is RemovableChannelHandler {\n                context.startUserTriggeredRemoval(promise: promise)\n            } else {\n                promise?.fail(ChannelError.unremovableHandler)\n            }\n        }\n\n        /// Returns the `ChannelHandlerContext` for the given handler instance if it is in\n        /// the `ChannelPipeline`, if it exists.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameter handler: The handler belonging to the context to fetch.\n        /// - Returns: The `ChannelHandlerContext` associated with the handler.\n        public func context(handler: ChannelHandler) throws -> ChannelHandlerContext {\n            try self._pipeline._contextSync({ $0.handler === handler }).get()\n        }\n\n        /// Returns the `ChannelHandlerContext` for the handler with the given name, if one exists.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameter name: The name of the handler whose context is being fetched.\n        /// - Returns: The `ChannelHandlerContext` associated with the handler.\n        public func context(name: String) throws -> ChannelHandlerContext {\n            try self._pipeline.contextSync(name: name).get()\n        }\n\n        /// Returns the `ChannelHandlerContext` for the handler of given type, if one exists.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Parameter handlerType: The type of the handler to search for.\n        /// - Returns: The `ChannelHandlerContext` associated with the handler.\n        @inlinable\n        public func context<Handler: ChannelHandler>(handlerType: Handler.Type) throws -> ChannelHandlerContext {\n            try self._pipeline._contextSync(handlerType: handlerType).get()\n        }\n\n        /// Returns the `ChannelHandler` of the given type from the `ChannelPipeline`, if it exists.\n        ///\n        /// - Important: This *must* be called on the event loop.\n        /// - Returns: A `ChannelHandler` of the given type if one exists in the `ChannelPipeline`.\n        @inlinable\n        public func handler<Handler: ChannelHandler>(type _: Handler.Type) throws -> Handler {\n            try self._pipeline._handlerSync(type: Handler.self).get()\n        }\n\n        /// Fires `channelRegistered` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelRegistered() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireChannelRegistered0()\n        }\n\n        /// Fires `channelUnregistered` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelUnregistered() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireChannelUnregistered0()\n        }\n\n        /// Fires `channelInactive` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelInactive() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireChannelInactive0()\n        }\n\n        /// Fires `channelActive` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelActive() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireChannelActive0()\n        }\n\n        /// Fires `channelRead` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelRead(_ data: NIOAny) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline._fireChannelRead0(data)\n        }\n\n        /// Fires `channelReadComplete` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelReadComplete() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireChannelReadComplete0()\n        }\n\n        /// Fires `channelWritabilityChanged` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireChannelWritabilityChanged() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireChannelWritabilityChanged0()\n        }\n\n        /// Fires `userInboundEventTriggered` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireUserInboundEventTriggered(_ event: Any) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireUserInboundEventTriggered0(event)\n        }\n\n        /// Fires `errorCaught` from the head to the tail.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func fireErrorCaught(_ error: Error) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.fireErrorCaught0(error: error)\n        }\n\n        /// Fires `close` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func close(mode: CloseMode = .all, promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.close0(mode: mode, promise: promise)\n        }\n\n        /// Fires `flush` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func flush() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.flush0()\n        }\n\n        /// Fires `read` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func read() {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.read0()\n        }\n\n        /// Fires `write` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func write(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline._write0(data, promise: promise)\n        }\n\n        /// Fires `write` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func write(_ data: NIOAny) -> EventLoopFuture<Void> {\n            self.eventLoop.assertInEventLoop()\n            let promise = self.eventLoop.makePromise(of: Void.self)\n            self._pipeline._write0(data, promise: promise)\n            return promise.futureResult\n        }\n\n        /// Fires `writeAndFlush` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func writeAndFlush(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline._writeAndFlush0(data, promise: promise)\n        }\n\n        /// Fires `writeAndFlush` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func writeAndFlush(_ data: NIOAny) -> EventLoopFuture<Void> {\n            self.eventLoop.assertInEventLoop()\n            let promise = self.eventLoop.makePromise(of: Void.self)\n            self._pipeline._writeAndFlush0(data, promise: promise)\n            return promise.futureResult\n        }\n\n        /// Fires `bind` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func bind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.bind0(to: address, promise: promise)\n        }\n\n        /// Fires `connect` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func connect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.connect0(to: address, promise: promise)\n        }\n\n        /// Fires `register` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func register(promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.register0(promise: promise)\n        }\n\n        /// Fires `triggerUserOutboundEvent` from the tail to the head.\n        ///\n        /// This method should typically only be called by `Channel` implementations directly.\n        public func triggerUserOutboundEvent(_ event: Any, promise: EventLoopPromise<Void>?) {\n            self.eventLoop.assertInEventLoop()\n            self._pipeline.triggerUserOutboundEvent0(event, promise: promise)\n        }\n\n        /// Provides scoped access to the underlying transport, if the channel supports it.\n        ///\n        /// This is an advanced API for reading or manipulating the underlying transport that backs a channel. Users\n        /// must not close the transport or invalidate any invariants that the channel relies upon for its operation.\n        ///\n        /// Not all channels support access to the underlying channel. If the channel does not support this API, the\n        /// closure is not called and this function immediately returns `nil`.\n        ///\n        /// Note that you must call this API with an appropriate closure, or otherwise explicitly specify the correct\n        /// transport type prarameter, in order for the closure to be run. Calling this function such that the compiler\n        /// infers a type for the transport closure parameter that differs from the channel implementation will result\n        /// in the closure not being run and this function will return `nil`.\n        ///\n        /// For example, for socket-based channels, that expose the underlying socket handle:\n        ///\n        /// ```swift\n        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable { transport in\n        ///     // This closure is called.\n        ///     transport == NIOBSDSocketHandle.invalid\n        /// }\n        ///\n        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable { (_: NIOBSDSocket.Handle) in\n        ///     // This closure is called.\n        ///     return\n        /// }\n        ///\n        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable(of: NIOBSDSocket.Handle.self) { _ in\n        ///     // This closure is called.\n        ///     return\n        /// }\n        ///\n        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable {\n        ///     // This closure is NOT called.\n        ///     return\n        /// }\n        ///\n        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable { (_: Any.self) in\n        ///     // This closure is NOT called.\n        ///     return\n        /// }\n        ///\n        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable(of: Any.self) { _ in\n        ///     // This closure is NOT called.\n        ///     return\n        /// }\n        /// ```\n        ///\n        /// - Parameters:\n        ///   - type: The expected transport type the channel makes available.\n        ///   - body: /// A closure that takes the underlying transport, if the channel supports this operation.\n        /// - Returns: The value returned by the closure, or `nil` if the channel does not expose its transport.\n        /// - Throws: If there was an error accessing the underlying transport, or an error was thrown by the closure.\n        @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n        @inlinable\n        public func withUnsafeTransportIfAvailable<Transport, Result>(\n            of type: Transport.Type = Transport.self,\n            _ body: (_ transport: Transport) throws -> Result\n        ) throws -> Result? {\n            self.eventLoop.assertInEventLoop()\n            guard let core = self._pipeline.channel._channelCore as? any NIOTransportAccessibleChannelCore<Transport>\n            else {\n                return nil\n            }\n            return try core.withUnsafeTransport(body)\n        }\n    }\n\n    /// Returns a view of operations which can be performed synchronously on this pipeline. All\n    /// operations **must** be called on the event loop.\n    public var syncOperations: SynchronousOperations {\n        SynchronousOperations(pipeline: self)\n    }\n}\n\n@available(*, unavailable)\nextension ChannelPipeline.SynchronousOperations: Sendable {}\n\nextension ChannelPipeline {\n    /// A `Position` within the `ChannelPipeline` used to insert handlers into the `ChannelPipeline`.\n    @preconcurrency\n    public enum Position: Sendable {\n        /// The first `ChannelHandler` -- the front of the `ChannelPipeline`.\n        case first\n\n        /// The last `ChannelHandler` -- the back of the `ChannelPipeline`.\n        case last\n\n        /// Before the given `ChannelHandler`.\n        case before(ChannelHandler & Sendable)\n\n        /// After the given `ChannelHandler`.\n        case after(ChannelHandler & Sendable)\n    }\n}\n\nextension ChannelPipeline.SynchronousOperations {\n    /// A `Position` within the `ChannelPipeline`'s `SynchronousOperations` used to insert non-sendable handlers\n    /// into the `ChannelPipeline` at a certain position.\n    public enum Position {\n        /// The first `ChannelHandler` -- the front of the `ChannelPipeline`.\n        case first\n\n        /// The last `ChannelHandler` -- the back of the `ChannelPipeline`.\n        case last\n\n        /// Before the given `ChannelHandler`.\n        case before(ChannelHandler)\n\n        /// After the given `ChannelHandler`.\n        case after(ChannelHandler)\n\n        public init(_ position: ChannelPipeline.Position) {\n            switch position {\n            case .first:\n                self = .first\n            case .last:\n                self = .last\n            case .before(let handler):\n                self = .before(handler)\n            case .after(let handler):\n                self = .after(handler)\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n@available(*, unavailable)\nextension ChannelPipeline.SynchronousOperations.Position: Sendable {}\n\n/// Special `ChannelHandler` that forwards all events to the `Channel.Unsafe` implementation.\nfinal class HeadChannelHandler: _ChannelOutboundHandler, Sendable {\n\n    static let name = \"head\"\n    static let sharedInstance = HeadChannelHandler()\n\n    private init() {}\n\n    func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        context.channel._channelCore.register0(promise: promise)\n    }\n\n    func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        context.channel._channelCore.bind0(to: address, promise: promise)\n    }\n\n    func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        context.channel._channelCore.connect0(to: address, promise: promise)\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        context.channel._channelCore.write0(data, promise: promise)\n    }\n\n    func flush(context: ChannelHandlerContext) {\n        context.channel._channelCore.flush0()\n    }\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        context.channel._channelCore.close0(error: mode.error, mode: mode, promise: promise)\n    }\n\n    func read(context: ChannelHandlerContext) {\n        context.channel._channelCore.read0()\n    }\n\n    func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {\n        context.channel._channelCore.triggerUserOutboundEvent0(event, promise: promise)\n    }\n\n}\n\nextension CloseMode {\n    /// Returns the error to fail outstanding operations writes with.\n    fileprivate var error: any Error {\n        switch self {\n        case .all:\n            return ChannelError._ioOnClosedChannel\n        case .output:\n            return ChannelError._outputClosed\n        case .input:\n            return ChannelError._inputClosed\n        }\n    }\n}\n\n/// Special `ChannelInboundHandler` which will consume all inbound events.\nfinal class TailChannelHandler: _ChannelInboundHandler, Sendable {\n\n    static let name = \"tail\"\n    static let sharedInstance = TailChannelHandler()\n\n    private init() {}\n\n    func channelRegistered(context: ChannelHandlerContext) {\n        // Discard\n    }\n\n    func channelUnregistered(context: ChannelHandlerContext) {\n        // Discard\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        // Discard\n    }\n\n    func channelInactive(context: ChannelHandlerContext) {\n        // Discard\n    }\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        // Discard\n    }\n\n    func channelWritabilityChanged(context: ChannelHandlerContext) {\n        // Discard\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        // Discard\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        context.channel._channelCore.errorCaught0(error: error)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.channel._channelCore.channelRead0(data)\n    }\n}\n\n/// `Error` that is used by the `ChannelPipeline` to inform the user of an error.\npublic enum ChannelPipelineError: Error {\n    /// `ChannelHandler` was already removed.\n    case alreadyRemoved\n    /// `ChannelHandler` was not found.\n    case notFound\n}\n\n/// Every `ChannelHandler` has -- when added to a `ChannelPipeline` -- a corresponding `ChannelHandlerContext` which is\n/// the way `ChannelHandler`s can interact with other `ChannelHandler`s in the pipeline.\n///\n/// Most `ChannelHandler`s need to send events through the `ChannelPipeline` which they do by calling the respective\n/// method on their `ChannelHandlerContext`. In fact all the `ChannelHandler` default implementations just forward\n/// the event using the `ChannelHandlerContext`.\n///\n/// Many events are instrumental for a `ChannelHandler`'s life-cycle and it is therefore very important to send them\n/// at the right point in time. Often, the right behaviour is to react to an event and then forward it to the next\n/// `ChannelHandler`.\npublic final class ChannelHandlerContext: ChannelInvoker {\n    // visible for ChannelPipeline to modify\n    fileprivate var next: Optional<ChannelHandlerContext>\n    fileprivate var prev: Optional<ChannelHandlerContext>\n\n    public let pipeline: ChannelPipeline\n\n    public var channel: Channel {\n        self.pipeline.channel\n    }\n\n    public var handler: ChannelHandler {\n        self.inboundHandler ?? self.outboundHandler!\n    }\n\n    public var remoteAddress: SocketAddress? {\n        do {\n            // Fast-path access to the remoteAddress.\n            return try self.channel._channelCore.remoteAddress0()\n        } catch ChannelError.ioOnClosedChannel {\n            // Channel was closed already but we may still have the address cached so try to access it via the Channel\n            // so we are able to use it in channelInactive(...) / handlerRemoved(...) methods.\n            return self.channel.remoteAddress\n        } catch {\n            return nil\n        }\n    }\n\n    public var localAddress: SocketAddress? {\n        do {\n            // Fast-path access to the localAddress.\n            return try self.channel._channelCore.localAddress0()\n        } catch ChannelError.ioOnClosedChannel {\n            // Channel was closed already but we may still have the address cached so try to access it via the Channel\n            // so we are able to use it in channelInactive(...) / handlerRemoved(...) methods.\n            return self.channel.localAddress\n        } catch {\n            return nil\n        }\n    }\n\n    public var eventLoop: EventLoop {\n        self.pipeline.eventLoop\n    }\n\n    public let name: String\n    private let inboundHandler: _ChannelInboundHandler?\n    private let outboundHandler: _ChannelOutboundHandler?\n    private var removeHandlerInvoked = false\n    private var userTriggeredRemovalStarted = false\n\n    // Only created from within ChannelPipeline\n    fileprivate init(name: String, handler: ChannelHandler, pipeline: ChannelPipeline) {\n        self.name = name\n        self.pipeline = pipeline\n        self.inboundHandler = handler as? _ChannelInboundHandler\n        self.outboundHandler = handler as? _ChannelOutboundHandler\n        self.next = nil\n        self.prev = nil\n        precondition(\n            self.inboundHandler != nil || self.outboundHandler != nil,\n            \"ChannelHandlers need to either be inbound or outbound\"\n        )\n    }\n\n    /// Send a `channelRegistered` event to the next (inbound) `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Note: For correct operation it is very important to forward any `channelRegistered` event using this method at the right point in time, that is usually when received.\n    public func fireChannelRegistered() {\n        self.next?.invokeChannelRegistered()\n    }\n\n    /// Send a `channelUnregistered` event to the next (inbound) `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Note: For correct operation it is very important to forward any `channelUnregistered` event using this method at the right point in time, that is usually when received.\n    public func fireChannelUnregistered() {\n        self.next?.invokeChannelUnregistered()\n    }\n\n    /// Send a `channelActive` event to the next (inbound) `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Note: For correct operation it is very important to forward any `channelActive` event using this method at the right point in time, that is often when received.\n    public func fireChannelActive() {\n        self.next?.invokeChannelActive()\n    }\n\n    /// Send a `channelInactive` event to the next (inbound) `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Note: For correct operation it is very important to forward any `channelInactive` event using this method at the right point in time, that is often when received.\n    public func fireChannelInactive() {\n        self.next?.invokeChannelInactive()\n    }\n\n    /// Send data to the next inbound `ChannelHandler`. The data should be of type `ChannelInboundHandler.InboundOut`.\n    public func fireChannelRead(_ data: NIOAny) {\n        self.next?.invokeChannelRead(data)\n    }\n\n    /// Signal to the next `ChannelHandler` that a read burst has finished.\n    public func fireChannelReadComplete() {\n        self.next?.invokeChannelReadComplete()\n    }\n\n    /// Send a `writabilityChanged` event to the next (inbound) `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Note: For correct operation it is very important to forward any `writabilityChanged` event using this method at the right point in time, that is usually when received.\n    public func fireChannelWritabilityChanged() {\n        self.next?.invokeChannelWritabilityChanged()\n    }\n\n    /// Send an error to the next inbound `ChannelHandler`.\n    public func fireErrorCaught(_ error: Error) {\n        self.next?.invokeErrorCaught(error)\n    }\n\n    /// Send a user event to the next inbound `ChannelHandler`.\n    ///\n    /// This method exists for compatiblity with ``ChannelInboundInvoker``.\n    @available(*, deprecated)\n    @_disfavoredOverload\n    public func fireUserInboundEventTriggered(_ event: Any & Sendable) {\n        self.next?.invokeUserInboundEventTriggered(event)\n    }\n\n    /// Send a user event to the next inbound `ChannelHandler` from on the event loop.\n    public func fireUserInboundEventTriggered(_ event: Any) {\n        self.next?.invokeUserInboundEventTriggered(event)\n    }\n\n    /// Send a `register` event to the next (outbound) `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Note: For correct operation it is very important to forward any `register` event using this method at the right point in time, that is usually when received.\n    public func register(promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeRegister(promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    /// Send a `bind` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `bind` event reaches the `HeadChannelHandler` a `ServerSocketChannel` will be bound.\n    ///\n    /// - Parameters:\n    ///   - address: The address to bind to.\n    ///   - promise: The promise fulfilled when the socket is bound or failed if it cannot be bound.\n    public func bind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeBind(to: address, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    /// Send a `connect` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `connect` event reaches the `HeadChannelHandler` a `SocketChannel` will be connected.\n    ///\n    /// - Parameters:\n    ///   - address: The address to connect to.\n    ///   - promise: The promise fulfilled when the socket is connected or failed if it cannot be connected.\n    public func connect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeConnect(to: address, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    /// Send a `write` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `write` event reaches the `HeadChannelHandler` the data will be enqueued to be written on the next\n    /// `flush` event.\n    ///\n    /// - Parameters:\n    ///   - data: The data to write, should be of type `ChannelOutboundHandler.OutboundOut`.\n    ///   - promise: The promise fulfilled when the data has been written or failed if it cannot be written.\n    public func write(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeWrite(data, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    /// Send a `flush` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `flush` event reaches the `HeadChannelHandler` the data previously enqueued will be attempted to be\n    /// written to the socket.\n    public func flush() {\n        if let outboundNext = self.prev {\n            outboundNext.invokeFlush()\n        }\n    }\n\n    /// Send a `write` event followed by a `flush` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `write` event reaches the `HeadChannelHandler` the data will be enqueued to be written when the `flush`\n    /// also reaches the `HeadChannelHandler`.\n    ///\n    /// - Parameters:\n    ///   - data: The data to write, should be of type `ChannelOutboundHandler.OutboundOut`.\n    ///   - promise: The promise fulfilled when the previously written data been written and flushed or if that failed.\n    public func writeAndFlush(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeWriteAndFlush(data, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    /// Send a `read` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `read` event reaches the `HeadChannelHandler` the interest to read data will be signalled to the\n    /// `Selector`. This will subsequently -- when data becomes readable -- cause `channelRead` events containing the\n    /// data being sent through the `ChannelPipeline`.\n    public func read() {\n        if let outboundNext = self.prev {\n            outboundNext.invokeRead()\n        }\n    }\n\n    /// Send a `close` event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    /// When the `close` event reaches the `HeadChannelHandler` the socket will be closed.\n    ///\n    /// - Parameters:\n    ///   - mode: The `CloseMode` to use.\n    ///   - promise: The promise fulfilled when the `Channel` has been closed or failed if it the closing failed.\n    public func close(mode: CloseMode = .all, promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeClose(mode: mode, promise: promise)\n        } else {\n            promise?.fail(ChannelError._alreadyClosed)\n        }\n    }\n\n    /// Send a user event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - event: The user event to send.\n    ///   - promise: The promise fulfilled when the user event has been sent or failed if it couldn't be sent.\n    @available(*, deprecated)\n    @_disfavoredOverload\n    public func triggerUserOutboundEvent(_ event: Any & Sendable, promise: EventLoopPromise<Void>?) {\n        self._triggerUserOutboundEvent(event, promise: promise)\n    }\n\n    /// Send a user event to the next outbound `ChannelHandler` in the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - event: The user event to send.\n    ///   - promise: The promise fulfilled when the user event has been sent or failed if it couldn't be sent.\n    public func triggerUserOutboundEvent(_ event: Any, promise: EventLoopPromise<Void>?) {\n        self._triggerUserOutboundEvent(event, promise: promise)\n    }\n\n    private func _triggerUserOutboundEvent(_ event: Any, promise: EventLoopPromise<Void>?) {\n        if let outboundNext = self.prev {\n            outboundNext.invokeTriggerUserOutboundEvent(event, promise: promise)\n        } else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n        }\n    }\n\n    fileprivate func invokeChannelRegistered() {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelRegistered(context: self)\n        } else {\n            self.next?.invokeChannelRegistered()\n        }\n    }\n\n    fileprivate func invokeChannelUnregistered() {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelUnregistered(context: self)\n        } else {\n            self.next?.invokeChannelUnregistered()\n        }\n    }\n\n    fileprivate func invokeChannelActive() {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelActive(context: self)\n        } else {\n            self.next?.invokeChannelActive()\n        }\n    }\n\n    fileprivate func invokeChannelInactive() {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelInactive(context: self)\n        } else {\n            self.next?.invokeChannelInactive()\n        }\n    }\n\n    fileprivate func invokeChannelRead(_ data: NIOAny) {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelRead(context: self, data: data)\n        } else {\n            self.next?.invokeChannelRead(data)\n        }\n    }\n\n    fileprivate func invokeChannelReadComplete() {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelReadComplete(context: self)\n        } else {\n            self.next?.invokeChannelReadComplete()\n        }\n    }\n\n    fileprivate func invokeChannelWritabilityChanged() {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.channelWritabilityChanged(context: self)\n        } else {\n            self.next?.invokeChannelWritabilityChanged()\n        }\n    }\n\n    fileprivate func invokeErrorCaught(_ error: Error) {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.errorCaught(context: self, error: error)\n        } else {\n            self.next?.invokeErrorCaught(error)\n        }\n    }\n\n    fileprivate func invokeUserInboundEventTriggered(_ event: Any) {\n        self.eventLoop.assertInEventLoop()\n\n        if let inboundHandler = self.inboundHandler {\n            inboundHandler.userInboundEventTriggered(context: self, event: event)\n        } else {\n            self.next?.invokeUserInboundEventTriggered(event)\n        }\n    }\n\n    fileprivate func invokeRegister(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.register(context: self, promise: promise)\n        } else {\n            self.prev?.invokeRegister(promise: promise)\n        }\n    }\n\n    fileprivate func invokeBind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.bind(context: self, to: address, promise: promise)\n        } else {\n            self.prev?.invokeBind(to: address, promise: promise)\n        }\n    }\n\n    fileprivate func invokeConnect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.connect(context: self, to: address, promise: promise)\n        } else {\n            self.prev?.invokeConnect(to: address, promise: promise)\n        }\n    }\n\n    fileprivate func invokeWrite(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.write(context: self, data: data, promise: promise)\n        } else {\n            self.prev?.invokeWrite(data, promise: promise)\n        }\n    }\n\n    fileprivate func invokeFlush() {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.flush(context: self)\n        } else {\n            self.prev?.invokeFlush()\n        }\n    }\n\n    fileprivate func invokeWriteAndFlush(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.write(context: self, data: data, promise: promise)\n            outboundHandler.flush(context: self)\n        } else {\n            self.prev?.invokeWriteAndFlush(data, promise: promise)\n        }\n    }\n\n    fileprivate func invokeRead() {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.read(context: self)\n        } else {\n            self.prev?.invokeRead()\n        }\n    }\n\n    fileprivate func invokeClose(mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.close(context: self, mode: mode, promise: promise)\n        } else {\n            self.prev?.invokeClose(mode: mode, promise: promise)\n        }\n    }\n\n    fileprivate func invokeTriggerUserOutboundEvent(_ event: Any, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        if let outboundHandler = self.outboundHandler {\n            outboundHandler.triggerUserOutboundEvent(context: self, event: event, promise: promise)\n        } else {\n            self.prev?.invokeTriggerUserOutboundEvent(event, promise: promise)\n        }\n    }\n\n    fileprivate func invokeHandlerAdded() {\n        self.eventLoop.assertInEventLoop()\n\n        handler.handlerAdded(context: self)\n    }\n\n    fileprivate func invokeHandlerRemoved() {\n        self.eventLoop.assertInEventLoop()\n        guard !self.removeHandlerInvoked else {\n            return\n        }\n        self.removeHandlerInvoked = true\n\n        handler.handlerRemoved(context: self)\n    }\n}\n\n// This extension \"un-deprecates\" some parts of the ChannelInvoker API for\n// ChannelHandlerContext specifically. These methods were not sound elsewhere,\n// but they're fine here.\nextension ChannelHandlerContext {\n    /// Write data to the remote peer.\n    ///\n    /// Be aware that to be sure that data is really written to the remote peer you need to call `flush` or use `writeAndFlush`.\n    /// Calling `write` multiple times and then `flush` may allow the `Channel` to `write` multiple data objects to the remote peer with one syscall.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the operation completes.\n    public func write(_ data: NIOAny, file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self, file: file, line: line)\n        self.write(data, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Shortcut for calling `write` and `flush`.\n    ///\n    /// - Parameters:\n    ///   - data: the data to write\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    /// - Returns: the future which will be notified once the `write` operation completes.\n    public func writeAndFlush(_ data: NIOAny, file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Void>\n    {\n        let promise = self.eventLoop.makePromise(of: Void.self, file: file, line: line)\n        self.writeAndFlush(data, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Returns this `ChannelHandlerContext` as a `NIOLoopBound`, bound to `self.eventLoop`.\n    ///\n    /// This is a shorthand for `NIOLoopBound(self, eventLoop: self.eventLoop)`.\n    ///\n    /// Being able to capture `ChannelHandlerContext`s in `EventLoopFuture` callbacks is important in SwiftNIO programs.\n    /// Of course, this is not always safe because the `EventLoopFuture` callbacks may run on other threads. SwiftNIO\n    /// programmers therefore always had to manually arrange for those callbacks to run on the correct `EventLoop`\n    /// (i.e. `context.eventLoop`) which then made that construction safe.\n    ///\n    /// Newer Swift versions contain a static feature to automatically detect data races which of course can't detect\n    /// the only _dynamically_ ``EventLoop`` a ``EventLoopFuture`` callback is running on. ``NIOLoopBound`` can be used\n    /// to prove to the compiler that this is safe and in case it is not, ``NIOLoopBound`` will trap at runtime. This is\n    /// therefore dynamically enforce the correct behaviour.\n    public var loopBound: NIOLoopBound<ChannelHandlerContext> {\n        NIOLoopBound(self, eventLoop: self.eventLoop)\n    }\n}\n\n@available(*, unavailable)\nextension ChannelHandlerContext: Sendable {}\n\nextension ChannelHandlerContext {\n    /// A `RemovalToken` is handed to a `RemovableChannelHandler` when its `removeHandler` function is invoked. A\n    /// `RemovableChannelHandler` is then required to remove itself from the `ChannelPipeline`. The removal process\n    /// is finalized by handing the `RemovalToken` to the `ChannelHandlerContext.leavePipeline` function.\n    public struct RemovalToken: Sendable {\n        internal let promise: EventLoopPromise<Void>?\n    }\n\n    /// Synchronously remove the `ChannelHandler` with the given `ChannelHandlerContext`.\n    ///\n    /// - Note: This function must only be used from a `RemovableChannelHandler` to remove itself. Calling this method\n    ///         on any other `ChannelHandlerContext` leads to undefined behaviour.\n    ///\n    /// - Parameters:\n    ///    - removalToken: The removal token received from `RemovableChannelHandler.removeHandler`\n    public func leavePipeline(removalToken: RemovalToken) {\n        self.eventLoop.preconditionInEventLoop()\n        self.pipeline.removeHandlerFromPipeline(context: self, promise: removalToken.promise)\n    }\n\n    internal func startUserTriggeredRemoval(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n        guard !self.userTriggeredRemovalStarted else {\n            promise?.fail(NIOAttemptedToRemoveHandlerMultipleTimesError())\n            return\n        }\n        self.userTriggeredRemovalStarted = true\n        (self.handler as! RemovableChannelHandler).removeHandler(\n            context: self,\n            removalToken: .init(promise: promise)\n        )\n    }\n}\n\nextension ChannelHandlerContext {\n    var sendableView: SendableView {\n        SendableView(wrapping: self)\n    }\n\n    /// A wrapper over ``ChannelHandlerContext`` that allows access to the thread-safe API\n    /// surface on the type.\n    ///\n    /// Very little of ``ChannelHandlerContext`` is thread-safe, but in a rare few places\n    /// there are things we can access. This type makes those available.\n    struct SendableView: @unchecked Sendable {\n        private let context: ChannelHandlerContext\n\n        fileprivate init(wrapping context: ChannelHandlerContext) {\n            self.context = context\n        }\n\n        /// Whether the ``ChannelHandler`` associated with this context conforms to\n        /// ``RemovableChannelHandler``.\n        var channelHandlerIsRemovable: Bool {\n            // `context.handler` is not mutable, and set at construction, so this access is\n            // acceptable. The protocol conformance check is also safe.\n            self.context.handler is RemovableChannelHandler\n        }\n\n        /// Grabs the underlying ``ChannelHandlerContext``. May only be called on the\n        /// event loop.\n        var wrappedValue: ChannelHandlerContext {\n            // The event loop lookup here is also thread-safe, so we can grab the value out\n            // and use it.\n            self.context.eventLoop.preconditionInEventLoop()\n            return self.context\n        }\n    }\n}\n\nextension ChannelPipeline: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        // This method forms output in the following format:\n        //\n        // ChannelPipeline[0x0000000000000000]:\n        //                      [I] ↓↑ [O]\n        //  <incoming handler type> ↓↑                         [<name>]\n        //                          ↓↑ <outgoing handler type> [<name>]\n        //    <duplex handler type> ↓↑ <duplex handler type>   [<name>]\n        //\n        var desc = [\"ChannelPipeline[\\(ObjectIdentifier(self))]:\"]\n        let debugInfos = self.collectHandlerDebugInfos()\n        let maxIncomingTypeNameCount =\n            debugInfos.filter { $0.isIncoming }\n            .map { $0.typeName.count }\n            .max() ?? 0\n        let maxOutgoingTypeNameCount =\n            debugInfos.filter { $0.isOutgoing }\n            .map { $0.typeName.count }\n            .max() ?? 0\n\n        func whitespace(count: Int) -> String {\n            String(repeating: \" \", count: count)\n        }\n\n        if debugInfos.isEmpty {\n            desc.append(\" <no handlers>\")\n        } else {\n            desc.append(whitespace(count: maxIncomingTypeNameCount - 2) + \"[I] ↓↑ [O]\")\n            for debugInfo in debugInfos {\n                var line = [String]()\n                line.append(\" \")\n                if debugInfo.isIncoming {\n                    line.append(whitespace(count: maxIncomingTypeNameCount - debugInfo.typeName.count))\n                    line.append(debugInfo.typeName)\n                } else {\n                    line.append(whitespace(count: maxIncomingTypeNameCount))\n                }\n                line.append(\" ↓↑ \")\n                if debugInfo.isOutgoing {\n                    line.append(debugInfo.typeName)\n                    line.append(whitespace(count: maxOutgoingTypeNameCount - debugInfo.typeName.count))\n                } else {\n                    line.append(whitespace(count: maxOutgoingTypeNameCount))\n                }\n                line.append(\" \")\n                line.append(\"[\\(debugInfo.name)]\")\n                desc.append(line.joined())\n            }\n        }\n\n        return desc.joined(separator: \"\\n\")\n    }\n\n    /// Returns the first `ChannelHandler` of the given type.\n    ///\n    /// - Parameters:\n    ///   - type: the type of `ChannelHandler` to return.\n    @inlinable\n    @preconcurrency\n    public func handler<Handler: ChannelHandler & _NIOCoreSendableMetatype>(\n        type _: Handler.Type\n    ) -> EventLoopFuture<Handler> {\n        self.context(handlerType: Handler.self).map { context in\n            guard let typedContext = context.handler as? Handler else {\n                preconditionFailure(\n                    \"Expected channel handler of type \\(Handler.self), got \\(type(of: context.handler)) instead.\"\n                )\n            }\n\n            return typedContext\n        }\n    }\n\n    /// Synchronously finds and returns the first `ChannelHandler` of the given type.\n    ///\n    /// - Important: This must be called on the `EventLoop`.\n    /// - Parameters:\n    ///   - type: the type of `ChannelHandler` to return.\n    @inlinable  // should be fileprivate\n    internal func _handlerSync<Handler: ChannelHandler>(type _: Handler.Type) -> Result<Handler, Error> {\n        self._contextSync(handlerType: Handler.self).map { context in\n            guard let typedContext = context.handler as? Handler else {\n                preconditionFailure(\n                    \"Expected channel handler of type \\(Handler.self), got \\(type(of: context.handler)) instead.\"\n                )\n            }\n            return typedContext\n        }\n    }\n\n    private struct ChannelHandlerDebugInfo {\n        let handler: ChannelHandler\n        let name: String\n        var isIncoming: Bool {\n            self.handler is _ChannelInboundHandler\n        }\n        var isOutgoing: Bool {\n            self.handler is _ChannelOutboundHandler\n        }\n        var typeName: String {\n            \"\\(type(of: self.handler))\"\n        }\n    }\n\n    private func collectHandlerDebugInfos() -> [ChannelHandlerDebugInfo] {\n        var handlers = [ChannelHandlerDebugInfo]()\n        var node = self.head?.next\n        while let context = node, context !== self.tail {\n            handlers.append(.init(handler: context.handler, name: context.name))\n            node = context.next\n        }\n        return handlers\n    }\n}\n\nextension ChannelPipeline {\n    private enum BufferingDirection: Equatable {\n        case inbound\n        case outbound\n    }\n\n    /// Retrieve the total number of bytes buffered for outbound.\n    public func outboundBufferedBytes() -> EventLoopFuture<Int> {\n        let future: EventLoopFuture<Int>\n\n        if self.eventLoop.inEventLoop {\n            future = self.eventLoop.makeSucceededFuture(countAllBufferedBytes(direction: .outbound))\n        } else {\n            future = self.eventLoop.submit {\n                self.countAllBufferedBytes(direction: .outbound)\n            }\n        }\n\n        return future\n    }\n\n    /// Retrieve the total number of bytes buffered for inbound.\n    public func inboundBufferedBytes() -> EventLoopFuture<Int> {\n        let future: EventLoopFuture<Int>\n\n        if self.eventLoop.inEventLoop {\n            future = self.eventLoop.makeSucceededFuture(countAllBufferedBytes(direction: .inbound))\n        } else {\n            future = self.eventLoop.submit {\n                self.countAllBufferedBytes(direction: .inbound)\n            }\n        }\n\n        return future\n    }\n\n    private static func countBufferedBytes(context: ChannelHandlerContext, direction: BufferingDirection) -> Int? {\n        switch direction {\n        case .inbound:\n            guard let handler = context.handler as? NIOInboundByteBufferingChannelHandler else {\n                return nil\n            }\n            return handler.inboundBufferedBytes\n        case .outbound:\n            guard let handler = context.handler as? NIOOutboundByteBufferingChannelHandler else {\n                return nil\n            }\n            return handler.outboundBufferedBytes\n        }\n\n    }\n\n    private func countAllBufferedBytes(direction: BufferingDirection) -> Int {\n        self.eventLoop.assertInEventLoop()\n        var total = 0\n        var current = self.head?.next\n        switch direction {\n        case .inbound:\n            while let c = current, c !== self.tail {\n                if let inboundHandler = c.handler as? NIOInboundByteBufferingChannelHandler {\n                    total += inboundHandler.inboundBufferedBytes\n                }\n                current = current?.next\n            }\n        case .outbound:\n            while let c = current, c !== self.tail {\n                if let outboundHandler = c.handler as? NIOOutboundByteBufferingChannelHandler {\n                    total += outboundHandler.outboundBufferedBytes\n                }\n                current = current?.next\n            }\n        }\n\n        return total\n    }\n}\n\nextension ChannelPipeline.SynchronousOperations {\n    /// Retrieve the total number of bytes buffered for outbound.\n    ///\n    /// - Important: This *must* be called on the event loop.\n    public func outboundBufferedBytes() -> Int {\n        self.eventLoop.assertInEventLoop()\n        return self._pipeline.countAllBufferedBytes(direction: .outbound)\n    }\n\n    /// Retrieve the number of outbound bytes buffered in the `ChannelHandler` associated with the given`ChannelHandlerContext`.\n    ///\n    /// - Parameters:\n    ///   - context: the `ChannelHandlerContext` from which the outbound buffered bytes of the `ChannelHandler` will be retrieved.\n    /// - Important: This *must* be called on the event loop.\n    ///\n    /// - Returns: The number of bytes currently buffered in the `ChannelHandler` referenced by the `ChannelHandlerContext` parameter `in`.\n    ///            If the `ChannelHandler` in the given `ChannelHandlerContext` does not conform to\n    ///            `NIOOutboundByteBufferingChannelHandler`, this method will return `nil`.\n    public func outboundBufferedBytes(in context: ChannelHandlerContext) -> Int? {\n        self.eventLoop.assertInEventLoop()\n        return ChannelPipeline.countBufferedBytes(context: context, direction: .outbound)\n    }\n\n    /// Retrieve total number of bytes buffered for inbound.\n    ///\n    /// - Important: This *must* be called on the event loop.\n    public func inboundBufferedBytes() -> Int {\n        self.eventLoop.assertInEventLoop()\n        return self._pipeline.countAllBufferedBytes(direction: .inbound)\n    }\n\n    /// Retrieve the number of inbound bytes buffered in the `ChannelHandler` associated with the given `ChannelHandlerContext`.\n    ///\n    /// - Parameters:\n    ///   - context: the `ChannelHandlerContext` from which the inbound buffered bytes of the `handler` will be retrieved.\n    /// - Important: This *must* be called on the event loop.\n    ///\n    /// - Returns: The number of bytes currently buffered in the `ChannelHandler` referenced by the `ChannelHandlerContext` parameter `in`.\n    ///            If the `ChannelHandler` in the given `ChannelHandlerContext` does not conform to\n    ///            `NIOInboundByteBufferingChannelHandler`, this method will return `nil`.\n    public func inboundBufferedBytes(in context: ChannelHandlerContext) -> Int? {\n        self.eventLoop.assertInEventLoop()\n        return ChannelPipeline.countBufferedBytes(context: context, direction: .inbound)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/CircularBuffer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// An automatically expanding ring buffer implementation backed by a `ContiguousArray`. Even though this implementation\n/// will automatically expand if more elements than `initialCapacity` are stored, it's advantageous to prevent\n/// expansions from happening frequently. Expansions will always force an allocation and a copy to happen.\npublic struct CircularBuffer<Element>: CustomStringConvertible {\n    @usableFromInline\n    internal private(set) var _buffer: ContiguousArray<Element?>\n\n    @usableFromInline\n    internal private(set) var headBackingIndex: Int\n\n    @usableFromInline\n    internal private(set) var tailBackingIndex: Int\n\n    @inlinable\n    internal var mask: Int {\n        self._buffer.count &- 1\n    }\n\n    @inlinable\n    internal mutating func advanceHeadIdx(by: Int) {\n        self.headBackingIndex = indexAdvanced(index: self.headBackingIndex, by: by)\n    }\n\n    @inlinable\n    internal mutating func advanceTailIdx(by: Int) {\n        self.tailBackingIndex = indexAdvanced(index: self.tailBackingIndex, by: by)\n    }\n\n    @inlinable\n    internal func indexBeforeHeadIdx() -> Int {\n        self.indexAdvanced(index: self.headBackingIndex, by: -1)\n    }\n\n    @inlinable\n    internal func indexBeforeTailIdx() -> Int {\n        self.indexAdvanced(index: self.tailBackingIndex, by: -1)\n    }\n\n    @inlinable\n    internal func indexAdvanced(index: Int, by: Int) -> Int {\n        (index &+ by) & self.mask\n    }\n\n    /// An opaque `CircularBuffer` index.\n    ///\n    /// You may get indices offset from other indices by using `CircularBuffer.index(:offsetBy:)`,\n    /// `CircularBuffer.index(before:)`, or `CircularBuffer.index(after:)`.\n    ///\n    /// - Note: Every index is invalidated as soon as you perform a length-changing operating on the `CircularBuffer`\n    ///         but remains valid when you replace one item by another using the subscript.\n    public struct Index: Comparable, Sendable {\n        @usableFromInline private(set) var _backingIndex: UInt32\n        @usableFromInline private(set) var _backingCheck: _UInt24\n        @usableFromInline private(set) var isIndexGEQHeadIndex: Bool\n\n        @inlinable\n        internal var backingIndex: Int {\n            Int(self._backingIndex)\n        }\n\n        @inlinable\n        internal init(backingIndex: Int, backingCount: Int, backingIndexOfHead: Int) {\n            self.isIndexGEQHeadIndex = backingIndex >= backingIndexOfHead\n            self._backingCheck = .max\n            self._backingIndex = UInt32(backingIndex)\n            debugOnly {\n                // if we can, we store the check for the backing here\n                self._backingCheck = backingCount < Int(_UInt24.max) ? _UInt24(UInt32(backingCount)) : .max\n            }\n        }\n\n        @inlinable\n        public static func == (lhs: Index, rhs: Index) -> Bool {\n            lhs._backingIndex == rhs._backingIndex && lhs._backingCheck == rhs._backingCheck\n                && lhs.isIndexGEQHeadIndex == rhs.isIndexGEQHeadIndex\n        }\n\n        @inlinable\n        public static func < (lhs: Index, rhs: Index) -> Bool {\n            if lhs.isIndexGEQHeadIndex && rhs.isIndexGEQHeadIndex {\n                return lhs.backingIndex < rhs.backingIndex\n            } else if lhs.isIndexGEQHeadIndex && !rhs.isIndexGEQHeadIndex {\n                return true\n            } else if !lhs.isIndexGEQHeadIndex && rhs.isIndexGEQHeadIndex {\n                return false\n            } else {\n                return lhs.backingIndex < rhs.backingIndex\n            }\n        }\n\n        @usableFromInline\n        internal func isValidIndex(for ring: CircularBuffer<Element>) -> Bool {\n            self._backingCheck == _UInt24.max || Int(self._backingCheck) == ring.count\n        }\n    }\n}\n\n// MARK: Collection/MutableCollection implementation\nextension CircularBuffer: Collection, MutableCollection {\n    public typealias Element = Element\n    public typealias Indices = DefaultIndices<CircularBuffer<Element>>\n    public typealias RangeType<Bound> = Range<Bound> where Bound: Strideable, Bound.Stride: SignedInteger\n    public typealias SubSequence = CircularBuffer<Element>\n\n    /// Returns the position immediately after the given index.\n    ///\n    /// The successor of an index must be well defined. For an index `i` into a\n    /// collection `c`, calling `c.index(after: i)` returns the same index every\n    /// time.\n    ///\n    /// - Parameter after: A valid index of the collection. `i` must be less than\n    ///   `endIndex`.\n    /// - Returns: The index value immediately after `i`.\n    @inlinable\n    public func index(after: Index) -> Index {\n        self.index(after, offsetBy: 1)\n    }\n\n    /// Returns the index before `index`.\n    @inlinable\n    public func index(before: Index) -> Index {\n        self.index(before, offsetBy: -1)\n    }\n\n    /// Accesses the element at the specified index.\n    ///\n    /// You can subscript `CircularBuffer` with any valid index other than the\n    /// `CircularBuffer`'s end index. The end index refers to the position one\n    /// past the last element of a collection, so it doesn't correspond with an\n    /// element.\n    ///\n    /// - Parameter position: The position of the element to access. `position`\n    ///   must be a valid index of the collection that is not equal to the\n    ///   `endIndex` property.\n    ///\n    /// - Complexity: O(1)\n    @inlinable\n    public subscript(position: Index) -> Element {\n        get {\n            assert(\n                position.isValidIndex(for: self),\n                \"illegal index used, index was for CircularBuffer with count \\(position._backingCheck), \"\n                    + \"but actual count is \\(self.count)\"\n            )\n            return self._buffer[position.backingIndex]!\n        }\n        set {\n            assert(\n                position.isValidIndex(for: self),\n                \"illegal index used, index was for CircularBuffer with count \\(position._backingCheck), \"\n                    + \"but actual count is \\(self.count)\"\n            )\n            self._buffer[position.backingIndex] = newValue\n        }\n    }\n\n    /// The position of the first element in a nonempty `CircularBuffer`.\n    ///\n    /// If the `CircularBuffer` is empty, `startIndex` is equal to `endIndex`.\n    @inlinable\n    public var startIndex: Index {\n        .init(\n            backingIndex: self.headBackingIndex,\n            backingCount: self.count,\n            backingIndexOfHead: self.headBackingIndex\n        )\n    }\n\n    /// The `CircularBuffer`'s \"past the end\" position---that is, the position one\n    /// greater than the last valid subscript argument.\n    ///\n    /// When you need a range that includes the last element of a collection, use\n    /// the half-open range operator (`..<`) with `endIndex`. The `..<` operator\n    /// creates a range that doesn't include the upper bound, so it's always\n    /// safe to use with `endIndex`.\n    ///\n    /// If the `CircularBuffer` is empty, `endIndex` is equal to `startIndex`.\n    @inlinable\n    public var endIndex: Index {\n        .init(\n            backingIndex: self.tailBackingIndex,\n            backingCount: self.count,\n            backingIndexOfHead: self.headBackingIndex\n        )\n    }\n\n    /// Returns the distance between two indices.\n    ///\n    /// Unless the collection conforms to the `BidirectionalCollection` protocol,\n    /// `start` must be less than or equal to `end`.\n    ///\n    /// - Parameters:\n    ///   - start: A valid index of the collection.\n    ///   - end: Another valid index of the collection. If `end` is equal to\n    ///     `start`, the result is zero.\n    /// - Returns: The distance between `start` and `end`. The result can be\n    ///   negative only if the collection conforms to the\n    ///   `BidirectionalCollection` protocol.\n    ///\n    /// - Complexity: O(1) if the collection conforms to\n    ///   `RandomAccessCollection`; otherwise, O(*k*), where *k* is the\n    ///   resulting distance.\n    @inlinable\n    public func distance(from start: CircularBuffer<Element>.Index, to end: CircularBuffer<Element>.Index) -> Int {\n        let backingCount = self._buffer.count\n\n        switch (start.isIndexGEQHeadIndex, end.isIndexGEQHeadIndex) {\n        case (true, true):\n            return end.backingIndex &- start.backingIndex\n        case (true, false):\n            return backingCount &- (start.backingIndex &- end.backingIndex)\n        case (false, true):\n            return -(backingCount &- (end.backingIndex &- start.backingIndex))\n        case (false, false):\n            return end.backingIndex &- start.backingIndex\n        }\n    }\n\n    @inlinable\n    public func _copyContents(\n        initializing buffer: UnsafeMutableBufferPointer<Element>\n    ) -> (Iterator, UnsafeMutableBufferPointer<Element>.Index) {\n        precondition(buffer.count >= self.count)\n\n        guard var ptr = buffer.baseAddress else {\n            return (self.makeIterator(), buffer.startIndex)\n        }\n\n        if self.tailBackingIndex >= self.headBackingIndex {\n            for index in self.headBackingIndex..<self.tailBackingIndex {\n                ptr.initialize(to: self._buffer[index]!)\n                ptr += 1\n            }\n        } else {\n            for index in self.headBackingIndex..<self._buffer.endIndex {\n                ptr.initialize(to: self._buffer[index]!)\n                ptr += 1\n            }\n            for index in 0..<self.tailBackingIndex {\n                ptr.initialize(to: self._buffer[index]!)\n                ptr += 1\n            }\n        }\n\n        return (self[self.endIndex..<self.endIndex].makeIterator(), self.count)\n    }\n\n    // These are implemented as no-ops for performance reasons.\n    @inlinable\n    public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {}\n\n    @inlinable\n    public func _failEarlyRangeCheck(_ index: Index, bounds: ClosedRange<Index>) {}\n\n    @inlinable\n    public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {}\n}\n\n// MARK: RandomAccessCollection implementation\nextension CircularBuffer: RandomAccessCollection {\n    /// Returns the index offset by `distance` from `index`.\n    ///\n    /// The following example obtains an index advanced four positions from a\n    /// string's starting index and then prints the character at that position.\n    ///\n    ///     let s = \"Swift\"\n    ///     let i = s.index(s.startIndex, offsetBy: 4)\n    ///     print(s[i])\n    ///     // Prints \"t\"\n    ///\n    /// The value passed as `distance` must not offset `i` beyond the bounds of\n    /// the collection.\n    ///\n    /// - Parameters:\n    ///   - i: A valid index of the collection.\n    ///   - distance: The distance to offset `i`. `distance` must not be negative\n    ///     unless the collection conforms to the `BidirectionalCollection`\n    ///     protocol.\n    /// - Returns: An index offset by `distance` from the index `i`. If\n    ///   `distance` is positive, this is the same value as the result of\n    ///   `distance` calls to `index(after:)`. If `distance` is negative, this\n    ///   is the same value as the result of `abs(distance)` calls to\n    ///   `index(before:)`.\n    ///\n    /// - Complexity: O(1) if the collection conforms to\n    ///   `RandomAccessCollection`; otherwise, O(*k*), where *k* is the absolute\n    ///   value of `distance`.\n    @inlinable\n    public func index(_ i: Index, offsetBy distance: Int) -> Index {\n        .init(\n            backingIndex: (i.backingIndex &+ distance) & self.mask,\n            backingCount: self.count,\n            backingIndexOfHead: self.headBackingIndex\n        )\n    }\n\n    @inlinable\n    public subscript(bounds: Range<Index>) -> SubSequence {\n        get {\n            precondition(self.distance(from: self.startIndex, to: bounds.lowerBound) >= 0)\n            precondition(self.distance(from: bounds.upperBound, to: self.endIndex) >= 0)\n\n            var newRing = self\n            newRing.headBackingIndex = bounds.lowerBound.backingIndex\n            newRing.tailBackingIndex = bounds.upperBound.backingIndex\n            return newRing\n        }\n        set {\n            precondition(self.distance(from: self.startIndex, to: bounds.lowerBound) >= 0)\n            precondition(self.distance(from: bounds.upperBound, to: self.endIndex) >= 0)\n\n            self.replaceSubrange(bounds, with: newValue)\n        }\n    }\n}\n\nextension CircularBuffer {\n\n    /// Allocates a buffer that can hold up to `initialCapacity` elements and initialise an empty ring backed by\n    /// the buffer. When the ring grows to more than `initialCapacity` elements the buffer will be expanded.\n    @inlinable\n    public init(initialCapacity: Int) {\n        let capacity = Int(UInt32(initialCapacity).nextPowerOf2())\n        self.headBackingIndex = 0\n        self.tailBackingIndex = 0\n        self._buffer = ContiguousArray<Element?>(repeating: nil, count: capacity)\n        assert(self._buffer.count == capacity)\n    }\n\n    /// Allocates an empty buffer.\n    @inlinable\n    public init() {\n        self = .init(initialCapacity: 16)\n    }\n\n    /// Append an element to the end of the ring buffer.\n    ///\n    /// Amortized *O(1)*\n    @inlinable\n    public mutating func append(_ value: Element) {\n        self._buffer[self.tailBackingIndex] = value\n        self.advanceTailIdx(by: 1)\n\n        if self.headBackingIndex == self.tailBackingIndex {\n            // No more room left for another append so grow the buffer now.\n            self._doubleCapacity()\n        }\n    }\n\n    /// Prepend an element to the front of the ring buffer.\n    ///\n    /// Amortized *O(1)*\n    @inlinable\n    public mutating func prepend(_ value: Element) {\n        let idx = self.indexBeforeHeadIdx()\n        self._buffer[idx] = value\n        self.advanceHeadIdx(by: -1)\n\n        if self.headBackingIndex == self.tailBackingIndex {\n            // No more room left for another append so grow the buffer now.\n            self._doubleCapacity()\n        }\n    }\n\n    /// Double the capacity of the buffer and adjust the headIdx and tailIdx.\n    ///\n    /// Must only be called when buffer is full.\n    @inlinable\n    internal mutating func _doubleCapacity() {\n        // Double the storage. This can't use _resizeAndFlatten because the buffer is\n        // full at this stage. That's ok: we have some optimised code paths for this use-case.\n        let newCapacity = self.capacity << 1\n        assert(self.headBackingIndex == self.tailBackingIndex)\n\n        var newBacking: ContiguousArray<Element?> = []\n        precondition(newCapacity > 0, \"Can't change capacity to \\(newCapacity)\")\n        assert(newCapacity % 2 == 0)\n        assert(newCapacity > self.capacity)\n\n        newBacking.reserveCapacity(newCapacity)\n        newBacking.append(contentsOf: self._buffer[self.headBackingIndex...])\n        newBacking.append(contentsOf: self._buffer[..<self.tailBackingIndex])\n\n        let newTailIndex = newBacking.count\n        let paddingCount = newCapacity &- newTailIndex\n        newBacking.append(contentsOf: repeatElement(nil, count: paddingCount))\n\n        self.headBackingIndex = 0\n        self.tailBackingIndex = newTailIndex\n        self._buffer = newBacking\n        assert(self.verifyInvariants())\n    }\n\n    /// Resizes and flatten this buffer.\n    ///\n    /// Capacities are always powers of 2.\n    @inlinable\n    internal mutating func _resizeAndFlatten(newCapacity: Int) {\n        var newBacking: ContiguousArray<Element?> = []\n        precondition(newCapacity > 0, \"Can't change capacity to \\(newCapacity)\")\n        assert(newCapacity % 2 == 0)\n        assert(newCapacity > self.capacity)\n\n        newBacking.reserveCapacity(newCapacity)\n\n        if self.tailBackingIndex >= self.headBackingIndex {\n            newBacking.append(contentsOf: self._buffer[self.headBackingIndex..<self.tailBackingIndex])\n        } else {\n            newBacking.append(contentsOf: self._buffer[self.headBackingIndex...])\n            newBacking.append(contentsOf: self._buffer[..<self.tailBackingIndex])\n        }\n\n        let newTailIndex = newBacking.count\n        let paddingCount = newCapacity &- newTailIndex\n        newBacking.append(contentsOf: repeatElement(nil, count: paddingCount))\n\n        self.headBackingIndex = 0\n        self.tailBackingIndex = newTailIndex\n        self._buffer = newBacking\n        assert(self.verifyInvariants())\n    }\n\n    /// Return element `offset` from first element.\n    ///\n    /// *O(1)*\n    @inlinable\n    public subscript(offset offset: Int) -> Element {\n        get {\n            self[self.index(self.startIndex, offsetBy: offset)]\n        }\n        set {\n            self[self.index(self.startIndex, offsetBy: offset)] = newValue\n        }\n    }\n\n    /// Returns whether the ring is empty.\n    @inlinable\n    public var isEmpty: Bool {\n        self.headBackingIndex == self.tailBackingIndex\n    }\n\n    /// Returns the number of element in the ring.\n    @inlinable\n    public var count: Int {\n        if self.tailBackingIndex >= self.headBackingIndex {\n            return self.tailBackingIndex &- self.headBackingIndex\n        } else {\n            return self._buffer.count &- (self.headBackingIndex &- self.tailBackingIndex)\n        }\n    }\n\n    /// The total number of elements that the ring can contain without allocating new storage.\n    @inlinable\n    public var capacity: Int {\n        self._buffer.count\n    }\n\n    /// Removes all members from the circular buffer whist keeping the capacity.\n    @inlinable\n    public mutating func removeAll(keepingCapacity: Bool = false) {\n        if keepingCapacity {\n            self.removeFirst(self.count)\n        } else {\n            self._buffer.removeAll(keepingCapacity: false)\n            self._buffer.append(nil)\n        }\n        self.headBackingIndex = 0\n        self.tailBackingIndex = 0\n        assert(self.verifyInvariants())\n    }\n\n    /// Modify the element at `index`.\n    ///\n    /// This function exists to provide a method of modifying the element in its underlying backing storage, instead\n    /// of copying it out, modifying it, and copying it back in. This emulates the behaviour of the `_modify` accessor\n    /// that is part of the generalized accessors work. That accessor is currently underscored and not safe to use, so\n    /// this is the next best thing.\n    ///\n    /// Note that this function is not guaranteed to be fast. In particular, as it is both generic and accepts a closure\n    /// it is possible that it will be slower than using the get/modify/set path that occurs with the subscript. If you\n    /// are interested in using this function for performance you *must* test and verify that the optimisation applies\n    /// correctly in your situation.\n    ///\n    /// - Parameters:\n    ///   - index: The index of the object that should be modified. If this index is invalid this function will trap.\n    ///   - modifyFunc: The function to apply to the modified object.\n    @inlinable\n    public mutating func modify<Result>(\n        _ index: Index,\n        _ modifyFunc: (inout Element) throws -> Result\n    ) rethrows -> Result {\n        try modifyFunc(&self._buffer[index.backingIndex]!)\n    }\n\n    // MARK: CustomStringConvertible implementation\n    /// Returns a human readable description of the ring.\n    public var description: String {\n        var desc = \"[ \"\n        for el in self._buffer.enumerated() {\n            if el.0 == self.headBackingIndex {\n                desc += \"<\"\n            } else if el.0 == self.tailBackingIndex {\n                desc += \">\"\n            }\n            desc += el.1.map { \"\\($0) \" } ?? \"_ \"\n        }\n        desc += \"]\"\n        desc += \" (bufferCapacity: \\(self._buffer.count), ringLength: \\(self.count))\"\n        return desc\n    }\n}\n\n// MARK: - RangeReplaceableCollection\nextension CircularBuffer: RangeReplaceableCollection {\n    /// Removes and returns the first element of the `CircularBuffer`.\n    ///\n    /// Calling this method may invalidate all saved indices of this\n    /// `CircularBuffer`. Do not rely on a previously stored index value after\n    /// altering a `CircularBuffer` with any operation that can change its length.\n    ///\n    /// - Returns: The first element of the `CircularBuffer` if the `CircularBuffer` is not\n    ///            empty; otherwise, `nil`.\n    ///\n    /// - Complexity: O(1)\n    @inlinable\n    public mutating func popFirst() -> Element? {\n        if count > 0 {\n            return self.removeFirst()\n        } else {\n            return nil\n        }\n    }\n\n    /// Removes and returns the last element of the `CircularBuffer`.\n    ///\n    /// Calling this method may invalidate all saved indices of this\n    /// `CircularBuffer`. Do not rely on a previously stored index value after\n    /// altering a `CircularBuffer` with any operation that can change its length.\n    ///\n    /// - Returns: The last element of the `CircularBuffer` if the `CircularBuffer` is not\n    ///            empty; otherwise, `nil`.\n    ///\n    /// - Complexity: O(1)\n    @inlinable\n    public mutating func popLast() -> Element? {\n        if count > 0 {\n            return self.removeLast()\n        } else {\n            return nil\n        }\n    }\n\n    /// Removes the specified number of elements from the end of the\n    /// `CircularBuffer`.\n    ///\n    /// Attempting to remove more elements than exist in the `CircularBuffer`\n    /// triggers a runtime error.\n    ///\n    /// Calling this method may invalidate all saved indices of this\n    /// `CircularBuffer`. Do not rely on a previously stored index value after\n    /// altering a `CircularBuffer` with any operation that can change its length.\n    ///\n    /// - Parameter k: The number of elements to remove from the `CircularBuffer`.\n    ///   `k` must be greater than or equal to zero and must not exceed the\n    ///   number of elements in the `CircularBuffer`.\n    ///\n    /// - Complexity: O(*k*), where *k* is the specified number of elements.\n    @inlinable\n    public mutating func removeLast(_ k: Int) {\n        precondition(k <= self.count, \"Number of elements to drop bigger than the amount of elements in the buffer.\")\n        var idx = self.tailBackingIndex\n        for _ in 0..<k {\n            idx = self.indexAdvanced(index: idx, by: -1)\n            self._buffer[idx] = nil\n        }\n        self.tailBackingIndex = idx\n    }\n\n    /// Removes the specified number of elements from the beginning of the\n    /// `CircularBuffer`.\n    ///\n    /// Calling this method may invalidate any existing indices for use with this\n    /// `CircularBuffer`.\n    ///\n    /// - Parameter k: The number of elements to remove.\n    ///   `k` must be greater than or equal to zero and must not exceed the\n    ///   number of elements in the `CircularBuffer`.\n    ///\n    /// - Complexity: O(*k*), where *k* is the specified number of elements.\n    @inlinable\n    public mutating func removeFirst(_ k: Int) {\n        precondition(k <= self.count, \"Number of elements to drop bigger than the amount of elements in the buffer.\")\n        var idx = self.headBackingIndex\n        for _ in 0..<k {\n            self._buffer[idx] = nil\n            idx = self.indexAdvanced(index: idx, by: 1)\n        }\n        self.headBackingIndex = idx\n    }\n\n    /// Removes and returns the first element of the `CircularBuffer`.\n    ///\n    /// The `CircularBuffer` must not be empty.\n    ///\n    /// Calling this method may invalidate any existing indices for use with this\n    /// `CircularBuffer`.\n    ///\n    /// - Returns: The removed element.\n    ///\n    /// - Complexity: O(*1*)\n    @discardableResult\n    @inlinable\n    public mutating func removeFirst() -> Element {\n        defer {\n            self.removeFirst(1)\n        }\n        return self.first!\n    }\n\n    /// Removes and returns the last element of the `CircularBuffer`.\n    ///\n    /// The `CircularBuffer` must not be empty.\n    ///\n    /// Calling this method may invalidate all saved indices of this\n    /// `CircularBuffer`. Do not rely on a previously stored index value after\n    /// altering the `CircularBuffer` with any operation that can change its length.\n    ///\n    /// - Returns: The last element of the `CircularBuffer`.\n    ///\n    /// - Complexity: O(*1*)\n    @discardableResult\n    @inlinable\n    public mutating func removeLast() -> Element {\n        defer {\n            self.removeLast(1)\n        }\n        return self.last!\n    }\n\n    /// Replaces the specified subrange of elements with the given `CircularBuffer`.\n    ///\n    /// - Parameter subrange: The subrange of the collection to replace. The bounds of the range must be valid indices\n    ///                       of the `CircularBuffer`.\n    ///\n    /// - Parameter newElements: The new elements to add to the `CircularBuffer`.\n    ///\n    /// *O(n)* where _n_ is the length of the new elements collection if the subrange equals to _n_\n    ///\n    /// *O(m)* where _m_ is the combined length of the collection and _newElements_\n    @inlinable\n    public mutating func replaceSubrange<C: Collection>(_ subrange: Range<Index>, with newElements: C)\n    where Element == C.Element {\n        precondition(\n            subrange.lowerBound >= self.startIndex && subrange.upperBound <= self.endIndex,\n            \"Subrange out of bounds\"\n        )\n        assert(\n            subrange.lowerBound.isValidIndex(for: self),\n            \"illegal index used, index was for CircularBuffer with count \\(subrange.lowerBound._backingCheck), \"\n                + \"but actual count is \\(self.count)\"\n        )\n        assert(\n            subrange.upperBound.isValidIndex(for: self),\n            \"illegal index used, index was for CircularBuffer with count \\(subrange.upperBound._backingCheck), \"\n                + \"but actual count is \\(self.count)\"\n        )\n\n        let subrangeCount = self.distance(from: subrange.lowerBound, to: subrange.upperBound)\n\n        if subrangeCount == newElements.count {\n            var index = subrange.lowerBound\n            for element in newElements {\n                self._buffer[index.backingIndex] = element\n                index = self.index(after: index)\n            }\n        } else if subrangeCount == self.count && newElements.isEmpty {\n            self.removeSubrange(subrange)\n        } else {\n            var newBuffer: ContiguousArray<Element?> = []\n            let neededNewCapacity = self.count + newElements.count - subrangeCount + 1  // always one spare\n            let newCapacity = Swift.max(self.capacity, neededNewCapacity.nextPowerOf2())\n            newBuffer.reserveCapacity(newCapacity)\n\n            // This mapping is required due to an inconsistent ability to append sequences of non-optional\n            // to optional sequences.\n            // https://bugs.swift.org/browse/SR-7921\n            newBuffer.append(contentsOf: self[self.startIndex..<subrange.lowerBound].lazy.map { $0 })\n            newBuffer.append(contentsOf: newElements.lazy.map { $0 })\n            newBuffer.append(contentsOf: self[subrange.upperBound..<self.endIndex].lazy.map { $0 })\n\n            let repetitionCount = newCapacity &- newBuffer.count\n            if repetitionCount > 0 {\n                newBuffer.append(contentsOf: repeatElement(nil, count: repetitionCount))\n            }\n            self._buffer = newBuffer\n            self.headBackingIndex = 0\n            self.tailBackingIndex = newBuffer.count &- repetitionCount\n        }\n        assert(self.verifyInvariants())\n    }\n\n    /// Removes the elements in the specified subrange from the circular buffer.\n    ///\n    /// - Parameter bounds: The range of the circular buffer to be removed. The bounds of the range must be valid indices of the collection.\n    @inlinable\n    public mutating func removeSubrange(_ bounds: Range<Index>) {\n        precondition(bounds.upperBound >= self.startIndex && bounds.upperBound <= self.endIndex, \"Invalid bounds.\")\n\n        let boundsCount = self.distance(from: bounds.lowerBound, to: bounds.upperBound)\n        switch boundsCount {\n        case 1:\n            remove(at: bounds.lowerBound)\n        case self.count:\n            self = .init(initialCapacity: self._buffer.count)\n        default:\n            replaceSubrange(bounds, with: [])\n        }\n        assert(self.verifyInvariants())\n    }\n\n    /// Removes & returns the item at `position` from the buffer\n    ///\n    /// - Parameter position: The index of the item to be removed from the buffer.\n    ///\n    /// *O(1)* if the position is `headIdx` or `tailIdx`.\n    /// otherwise\n    /// *O(n)* where *n* is the number of elements between `position` and `tailIdx`.\n    @discardableResult\n    @inlinable\n    public mutating func remove(at position: Index) -> Element {\n        assert(\n            position.isValidIndex(for: self),\n            \"illegal index used, index was for CircularBuffer with count \\(position._backingCheck), \"\n                + \"but actual count is \\(self.count)\"\n        )\n        defer {\n            assert(self.verifyInvariants())\n        }\n        precondition(self.indices.contains(position), \"Position out of bounds.\")\n        var bufferIndex = position.backingIndex\n        let element = self._buffer[bufferIndex]!\n\n        switch bufferIndex {\n        case self.headBackingIndex:\n            self.advanceHeadIdx(by: 1)\n            self._buffer[bufferIndex] = nil\n        case self.indexBeforeTailIdx():\n            self.advanceTailIdx(by: -1)\n            self._buffer[bufferIndex] = nil\n        default:\n            self._buffer[bufferIndex] = nil\n            var nextIndex = self.indexAdvanced(index: bufferIndex, by: 1)\n            while nextIndex != self.tailBackingIndex {\n                self._buffer.swapAt(bufferIndex, nextIndex)\n                bufferIndex = nextIndex\n                nextIndex = self.indexAdvanced(index: bufferIndex, by: 1)\n            }\n            self.advanceTailIdx(by: -1)\n        }\n\n        return element\n    }\n\n    /// The first `Element` of the `CircularBuffer` (or `nil` if empty).\n    @inlinable\n    public var first: Element? {\n        // We implement this here to work around https://bugs.swift.org/browse/SR-14516\n        guard !self.isEmpty else {\n            return nil\n        }\n        return self[self.startIndex]\n    }\n\n    /// Prepares the `CircularBuffer` to store the specified number of elements.\n    @inlinable\n    public mutating func reserveCapacity(_ minimumCapacity: Int) {\n        if self.capacity >= minimumCapacity {\n            // Already done, do nothing.\n            return\n        }\n\n        // We need to allocate a larger buffer. We take this opportunity to make ourselves contiguous\n        // again as needed.\n        let targetCapacity = minimumCapacity.nextPowerOf2()\n        self._resizeAndFlatten(newCapacity: targetCapacity)\n    }\n}\n\nextension CircularBuffer {\n    @usableFromInline\n    internal func verifyInvariants() -> Bool {\n        var index = self.headBackingIndex\n        while index != self.tailBackingIndex {\n            if self._buffer[index] == nil {\n                return false\n            }\n            index = self.indexAdvanced(index: index, by: 1)\n        }\n        return true\n    }\n\n    // this is not a general invariant (not true for CircularBuffer that have been sliced)\n    private func unreachableAreNil() -> Bool {\n        var index = self.tailBackingIndex\n        while index != self.headBackingIndex {\n            if self._buffer[index] != nil {\n                return false\n            }\n            index = self.indexAdvanced(index: index, by: 1)\n        }\n        return true\n    }\n\n    internal func testOnly_verifyInvariantsForNonSlices() -> Bool {\n        self.verifyInvariants() && self.unreachableAreNil()\n    }\n}\n\nextension CircularBuffer: Equatable where Element: Equatable {\n    public static func == (lhs: CircularBuffer, rhs: CircularBuffer) -> Bool {\n        lhs.count == rhs.count && zip(lhs, rhs).allSatisfy(==)\n    }\n}\n\nextension CircularBuffer: Hashable where Element: Hashable {\n    public func hash(into hasher: inout Hasher) {\n        for element in self {\n            hasher.combine(element)\n        }\n    }\n}\n\nextension CircularBuffer: Sendable where Element: Sendable {}\n\nextension CircularBuffer: ExpressibleByArrayLiteral {\n    public init(arrayLiteral elements: Element...) {\n        self.init(elements)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/Codec.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// State of the current decoding process.\npublic enum DecodingState: Sendable {\n    /// Continue decoding.\n    case `continue`\n\n    /// Stop decoding until more data is ready to be processed.\n    case needMoreData\n}\n\n/// Common errors thrown by `ByteToMessageDecoder`s.\npublic enum ByteToMessageDecoderError: Error {\n    /// More data has been received by a `ByteToMessageHandler` despite the fact that an error has previously been\n    /// emitted. The associated `Error` is the error previously emitted and the `ByteBuffer` is the extra data that has\n    /// been received. The common cause for this error to be emitted is the user not having torn down the `Channel`\n    /// after previously an `Error` has been sent through the pipeline using `fireErrorCaught`.\n    case dataReceivedInErrorState(Error, ByteBuffer)\n\n    /// This error can be thrown by `ByteToMessageDecoder`s if there was unexpectedly some left-over data when the\n    /// `ByteToMessageDecoder` was removed from the pipeline or the `Channel` was closed.\n    case leftoverDataWhenDone(ByteBuffer)\n}\n\nextension ByteToMessageDecoderError {\n    // TODO: For NIO 3, make this an enum case (or whatever best way for Errors we have come up with).\n    /// This error can be thrown by `ByteToMessageDecoder`s if the incoming payload is larger than the max specified.\n    public struct PayloadTooLargeError: Error {\n        public init() {}\n    }\n}\n\n/// `ByteToMessageDecoder`s decode bytes in a stream-like fashion from `ByteBuffer` to another message type.\n///\n/// ### Purpose\n///\n/// A `ByteToMessageDecoder` provides a simplified API for handling streams of incoming data that can be broken\n/// up into messages. This API boils down to two methods: `decode`, and `decodeLast`. These two methods, when\n/// implemented, will be used by a `ByteToMessageHandler` paired with a `ByteToMessageDecoder` to decode the\n/// incoming byte stream into a sequence of messages.\n///\n/// The reason this helper exists is to smooth away some of the boilerplate and edge case handling code that\n/// is often necessary when implementing parsers in a SwiftNIO `ChannelPipeline`. A `ByteToMessageDecoder`\n/// never needs to worry about how inbound bytes will be buffered, as `ByteToMessageHandler` deals with that\n/// automatically. A `ByteToMessageDecoder` also never needs to worry about memory exclusivity violations\n/// that can occur when re-entrant `ChannelPipeline` operations occur, as `ByteToMessageHandler` will deal with\n/// those as well.\n///\n/// ### Implementing ByteToMessageDecoder\n///\n/// A type that implements `ByteToMessageDecoder` may implement two methods: decode and decodeLast. Implementations\n/// must implement decode: if they do not implement decodeLast, a default implementation will be used that\n/// simply calls decode.\n///\n/// `decode` is the main decoding method, and is the one that will be called most often. `decode` is invoked\n/// whenever data is received by the wrapping `ByteToMessageHandler`. It is invoked with a `ByteBuffer` containing\n/// all the received data (including any data previously buffered), as well as a `ChannelHandlerContext` that can be\n/// used in the `decode` function.\n///\n/// `decode` is called in a loop by the `ByteToMessageHandler`. This loop continues until one of two cases occurs:\n///\n/// 1. The input `ByteBuffer` has no more readable bytes (i.e. `.readableBytes == 0`); OR\n/// 2. The `decode` method returns `.needMoreData`.\n///\n/// The reason this method is invoked in a loop is to ensure that the stream-like properties of inbound data are\n/// respected. It is entirely possible for `ByteToMessageDecoder` to receive either fewer bytes than a single message,\n/// or multiple messages in one go. Rather than have the `ByteToMessageDecoder` handle all of the complexity of this,\n/// the logic can be boiled down to a single choice: has the `ByteToMessageDecoder` been able to move the state forward\n/// or not? If it has, rather than containing an internal loop it may simply return `.continue` in order to request that\n/// `decode` be invoked again immediately. If it has not, it can return `.needMoreData` to ask to be left alone until more\n/// data has been returned from the network.\n///\n/// Essentially, if the next parsing step could not be taken because there wasn't enough data available, return `.needMoreData`.\n/// Otherwise, return `.continue`. This will allow a `ByteToMessageDecoder` implementation to ignore the awkward way data\n/// arrives from the network, and to just treat it as a series of `decode` calls.\n///\n/// `decodeLast` is a cousin of `decode`. It is also called in a loop, but unlike with `decode` this loop will only ever\n/// occur once: when the `ChannelHandlerContext` belonging to this `ByteToMessageDecoder` is about to become invalidated.\n/// This invalidation happens in two situations: when EOF is received from the network, or when the `ByteToMessageDecoder`\n/// is being removed from the `ChannelPipeline`. The distinction between these two states is captured by the value of\n/// `seenEOF`.\n///\n/// In this condition, the `ByteToMessageDecoder` must now produce any final messages it can with the bytes it has\n/// available. In protocols where EOF is used as a message delimiter, having `decodeLast` called with `seenEOF == true`\n/// may produce further messages. In other cases, `decodeLast` may choose to deliver any buffered bytes as \"leftovers\",\n/// either in error messages or via `channelRead`. This can occur if, for example, a protocol upgrade is occurring.\n///\n/// As with `decode`, `decodeLast` is invoked in a loop. This allows the same simplification as `decode` allows: when\n/// a message is completely parsed, the `decodeLast` function can return `.continue` and be re-invoked from the top,\n/// rather than containing an internal loop.\n///\n/// Note that the value of `seenEOF` may change between calls to `decodeLast` in some rare situations.\n///\n/// ### Implementers Notes\n///\n/// `ByteToMessageHandler` will turn your `ByteToMessageDecoder` into a `ChannelInboundHandler`. `ByteToMessageHandler`\n/// also solves a couple of tricky issues for you. Most importantly, in a `ByteToMessageDecoder` you do _not_ need to\n/// worry about re-entrancy. Your code owns the passed-in `ByteBuffer` for the duration of the `decode`/`decodeLast` call and\n/// can modify it at will.\n///\n/// If a custom frame decoder is required, then one needs to be careful when implementing\n/// one with `ByteToMessageDecoder`. Ensure there are enough bytes in the buffer for a\n/// complete frame by checking `buffer.readableBytes`. If there are not enough bytes\n/// for a complete frame, return without modifying the reader index to allow more bytes to arrive.\n///\n/// To check for complete frames without modifying the reader index, use methods like `buffer.getInteger`.\n/// You  _MUST_ use the reader index when using methods like `buffer.getInteger`.\n/// For example calling `buffer.getInteger(at: 0)` is assuming the frame starts at the beginning of the buffer, which\n/// is not always the case. Use `buffer.getInteger(at: buffer.readerIndex)` instead.\n///\n/// If you move the reader index forward, either manually or by using one of `buffer.read*` methods, you must ensure\n/// that you no longer need to see those bytes again as they will not be returned to you the next time `decode` is\n/// called. If you still need those bytes to come back, consider taking a local copy of buffer inside the function to\n/// perform your read operations on.\n///\n/// The `ByteBuffer` passed in as `buffer` is a slice of a larger buffer owned by the `ByteToMessageDecoder`\n/// implementation. Some aspects of this buffer are preserved across calls to `decode`, meaning that any changes to\n/// those properties you make in your `decode` method will be reflected in the next call to decode. In particular,\n/// moving the reader index forward persists across calls. When your method returns, if the reader index has advanced,\n/// those bytes are considered \"consumed\" and will not be available in future calls to `decode`.\n/// Please note, however, that the numerical value of the `readerIndex` itself is not preserved, and may not be the same\n/// from one call to the next. Please do not rely on this numerical value: if you need\n/// to recall where a byte is relative to the `readerIndex`, use an offset rather than an absolute value.\n///\n/// ### Using ByteToMessageDecoder\n///\n/// To add a `ByteToMessageDecoder` to the `ChannelPipeline` use\n///\n///     channel.pipeline.addHandler(ByteToMessageHandler(MyByteToMessageDecoder()))\n///\npublic protocol ByteToMessageDecoder {\n    /// The type of the messages this `ByteToMessageDecoder` decodes to.\n    associatedtype InboundOut\n\n    /// Decode from a `ByteBuffer`.\n    ///\n    /// This method will be called in a loop until either the input `ByteBuffer` has nothing to read left or\n    /// `DecodingState.needMoreData` is returned. If `DecodingState.continue` is returned and the `ByteBuffer`\n    /// contains more readable bytes, this method will immediately be invoked again, unless `decodeLast` needs\n    /// to be invoked instead.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ByteToMessageDecoder` belongs to.\n    ///   - buffer: The `ByteBuffer` from which we decode.\n    /// - Returns: `DecodingState.continue` if we should continue calling this method or `DecodingState.needMoreData` if it should be called\n    ///            again once more data is present in the `ByteBuffer`.\n    mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState\n\n    /// Decode from a `ByteBuffer` when no more data is incoming and the `ByteToMessageDecoder` is about to leave\n    /// the pipeline.\n    ///\n    /// This method is called in a loop only once, when the `ChannelHandlerContext` goes inactive (i.e. when `channelInactive` is fired or\n    /// the `ByteToMessageDecoder` is removed from the pipeline).\n    ///\n    /// Like with `decode`, this method will be called in a loop until either `DecodingState.needMoreData` is returned from the method\n    /// or until the input `ByteBuffer` has no more readable bytes. If `DecodingState.continue` is returned and the `ByteBuffer`\n    /// contains more readable bytes, this method will immediately be invoked again.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ByteToMessageDecoder` belongs to.\n    ///   - buffer: The `ByteBuffer` from which we decode.\n    ///   - seenEOF: `true` if EOF has been seen. Usually if this is `false` the handler has been removed.\n    /// - Returns: `DecodingState.continue` if we should continue calling this method or `DecodingState.needMoreData` if it should be called\n    ///            again when more data is present in the `ByteBuffer`.\n    mutating func decodeLast(\n        context: ChannelHandlerContext,\n        buffer: inout ByteBuffer,\n        seenEOF: Bool\n    ) throws -> DecodingState\n\n    /// Called once this `ByteToMessageDecoder` is removed from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ByteToMessageDecoder` belongs to.\n    mutating func decoderRemoved(context: ChannelHandlerContext)\n\n    /// Called when this `ByteToMessageDecoder` is added to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ByteToMessageDecoder` belongs to.\n    mutating func decoderAdded(context: ChannelHandlerContext)\n\n    /// Determine if the read bytes in the given `ByteBuffer` should be reclaimed and their associated memory freed.\n    /// Be aware that reclaiming memory may involve memory copies and so is not free.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` to check\n    /// - return: `true` if memory should be reclaimed, `false` otherwise.\n    mutating func shouldReclaimBytes(buffer: ByteBuffer) -> Bool\n}\n\n/// Some `ByteToMessageDecoder`s need to observe `write`s (which are outbound events). `ByteToMessageDecoder`s which\n/// implement the `WriteObservingByteToMessageDecoder` protocol will be notified about every outbound write.\n///\n/// `WriteObservingByteToMessageDecoder` may only observe a `write` and must not try to transform or block it in any\n/// way. After the `write` method returns the `write` will be forwarded to the next outbound handler.\npublic protocol WriteObservingByteToMessageDecoder: ByteToMessageDecoder {\n    /// The type of `write`s.\n    associatedtype OutboundIn\n\n    /// `write` is called for every incoming `write` incoming to the corresponding `ByteToMessageHandler`.\n    ///\n    /// - Parameters:\n    ///    - data: The data that was written.\n    mutating func write(data: OutboundIn)\n}\n\nextension ByteToMessageDecoder {\n    public mutating func decoderRemoved(context: ChannelHandlerContext) {\n    }\n\n    public mutating func decoderAdded(context: ChannelHandlerContext) {\n    }\n\n    /// Default implementation to detect once bytes should be reclaimed.\n    public func shouldReclaimBytes(buffer: ByteBuffer) -> Bool {\n        // We want to reclaim in the following cases:\n        //\n        // 1. If there is at least 2kB of memory to reclaim\n        // 2. If the buffer is more than 50% reclaimable memory and is at least\n        //    1kB in size.\n        if buffer.readerIndex >= 2048 {\n            return true\n        }\n        return buffer.storageCapacity > 1024 && (buffer.storageCapacity - buffer.readerIndex) < buffer.readerIndex\n    }\n\n    @inlinable\n    public func wrapInboundOut(_ value: InboundOut) -> NIOAny {\n        NIOAny(value)\n    }\n\n    @inlinable\n    public static func wrapInboundOut(_ value: InboundOut) -> NIOAny {\n        NIOAny(value)\n    }\n\n    public mutating func decodeLast(\n        context: ChannelHandlerContext,\n        buffer: inout ByteBuffer,\n        seenEOF: Bool\n    ) throws -> DecodingState {\n        while try self.decode(context: context, buffer: &buffer) == .continue {}\n        return .needMoreData\n    }\n}\n\nprivate struct B2MDBuffer {\n    /// `B2MDBuffer`'s internal state, either we're already processing a buffer or we're ready to.\n    private enum State {\n        case processingInProgress\n        case ready\n    }\n\n    /// Can we produce a buffer to be processed right now or not?\n    enum BufferAvailability {\n        /// No, because no bytes available\n        case nothingAvailable\n        /// No, because we're already processing one\n        case bufferAlreadyBeingProcessed\n        /// Yes please, here we go.\n        case available(ByteBuffer)\n    }\n\n    /// Result of a try to process a buffer.\n    enum BufferProcessingResult {\n        /// Could not process a buffer because we are already processing one on the same call stack.\n        case cannotProcessReentrantly\n        /// Yes, we did process some.\n        case didProcess(DecodingState)\n    }\n\n    private var state: State = .ready\n    private var buffers: CircularBuffer<ByteBuffer> = CircularBuffer(initialCapacity: 4)\n    private let emptyByteBuffer: ByteBuffer\n\n    init(emptyByteBuffer: ByteBuffer) {\n        assert(emptyByteBuffer.readableBytes == 0)\n        self.emptyByteBuffer = emptyByteBuffer\n    }\n}\n\n// MARK: B2MDBuffer Main API\nextension B2MDBuffer {\n    /// Start processing some bytes if possible, if we receive a returned buffer (through `.available(ByteBuffer)`)\n    /// we _must_ indicate the processing has finished by calling `finishProcessing`.\n    mutating func startProcessing(allowEmptyBuffer: Bool) -> BufferAvailability {\n        switch self.state {\n        case .processingInProgress:\n            return .bufferAlreadyBeingProcessed\n        case .ready where self.buffers.count > 0:\n            var buffer = self.buffers.removeFirst()\n            buffer.writeBuffers(self.buffers)\n            self.buffers.removeAll(keepingCapacity: self.buffers.capacity < 16)  // don't grow too much\n            if buffer.readableBytes > 0 || allowEmptyBuffer {\n                self.state = .processingInProgress\n                return .available(buffer)\n            } else {\n                return .nothingAvailable\n            }\n        case .ready:\n            assert(self.buffers.isEmpty)\n            if allowEmptyBuffer {\n                self.state = .processingInProgress\n                return .available(self.emptyByteBuffer)\n            }\n            return .nothingAvailable\n        }\n    }\n\n    mutating func finishProcessing(remainder buffer: inout ByteBuffer) {\n        assert(self.state == .processingInProgress)\n        self.state = .ready\n        if buffer.readableBytes == 0 && self.buffers.isEmpty {\n            // fast path, no bytes left and no other buffers, just return\n            return\n        }\n        if buffer.readableBytes > 0 {\n            self.buffers.prepend(buffer)\n        } else {\n            buffer.discardReadBytes()\n            buffer.writeBuffers(self.buffers)\n            // don't grow too much\n            self.buffers.removeAll(keepingCapacity: self.buffers.capacity < 16)\n            self.buffers.append(buffer)\n        }\n    }\n\n    mutating func append(buffer: ByteBuffer) {\n        if buffer.readableBytes > 0 {\n            self.buffers.append(buffer)\n        }\n    }\n}\n\n// MARK: B2MDBuffer Helpers\nextension ByteBuffer {\n    fileprivate mutating func writeBuffers(_ buffers: CircularBuffer<ByteBuffer>) {\n        guard buffers.count > 0 else {\n            return\n        }\n        var requiredCapacity: Int = self.writerIndex\n        for buffer in buffers {\n            requiredCapacity += buffer.readableBytes\n        }\n        self.reserveCapacity(requiredCapacity)\n        for var buffer in buffers {\n            self.writeBuffer(&buffer)\n        }\n    }\n}\n\nextension B2MDBuffer {\n    fileprivate func _testOnlyOneBuffer() -> ByteBuffer? {\n        switch self.buffers.count {\n        case 0:\n            return nil\n        case 1:\n            return self.buffers.first\n        default:\n            let firstIndex = self.buffers.startIndex\n            var firstBuffer = self.buffers[firstIndex]\n            for var buffer in self.buffers[self.buffers.index(after: firstIndex)...] {\n                firstBuffer.writeBuffer(&buffer)\n            }\n            return firstBuffer\n        }\n    }\n}\n\n/// A handler which turns a given `ByteToMessageDecoder` into a `ChannelInboundHandler` that can then be added to a\n/// `ChannelPipeline`.\n///\n/// Most importantly, `ByteToMessageHandler` handles the tricky buffer management for you and flattens out all\n/// re-entrancy on `channelRead` that may happen in the `ChannelPipeline`.\npublic final class ByteToMessageHandler<Decoder: ByteToMessageDecoder> {\n    public typealias InboundIn = ByteBuffer\n    public typealias InboundOut = Decoder.InboundOut\n\n    private enum DecodeMode {\n        /// This is a usual decode, ie. not the last chunk\n        case normal\n\n        /// Last chunk\n        case last\n    }\n\n    private enum RemovalState {\n        /// Not added to any `ChannelPipeline` yet.\n        case notAddedToPipeline\n\n        /// No one tried to remove this handler.\n        case notBeingRemoved\n\n        /// The user-triggered removal has been started but isn't complete yet. This state will not be entered if the\n        /// removal is triggered by Channel teardown.\n        case removalStarted\n\n        /// The user-triggered removal is complete. This state will not be entered if the removal is triggered by\n        /// Channel teardown.\n        case removalCompleted\n\n        /// This handler has been removed from the pipeline.\n        case handlerRemovedCalled\n    }\n\n    private enum State {\n        case active\n        case leftoversNeedProcessing\n        case done\n        case error(Error)\n\n        var isError: Bool {\n            switch self {\n            case .active, .leftoversNeedProcessing, .done:\n                return false\n            case .error:\n                return true\n            }\n        }\n\n        var isFinalState: Bool {\n            switch self {\n            case .active, .leftoversNeedProcessing:\n                return false\n            case .done, .error:\n                return true\n            }\n        }\n\n        var isActive: Bool {\n            switch self {\n            case .done, .error, .leftoversNeedProcessing:\n                return false\n            case .active:\n                return true\n            }\n        }\n\n        var isLeftoversNeedProcessing: Bool {\n            switch self {\n            case .done, .error, .active:\n                return false\n            case .leftoversNeedProcessing:\n                return true\n            }\n        }\n    }\n\n    // only `nil` if we're already decoding (ie. we're re-entered)\n    internal private(set) var decoder: Decoder?\n    private let maximumBufferSize: Int?\n    // queues writes received whilst we're already decoding (re-entrant write)\n    private var queuedWrites = CircularBuffer<NIOAny>(initialCapacity: 1)\n    private var state: State = .active {\n        willSet {\n            // we can never leave final states\n            assert(!self.state.isFinalState, \"illegal state on state set: \\(self.state)\")\n        }\n    }\n    private var removalState: RemovalState = .notAddedToPipeline\n    // sadly to construct a B2MDBuffer we need an empty ByteBuffer which we can only get from the allocator, so IUO.\n    private var buffer: B2MDBuffer!\n    private var seenEOF: Bool = false\n    private var selfAsCanDequeueWrites: CanDequeueWrites? = nil\n\n    /// @see: ByteToMessageHandler.init(_:maximumBufferSize)\n    public convenience init(_ decoder: Decoder) {\n        self.init(decoder, maximumBufferSize: nil)\n    }\n\n    /// Initialize a `ByteToMessageHandler`.\n    ///\n    /// - Parameters:\n    ///   - decoder: The `ByteToMessageDecoder` to decode the bytes into message.\n    ///   - maximumBufferSize: The maximum number of bytes to aggregate in-memory.\n    public init(_ decoder: Decoder, maximumBufferSize: Int? = nil) {\n        self.decoder = decoder\n        self.maximumBufferSize = maximumBufferSize\n    }\n\n    deinit {\n        if self.removalState != .notAddedToPipeline {\n            // we have been added to the pipeline, if not, we don't need to check our state.\n            assert(\n                self.removalState == .handlerRemovedCalled,\n                \"illegal state in deinit: removalState = \\(self.removalState)\"\n            )\n            assert(self.state.isFinalState, \"illegal state in deinit: state = \\(self.state)\")\n        }\n    }\n}\n\n@available(*, unavailable)\nextension ByteToMessageHandler: Sendable {}\n\n// MARK: ByteToMessageHandler: Test Helpers\nextension ByteToMessageHandler {\n    internal var cumulationBuffer: ByteBuffer? {\n        self.buffer._testOnlyOneBuffer()\n    }\n}\n\nprivate protocol CanDequeueWrites {\n    func dequeueWrites()\n}\n\nextension ByteToMessageHandler: CanDequeueWrites where Decoder: WriteObservingByteToMessageDecoder {\n    fileprivate func dequeueWrites() {\n        while self.queuedWrites.count > 0 {\n            // self.decoder can't be `nil`, this is only allowed to be called when we're not already on the stack\n            self.decoder!.write(data: ByteToMessageHandler.unwrapOutboundIn(self.queuedWrites.removeFirst()))\n        }\n    }\n}\n\n// MARK: ByteToMessageHandler's Main API\nextension ByteToMessageHandler {\n    @inline(__always)  // allocations otherwise (reconsider with Swift 5.1)\n    private func withNextBuffer(\n        allowEmptyBuffer: Bool,\n        _ body: (inout Decoder, inout ByteBuffer) throws -> DecodingState\n    ) rethrows -> B2MDBuffer.BufferProcessingResult {\n        switch self.buffer.startProcessing(allowEmptyBuffer: allowEmptyBuffer) {\n        case .bufferAlreadyBeingProcessed:\n            return .cannotProcessReentrantly\n        case .nothingAvailable:\n            return .didProcess(.needMoreData)\n        case .available(var buffer):\n            var possiblyReclaimBytes = false\n            var decoder: Decoder? = nil\n            swap(&decoder, &self.decoder)\n            // self.decoder only `nil` if we're being re-entered, but .available means we're not\n            assert(decoder != nil)\n            defer {\n                swap(&decoder, &self.decoder)\n                if buffer.readableBytes > 0 && possiblyReclaimBytes {\n                    // we asserted above that the decoder we just swapped back in was non-nil so now `self.decoder` must\n                    // be non-nil.\n                    if self.decoder!.shouldReclaimBytes(buffer: buffer) {\n                        buffer.discardReadBytes()\n                    }\n                }\n                self.buffer.finishProcessing(remainder: &buffer)\n            }\n            let decodeResult = try body(&decoder!, &buffer)\n\n            // If we .continue, there's no point in trying to reclaim bytes because we'll loop again. If we need more\n            // data on the other hand, we should try to reclaim some of those bytes.\n            possiblyReclaimBytes = decodeResult == .needMoreData\n            return .didProcess(decodeResult)\n        }\n    }\n\n    private func processLeftovers(context: ChannelHandlerContext) {\n        guard self.state.isActive else {\n            // we are processing or have already processed the leftovers\n            return\n        }\n\n        do {\n            switch try self.decodeLoop(context: context, decodeMode: .last) {\n            case .didProcess:\n                self.state = .done\n            case .cannotProcessReentrantly:\n                self.state = .leftoversNeedProcessing\n            }\n        } catch {\n            self.state = .error(error)\n            context.fireErrorCaught(error)\n        }\n    }\n\n    private func tryDecodeWrites() {\n        if self.queuedWrites.count > 0 {\n            // this must succeed because unless we implement `CanDequeueWrites`, `queuedWrites` must always be empty.\n            self.selfAsCanDequeueWrites!.dequeueWrites()\n        }\n    }\n\n    private func decodeLoop(\n        context: ChannelHandlerContext,\n        decodeMode: DecodeMode\n    ) throws -> B2MDBuffer.BufferProcessingResult {\n        assert(!self.state.isError)\n        var allowEmptyBuffer = decodeMode == .last\n        while (self.state.isActive && self.removalState == .notBeingRemoved) || decodeMode == .last {\n            let result = try self.withNextBuffer(allowEmptyBuffer: allowEmptyBuffer) { decoder, buffer in\n                let decoderResult: DecodingState\n                if decodeMode == .normal {\n                    assert(self.state.isActive, \"illegal state for normal decode: \\(self.state)\")\n                    decoderResult = try decoder.decode(context: context, buffer: &buffer)\n                } else {\n                    allowEmptyBuffer = false\n                    decoderResult = try decoder.decodeLast(context: context, buffer: &buffer, seenEOF: self.seenEOF)\n                }\n                if decoderResult == .needMoreData, let maximumBufferSize = self.maximumBufferSize,\n                    buffer.readableBytes > maximumBufferSize\n                {\n                    throw ByteToMessageDecoderError.PayloadTooLargeError()\n                }\n                return decoderResult\n            }\n            switch result {\n            case .didProcess(.continue):\n                self.tryDecodeWrites()\n                continue\n            case .didProcess(.needMoreData):\n                if self.queuedWrites.count > 0 {\n                    self.tryDecodeWrites()\n                    continue  // we might have received more, so let's spin once more\n                } else {\n                    return .didProcess(.needMoreData)\n                }\n            case .cannotProcessReentrantly:\n                return .cannotProcessReentrantly\n            }\n        }\n        return .didProcess(.continue)\n    }\n}\n\n// MARK: ByteToMessageHandler: ChannelInboundHandler\nextension ByteToMessageHandler: ChannelInboundHandler {\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        guard self.removalState == .notAddedToPipeline else {\n            preconditionFailure(\"\\(self) got readded to a ChannelPipeline but ByteToMessageHandler is single-use\")\n        }\n        self.removalState = .notBeingRemoved\n        self.buffer = B2MDBuffer(emptyByteBuffer: context.channel.allocator.buffer(capacity: 0))\n        // here we can force it because we know that the decoder isn't in use if we're just adding this handler\n        self.selfAsCanDequeueWrites = self as? CanDequeueWrites  // we need to cache this as it allocates.\n        self.decoder!.decoderAdded(context: context)\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        // very likely, the removal state is `.notBeingRemoved` or `.removalCompleted` here but we can't assert it\n        // because the pipeline might be torn down during the formal removal process.\n        self.removalState = .handlerRemovedCalled\n        if !self.state.isFinalState {\n            self.state = .done\n        }\n\n        self.selfAsCanDequeueWrites = nil\n\n        // here we can force it because we know that the decoder isn't in use because the removal is always\n        // eventLoop.execute'd\n        self.decoder!.decoderRemoved(context: context)\n    }\n\n    /// Calls `decode` until there is nothing left to decode.\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let buffer = ByteToMessageHandler.unwrapInboundIn(data)\n        if case .error(let error) = self.state {\n            context.fireErrorCaught(ByteToMessageDecoderError.dataReceivedInErrorState(error, buffer))\n            return\n        }\n        self.buffer.append(buffer: buffer)\n        do {\n            switch try self.decodeLoop(context: context, decodeMode: .normal) {\n            case .didProcess:\n                switch self.state {\n                case .active:\n                    ()  // cool, all normal\n                case .done, .error:\n                    ()  // fair, all done already\n                case .leftoversNeedProcessing:\n                    // seems like we received a `channelInactive` or `handlerRemoved` whilst we were processing a read\n                    switch try self.decodeLoop(context: context, decodeMode: .last) {\n                    case .didProcess:\n                        ()  // expected and cool\n                    case .cannotProcessReentrantly:\n                        preconditionFailure(\"bug in NIO: non-reentrant decode loop couldn't run \\(self), \\(self.state)\")\n                    }\n                    self.state = .done\n                }\n            case .cannotProcessReentrantly:\n                // fine, will be done later\n                ()\n            }\n        } catch {\n            self.state = .error(error)\n            context.fireErrorCaught(error)\n        }\n    }\n\n    /// Call `decodeLast` before forward the event through the pipeline.\n    public func channelInactive(context: ChannelHandlerContext) {\n        self.seenEOF = true\n\n        self.processLeftovers(context: context)\n\n        context.fireChannelInactive()\n    }\n\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        if event as? ChannelEvent == .some(.inputClosed) {\n            self.seenEOF = true\n\n            self.processLeftovers(context: context)\n        }\n        context.fireUserInboundEventTriggered(event)\n    }\n}\n\nextension ByteToMessageHandler: ChannelOutboundHandler, _ChannelOutboundHandler\nwhere Decoder: WriteObservingByteToMessageDecoder {\n    public typealias OutboundIn = Decoder.OutboundIn\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if self.decoder != nil {\n            let data = ByteToMessageHandler.unwrapOutboundIn(data)\n            assert(self.queuedWrites.isEmpty)\n            self.decoder!.write(data: data)\n        } else {\n            self.queuedWrites.append(data)\n        }\n        context.write(data, promise: promise)\n    }\n}\n\n/// A protocol for straightforward encoders which encode custom messages to `ByteBuffer`s.\n/// To add a `MessageToByteEncoder` to a `ChannelPipeline`, use\n/// `channel.pipeline.addHandler(MessageToByteHandler(myEncoder)`.\npublic protocol MessageToByteEncoder {\n    associatedtype OutboundIn\n\n    /// Called once there is data to encode.\n    ///\n    /// - Parameters:\n    ///   - data: The data to encode into a `ByteBuffer`.\n    ///   - out: The `ByteBuffer` into which we want to encode.\n    func encode(data: OutboundIn, out: inout ByteBuffer) throws\n}\n\nextension ByteToMessageHandler: RemovableChannelHandler {\n    public func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n        precondition(self.removalState == .notBeingRemoved)\n        self.removalState = .removalStarted\n        context.eventLoop.assumeIsolatedUnsafeUnchecked().execute {\n            self.processLeftovers(context: context)\n            assert(!self.state.isLeftoversNeedProcessing, \"illegal state: \\(self.state)\")\n            switch self.removalState {\n            case .removalStarted:\n                self.removalState = .removalCompleted\n            case .handlerRemovedCalled:\n                // if we're here, then the channel has also been torn down between the start and the completion of\n                // the user-triggered removal. That's okay.\n                ()\n            default:\n                assertionFailure(\"illegal removal state: \\(self.removalState)\")\n            }\n            // this is necessary as it'll complete the promise.\n            context.leavePipeline(removalToken: removalToken)\n        }\n    }\n}\n\n/// A handler which turns a given `MessageToByteEncoder` into a `ChannelOutboundHandler` that can then be added to a\n/// `ChannelPipeline`.\npublic final class MessageToByteHandler<Encoder: MessageToByteEncoder>: ChannelOutboundHandler {\n    public typealias OutboundOut = ByteBuffer\n    public typealias OutboundIn = Encoder.OutboundIn\n\n    private enum State {\n        case notInChannelYet\n        case operational\n        case error(Error)\n        case done\n\n        var readyToBeAddedToChannel: Bool {\n            switch self {\n            case .notInChannelYet:\n                return true\n            case .operational, .error, .done:\n                return false\n            }\n        }\n    }\n\n    private var state: State = .notInChannelYet\n    private let encoder: Encoder\n    private var buffer: ByteBuffer? = nil\n    private let desiredBufferCapacity: Int?\n\n    public init(_ encoder: Encoder, desiredBufferCapacity: Int) {\n        self.encoder = encoder\n        self.desiredBufferCapacity = desiredBufferCapacity\n    }\n\n    public init(_ encoder: Encoder) {\n        self.encoder = encoder\n        self.desiredBufferCapacity = nil\n    }\n}\n\n@available(*, unavailable)\nextension MessageToByteHandler: Sendable {}\n\nextension MessageToByteHandler {\n    public func handlerAdded(context: ChannelHandlerContext) {\n        precondition(\n            self.state.readyToBeAddedToChannel,\n            \"illegal state when adding to Channel: \\(self.state)\"\n        )\n        self.state = .operational\n        self.buffer = context.channel.allocator.buffer(capacity: 256)\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        self.state = .done\n        self.buffer = nil\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        switch self.state {\n        case .notInChannelYet:\n            preconditionFailure(\"MessageToByteHandler.write called before it was added to a Channel\")\n        case .error(let error):\n            promise?.fail(error)\n            context.fireErrorCaught(error)\n            return\n        case .done:\n            // let's just ignore this\n            return\n        case .operational:\n            // there's actually some work to do here\n            break\n        }\n        let data = MessageToByteHandler.unwrapOutboundIn(data)\n\n        do {\n            self.buffer!.clear()\n            try self.encoder.encode(data: data, out: &self.buffer!)\n            context.write(MessageToByteHandler.wrapOutboundOut(self.buffer!), promise: promise)\n        } catch {\n            self.state = .error(error)\n            promise?.fail(error)\n            context.fireErrorCaught(error)\n        }\n    }\n\n    public func flush(context: ChannelHandlerContext) {\n        if let desiredBufferCapacity = self.desiredBufferCapacity {\n            self.buffer?.shrinkBufferCapacity(to: desiredBufferCapacity)\n        }\n        context.flush()\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/ConvenienceOptionSupport.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// MARK:  Universal Client Bootstrap\nextension NIOClientTCPBootstrapProtocol {\n    /// Apply any understood convenience options to the bootstrap, removing them from the set of options if they are consumed.\n    /// - Parameters:\n    ///   - options:  The options to try applying - the options applied should be consumed from here.\n    /// - Returns: The updated bootstrap with and options applied.\n    public func _applyChannelConvenienceOptions(_ options: inout ChannelOptions.TCPConvenienceOptions) -> Self {\n        // Default is to consume no options and not update self.\n        self\n    }\n}\n\nextension NIOClientTCPBootstrap {\n    /// Specifies some `TCPConvenienceOption`s to be applied to the channel.\n    /// These are preferred over regular channel options as they are easier to use and restrict\n    /// options to those which a normal user would consider.\n    /// - Parameter options: Set of convenience options to apply.\n    /// - Returns: The updated bootstrap (`self` being mutated)\n    public func channelConvenienceOptions(_ options: ChannelOptions.TCPConvenienceOptions) -> NIOClientTCPBootstrap {\n        var optionsRemaining = options\n        // First give the underlying a chance to consume options.\n        let withUnderlyingOverrides =\n            NIOClientTCPBootstrap(\n                self,\n                updating: underlyingBootstrap._applyChannelConvenienceOptions(&optionsRemaining)\n            )\n        // Default apply any remaining options.\n        return optionsRemaining.applyFallbackMapping(withUnderlyingOverrides)\n    }\n}\n\n// MARK: Utility\nextension ChannelOptions.Types {\n    /// Has an option been set?\n    /// Option has a value of generic type ValueType.\n    public enum ConvenienceOptionValue<ValueType> {\n        /// The option was not set.\n        case notSet\n        /// The option was set with a value of type ValueType.\n        case set(ValueType)\n    }\n}\n\nextension ChannelOptions.Types.ConvenienceOptionValue: Sendable where ValueType: Sendable {}\n\nextension ChannelOptions.Types.ConvenienceOptionValue where ValueType == () {\n    /// Convenience method working with bool options as bool values for set.\n    public var isSet: Bool {\n        get {\n            switch self {\n            case .notSet:\n                return false\n            case .set(()):\n                return true\n            }\n        }\n    }\n}\n\nextension ChannelOptions.Types.ConvenienceOptionValue where ValueType == () {\n    fileprivate init(flag: Bool) {\n        if flag {\n            self = .set(())\n        } else {\n            self = .notSet\n        }\n    }\n}\n\n// MARK: TCP - data\nextension ChannelOptions {\n    /// A TCP channel option which can be applied to a bootstrap using convenience notation.\n    public struct TCPConvenienceOption: Hashable, Sendable {\n        fileprivate var data: ConvenienceOption\n\n        private init(_ data: ConvenienceOption) {\n            self.data = data\n        }\n\n        fileprivate enum ConvenienceOption: Hashable {\n            case allowLocalEndpointReuse\n            case disableAutoRead\n            case allowRemoteHalfClosure\n        }\n    }\n}\n\n/// Approved convenience options.\nextension ChannelOptions.TCPConvenienceOption {\n    /// Allow immediately reusing a local address.\n    public static let allowLocalEndpointReuse = ChannelOptions.TCPConvenienceOption(.allowLocalEndpointReuse)\n\n    /// The user will manually call `Channel.read` once all the data is read from the transport.\n    public static let disableAutoRead = ChannelOptions.TCPConvenienceOption(.disableAutoRead)\n\n    /// Allows users to configure whether the `Channel` will close itself when its remote\n    /// peer shuts down its send stream, or whether it will remain open. If set to `false` (the default), the `Channel`\n    /// will be closed automatically if the remote peer shuts down its send stream. If set to true, the `Channel` will\n    /// not be closed: instead, a `ChannelEvent.inboundClosed` user event will be sent on the `ChannelPipeline`,\n    /// and no more data will be received.\n    public static let allowRemoteHalfClosure =\n        ChannelOptions.TCPConvenienceOption(.allowRemoteHalfClosure)\n}\n\nextension ChannelOptions {\n    /// A set of `TCPConvenienceOption`s\n    public struct TCPConvenienceOptions: ExpressibleByArrayLiteral, Hashable, Sendable {\n        var allowLocalEndpointReuse = false\n        var disableAutoRead = false\n        var allowRemoteHalfClosure = false\n\n        /// Construct from an array literal.\n        @inlinable\n        public init(arrayLiteral elements: TCPConvenienceOption...) {\n            for element in elements {\n                self.add(element)\n            }\n        }\n\n        @usableFromInline\n        mutating func add(_ element: TCPConvenienceOption) {\n            switch element.data {\n            case .allowLocalEndpointReuse:\n                self.allowLocalEndpointReuse = true\n            case .allowRemoteHalfClosure:\n                self.allowRemoteHalfClosure = true\n            case .disableAutoRead:\n                self.disableAutoRead = true\n            }\n        }\n\n        /// Caller is consuming the knowledge that `allowLocalEndpointReuse` was set or not.\n        /// The setting will nolonger be set after this call.\n        /// - Returns: If `allowLocalEndpointReuse` was set.\n        public mutating func consumeAllowLocalEndpointReuse() -> Types.ConvenienceOptionValue<Void> {\n            defer {\n                self.allowLocalEndpointReuse = false\n            }\n            return Types.ConvenienceOptionValue<Void>(flag: self.allowLocalEndpointReuse)\n        }\n\n        /// Caller is consuming the knowledge that disableAutoRead was set or not.\n        /// The setting will nolonger be set after this call.\n        /// - Returns: If disableAutoRead was set.\n        public mutating func consumeDisableAutoRead() -> Types.ConvenienceOptionValue<Void> {\n            defer {\n                self.disableAutoRead = false\n            }\n            return Types.ConvenienceOptionValue<Void>(flag: self.disableAutoRead)\n        }\n\n        /// Caller is consuming the knowledge that allowRemoteHalfClosure was set or not.\n        /// The setting will nolonger be set after this call.\n        /// - Returns: If allowRemoteHalfClosure was set.\n        public mutating func consumeAllowRemoteHalfClosure() -> Types.ConvenienceOptionValue<Void> {\n            defer {\n                self.allowRemoteHalfClosure = false\n            }\n            return Types.ConvenienceOptionValue<Void>(flag: self.allowRemoteHalfClosure)\n        }\n\n        mutating func applyFallbackMapping(_ universalBootstrap: NIOClientTCPBootstrap) -> NIOClientTCPBootstrap {\n            var result = universalBootstrap\n            #if !os(WASI)\n            if self.consumeAllowLocalEndpointReuse().isSet {\n                result = result.channelOption(.socketOption(.so_reuseaddr), value: 1)\n            }\n            #endif\n            if self.consumeAllowRemoteHalfClosure().isSet {\n                result = result.channelOption(.allowRemoteHalfClosure, value: true)\n            }\n            if self.consumeDisableAutoRead().isSet {\n                result = result.channelOption(.autoRead, value: false)\n            }\n            return result\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/DeadChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A `DeadChannelCore` is a `ChannelCore` for a `DeadChannel`. A `DeadChannel` is used as a replacement `Channel` when\n/// the original `Channel` is closed. Given that the original `Channel` is closed the `DeadChannelCore` should fail\n/// all operations.\nprivate final class DeadChannelCore: ChannelCore {\n    func localAddress0() throws -> SocketAddress {\n        throw ChannelError._ioOnClosedChannel\n    }\n\n    func remoteAddress0() throws -> SocketAddress {\n        throw ChannelError._ioOnClosedChannel\n    }\n\n    func register0(promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._ioOnClosedChannel)\n    }\n\n    func registerAlreadyConfigured0(promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._ioOnClosedChannel)\n    }\n\n    func bind0(to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._ioOnClosedChannel)\n    }\n\n    func connect0(to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._ioOnClosedChannel)\n    }\n\n    func write0(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._ioOnClosedChannel)\n    }\n\n    func flush0() {\n    }\n\n    func read0() {\n    }\n\n    func close0(error: Error, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._alreadyClosed)\n    }\n\n    func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._ioOnClosedChannel)\n    }\n\n    func channelRead0(_ data: NIOAny) {\n        // a `DeadChannel` should never be in any running `ChannelPipeline` and therefore the `TailChannelHandler`\n        // should never invoke this.\n        fatalError(\"\\(#function) called on DeadChannelCore\")\n    }\n\n    func errorCaught0(error: Error) {\n        // a `DeadChannel` should never be in any running `ChannelPipeline` and therefore the `TailChannelHandler`\n        // should never invoke this.\n        fatalError(\"\\(#function) called on DeadChannelCore\")\n    }\n}\n\n/// This represents a `Channel` which is already closed and therefore all the operations do fail.\n/// A `ChannelPipeline` that is associated with a closed `Channel` must be careful to no longer use that original\n/// channel as it only holds an unowned reference to the original `Channel`. `DeadChannel` serves as a replacement\n/// that can be used when the original `Channel` might no longer be valid.\ninternal final class DeadChannel: Channel, @unchecked Sendable {\n    let eventLoop: EventLoop\n    let pipeline: ChannelPipeline\n\n    public var closeFuture: EventLoopFuture<Void> {\n        self.eventLoop.makeSucceededFuture(())\n    }\n\n    internal init(pipeline: ChannelPipeline) {\n        self.pipeline = pipeline\n        self.eventLoop = pipeline.eventLoop\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    var allocator: ByteBufferAllocator {\n        ByteBufferAllocator()\n    }\n\n    var localAddress: SocketAddress? {\n        nil\n    }\n\n    var remoteAddress: SocketAddress? {\n        nil\n    }\n\n    let parent: Channel? = nil\n\n    func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void> {\n        self.pipeline.eventLoop.makeFailedFuture(ChannelError._ioOnClosedChannel)\n    }\n\n    func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value> {\n        eventLoop.makeFailedFuture(ChannelError._ioOnClosedChannel)\n    }\n\n    let isWritable = false\n    let isActive = false\n    let _channelCore: ChannelCore = DeadChannelCore()\n}\n"
  },
  {
    "path": "Sources/NIOCore/DispatchQueue+WithFuture.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Dispatch)\nimport Dispatch\n\nextension DispatchQueue {\n    /// Schedules a work item for immediate execution and immediately returns with an `EventLoopFuture` providing the\n    /// result. For example:\n    ///\n    ///     let futureResult = DispatchQueue.main.asyncWithFuture(eventLoop: myEventLoop) { () -> String in\n    ///         callbackMayBlock()\n    ///     }\n    ///     try let value = futureResult.wait()\n    ///\n    /// - Parameters:\n    ///   - eventLoop: the `EventLoop` on which to processes the IO / task specified by `callbackMayBlock`.\n    ///   - callbackMayBlock: The scheduled callback for the IO / task.\n    /// - returns a new `EventLoopFuture<ReturnType>` with value returned by the `block` parameter.\n    @inlinable\n    @preconcurrency\n    public func asyncWithFuture<NewValue: Sendable>(\n        eventLoop: EventLoop,\n        _ callbackMayBlock: @escaping @Sendable () throws -> NewValue\n    ) -> EventLoopFuture<NewValue> {\n        let promise = eventLoop.makePromise(of: NewValue.self)\n\n        self.async {\n            do {\n                let result = try callbackMayBlock()\n                promise.succeed(result)\n            } catch {\n                promise.fail(error)\n            }\n        }\n        return promise.futureResult\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCore/Docs.docc/ByteBuffer-lengthPrefix.md",
    "content": "# Writing length-prefixed data in ByteBuffer\n\nThis article explains how to write data prefixed with a length, where the length could be encoded in various ways.\n\n## Overview\n\nWe often need to write some data prefixed by its length. Sometimes, this may simply be a fixed width integer. But many\nprotocols encode the length differently, depending on how big it is. For example, the QUIC protocol uses variable-length\ninteger encodings, in which smaller numbers can be encoded in fewer bytes.\n\nWe have added functions to help with reading and writing data which is prefixed with lengths encoded by various\nstrategies.\n\n## ``NIOBinaryIntegerEncodingStrategy`` protocol\n\nThe first building block is a protocol which describes how to encode and decode an integer.\n\nAn implementation of this protocol is needed for any encoding strategy. One example is the ``ByteBuffer/QUICBinaryEncodingStrategy``.\n\nThis protocol only has two requirements which don't have default implementations:\n\n- `readInteger`: Reads an integer from the `ByteBuffer` using this encoding. Implementations will read as many bytes as\n  they need to, according to their wire format, and move the reader index accordingly\n- `writeInteger`: Write an integer to the `ByteBuffer` using this encoding. Implementations will write as many bytes as\n  they need to, according to their wire format, and move the writer index accordingly.\n\nNote that implementations of this protocol need to either:\n\n- Encode the length of the integer into the integer itself when writing, so it knows how many bytes to read when\n  reading. This is what QUIC does.\n- Always use the same length, e.g. a simple strategy which always writes the integer as a `UInt64`.\n\n## Extensions on ``ByteBuffer``\n\nTo provide a more user-friendly API, we have added extensions on `ByteBuffer` for writing integers with a\nchosen ``NIOBinaryIntegerEncodingStrategy``. These are ``ByteBuffer/writeEncodedInteger(_:strategy:)``\nand ``ByteBuffer/readEncodedInteger(as:strategy:)``.\n\n## Reading and writing length-prefixed data\n\nWe added further APIs on ByteBuffer for reading data, strings and buffers which are written with a length prefix. These\nAPIs first read an integer using a chosen encoding strategy. The integer then dictates how many bytes of data are read\nstarting from after the integer.\n\nSimilarly, there are APIs which take data, write its length using the provided strategy, and then write the data itself.\n\n## Writing complex data with a length-prefix\n\nConsider the scenario where we want to write multiple pieces of data with a length-prefix, but it is difficult or\ncomplex to work out the total length of that data.\n\nWe decided to add the following API to ByteBuffer:\n\n```swift\n/// - Parameters:\n///   - strategy: The strategy to use for encoding the length.\n///   - writeData: A closure that takes a buffer, writes some data to it, and returns the number of bytes written.\n/// - Returns: Number of total bytes written. This is the length of the written data + the number of bytes used to write the length before it.\npublic mutating func writeLengthPrefixed<Strategy: NIOBinaryIntegerEncodingStrategy, ErrorType: Error>(\n    strategy: Strategy,\n    writeData: (_ buffer: inout ByteBuffer) throws(ErrorType) -> Int\n) throws(ErrorType) -> Int\n```\n\nUsers could use the function as follows:\n\n```swift\nmyBuffer.writeLengthPrefixed(strategy: .quic) { buffer in\n    buffer.writeString(\"something\")\n    buffer.writeSomethingComplex(something)\n}\n```\n\nWriting the implementation of `writeLengthPrefixed` presents a challenge. We need to write the length _before_ the\ndata. But we do not know the length until the data is written.\n\nIdeally, we would reserve some number of bytes, then call the `writeData` closure, and then go back and write the length\nin the reserved space. However, we would not even know how many bytes of space to reserve, because the number of bytes\nneeded to write an integer will depend on the integer!\n\nThe solution we landed on is the following:\n\n- Added ``NIOBinaryIntegerEncodingStrategy/requiredBytesHint``. This allows strategies to provide an estimate of how\n  many bytes they need for encoding a length\n- Using this property, reserve the estimated number of bytes\n- Call the `writeData` closure to write the data\n- Go back to the reserved space to write the length\n    - If the length ends up needing fewer bytes than we had reserved, shuffle the data back to close the gap\n    - If the length ends up needing more bytes than we had reserved, shuffle the data forward to make space\n\nThis code will be most performant when the `requiredBytesHint` is exactly correct, because it will avoid needing to\nshuffle any bytes. With that in mind, we can actually make one more optimisation: when we call the `writeInteger` function\non a strategy, we can tell the strategy that we have already reserved some number of bytes. Some encoding strategies\nwill be able to adjust the way they encode such that they can use exactly that many bytes.\n\nWe added the following function to the ``NIOBinaryIntegerEncodingStrategy`` protocol. This is optional to implement, and\nwill default to simply calling the existing ``NIOBinaryIntegerEncodingStrategy/writeInteger(_:to:)`` function.\n\n```swift\n/// - Parameters:\n///   - integer: The integer to write\n///   - reservedCapacity: The capacity already reserved for writing this integer\n///   - buffer: The buffer to write into.\n/// - Returns: The number of bytes used to write the integer.\nfunc writeInteger(\n    _ integer: Int,\n    reservedCapacity: Int,\n    to buffer: inout ByteBuffer\n) -> Int\n```\n\nMany strategies will not be able to do anything useful with the additional `reservedCapacity` parameter. For example, in\nASN1, there is only one possible encoding for a given integer. However, some protocols, such as QUIC, do allow less\nefficient encodings. E.g. it is valid in QUIC to encode the number `6` using 4 bytes, even though it could be encoded\nusing just 1. Such encoding strategies need to make a decision here: they can either use the less efficient\nencoding (and therefore use more bytes to encode the integer than would otherwise be necessary), or they can use the\nmore efficient encoding (and therefore suffer a performance penalty as the bytes need to be shuffled).\n"
  },
  {
    "path": "Sources/NIOCore/Docs.docc/index.md",
    "content": "# ``NIOCore``\n\nThe core abstractions that make up SwiftNIO.\n\n## Overview\n\n``NIOCore`` contains the fundamental abstractions that are used in all SwiftNIO programs. The goal of this module is to\nbe platform-independent, and to be the most-common building block used for NIO protocol implementations.\n\nMore specialized modules provide concrete implementations of many of the abstractions defined in NIOCore.\n\n## Topics\n\n### Articles\n\n- <doc:swift-concurrency>\n- <doc:ByteBuffer-lengthPrefix>\n- <doc:loops-futures-concurrency>\n\n### Event Loops and Event Loop Groups\n\n- ``EventLoopGroup``\n- ``EventLoop``\n- ``EventLoopIterator``\n- ``Scheduled``\n- ``RepeatedTask``\n- ``NIOLoopBound``\n- ``NIOLoopBoundBox``\n\n### Channels and Channel Handlers\n\n- ``Channel``\n- ``MulticastChannel``\n- ``ChannelHandler``\n- ``ChannelOutboundHandler``\n- ``ChannelInboundHandler``\n- ``ChannelDuplexHandler``\n- ``ChannelHandlerContext``\n- ``ChannelPipeline``\n- ``RemovableChannelHandler``\n- ``NIOAny``\n- ``ChannelEvent``\n- ``CloseMode``\n- ``ChannelShouldQuiesceEvent``\n\n### Buffers and Files\n\n- ``ByteBuffer``\n- ``ByteBufferView``\n- ``ByteBufferAllocator``\n- ``Endianness``\n- ``NIOFileHandle``\n- ``FileDescriptor``\n- ``FileRegion``\n- ``NIOPOSIXFileMode``\n- ``IOData``\n\n### Futures and Promises\n\n- ``EventLoopFuture``\n- ``EventLoopPromise``\n\n### Configuring Channels\n\n- ``ChannelOption``\n- ``NIOSynchronousChannelOptions``\n- ``ChannelOptions``\n- ``SocketOptionProvider``\n- ``RecvByteBufferAllocator``\n- ``AdaptiveRecvByteBufferAllocator``\n- ``FixedSizeRecvByteBufferAllocator``\n- ``AllocatorOption``\n- ``AllowRemoteHalfClosureOption``\n- ``AutoReadOption``\n- ``BacklogOption``\n- ``ConnectTimeoutOption``\n- ``DatagramVectorReadMessageCountOption``\n- ``MaxMessagesPerReadOption``\n- ``RecvAllocatorOption``\n- ``SocketOption``\n- ``SocketOptionLevel``\n- ``SocketOptionName``\n- ``SocketOptionValue``\n- ``WriteBufferWaterMarkOption``\n- ``WriteBufferWaterMark``\n- ``WriteSpinOption``\n\n### Message Oriented Protocol Helpers\n\n- ``AddressedEnvelope``\n- ``NIOPacketInfo``\n- ``NIOExplicitCongestionNotificationState``\n\n### Generic Bootstraps\n\n- ``NIOClientTCPBootstrap``\n- ``NIOClientTCPBootstrapProtocol``\n- ``NIOClientTLSProvider``\n- ``NIOInsecureNoTLS``\n\n### Simple Message Handling\n\n- ``ByteToMessageDecoder``\n- ``WriteObservingByteToMessageDecoder``\n- ``DecodingState``\n- ``ByteToMessageHandler``\n- ``NIOSingleStepByteToMessageDecoder``\n- ``NIOSingleStepByteToMessageProcessor``\n- ``MessageToByteEncoder``\n- ``MessageToByteHandler``\n\n### Core Channel Handlers\n\n- ``AcceptBackoffHandler``\n- ``BackPressureHandler``\n- ``NIOCloseOnErrorHandler``\n- ``IdleStateHandler``\n\n### Async Sequences\n\n- ``NIOAsyncSequenceProducer``\n- ``NIOThrowingAsyncSequenceProducer``\n- ``NIOAsyncSequenceProducerBackPressureStrategy``\n- ``NIOAsyncSequenceProducerBackPressureStrategies``\n- ``NIOAsyncSequenceProducerDelegate``\n- ``NIOAsyncWriter``\n- ``NIOAsyncWriterSinkDelegate``\n\n### Time\n\n- ``TimeAmount``\n- ``NIODeadline``\n\n### Circular Buffers\n\n- ``CircularBuffer``\n- ``MarkedCircularBuffer``\n\n### Operating System State\n\n- ``System``\n- ``NIONetworkDevice``\n- ``NIONetworkInterface``\n- ``SocketAddress``\n- ``NIOBSDSocket``\n- ``NIOIPProtocol``\n\n### Implementing Core Abstractions\n\n- ``ChannelCore``\n- ``ChannelInvoker``\n- ``ChannelInboundInvoker``\n- ``ChannelOutboundInvoker``\n\n### Sendable Helpers\n\n- ``NIOSendable``\n- ``NIOPreconcurrencySendable``\n\n### Error Types\n\n- ``ByteToMessageDecoderError``\n- ``ChannelError``\n- ``ChannelPipelineError``\n- ``DatagramChannelError``\n- ``EventLoopError``\n- ``IOError``\n- ``NIOAsyncWriterError``\n- ``NIOAttemptedToRemoveHandlerMultipleTimesError``\n- ``NIOMulticastNotImplementedError``\n- ``NIOMulticastNotSupportedError``\n- ``NIOTooManyBytesError``\n- ``SocketAddressError``\n\n"
  },
  {
    "path": "Sources/NIOCore/Docs.docc/loops-futures-concurrency.md",
    "content": "# EventLoops, EventLoopFutures, and Swift Concurrency\n\nThis article aims to communicate how NIO's ``EventLoop``s and ``EventLoopFuture``s interact with the Swift 6\nconcurrency model, particularly regarding data-race safety. It aims to be a reference for writing correct\nconcurrent code in the NIO model.\n\nNIO predates the Swift concurrency model. As a result, several of NIO's concepts are not perfect matches to\nthe concepts that Swift uses, or have overlapping responsibilities.\n\n## Isolation domains and executors\n\nFirst, a quick recap. The core of Swift 6's data-race safety protection is the concept of an \"isolation\ndomain\". Some valuable reading regarding the concept can be found in\n[SE-0414 (Region based isolation)](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0414-region-based-isolation.md)\nbut at a high level an isolation domain can be understood to be a collection of state and methods within which there cannot be\nmultiple executors executing code at the same time.\n\nIn standard Swift Concurrency, the main boundaries of isolation domains are actors and tasks. Each actor,\nincluding global actors, defines an isolation domain. Additionally, for functions and methods that are\nnot isolated to an actor, the `Task` within which that code executes defines an isolation domain. Passing\nvalues between these isolation domains requires that these values are either `Sendable` (safe to hold in\nmultiple domains), or that the `sending` keyword is used to force the value to be passed from one domain\nto another.\n\nA related concept to an \"isolation domain\" is an \"executor\". Again, useful reading can be found in\n[SE-0392 (Custom actor executors)](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0392-custom-actor-executors.md).\nAt a high level, an executor is simply an object that is capable of executing Swift `Task`s. Executors can be\nconcurrent, or they can be serial. Serial executors are the most common, as they can be used to back an\nactor.\n\n## Event Loops\n\nNIO's core execution primitive is the ``EventLoop``. An ``EventLoop`` is fundamentally nothing more than\na Swift Concurrency Serial Executor that can also perform I/O operations directly. Indeed, NIO's\n``EventLoop``s can be exposed as serial executors, using ``EventLoop/executor``. This provides a mechanism\nto protect actor-isolated state using a NIO event-loop. With [the introduction of task executors](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0417-task-executor-preference.md),\nfuture versions of SwiftNIO will also be able to offer their event loops for individual `Task`s to execute\non as well.\n\nIn a Swift 6 world, it is possible that these would be the API that NIO offered to execute tasks on the\nloop. However, as NIO predates Swift 6, it also offers its own set of APIs to enqueue work. This includes\n(but is not limited to):\n\n- ``EventLoop/execute(_:)``\n- ``EventLoop/submit(_:)``\n- ``EventLoop/scheduleTask(in:_:)``\n- ``EventLoop/scheduleRepeatedTask(initialDelay:delay:notifying:_:)``\n- ``EventLoop/scheduleCallback(at:handler:)-2xm6l``\n\nThe existence of these APIs requires us to also ask the question of where the submitted code executes. The\nanswer is that the submitted code executes on the event loop (or, in Swift Concurrency terms, on the\nexecutor provided by the event loop).\n\nAs the event loop only ever executes a single item of work (either an `async` function or one of the\nclosures above) at a time, it is a _serial_ executor. It also provides an _isolation domain_: code\nsubmitted to a given `EventLoop` never runs in parallel with other code submitted to the same loop.\n\nThe result here is that a all closures passed into the event loop to do work must be transferred\nin: they may not be kept hold of outside of the event loop. That means they must be sent using\nthe `sending` keyword.\n\n> Note: As of the current 2.75.0 release, NIO enforces the stricter requirement that these closures\n    are `@Sendable`. This is not a long-term position, but reflects the need to continue\n    to support Swift 5 code which requires this stricter standard. In a future release of\n    SwiftNIO we expect to relax this constraint: if you need this relaxed constraint\n    then please file an issue.\n\n## Event loop futures\n\nIn Swift NIO the most common mechanism to arrange a series of asynchronous work items is\n_not_ to queue up a series of ``EventLoop/execute(_:)`` calls. Instead, users typically\nuse ``EventLoopFuture``.\n\n``EventLoopFuture`` has some extensive semantics documented in its API documentation. The\nmost important principal for this discussion is that all callbacks added to an\n``EventLoopFuture`` will execute on the ``EventLoop`` to which that ``EventLoopFuture`` is\nbound. By extension, then, all callbacks added to an ``EventLoopFuture`` execute on the same\nexecutor (the ``EventLoop``) in the same isolation domain.\n\nThe analogy to an actor here is hopefully fairly clear. Conceptually, an ``EventLoopFuture``\ncould be modelled as an actor. That means all the callbacks have the same logical semantics:\nthe ``EventLoopFuture`` uses the isolation domain of its associated ``EventLoop``, and all\nthe callbacks are `sent` into the isolation domain. To that end, all the callback-taking APIs\nrequire that the callback is sent using `sending` into the ``EventLoopFuture``.\n\n> Note: As of the current 2.75.0 release, NIO enforces the stricter requirement that these callbacks\n    are `@Sendable`. This is not a long-term position, but reflects the need to continue\n    to support Swift 5 code which requires this stricter standard. In a future release of\n    SwiftNIO we expect to relax this constraint: if you need this relaxed constraint\n    then please file an issue.\n\nUnlike ``EventLoop``s, however, ``EventLoopFuture``s also have value-receiving and value-taking\nAPIs. This is because ``EventLoopFuture``s pass a value along to their various callbacks, and\nso need to be both given an initial value (via an ``EventLoopPromise``) and in some cases to\nextract that value from the ``EventLoopFuture`` wrapper.\n\nThis implies that ``EventLoopPromise``'s various success functions\n(_and_ ``EventLoop/makeSucceededFuture(_:)``) need to take their value as `sending`. The value\nis potentially sent from its current isolation domain into the ``EventLoop``, which will require\nthat the value is safe to move.\n\n> Note: As of the current 2.75.0 release, NIO enforces the stricter requirement that these values\n    are `Sendable`. This is not a long-term position, but reflects the need to continue\n    to support Swift 5 code which requires this stricter standard. In a future release of\n    SwiftNIO we expect to relax this constraint: if you need this relaxed constraint\n    then please file an issue.\n\nThere are also a few ways to extract a value, such as ``EventLoopFuture/wait(file:line:)``\nand ``EventLoopFuture/get()``. These APIs can only safely be called when the ``EventLoopFuture``\nis carrying a `Sendable` value. This is because ``EventLoopFuture``s hold on to their value and\ncan give it to other closures or other callers of `get` and `wait`. Thus, `sending` is not\nsufficient.\n\n## Combining Futures\n\nNIO provides a number of APIs for combining futures, such as ``EventLoopFuture/and(_:)``.\nThis potentially represents an issue, as two futures may not share the same isolation domain.\nAs a result, we can only safely call these combining functions when the ``EventLoopFuture``\nvalues are `Sendable`.\n\n> Note: We can conceptually relax this constraint somewhat by offering equivalent\n    functions that can only safely be called when all the combined futures share the\n    same bound event loop: that is, when they are all within the same isolation domain.\n\n    This can be enforced with runtime isolation checks. If you have a need for these\n    functions, please reach out to the NIO team.\n\n## Interacting with Futures on the Event Loop\n\nIn a number of contexts (such as in ``ChannelHandler``s), the programmer has static knowledge\nthat they are within an isolation domain. That isolation domain may well be shared with the\nisolation domain of many futures and promises with which they interact. For example,\nfutures that are provided from ``ChannelHandlerContext/write(_:promise:)`` will be bound to\nthe event loop on which the ``ChannelHandler`` resides.\n\nIn this context, the `sending` constraint is unnecessarily strict. The future callbacks are\nguaranteed to fire on the same isolation domain as the ``ChannelHandlerContext``: no risk\nof data race is present. However, Swift Concurrency cannot guarantee this at compile time,\nas the specific isolation domain is determined only at runtime.\n\nIn these contexts, users that cannot require NIO 2.77.0 can make their callbacks\nsafe using ``NIOLoopBound`` and ``NIOLoopBoundBox``. These values can only be\nconstructed on the event loop, and only allow access to their values on the same\nevent loop. These constraints are enforced at runtime, so at compile time these are\nunconditionally `Sendable`.\n\n> Warning: ``NIOLoopBound`` and ``NIOLoopBoundBox`` replace compile-time isolation checks\n    with runtime ones. This makes it possible to introduce crashes in your code. Please\n    ensure that you are 100% confident that the isolation domains align. If you are not\n    sure that the ``EventLoopFuture`` you wish to attach a callback to is bound to your\n    ``EventLoop``, use ``EventLoopFuture/hop(to:)`` to move it to your isolation domain\n    before using these types.\n\nFrom NIO 2.77.0, new types were introduced to make this common problem easier. These types are\n``EventLoopFuture/Isolated`` and ``EventLoopPromise/Isolated``. These isolated view types\ncan only be constructed from an existing Future or Promise, and they can only be constructed\non the ``EventLoop`` to which those futures or promises are bound. Because they are not\n`Sendable`, we can be confident that these values never escape the isolation domain in which\nthey are created, which must be the same isolation domain where the callbacks execute.\n\nAs a result, these types can drop the `@Sendable` requirements on all the future closures, and\nmany of the `Sendable` requirements on the return types from future closures. They can also\ndrop the `Sendable` requirements from the promise completion functions.\n\nThese isolated views can be obtained by calling ``EventLoopFuture/assumeIsolated()`` or\n``EventLoopPromise/assumeIsolated()``.\n\n> Warning: ``EventLoopFuture/assumeIsolated()`` and ``EventLoopPromise/assumeIsolated()``\n    supplement compile-time isolation checks with runtime ones. This makes it possible\n    to introduce crashes in your code. Please ensure that you are 100% confident that the\n    isolation domains align. If you are not sure that the ``EventLoopFuture`` or\n    ``EventLoopPromise`` you wish to attach a callback to is bound to your\n    ``EventLoop``, use ``EventLoopFuture/hop(to:)`` to move it to your isolation domain\n    before using these types.\n\n> Warning: ``EventLoopFuture/assumeIsolated()`` and ``EventLoopPromise/assumeIsolated()``\n    **must not** be called from a Swift concurrency context, either an async method or\n    from within an actor. This is because it uses runtime checking of the event loop\n    to confirm that the value is not being sent to a different concurrency domain.\n    \n    When using an ``EventLoop`` as a custom actor executor, this API can be used to retrieve\n    a value that region based isolation will then allow to be sent to another domain.\n\n## Interacting with Event Loops on the Event Loop\n\nAs with Futures, there are occasionally times where it is necessary to schedule\n``EventLoop`` operations on the ``EventLoop`` where your code is currently executing.\n\nMuch like with ``EventLoopFuture``, if you need to support NIO versions before 2.77.0\nyou can use ``NIOLoopBound`` and ``NIOLoopBoundBox`` to make these callbacks safe.\n\n> Warning: ``NIOLoopBound`` and ``NIOLoopBoundBox`` replace compile-time isolation checks\n    with runtime ones. This makes it possible to introduce crashes in your code. Please\n    ensure that you are 100% confident that the isolation domains align. If you are not\n    sure that the ``EventLoopFuture`` you wish to attach a callback to is bound to your\n    ``EventLoop``, use ``EventLoopFuture/hop(to:)`` to move it to your isolation domain\n    before using these types.\n\nFrom NIO 2.77.0, a new type was introduced to make this common problem easier. This type is\n``NIOIsolatedEventLoop``. This isolated view type can only be constructed from an existing\n``EventLoop``, and it can only be constructed on the ``EventLoop`` that is being wrapped.\nBecause this type is not `Sendable`, we can be confident that this value never escapes the\nisolation domain in which it was created, which must be the same isolation domain where the\ncallbacks execute.\n\nAs a result, this type can drop the `@Sendable` requirements on all the operation closures, and\nmany of the `Sendable` requirements on the return types from these closures.\n\nThis isolated view can be obtained by calling ``EventLoop/assumeIsolated()``.\n\n> Warning: ``EventLoop/assumeIsolated()`` supplements compile-time isolation checks with\n    runtime ones. This makes it possible to introduce crashes in your code. Please ensure\n    that you are 100% confident that the isolation domains align. If you are not sure that\n    the your code is running on the relevant ``EventLoop``, prefer the non-isolated type.\n\n> Warning: ``EventLoop/assumeIsolated()`` **must not** be called from a Swift concurrency\n    context, either an async method or from within an actor. This is because it uses runtime\n    checking of the event loop to confirm that the value is not being sent to a different\n    concurrency domain.\n    \n    When using an ``EventLoop`` as a custom actor executor, this API can be used to retrieve\n    a value that region based isolation will then allow to be sent to another domain.\n"
  },
  {
    "path": "Sources/NIOCore/Docs.docc/swift-concurrency.md",
    "content": "# NIO and Swift Concurrency\n\nThis article explains how to interface between NIO and Swift Concurrency.\n\nNIO was created before native Concurrency support in Swift existed, hence, NIO\nhad to solve a few problems that have solutions in the language today. Since the\nintroduction of Swift Concurrency, NIO has added numerous features to make the\ninterop between NIO's ``Channel`` eventing system and Swift's Concurrency\nprimitives as easy as possible.\n\n### EventLoopFuture/Promise bridges\n\nThe first bridges that NIO introduced added methods on ``EventLoopFuture`` and\n``EventLoopPromise`` to enable communication between Concurrency and NIO. These\nmethods are ``EventLoopFuture/get()`` and\n``EventLoopPromise/completeWithTask(_:)``.\n\n> Warning: The future ``EventLoopFuture/get()`` method does not support task\n> cancellation.\n\nHere is a small example of how these work:\n\n```swift\nlet eventLoop: EventLoop\n\nlet promise = eventLoop.makePromise(of: Bool.self)\n\npromise.completeWithTask {\n    try await Task.sleep(for: .seconds(1))\n    return true\n}\n\nlet result = try await promise.futureResult.get()\n```\n\n> Note: The `completeWithTask` method creates an unstructured task under the\n> hood.\n\n### Channel bridges\n\nThe ``EventLoopFuture`` and ``EventLoopPromise`` bridges already allow async\ncode to interact with some of NIO's types. However, they only work where we have\nrequest-response-like interfaces. On the other hand, NIO's ``Channel`` type\ncontains a ``ChannelPipeline`` which can be roughly described as a\nbi-directional streaming pipeline. To bridge such a pipeline into Concurrency\nrequired new types. Importantly, these types need to uphold the channel's\nback pressure and writability guarantees. NIO introduced the\n``NIOThrowingAsyncSequenceProducer``, ``NIOAsyncSequenceProducer`` and the\n``NIOAsyncChannelOutboundWriter`` which form the foundation to bridge a ``Channel``. On top of\nthese foundational types, NIO provides the `NIOAsyncChannel` which is used to\nwrap a ``Channel`` to produce an interface that can be consumed directly from\nSwift Concurrency. The following sections cover the details of the foundational\ntypes and how the `NIOAsyncChannel` works.\n\n#### NIOThrowingAsyncSequenceProducer and NIOAsyncSequenceProducer\n\nThe ``NIOThrowingAsyncSequenceProducer`` and ``NIOAsyncSequenceProducer`` are\nasynchronous sequences similar to Swift's `AsyncStream`. Their purpose is to\nprovide a back pressured bridge between a synchronous producer and an\nasynchronous consumer. These types are highly configurable and generic which\nmakes them usable in a lot of places with very good performance; however, at the\nsame time they are not the easiest types to hold. We recommend that you\n**never** expose them in public API but rather wrap them in your own async\nsequence.\n\n#### NIOAsyncWriter\n\nThe ``NIOAsyncChannelOutboundWriter`` is used for bridging from an asynchronous producer to a\nsynchronous consumer. It also has back pressure support which allows the\nconsumer to stop the producer by suspending the\n``NIOAsyncWriter/yield(contentsOf:)`` method.\n\n#### NIOAsyncChannel\n\nThe above types are used to bridge both the read and write side of a ``Channel``\ninto Swift Concurrency. This can be done by wrapping a ``Channel`` via the\n`NIOAsyncChannel/init(synchronouslyWrapping:configuration:)`\ninitializer. Under the hood, this initializer adds two channel handlers to the\nend of the channel's pipeline. These handlers bridge the read and write side of\nthe channel. Additionally, the handlers work together to close the channel once\nboth the reading and the writing have finished.\n\nThis is how you can wrap an existing channel into a `NIOAsyncChannel`, consume\nthe inbound data and echo it back outbound.\n\n```swift\nlet channel = ...\nlet asyncChannel = try NIOAsyncChannel<ByteBuffer, ByteBuffer>(wrappingChannelSynchronously: channel)\n\ntry await asyncChannel.executeThenClose { inbound, outbound in\n    for try await inboundData in inbound {\n        try await outbound.write(inboundData)\n    }\n}\n```\n\nThe above code works nicely; however, you must be very careful at what point you\nwrap your channel otherwise you might lose some reads. For example your channel\nmight be created by a `ServerBootstrap` for a new inbound connection. The\nchannel might start to produce reads as soon as it registered its IO which\nhappens after your channel initializer ran. To avoid potentially losing reads\nthe channel must be wrapped before it registered its IO. Another example is when\nthe channel contains a handler that does protocol negotiation. Protocol\nnegotiation handlers are usually waiting for some data to be exchanged before\ndeciding what protocol to chose. Afterwards, they often modify the channel's\npipeline and add the protocol appropriate handlers to it. This is another case\nwhere wrapping of the `Channel` into a `NIOAsyncChannel` needs to happen at the\nright time to avoid losing reads.\n\n### Asynchronous bootstrap methods\n\nNIO offers a multitude of bootstraps. To avoid the above problems\nand enable a seamless experience when using NIO from Swift Concurrency,\nthe bootstraps gained new generic asynchronous methods.\n\nThe next section is going to focus on how to use the methods to boostrap a TCP\nserver and client.\n\n#### ServerBootstrap\n\nThe server bootstrap is used to create a new TCP based server. Once any of the\nbind methods on the `ServerBootstrap` is called, a new listening socket is\ncreated to handle new inbound TCP connections. Let's use the new methods\nto setup a TCP server and configure a `NIOAsyncChannel` for each inbound\nconnection.\n\n```swift\nlet serverChannel = try await ServerBootstrap(group: eventLoopGroup)\n    .bind(\n        host: \"127.0.0.1\",\n        port: 1234\n    ) { childChannel in\n        // This closure is called for every inbound connection\n        childChannel.eventLoop.makeCompletedFuture {\n            return try NIOAsyncChannel<ByteBuffer, ByteBuffer>(\n                synchronouslyWrapping: childChannel\n            )\n        }\n    }\n\ntry await withThrowingDiscardingTaskGroup { group in\n    try await serverChannel.executeThenClose { serverChannelInbound in\n        for try await connectionChannel in serverChannelInbound {\n            group.addTask {\n                do {\n                    try await connectionChannel.executeThenClose { connectionChannelInbound, connectionChannelOutbound in\n                        for try await inboundData in connectionChannelInbound {\n                            // Let's echo back all inbound data\n                            try await connectionChannelOutbound.write(inboundData)\n                        }\n                    }\n                } catch {\n                    // Handle errors\n                }\n            }\n        }\n    }\n}\n```\n\nIn the above code, we are bootstrapping a new TCP server which we assign to\n`serverChannel`. Furthermore, in the trailing closure of `bind` we are\nconfiguring the pipeline of each inbound connection. In our example, we are\nwrapping each child channel in a `NIOAsyncChannel`. The resulting\n`serverChannel` is a `NIOAsyncChannel` whose inbound type is a `NIOAsyncChannel`\nand  whose outbound type is `Never`. This is due to the fact that each inbound\nconnection gets its own separate child channel. The inbound and outbound types\nof each inbound connection is `ByteBuffer` as specified in the bootstrap.\nAfterwards, we handle each inbound connection in separate child tasks and echo\nthe data back.\n\n> Important: Make sure to use discarding task groups which automatically reap\nfinished child tasks. Normal task groups will result in a memory leak since they\ndo not reap their child tasks automatically.\n\n#### ClientBootstrap\n\nThe client bootstrap is used to create a new TCP based client. Let's take a look\nhow to bootstrap a TCP connection and send some data to the server.\n\n```swift\nlet clientChannel = try await ClientBootstrap(group: eventLoopGroup)\n    .connect(\n        host: \"127.0.0.1\",\n        port: 1234\n    ) { channel in\n        channel.eventLoop.makeCompletedFuture {\n            return try NIOAsyncChannel<ByteBuffer, ByteBuffer>(\n                wrappingChannelSynchronously: channel\n            )\n        }\n    }\n\ntry await clientChannel.executeThenClose { inbound, outbound in\n    try await outbound.write(ByteBuffer(string: \"hello\"))\n\n    for try await inboundData in inbound {\n        print(inboundData)\n    }\n}\n```\n\n#### Dynamic pipeline modifications\n\nThe above bootstrap methods work great in the case where we know the types of\nthe resulting channels at compile time. However, there are some scenarios where\nthe type is only determined at runtime. Such cases include\n[Application-Layer-Protocol-Negotiation](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation)\nor [HTTP protocol\nupgrades](https://en.wikipedia.org/wiki/HTTP/1.1_Upgrade_header). To support\nthose scenarios it is essential that channel handlers that dynamically configure\nthe pipeline carry type information which allows us to runtime to determine how\nthe pipeline was configured at runtime. To support this NIO introduced multiple\nnew `ChannelHandler` and corresponding pipeline configuration methods. Those\ntypes are:\n\n1. `NIOTypedApplicationProtocolNegotiationHandler` for TLS based ALPN\n2. `NIOTypedHTTPServerUpgradeHandler` and\n   `configureUpgradableHTTPServerPipeline` for server-side HTTP protocol\n   upgrades\n2. `NIOTypedHTTPClientUpgradeHandler` and\n   `configureUpgradableHTTPClientPipeline` for client-side HTTP protocol\n   upgrades\n\nAll of those types have one thing in common - they are generic over the result\nof the dynamic pipeline configuration. This allows users to exhaustively switch\nover the result and correctly handle each case. The following example\ndemonstrates how this works for a client-side websocket upgrade.\n\n```swift\nenum UpgradeResult {\n    case websocket(NIOAsyncChannel<WebSocketFrame, WebSocketFrame>)\n    case notUpgraded\n}\n\nlet upgradeResult: EventLoopFuture<UpgradeResult> = try await ClientBootstrap(group: eventLoopGroup)\n    .connect(\n        host: \"127.0.0.1\",\n        port: 1234\n    ) { channel in\n        channel.eventLoop.makeCompletedFuture {\n            // Configure the websocket upgrader\n            let upgrader = NIOTypedWebSocketClientUpgrader<UpgradeResult>(\n                upgradePipelineHandler: { channel, _ in\n                    // This configures the pipeline after the websocket upgrade was successful.\n                    // We are wrapping the pipeline in a NIOAsyncChannel.\n                    channel.eventLoop.makeCompletedFuture {\n                        let asyncChannel = try NIOAsyncChannel<WebSocketFrame, WebSocketFrame>(wrappingChannelSynchronously: channel)\n                        return UpgradeResult.websocket(asyncChannel)\n                    }\n                }\n            )\n\n            var headers = HTTPHeaders()\n            headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n            headers.add(name: \"Content-Length\", value: \"0\")\n\n            let requestHead = HTTPRequestHead(\n                version: .http1_1,\n                method: .GET,\n                uri: \"/\",\n                headers: headers\n            )\n\n            let clientUpgradeConfiguration = NIOTypedHTTPClientUpgradeConfiguration(\n                upgradeRequestHead: requestHead,\n                upgraders: [upgrader],\n                notUpgradingCompletionHandler: { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        return UpgradeResult.notUpgraded\n                    }\n                }\n            )\n\n            let upgradeResult = try channel.pipeline.syncOperations.configureUpgradableHTTPClientPipeline(\n                configuration: .init(upgradeConfiguration: clientUpgradeConfiguration)\n            )\n\n            return upgradeResult\n        }\n    }\n```\n\nAfter having configured the pipeline to negotiate a websocket upgrade. We can\nswitch over the the `upgradeResult`. Importantly, we have to `await` the\n`upgradeResult` first since it has to be negotiated on the connection.\n\n```\nswitch try await upgradeResult.get() {\ncase .websocket(let websocketChannel):\n    print(\"Handling websocket connection\")\n    try await self.handleWebsocketChannel(websocketChannel)\n    print(\"Done handling websocket connection\")\ncase .notUpgraded:\n    // The upgrade to websocket did not succeed.\n    print(\"Upgrade declined\")\n}\n```\n\n### NIOAny\n\nIn NIO 2.77.0, a number of methods that took `NIOAny` as a parameter started\nemitting deprecation warnings. These deprecation warnings are a substitute for the\nconcurrency warnings that you might otherwise see.\n\nThe problem with these methods (most of which were defined on ``ChannelInvoker``)\nis that they frequently would send a `NIOAny` across an event loop boundary.\nMost commonly users will encounter this when calling methods on ``Channel`` types\n(which conform to ``ChannelInvoker``), though they may encounter it on\n``ChannelPipeline`` as well.\n\nThe problem these methods have is that they can be safely called both on and off\nof the ``EventLoop`` to which a ``Channel`` is bound. That means that they must be\ncapable of sending the value across an isolation domain, into the ``EventLoop``.\nThat requires the parameter to be `Sendable` (or to be `sending`).\n\n`NIOAny` cannot be made to be `Sendable`, so these methods are now deprecated.\nThey have been replaced with equivalent methods that take a generic type that\nmust be `Sendable`, and they take charge of wrapping the type in `NIOAny`. If\nyou encounter such a warning, this is the most common change.\n\nIn cases where a non-`Sendable` value must actually be sent into the pipeline, there\nare a few methods that can still be used. These methods are available on\n``ChannelPipeline/SynchronousOperations``, which can be accessed via\n``ChannelPipeline/syncOperations``. The ``ChannelPipeline/SynchronousOperations`` type\ncan only be accessed from on the `EventLoop`, and so no sending of a value\nacross isolation domains will occur here.\n\n### General guidance\n\n#### Where should your code live?\n\nBefore the introduction of Swift Concurrency both implementations of network\nprotocols and business logic were often written inside ``ChannelHandler``s. This\nmade it easier to get started; however, it came with some downsides. First,\nimplementing business logic inside channel handlers requires the business logic\nto also handle all of the invariants that the ``ChannelHandler`` protocol brings\nwith it. This often requires writing complex state machines. Additionally, the\nbusiness logic becomes very tied to NIO and hard to port between different\nsystems. Because of the above reasons we recommend to implement your business\nlogic using Swift Concurrency primitives and the `NIOAsyncChannel` based\nbootstraps. Network protocol implementation should still be implemented as\n``ChannelHandler``s.\n"
  },
  {
    "path": "Sources/NIOCore/EventLoop+Deprecated.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension EventLoop {\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func makeFailedFuture<T>(\n        _ error: Error,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<T> {\n        self.makeFailedFuture(error)\n    }\n\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func makeSucceededFuture<Success: Sendable>(\n        _ value: Success,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<Success> {\n        self.makeSucceededFuture(value)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/EventLoop+SerialExecutor.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A helper protocol that can be mixed in to a NIO ``EventLoop`` to provide an\n/// automatic conformance to `SerialExecutor`.\n///\n/// Implementers of `EventLoop` should consider conforming to this protocol as\n/// well on Swift 5.9 and later.\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\npublic protocol NIOSerialEventLoopExecutor: EventLoop, SerialExecutor {}\n\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\nextension NIOSerialEventLoopExecutor {\n    @inlinable\n    public func enqueue(_ job: consuming ExecutorJob) {\n        // By default we are just going to use execute to run the job\n        // this is quite heavy since it allocates the closure for\n        // every single job.\n        let unownedJob = UnownedJob(job)\n        self.execute {\n            unownedJob.runSynchronously(on: self.asUnownedSerialExecutor())\n        }\n    }\n\n    @inlinable\n    public func asUnownedSerialExecutor() -> UnownedSerialExecutor {\n        UnownedSerialExecutor(complexEquality: self)\n    }\n\n    @inlinable\n    public var executor: any SerialExecutor {\n        self\n    }\n\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    @inlinable\n    public func isSameExclusiveExecutionContext(other: Self) -> Bool {\n        other === self\n    }\n\n    @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, *)\n    @inlinable\n    public func checkIsolated() {\n        self.preconditionInEventLoop()\n    }\n}\n\n/// A type that wraps a NIO ``EventLoop`` into a `SerialExecutor`\n/// for use with Swift concurrency.\n///\n/// This type is not recommended for use because it risks problems with unowned\n/// executors. Adopters are recommended to conform their own event loop\n/// types to `SerialExecutor`.\nfinal class NIODefaultSerialEventLoopExecutor {\n    @usableFromInline\n    let loop: EventLoop\n\n    @inlinable\n    init(_ loop: EventLoop) {\n        self.loop = loop\n    }\n}\n\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\nextension NIODefaultSerialEventLoopExecutor: SerialExecutor {\n    @inlinable\n    public func enqueue(_ job: consuming ExecutorJob) {\n        self.loop.enqueue(job)\n    }\n\n    @inlinable\n    public func asUnownedSerialExecutor() -> UnownedSerialExecutor {\n        UnownedSerialExecutor(complexEquality: self)\n\n    }\n\n    @inlinable\n    public func isSameExclusiveExecutionContext(other: NIODefaultSerialEventLoopExecutor) -> Bool {\n        self.loop === other.loop\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/EventLoop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\n#if canImport(WASILibc)\n@preconcurrency import WASILibc\nimport CNIOWASI\n#endif\n\n#if os(Linux)\nimport CNIOLinux\n#endif  // os(Linux)\n\n/// Returned once a task was scheduled on the `EventLoop` for later execution.\n///\n/// A `Scheduled` allows the user to either `cancel()` the execution of the scheduled task (if possible) or obtain a reference to the `EventLoopFuture` that\n/// will be notified once the execution is complete.\npublic struct Scheduled<T> {\n    @usableFromInline typealias CancelationCallback = @Sendable () -> Void\n    @usableFromInline let _promise: EventLoopPromise<T>\n    @usableFromInline let _cancellationTask: CancelationCallback\n\n    @inlinable\n    @preconcurrency\n    public init(promise: EventLoopPromise<T>, cancellationTask: @escaping @Sendable () -> Void) {\n        self._promise = promise\n        self._cancellationTask = cancellationTask\n    }\n\n    /// Try to cancel the execution of the scheduled task.\n    ///\n    /// Whether this is successful depends on whether the execution of the task already begun.\n    ///  This means that cancellation is not guaranteed.\n    @inlinable\n    public func cancel() {\n        self._promise.fail(EventLoopError._cancelled)\n        self._cancellationTask()\n    }\n\n    /// Returns the `EventLoopFuture` which will be notified once the execution of the scheduled task completes.\n    @inlinable\n    public var futureResult: EventLoopFuture<T> {\n        self._promise.futureResult\n    }\n}\n\nextension Scheduled: Sendable {}\n\n/// Returned once a task was scheduled to be repeatedly executed on the `EventLoop`.\n///\n/// A `RepeatedTask` allows the user to `cancel()` the repeated scheduling of further tasks.\npublic final class RepeatedTask {\n    typealias RepeatedTaskCallback = @Sendable (RepeatedTask) -> EventLoopFuture<Void>\n    private let delay: TimeAmount\n    private let eventLoop: EventLoop\n    private let cancellationPromise: EventLoopPromise<Void>?\n    private var scheduled: Optional<Scheduled<EventLoopFuture<Void>>>\n    private var task: Optional<RepeatedTaskCallback>\n\n    internal init(\n        interval: TimeAmount,\n        eventLoop: EventLoop,\n        cancellationPromise: EventLoopPromise<Void>? = nil,\n        task: @escaping RepeatedTaskCallback\n    ) {\n        self.delay = interval\n        self.eventLoop = eventLoop\n        self.cancellationPromise = cancellationPromise\n        self.task = task\n        self.scheduled = nil\n    }\n\n    internal func begin(in delay: TimeAmount) {\n        if self.eventLoop.inEventLoop {\n            self.begin0(in: delay)\n        } else {\n            self.eventLoop.execute {\n                self.begin0(in: delay)\n            }\n        }\n    }\n\n    private func begin0(in delay: TimeAmount) {\n        self.eventLoop.assertInEventLoop()\n        guard let task = self.task else {\n            return\n        }\n        self.scheduled = self.eventLoop.scheduleTask(in: delay) {\n            task(self)\n        }\n        self.reschedule()\n    }\n\n    /// Try to cancel the execution of the repeated task.\n    ///\n    /// Whether the execution of the task is immediately canceled depends on whether the execution of a task has already begun.\n    ///  This means immediate cancellation is not guaranteed.\n    ///\n    /// The safest way to cancel is by using the passed reference of `RepeatedTask` inside the task closure.\n    ///\n    /// If the promise parameter is not `nil`, the passed promise is fulfilled when cancellation is complete.\n    /// Passing a promise does not prevent fulfillment of any promise provided on original task creation.\n    public func cancel(promise: EventLoopPromise<Void>? = nil) {\n        if self.eventLoop.inEventLoop {\n            self.cancel0(localCancellationPromise: promise)\n        } else {\n            self.eventLoop.execute {\n                self.cancel0(localCancellationPromise: promise)\n            }\n        }\n    }\n\n    private func cancel0(localCancellationPromise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n        self.scheduled?.cancel()\n        self.scheduled = nil\n        self.task = nil\n\n        // Possible states at this time are:\n        //  1) Task is scheduled but has not yet executed.\n        //  2) Task is currently executing and invoked `cancel()` on itself.\n        //  3) Task is currently executing and `cancel0()` has been reentrantly invoked.\n        //  4) NOT VALID: Task is currently executing and has NOT invoked `cancel()` (`EventLoop` guarantees serial execution)\n        //  5) NOT VALID: Task has completed execution in a success state (`reschedule()` ensures state #2).\n        //  6) Task has completed execution in a failure state.\n        //  7) Task has been fully cancelled at a previous time.\n        //\n        // It is desirable that the task has fully completed any execution before any cancellation promise is\n        // fulfilled. States 2 and 3 occur during execution, so the requirement is implemented by deferring\n        // fulfillment to the next `EventLoop` cycle. The delay is harmless to other states and distinguishing\n        // them from 2 and 3 is not practical (or necessarily possible), so is used unconditionally. Check the\n        // promises for nil so as not to otherwise invoke `execute()` unnecessarily.\n        if self.cancellationPromise != nil || localCancellationPromise != nil {\n            self.eventLoop.execute {\n                self.cancellationPromise?.succeed(())\n                localCancellationPromise?.succeed(())\n            }\n        }\n    }\n\n    private func reschedule() {\n        self.eventLoop.assertInEventLoop()\n        guard let scheduled = self.scheduled else {\n            return\n        }\n\n        scheduled.futureResult.whenSuccess { future in\n            future.hop(to: self.eventLoop).whenComplete { (_: Result<Void, Error>) in\n                self.reschedule0()\n            }\n        }\n\n        scheduled.futureResult.whenFailure { (_: Error) in\n            self.cancel0(localCancellationPromise: nil)\n        }\n    }\n\n    private func reschedule0() {\n        self.eventLoop.assertInEventLoop()\n        guard self.task != nil else {\n            return\n        }\n        self.scheduled = self.eventLoop.scheduleTask(in: self.delay) {\n            // we need to repeat this as we might have been cancelled in the meantime\n            guard let task = self.task else {\n                return self.eventLoop.makeSucceededFuture(())\n            }\n            return task(self)\n        }\n        self.reschedule()\n    }\n}\n\nextension RepeatedTask: @unchecked Sendable {}\n\n/// An iterator over the `EventLoop`s forming an `EventLoopGroup`.\n///\n/// Usually returned by an `EventLoopGroup`'s `makeIterator()` method.\n///\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///     group.makeIterator().forEach { loop in\n///         // Do something with each loop\n///     }\n///\npublic struct EventLoopIterator: Sequence, IteratorProtocol {\n    public typealias Element = EventLoop\n    private var eventLoops: IndexingIterator<[EventLoop]>\n\n    /// Create an `EventLoopIterator` from an array of `EventLoop`s.\n    public init(_ eventLoops: [EventLoop]) {\n        self.eventLoops = eventLoops.makeIterator()\n    }\n\n    /// Advances to the next `EventLoop` and returns it, or `nil` if no next element exists.\n    ///\n    /// - Returns: The next `EventLoop` if a next element exists; otherwise, `nil`.\n    public mutating func next() -> EventLoop? {\n        self.eventLoops.next()\n    }\n}\n\nextension EventLoopIterator: Sendable {}\n\n/// An EventLoop processes IO / tasks in an endless loop for `Channel`s until it's closed.\n///\n/// Usually multiple `Channel`s share the same `EventLoop` for processing IO / tasks and so share the same processing `NIOThread`.\n/// For a better understanding of how such an `EventLoop` works internally the following pseudo code may be helpful:\n///\n/// ```\n/// while eventLoop.isOpen {\n///     /// Block until there is something to process for 1...n Channels\n///     let readyChannels = blockUntilIoOrTasksAreReady()\n///     /// Loop through all the Channels\n///     for channel in readyChannels {\n///         /// Process IO and / or tasks for the Channel.\n///         /// This may include things like:\n///         ///    - accept new connection\n///         ///    - connect to a remote host\n///         ///    - read from socket\n///         ///    - write to socket\n///         ///    - tasks that were submitted via EventLoop methods\n///         /// and others.\n///         processIoAndTasks(channel)\n///     }\n/// }\n/// ```\n///\n/// Because an `EventLoop` may be shared between multiple `Channel`s it's important to _NOT_ block while processing IO / tasks. This also includes long running computations which will have the same\n/// effect as blocking in this case.\npublic protocol EventLoop: EventLoopGroup {\n    /// Returns `true` if the current `NIOThread` is the same as the `NIOThread` that is tied to this `EventLoop`. `false` otherwise.\n    ///\n    /// This method is intended principally as an optimization point, allowing users to write code that can provide fast-paths when this\n    /// property is true. It is _not suitable_ as a correctness guard. Code must be correct if this value returns `false` _even if_\n    /// the event loop context is actually held. That's because this property is allowed to produce false-negatives\n    ///\n    /// Implementers may implement this method in a way that may produce false-negatives: that is, this value may return `false` in\n    /// cases where the code in question actually is executing on the event loop. It may _never_ produce false positives: this value\n    /// must never return `true` when event loop context is not actually held.\n    ///\n    /// If it is necessary for correctness to confirm that you're on an event loop, prefer ``preconditionInEventLoop(file:line:)-7ukrq``.\n    var inEventLoop: Bool { get }\n\n    /// Submit a given task to be executed by the `EventLoop`\n    @preconcurrency\n    func execute(_ task: @escaping @Sendable () -> Void)\n\n    /// Submit a given task to be executed by the `EventLoop`. Once the execution is complete the returned `EventLoopFuture` is notified.\n    ///\n    /// - Parameters:\n    ///   - task: The closure that will be submitted to the `EventLoop` for execution.\n    /// - Returns: `EventLoopFuture` that is notified once the task was executed.\n    @preconcurrency\n    func submit<T>(_ task: @escaping @Sendable () throws -> T) -> EventLoopFuture<T>\n\n    /// The current time of the event loop.\n    var now: NIODeadline { get }\n\n    /// Schedule a `task` that is executed by this `EventLoop` at the given time.\n    ///\n    /// - Parameters:\n    ///   - deadline: The instant in time before which the task will not execute.\n    ///   - task: The synchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the completion of the task.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    @discardableResult\n    @preconcurrency\n    func scheduleTask<T>(deadline: NIODeadline, _ task: @escaping @Sendable () throws -> T) -> Scheduled<T>\n\n    /// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.\n    ///\n    /// - Parameters:\n    ///   - in: The amount of time before which the task will not execute.\n    ///   - task: The synchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the completion of the task.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    /// - Note: The `in` value is clamped to a maximum when running on a Darwin-kernel.\n    @discardableResult\n    @preconcurrency\n    func scheduleTask<T>(in: TimeAmount, _ task: @escaping @Sendable () throws -> T) -> Scheduled<T>\n\n    /// Asserts that the current thread is the one tied to this `EventLoop`.\n    /// Otherwise, the process will be abnormally terminated as per the semantics of `preconditionFailure(_:file:line:)`.\n    ///\n    /// This method may never produce false positives or false negatives in conforming implementations. It may never\n    /// terminate the process when event loop context is actually held, and it may never fail to terminate the process\n    /// when event loop context is not held.\n    func preconditionInEventLoop(file: StaticString, line: UInt)\n\n    /// Asserts that the current thread is _not_ the one tied to this `EventLoop`.\n    /// Otherwise, the process will be abnormally terminated as per the semantics of `preconditionFailure(_:file:line:)`.\n    ///\n    /// This method may never produce false positives or false negatives in conforming implementations. It may never\n    /// terminate the process when event loop context is not held, and it may never fail to terminate the process\n    /// when event loop context is held.\n    func preconditionNotInEventLoop(file: StaticString, line: UInt)\n\n    /// Return a succeeded `Void` future.\n    ///\n    /// Semantically, this function is equivalent to calling `makeSucceededFuture(())`.\n    /// Contrary to `makeSucceededFuture`, `makeSucceededVoidFuture` is a customization point for `EventLoop`s which\n    /// allows `EventLoop`s to cache a pre-succeeded `Void` future to prevent superfluous allocations.\n    func makeSucceededVoidFuture() -> EventLoopFuture<Void>\n\n    /// Returns a `SerialExecutor` corresponding to this ``EventLoop``.\n    ///\n    /// This executor can be used to isolate an actor to a given ``EventLoop``. Implementers are encouraged to customise\n    /// this implementation by conforming their ``EventLoop`` to ``NIOSerialEventLoopExecutor`` which will provide an\n    /// optimised implementation of this method, and will conform their type to `SerialExecutor`. The default\n    /// implementation provides suboptimal performance.\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    var executor: any SerialExecutor { get }\n\n    /// Submit a job to be executed by the `EventLoop`\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    func enqueue(_ job: consuming ExecutorJob)\n\n    /// Must crash if it is not safe to call `wait()` on an `EventLoopFuture`.\n    ///\n    /// This method is a debugging hook that can be used to override the behaviour of `EventLoopFuture.wait()` when called.\n    /// By default this simply becomes `preconditionNotInEventLoop`, but some `EventLoop`s are capable of more exhaustive\n    /// checking and can validate that the wait is not occurring on an entire `EventLoopGroup`, or even more broadly.\n    ///\n    /// This method should not be called by users directly, it should only be implemented by `EventLoop` implementers that\n    /// need to customise the behaviour.\n    func _preconditionSafeToWait(file: StaticString, line: UInt)\n\n    /// Debug hook: track a promise creation and its location.\n    ///\n    /// This debug hook is called by EventLoopFutures and EventLoopPromises when they are created, and tracks the location\n    /// of their creation. It combines with `_promiseCompleted` to provide high-fidelity diagnostics for debugging leaked\n    /// promises.\n    ///\n    /// In release mode, this function will never be called.\n    ///\n    /// It is valid for an `EventLoop` not to implement any of the two `_promise` functions. If either of them are implemented,\n    /// however, both of them should be implemented.\n    func _promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier, file: StaticString, line: UInt)\n\n    /// Debug hook: complete a specific promise and return its creation location.\n    ///\n    /// This debug hook is called by EventLoopFutures and EventLoopPromises when they are deinited, and removes the data from\n    /// the promise tracking map and, if available, provides that data as its return value. It combines with `_promiseCreated`\n    /// to provide high-fidelity diagnostics for debugging leaked promises.\n    ///\n    /// In release mode, this function will never be called.\n    ///\n    /// It is valid for an `EventLoop` not to implement any of the two `_promise` functions. If either of them are implemented,\n    /// however, both of them should be implemented.\n    func _promiseCompleted(futureIdentifier: _NIOEventLoopFutureIdentifier) -> (file: StaticString, line: UInt)?\n\n    /// Schedule a callback at a given time.\n    ///\n    /// - Parameters:\n    ///   - deadline: The instant in time before which the task will not execute.\n    ///   - handler: The handler that defines the behavior of the callback when executed or canceled.\n    /// - Returns: A ``NIOScheduledCallback`` that can be used to cancel the scheduled callback.\n    ///\n    /// - NOTE: Event loops that provide a custom scheduled callback implementation **must** also implement\n    ///         `cancelScheduledCallback`. Failure to do so will result in a runtime error.\n    @preconcurrency\n    @discardableResult\n    func scheduleCallback(\n        at deadline: NIODeadline,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) throws -> NIOScheduledCallback\n\n    /// Schedule a callback after given time.\n    ///\n    /// - Parameters:\n    ///   - amount: The amount of time before which the task will not execute.\n    ///   - handler: The handler that defines the behavior of the callback when executed or canceled.\n    ///  - Returns: A ``NIOScheduledCallback`` that can be used to cancel the scheduled callback.\n    ///\n    /// - NOTE: Event loops that provide a custom scheduled callback implementation **must** also implement\n    ///         `cancelScheduledCallback`. Failure to do so will result in a runtime error.\n    @preconcurrency\n    @discardableResult\n    func scheduleCallback(\n        in amount: TimeAmount,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) throws -> NIOScheduledCallback\n\n    /// Cancel a scheduled callback.\n    ///\n    /// - NOTE: Event loops only need to implemented this if they provide a custom scheduled callback implementation.\n    func cancelScheduledCallback(_ scheduledCallback: NIOScheduledCallback)\n\n    /// Submit a given task to be executed by the ``EventLoop``, from a context where the caller\n    /// statically knows that the context is isolated.\n    ///\n    /// This is an optional performance hook. ``EventLoop`` implementers are not required to implement\n    /// this witness, but may choose to do so to enable better performance of the isolated EL views. If\n    /// they do so, ``EventLoop/Isolated/execute`` will perform better.\n    func _executeIsolatedUnsafeUnchecked(_ task: @escaping () -> Void)\n\n    /// Submit a given task to be executed by the ``EventLoop```, from a context where the caller\n    /// statically knows that the context is isolated.\n    ///\n    /// Once the execution is complete the returned ``EventLoopFuture`` is notified.\n    ///\n    /// This is an optional performance hook. ``EventLoop`` implementers are not required to implement\n    /// this witness, but may choose to do so to enable better performance of the isolated EL views. If\n    /// they do so, ``EventLoop/Isolated/submit`` will perform better.\n    ///\n    /// - Parameters:\n    ///   - task: The closure that will be submitted to the ``EventLoop`` for execution.\n    /// - Returns: ``EventLoopFuture`` that is notified once the task was executed.\n    func _submitIsolatedUnsafeUnchecked<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T>\n\n    /// Schedule a `task` that is executed by this ``EventLoop`` at the given time, from a context where the caller\n    /// statically knows that the context is isolated.\n    ///\n    /// This is an optional performance hook. ``EventLoop`` implementers are not required to implement\n    /// this witness, but may choose to do so to enable better performance of the isolated EL views. If\n    /// they do so, ``EventLoop/Isolated/scheduleTask(deadline:_:)`` will perform better.\n    ///\n    /// - Parameters:\n    ///   - deadline: The instant in time before which the task will not execute.\n    ///   - task: The synchronous task to run. As with everything that runs on the ``EventLoop```, it must not block.\n    /// - Returns: A ``Scheduled``` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the completion of the task.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    @discardableResult\n    func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        deadline: NIODeadline,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T>\n\n    /// Schedule a `task` that is executed by this ``EventLoop`` after the given amount of time, from a context where the caller\n    /// statically knows that the context is isolated.\n    ///\n    /// This is an optional performance hook. ``EventLoop`` implementers are not required to implement\n    /// this witness, but may choose to do so to enable better performance of the isolated EL views. If\n    /// they do so, ``EventLoop/Isolated/scheduleTask(in:_:)`` will perform better.\n    ///\n    /// - Parameters:\n    ///   - in: The amount of time before which the task will not execute.\n    ///   - task: The synchronous task to run. As with everything that runs on the ``EventLoop``, it must not block.\n    /// - Returns: A ``Scheduled`` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the completion of the task.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    /// - Note: The `in` value is clamped to a maximum when running on a Darwin-kernel.\n    @discardableResult\n    func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        in: TimeAmount,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T>\n\n    /// Schedule a callback that is executed by this ``EventLoop`` at a given time, from a context where the caller\n    /// statically knows that the context is isolated.\n    ///\n    /// This is an optional performance hook. ``EventLoop`` implementers are not required to implement\n    /// this witness, but may choose to do so to enable better performance of the isolated EL views. If\n    /// they do so, ``EventLoop/Isolated/scheduleCallback(at:_:)`` will perform better.\n    ///\n    /// - Parameters:\n    ///   - at: The instant in time before which the task will not execute.\n    ///   - handler: The handler that defines the behavior of the callback when executed or canceled.\n    /// - Returns: A ``NIOScheduledCallback`` that can be used to cancel the scheduled callback.\n    @discardableResult\n    func _scheduleCallbackIsolatedUnsafeUnchecked(\n        at deadline: NIODeadline,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback\n\n    /// Schedule a callback that is executed by this ``EventLoop`` after a given time, from a context where the caller\n    /// statically knows that the context is isolated.\n    ///\n    /// This is an optional performance hook. ``EventLoop`` implementers are not required to implement\n    /// this witness, but may choose to do so to enable better performance of the isolated EL views. If\n    /// they do so, ``EventLoop/Isolated/scheduleCallback(in:_:)`` will perform better.\n    ///\n    /// - Parameters:\n    ///   - in: The amount of time before which the task will not execute.\n    ///   - handler: The handler that defines the behavior of the callback when executed or canceled.\n    /// - Returns: A ``NIOScheduledCallback`` that can be used to cancel the scheduled callback.\n    @discardableResult\n    func _scheduleCallbackIsolatedUnsafeUnchecked(\n        in amount: TimeAmount,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback\n}\n\nextension EventLoop {\n    /// Default implementation of `now`: Returns `NIODeadline.now()`.\n    public var now: NIODeadline { .now() }\n}\n\nextension EventLoop {\n    /// Default implementation of `makeSucceededVoidFuture`: Return a fresh future (which will allocate).\n    public func makeSucceededVoidFuture() -> EventLoopFuture<Void> {\n        EventLoopFuture(eventLoop: self, value: ())\n    }\n\n    public func _preconditionSafeToWait(file: StaticString, line: UInt) {\n        self.preconditionNotInEventLoop(file: file, line: line)\n    }\n\n    /// Default implementation of `_promiseCreated`: does nothing.\n    public func _promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier, file: StaticString, line: UInt) {\n        return\n    }\n\n    /// Default implementation of `_promiseCompleted`: does nothing.\n    public func _promiseCompleted(futureIdentifier: _NIOEventLoopFutureIdentifier) -> (file: StaticString, line: UInt)?\n    {\n        nil\n    }\n\n    /// Default implementation: wraps the task in an UnsafeTransfer.\n    @inlinable\n    public func _executeIsolatedUnsafeUnchecked(_ task: @escaping () -> Void) {\n        self.assertInEventLoop()\n        let unsafeTransfer = UnsafeTransfer(task)\n        self.execute {\n            unsafeTransfer.wrappedValue()\n        }\n    }\n\n    /// Default implementation: wraps the task in an UnsafeTransfer.\n    @inlinable\n    public func _submitIsolatedUnsafeUnchecked<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        self.assertInEventLoop()\n        let unsafeTransfer = UnsafeTransfer(task)\n        return self.submit {\n            try unsafeTransfer.wrappedValue()\n        }\n    }\n\n    /// Default implementation: wraps the task in an UnsafeTransfer.\n    @inlinable\n    @discardableResult\n    public func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        deadline: NIODeadline,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        self.assertInEventLoop()\n        let unsafeTransfer = UnsafeTransfer(task)\n        return self.scheduleTask(deadline: deadline) {\n            try unsafeTransfer.wrappedValue()\n        }\n    }\n\n    /// Default implementation: wraps the task in an UnsafeTransfer.\n    @inlinable\n    @discardableResult\n    public func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        in delay: TimeAmount,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        self.assertInEventLoop()\n        let unsafeTransfer = UnsafeTransfer(task)\n        return self.scheduleTask(in: delay) {\n            try unsafeTransfer.wrappedValue()\n        }\n    }\n\n    @inlinable\n    @discardableResult\n    public func _scheduleCallbackIsolatedUnsafeUnchecked(\n        at deadline: NIODeadline,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback {\n        let unsafeHandlerWrapper = LoopBoundScheduledCallbackHandlerWrapper(wrapping: handler, eventLoop: self)\n        return try self.scheduleCallback(at: deadline, handler: unsafeHandlerWrapper)\n    }\n\n    @inlinable\n    @discardableResult\n    public func _scheduleCallbackIsolatedUnsafeUnchecked(\n        in amount: TimeAmount,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback {\n        let unsafeHandlerWrapper = LoopBoundScheduledCallbackHandlerWrapper(wrapping: handler, eventLoop: self)\n        return try self.scheduleCallback(in: amount, handler: unsafeHandlerWrapper)\n    }\n}\n\nextension EventLoop {\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    public var executor: any SerialExecutor {\n        NIODefaultSerialEventLoopExecutor(self)\n    }\n\n    @inlinable\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    public func enqueue(_ job: consuming ExecutorJob) {\n        // By default we are just going to use execute to run the job\n        // this is quite heavy since it allocates the closure for\n        // every single job.\n        let unownedJob = UnownedJob(job)\n        self.execute {\n            unownedJob.runSynchronously(on: self.executor.asUnownedSerialExecutor())\n        }\n    }\n}\n\nextension EventLoopGroup {\n    public var description: String {\n        String(describing: self)\n    }\n}\n\n/// Represents a time _interval_.\n///\n/// - Note: `TimeAmount` should not be used to represent a point in time.\npublic struct TimeAmount: Hashable, Sendable {\n    @available(*, deprecated, message: \"This typealias doesn't serve any purpose. Please use Int64 directly.\")\n    public typealias Value = Int64\n\n    /// The nanoseconds representation of the `TimeAmount`.\n    public let nanoseconds: Int64\n\n    @inlinable\n    init(_ nanoseconds: Int64) {\n        self.nanoseconds = nanoseconds\n    }\n\n    /// Creates a new `TimeAmount` for the given amount of nanoseconds.\n    ///\n    /// - Parameters:\n    ///   - amount: the amount of nanoseconds this `TimeAmount` represents.\n    /// - Returns: the `TimeAmount` for the given amount.\n    @inlinable\n    public static func nanoseconds(_ amount: Int64) -> TimeAmount {\n        TimeAmount(amount)\n    }\n\n    /// Creates a new `TimeAmount` for the given amount of microseconds.\n    ///\n    /// - Parameters:\n    ///   - amount: the amount of microseconds this `TimeAmount` represents.\n    /// - Returns: the `TimeAmount` for the given amount.\n    ///\n    /// - Note: returns `TimeAmount(.max)` if the amount overflows when converted to nanoseconds and `TimeAmount(.min)` if it underflows.\n    @inlinable\n    public static func microseconds(_ amount: Int64) -> TimeAmount {\n        TimeAmount(_cappedNanoseconds(amount: amount, multiplier: 1000))\n    }\n\n    /// Creates a new `TimeAmount` for the given amount of milliseconds.\n    ///\n    /// - Parameters:\n    ///   - amount: the amount of milliseconds this `TimeAmount` represents.\n    /// - Returns: the `TimeAmount` for the given amount.\n    ///\n    /// - Note: returns `TimeAmount(.max)` if the amount overflows when converted to nanoseconds and `TimeAmount(.min)` if it underflows.\n    @inlinable\n    public static func milliseconds(_ amount: Int64) -> TimeAmount {\n        TimeAmount(_cappedNanoseconds(amount: amount, multiplier: 1000 * 1000))\n    }\n\n    /// Creates a new `TimeAmount` for the given amount of seconds.\n    ///\n    /// - Parameters:\n    ///   - amount: the amount of seconds this `TimeAmount` represents.\n    /// - Returns: the `TimeAmount` for the given amount.\n    ///\n    /// - Note: returns `TimeAmount(.max)` if the amount overflows when converted to nanoseconds and `TimeAmount(.min)` if it underflows.\n    @inlinable\n    public static func seconds(_ amount: Int64) -> TimeAmount {\n        TimeAmount(_cappedNanoseconds(amount: amount, multiplier: 1000 * 1000 * 1000))\n    }\n\n    /// Creates a new `TimeAmount` for the given amount of minutes.\n    ///\n    /// - Parameters:\n    ///   - amount: the amount of minutes this `TimeAmount` represents.\n    /// - Returns: the `TimeAmount` for the given amount.\n    ///\n    /// - Note: returns `TimeAmount(.max)` if the amount overflows when converted to nanoseconds and `TimeAmount(.min)` if it underflows.\n    @inlinable\n    public static func minutes(_ amount: Int64) -> TimeAmount {\n        TimeAmount(_cappedNanoseconds(amount: amount, multiplier: 1000 * 1000 * 1000 * 60))\n    }\n\n    /// Creates a new `TimeAmount` for the given amount of hours.\n    ///\n    /// - Parameters:\n    ///   - amount: the amount of hours this `TimeAmount` represents.\n    /// - Returns: the `TimeAmount` for the given amount.\n    ///\n    /// - Note: returns `TimeAmount(.max)` if the amount overflows when converted to nanoseconds and `TimeAmount(.min)` if it underflows.\n    @inlinable\n    public static func hours(_ amount: Int64) -> TimeAmount {\n        TimeAmount(_cappedNanoseconds(amount: amount, multiplier: 1000 * 1000 * 1000 * 60 * 60))\n    }\n\n    /// Converts `amount` to nanoseconds multiplying it by `multiplier`. The return value is capped to `Int64.max` if the multiplication overflows and `Int64.min` if it underflows.\n    ///\n    ///  - parameters:\n    ///   - amount: the amount to be converted to nanoseconds.\n    ///   - multiplier: the multiplier that converts the given amount to nanoseconds.\n    ///  - returns: the amount converted to nanoseconds within [Int64.min, Int64.max].\n    @inlinable\n    static func _cappedNanoseconds(amount: Int64, multiplier: Int64) -> Int64 {\n        let nanosecondsMultiplication = amount.multipliedReportingOverflow(by: multiplier)\n        if nanosecondsMultiplication.overflow {\n            return amount >= 0 ? .max : .min\n        } else {\n            return nanosecondsMultiplication.partialValue\n        }\n    }\n}\n\n/// Contains the logic for parsing time amounts from strings,\n/// and printing pretty strings to represent time amounts.\nextension TimeAmount: CustomStringConvertible {\n\n    /// Errors thrown when parsint a TimeAmount from a string\n    internal enum ValidationError: Error, Equatable {\n        /// Can't parse the provided unit\n        case unsupportedUnit(String)\n\n        /// Can't parse the number into a Double\n        case invalidNumber(String)\n    }\n\n    /// Creates a TimeAmount from a string representation with an optional default unit.\n    ///\n    /// Supports formats like:\n    /// - \"5s\" (5 seconds)\n    /// - \"100ms\" (100 milliseconds)\n    /// - \"42\" (42 of default unit)\n    /// - \"1 hr\" (1 hour)\n    ///\n    /// This function only supports one pair of the number and units, i.e. \"5s\" or \"100ms\" but not \"5s 100ms\".\n    ///\n    /// Supported units:\n    /// - h, hr, hrs (hours)\n    /// - m, min (minutes)\n    /// - s, sec, secs (seconds)\n    /// - ms, millis (milliseconds)\n    /// - us, µs, micros (microseconds)\n    /// - ns, nanos (nanoseconds)\n    ///\n    /// - Parameters:\n    ///   - userProvidedString: The string to parse\n    ///\n    /// - Throws: ValidationError if the string cannot be parsed\n    public init(_ userProvidedString: String) throws {\n        let lowercased = String(userProvidedString.filter { !$0.isWhitespace }).lowercased()\n        let parsedNumbers = lowercased.prefix(while: { $0.isWholeNumber || $0 == \",\" || $0 == \".\" })\n        let parsedUnit = String(lowercased.dropFirst(parsedNumbers.count))\n\n        guard let numbers = Int64(parsedNumbers) else {\n            throw ValidationError.invalidNumber(\"'\\(userProvidedString)' cannot be parsed as number and unit\")\n        }\n\n        switch parsedUnit {\n        case \"h\", \"hr\", \"hrs\":\n            self = .hours(numbers)\n        case \"m\", \"min\":\n            self = .minutes(numbers)\n        case \"s\", \"sec\", \"secs\":\n            self = .seconds(numbers)\n        case \"ms\", \"millis\":\n            self = .milliseconds(numbers)\n        case \"us\", \"µs\", \"micros\":\n            self = .microseconds(numbers)\n        case \"ns\", \"nanos\":\n            self = .nanoseconds(numbers)\n        default:\n            throw ValidationError.unsupportedUnit(\"Unknown unit '\\(parsedUnit)' in '\\(userProvidedString)'\")\n        }\n    }\n\n    /// Returns a human-readable string representation of the time amount\n    /// using the most appropriate unit\n    public var description: String {\n        let fullNS = self.nanoseconds\n        let (fullUS, remUS) = fullNS.quotientAndRemainder(dividingBy: 1_000)\n        let (fullMS, remMS) = fullNS.quotientAndRemainder(dividingBy: 1_000_000)\n        let (fullS, remS) = fullNS.quotientAndRemainder(dividingBy: 1_000_000_000)\n\n        if remS == 0 {\n            return \"\\(fullS) s\"\n        } else if remMS == 0 {\n            return \"\\(fullMS) ms\"\n        } else if remUS == 0 {\n            return \"\\(fullUS) us\"\n        } else {\n            return \"\\(fullNS) ns\"\n        }\n    }\n}\n\nextension TimeAmount: Comparable {\n    @inlinable\n    public static func < (lhs: TimeAmount, rhs: TimeAmount) -> Bool {\n        lhs.nanoseconds < rhs.nanoseconds\n    }\n}\n\nextension TimeAmount: AdditiveArithmetic {\n    /// The zero value for `TimeAmount`.\n    @inlinable\n    public static var zero: TimeAmount {\n        TimeAmount.nanoseconds(0)\n    }\n\n    @inlinable\n    public static func + (lhs: TimeAmount, rhs: TimeAmount) -> TimeAmount {\n        TimeAmount(lhs.nanoseconds + rhs.nanoseconds)\n    }\n\n    @inlinable\n    public static func += (lhs: inout TimeAmount, rhs: TimeAmount) {\n        lhs = lhs + rhs\n    }\n\n    @inlinable\n    public static func - (lhs: TimeAmount, rhs: TimeAmount) -> TimeAmount {\n        TimeAmount(lhs.nanoseconds - rhs.nanoseconds)\n    }\n\n    @inlinable\n    public static func -= (lhs: inout TimeAmount, rhs: TimeAmount) {\n        lhs = lhs - rhs\n    }\n\n    @inlinable\n    public static func * <T: BinaryInteger>(lhs: T, rhs: TimeAmount) -> TimeAmount {\n        TimeAmount(Int64(lhs) * rhs.nanoseconds)\n    }\n\n    @inlinable\n    public static func * <T: BinaryInteger>(lhs: TimeAmount, rhs: T) -> TimeAmount {\n        TimeAmount(lhs.nanoseconds * Int64(rhs))\n    }\n}\n\n/// Represents a point in time.\n///\n/// Stores the time in nanoseconds as returned by `DispatchTime.now().uptimeNanoseconds`\n///\n/// `NIODeadline` allow chaining multiple tasks with the same deadline without needing to\n/// compute new timeouts for each step\n///\n/// ```\n/// func doSomething(deadline: NIODeadline) -> EventLoopFuture<Void> {\n///     return step1(deadline: deadline).flatMap {\n///         step2(deadline: deadline)\n///     }\n/// }\n/// doSomething(deadline: .now() + .seconds(5))\n/// ```\n///\n/// - Note: `NIODeadline` should not be used to represent a time interval\npublic struct NIODeadline: Equatable, Hashable, Sendable {\n    @available(*, deprecated, message: \"This typealias doesn't serve any purpose, please use UInt64 directly.\")\n    public typealias Value = UInt64\n\n    // This really should be an UInt63 but we model it as Int64 with >=0 assert\n    @usableFromInline var _uptimeNanoseconds: Int64 {\n        didSet {\n            assert(self._uptimeNanoseconds >= 0)\n        }\n    }\n\n    /// The nanoseconds since boot representation of the `NIODeadline`.\n    @inlinable\n    public var uptimeNanoseconds: UInt64 {\n        .init(self._uptimeNanoseconds)\n    }\n\n    @inlinable\n    public static var distantPast: NIODeadline { NIODeadline(0) }\n\n    @inlinable\n    public static var distantFuture: NIODeadline { NIODeadline(.init(Int64.max)) }\n\n    @inlinable init(_ nanoseconds: Int64) {\n        precondition(nanoseconds >= 0)\n        self._uptimeNanoseconds = nanoseconds\n    }\n\n    /// Getting the time is a very common operation so it warrants optimization.\n    ///\n    /// Prior to this function, NIO relied on `DispatchTime.now()`, on all platforms. In addition to\n    /// the overhead of making a library call, the underlying implementation has a lot of branches\n    /// because `libdispatch` supports many more usecases than we are making use of here.\n    ///\n    /// On Linux, `DispachTime.now()` _always_ results in a simple call to `clock_gettime(3)` and so\n    /// we make that call here, directly from NIO.\n    ///\n    /// - TODO: Investigate optimizing the call to `DispatchTime.now()` away on other platforms too.\n    @inlinable\n    static func timeNow() -> UInt64 {\n        #if os(Linux)\n        var ts = timespec()\n        clock_gettime(CLOCK_MONOTONIC, &ts)\n        /// We use unsafe arithmetic here because `UInt64.max` nanoseconds is more than 580 years,\n        /// and the odds that this code will still be running 530 years from now is very, very low,\n        /// so as a practical matter this will never overflow.\n        return UInt64(ts.tv_sec) &* 1_000_000_000 &+ UInt64(ts.tv_nsec)\n        #elseif os(WASI)\n        var ts = timespec()\n        CNIOWASI_gettime(&ts)\n        /// We use unsafe arithmetic here because `UInt64.max` nanoseconds is more than 580 years,\n        /// and the odds that this code will still be running 530 years from now is very, very low,\n        /// so as a practical matter this will never overflow.\n        return UInt64(ts.tv_sec) &* 1_000_000_000 &+ UInt64(ts.tv_nsec)\n        #else\n        return DispatchTime.now().uptimeNanoseconds\n        #endif  // os(Linux)\n    }\n\n    @inlinable\n    public static func now() -> NIODeadline {\n        NIODeadline.uptimeNanoseconds(timeNow())\n    }\n\n    @inlinable\n    public static func uptimeNanoseconds(_ nanoseconds: UInt64) -> NIODeadline {\n        NIODeadline(Int64(min(UInt64(Int64.max), nanoseconds)))\n    }\n\n    @inlinable\n    public static func == (lhs: NIODeadline, rhs: NIODeadline) -> Bool {\n        lhs.uptimeNanoseconds == rhs.uptimeNanoseconds\n    }\n\n    @inlinable\n    public func hash(into hasher: inout Hasher) {\n        hasher.combine(self.uptimeNanoseconds)\n    }\n}\n\nextension NIODeadline: Comparable {\n    @inlinable\n    public static func < (lhs: NIODeadline, rhs: NIODeadline) -> Bool {\n        lhs.uptimeNanoseconds < rhs.uptimeNanoseconds\n    }\n\n    @inlinable\n    public static func > (lhs: NIODeadline, rhs: NIODeadline) -> Bool {\n        lhs.uptimeNanoseconds > rhs.uptimeNanoseconds\n    }\n}\n\nextension NIODeadline: CustomStringConvertible {\n    @inlinable\n    public var description: String {\n        self.uptimeNanoseconds.description\n    }\n}\n\nextension NIODeadline {\n    @inlinable\n    public static func - (lhs: NIODeadline, rhs: NIODeadline) -> TimeAmount {\n        // This won't ever crash, NIODeadlines are guaranteed to be within 0 ..< 2^63-1 nanoseconds so the result can\n        // definitely be stored in a TimeAmount (which is an Int64).\n        .nanoseconds(Int64(lhs.uptimeNanoseconds) - Int64(rhs.uptimeNanoseconds))\n    }\n\n    @inlinable\n    public static func + (lhs: NIODeadline, rhs: TimeAmount) -> NIODeadline {\n        let partial: Int64\n        let overflow: Bool\n        (partial, overflow) = Int64(lhs.uptimeNanoseconds).addingReportingOverflow(rhs.nanoseconds)\n        if overflow {\n            assert(rhs.nanoseconds > 0)  // this certainly must have overflowed towards +infinity\n            return NIODeadline.distantFuture\n        }\n        guard partial >= 0 else {\n            return NIODeadline.uptimeNanoseconds(0)\n        }\n        return NIODeadline(partial)\n    }\n\n    @inlinable\n    public static func - (lhs: NIODeadline, rhs: TimeAmount) -> NIODeadline {\n        if rhs.nanoseconds < 0 {\n            // The addition won't crash because the worst that could happen is `UInt64(Int64.max) + UInt64(Int64.max)`\n            // which fits into an UInt64 (and will then be capped to Int64.max == distantFuture by `uptimeNanoseconds`).\n            return NIODeadline.uptimeNanoseconds(lhs.uptimeNanoseconds + rhs.nanoseconds.magnitude)\n        } else if rhs.nanoseconds > lhs.uptimeNanoseconds {\n            // Cap it at `0` because otherwise this would be negative.\n            return NIODeadline.init(0)\n        } else {\n            // This will be positive but still fix in an Int64.\n            let result = Int64(lhs.uptimeNanoseconds) - rhs.nanoseconds\n            assert(result >= 0)\n            return NIODeadline(result)\n        }\n    }\n}\n\nextension EventLoop {\n    /// Submit `task` to be run on this `EventLoop`.\n    ///\n    /// The returned `EventLoopFuture` will be completed when `task` has finished running. It will be succeeded with\n    /// `task`'s return value or failed if the execution of `task` threw an error.\n    ///\n    /// - Parameters:\n    ///   - task: The synchronous task to run. As everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: An `EventLoopFuture` containing the result of `task`'s execution.\n    @inlinable\n    @preconcurrency\n    public func submit<T>(_ task: @escaping @Sendable () throws -> T) -> EventLoopFuture<T> {\n        let promise: EventLoopPromise<T> = makePromise(file: #fileID, line: #line)\n\n        self.execute {\n            do {\n                // UnsafeUnchecked is allowed here because we know we are on the EL.\n                promise.assumeIsolatedUnsafeUnchecked().succeed(try task())\n            } catch let err {\n                promise.fail(err)\n            }\n        }\n\n        return promise.futureResult\n    }\n\n    /// Submit `task` to be run on this `EventLoop`.\n    ///\n    /// The returned `EventLoopFuture` will be completed when `task` has finished running. It will be identical to\n    /// the `EventLoopFuture` returned by `task`.\n    ///\n    /// - Parameters:\n    ///   - task: The asynchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: An `EventLoopFuture` identical to the `EventLoopFuture` returned from `task`.\n    @inlinable\n    @preconcurrency\n    public func flatSubmit<T: Sendable>(_ task: @escaping @Sendable () -> EventLoopFuture<T>) -> EventLoopFuture<T> {\n        self.submit(task).flatMap { $0 }\n    }\n\n    /// Schedule a `task` that is executed by this `EventLoop` at the given time.\n    ///\n    /// - Note: The `T` must be `Sendable` since the isolation domains of the event loop future returned from `task` and\n    /// this event loop might differ.\n    ///\n    /// - Parameters:\n    ///   - deadline: The instant in time before which the task will not execute.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    ///   - task: The asynchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the full execution of the task, including its returned `EventLoopFuture`.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    @discardableResult\n    @inlinable\n    @preconcurrency\n    public func flatScheduleTask<T: Sendable>(\n        deadline: NIODeadline,\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ task: @escaping @Sendable () throws -> EventLoopFuture<T>\n    ) -> Scheduled<T> {\n        let promise: EventLoopPromise<T> = self.makePromise(file: file, line: line)\n        let scheduled = self.scheduleTask(deadline: deadline, task)\n\n        scheduled.futureResult.whenComplete { result in\n            switch result {\n            case .success(let futureResult):\n                promise.completeWith(futureResult)\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n\n        return .init(promise: promise, cancellationTask: { scheduled.cancel() })\n    }\n\n    /// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.\n    ///\n    /// - Note: The `T` must be `Sendable` since the isolation domains of the event loop future returned from `task` and\n    /// this event loop might differ.\n    ///\n    /// - Parameters:\n    ///   - delay: The amount of time before which the task will not execute.\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    ///   - task: The asynchronous task to run. As everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the full execution of the task, including its returned `EventLoopFuture`.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    @discardableResult\n    @inlinable\n    @preconcurrency\n    public func flatScheduleTask<T: Sendable>(\n        in delay: TimeAmount,\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ task: @escaping @Sendable () throws -> EventLoopFuture<T>\n    ) -> Scheduled<T> {\n        self._flatScheduleTask(in: delay, file: file, line: line, task)\n    }\n\n    @usableFromInline typealias FlatScheduleTaskDelayCallback<T> = @Sendable () throws -> EventLoopFuture<T>\n\n    @inlinable\n    func _flatScheduleTask<T: Sendable>(\n        in delay: TimeAmount,\n        file: StaticString,\n        line: UInt,\n        _ task: @escaping FlatScheduleTaskDelayCallback<T>\n    ) -> Scheduled<T> {\n        let promise: EventLoopPromise<T> = self.makePromise(file: file, line: line)\n        let scheduled = self.scheduleTask(in: delay, task)\n\n        scheduled.futureResult.whenComplete { result in\n            switch result {\n            case .success(let futureResult):\n                promise.completeWith(futureResult)\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n\n        return .init(promise: promise, cancellationTask: { scheduled.cancel() })\n    }\n\n    /// Creates and returns a new `EventLoopPromise` that will be notified using this `EventLoop` as execution `NIOThread`.\n    @inlinable\n    public func makePromise<T>(\n        of type: T.Type = T.self,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopPromise<T> {\n        EventLoopPromise<T>(eventLoop: self, file: file, line: line)\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is already marked as failed. Notifications will be done using this `EventLoop` as execution `NIOThread`.\n    ///\n    /// - Parameters:\n    ///   - error: the `Error` that is used by the `EventLoopFuture`.\n    /// - Returns: a failed `EventLoopFuture`.\n    @inlinable\n    public func makeFailedFuture<T>(_ error: Error) -> EventLoopFuture<T> {\n        EventLoopFuture<T>(eventLoop: self, error: error)\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is already marked as success. Notifications will be done using this `EventLoop` as execution `NIOThread`.\n    ///\n    /// - Parameters:\n    ///   - value: the value that is used by the `EventLoopFuture`.\n    /// - Returns: a succeeded `EventLoopFuture`.\n    @preconcurrency\n    @inlinable\n    public func makeSucceededFuture<Success: Sendable>(_ value: Success) -> EventLoopFuture<Success> {\n        if Success.self == Void.self {\n            // The as! will always succeed because we previously checked that Success.self == Void.self.\n            return self.makeSucceededVoidFuture() as! EventLoopFuture<Success>\n        } else {\n            return EventLoopFuture<Success>(eventLoop: self, value: value)\n        }\n    }\n\n    /// Creates and returns a new isolated `EventLoopFuture` that is already marked as success. Notifications will be done using this `EventLoop.\n    ///\n    /// - Parameters:\n    ///   - value: the value that is used by the `EventLoopFuture.Isolated`.\n    /// - Returns: a succeeded `EventLoopFuture.Isolated`.\n    @inlinable\n    @available(*, noasync)\n    public func makeSucceededIsolatedFuture<Success>(_ value: Success) -> EventLoopFuture<Success>.Isolated {\n        if Success.self == Void.self {\n            // The as! will always succeed because we previously checked that Success.self == Void.self.\n            return self.makeSucceededVoidFuture().assumeIsolated() as! EventLoopFuture<Success>.Isolated\n        } else {\n            return EventLoopFuture.Isolated(_wrapped: EventLoopFuture(eventLoop: self, isolatedValue: value))\n        }\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is marked as succeeded or failed with the value held by `result`.\n    ///\n    /// - Parameters:\n    ///   - result: The value that is used by the `EventLoopFuture`\n    /// - Returns: A completed `EventLoopFuture`.\n    @preconcurrency\n    @inlinable\n    public func makeCompletedFuture<Success: Sendable>(_ result: Result<Success, Error>) -> EventLoopFuture<Success> {\n        switch result {\n        case .success(let value):\n            return self.makeSucceededFuture(value)\n        case .failure(let error):\n            return self.makeFailedFuture(error)\n        }\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is marked as succeeded or failed with the value returned by `body`.\n    ///\n    /// - Parameters:\n    ///   - body: The function that is used to complete the `EventLoopFuture`\n    /// - Returns: A completed `EventLoopFuture`.\n    @preconcurrency\n    @inlinable\n    public func makeCompletedFuture<Success: Sendable>(\n        withResultOf body: () throws -> Success\n    ) -> EventLoopFuture<Success> {\n        let trans = Result(catching: body)\n        return self.makeCompletedFuture(trans)\n    }\n\n    /// An `EventLoop` forms a singular `EventLoopGroup`, returning itself as the 'next' `EventLoop`.\n    ///\n    /// - Returns: Itself, because an `EventLoop` forms a singular `EventLoopGroup`.\n    public func next() -> EventLoop {\n        self\n    }\n\n    /// An `EventLoop` forms a singular `EventLoopGroup`, returning itself as 'any' `EventLoop`.\n    ///\n    /// - Returns: Itself, because an `EventLoop` forms a singular `EventLoopGroup`.\n    public func any() -> EventLoop {\n        self\n    }\n\n    /// Close this `EventLoop`.\n    public func close() throws {\n        // Do nothing\n    }\n\n    /// Schedule a repeated task to be executed by the `EventLoop` with a fixed delay between the end and start of each\n    /// task.\n    ///\n    /// - Parameters:\n    ///   - initialDelay: The delay after which the first task is executed.\n    ///   - delay: The delay between the end of one task and the start of the next.\n    ///   - promise: If non-nil, a promise to fulfill when the task is cancelled and all execution is complete.\n    ///   - task: The closure that will be executed.\n    /// - return: `RepeatedTask`\n    @discardableResult\n    @preconcurrency\n    public func scheduleRepeatedTask(\n        initialDelay: TimeAmount,\n        delay: TimeAmount,\n        notifying promise: EventLoopPromise<Void>? = nil,\n        _ task: @escaping @Sendable (RepeatedTask) throws -> Void\n    ) -> RepeatedTask {\n        self._scheduleRepeatedTask(initialDelay: initialDelay, delay: delay, notifying: promise, task)\n    }\n\n    /// Schedule a repeated task to be executed by the `EventLoop` with a fixed delay between the end and start of each\n    /// task.\n    ///\n    /// - Parameters:\n    ///   - initialDelay: The delay after which the first task is executed.\n    ///   - delay: The delay between the end of one task and the start of the next.\n    ///   - maximumAllowableJitter: Exclusive upper bound of jitter range added to the `delay` parameter.\n    ///   - promise: If non-nil, a promise to fulfill when the task is cancelled and all execution is complete.\n    ///   - task: The closure that will be executed.\n    /// - return: `RepeatedTask`\n    @discardableResult\n    public func scheduleRepeatedTask(\n        initialDelay: TimeAmount,\n        delay: TimeAmount,\n        maximumAllowableJitter: TimeAmount,\n        notifying promise: EventLoopPromise<Void>? = nil,\n        _ task: @escaping @Sendable (RepeatedTask) throws -> Void\n    ) -> RepeatedTask {\n        let jitteredInitialDelay = Self._getJitteredDelay(\n            delay: initialDelay,\n            maximumAllowableJitter: maximumAllowableJitter\n        )\n        let jitteredDelay = Self._getJitteredDelay(delay: delay, maximumAllowableJitter: maximumAllowableJitter)\n        return self.scheduleRepeatedTask(\n            initialDelay: jitteredInitialDelay,\n            delay: jitteredDelay,\n            notifying: promise,\n            task\n        )\n    }\n    typealias ScheduleRepeatedTaskCallback = @Sendable (RepeatedTask) throws -> Void\n\n    func _scheduleRepeatedTask(\n        initialDelay: TimeAmount,\n        delay: TimeAmount,\n        notifying promise: EventLoopPromise<Void>?,\n        _ task: @escaping ScheduleRepeatedTaskCallback\n    ) -> RepeatedTask {\n        let futureTask: @Sendable (RepeatedTask) -> EventLoopFuture<Void> = { repeatedTask in\n            do {\n                try task(repeatedTask)\n                return self.makeSucceededFuture(())\n            } catch {\n                return self.makeFailedFuture(error)\n            }\n        }\n        return self.scheduleRepeatedAsyncTask(initialDelay: initialDelay, delay: delay, notifying: promise, futureTask)\n    }\n\n    /// Schedule a repeated asynchronous task to be executed by the `EventLoop` with a fixed delay between the end and\n    /// start of each task.\n    ///\n    /// - Note: The delay is measured from the completion of one run's returned future to the start of the execution of\n    ///         the next run. For example: If you schedule a task once per second but your task takes two seconds to\n    ///         complete, the time interval between two subsequent runs will actually be three seconds (2s run time plus\n    ///         the 1s delay.)\n    ///\n    /// - Parameters:\n    ///   - initialDelay: The delay after which the first task is executed.\n    ///   - delay: The delay between the end of one task and the start of the next.\n    ///   - promise: If non-nil, a promise to fulfill when the task is cancelled and all execution is complete.\n    ///   - task: The closure that will be executed. Task will keep repeating regardless of whether the future\n    ///             gets fulfilled with success or error.\n    ///\n    /// - return: `RepeatedTask`\n    @discardableResult\n    @preconcurrency\n    public func scheduleRepeatedAsyncTask(\n        initialDelay: TimeAmount,\n        delay: TimeAmount,\n        notifying promise: EventLoopPromise<Void>? = nil,\n        _ task: @escaping @Sendable (RepeatedTask) -> EventLoopFuture<Void>\n    ) -> RepeatedTask {\n        self._scheduleRepeatedAsyncTask(initialDelay: initialDelay, delay: delay, notifying: promise, task)\n    }\n\n    /// Schedule a repeated asynchronous task to be executed by the `EventLoop` with a fixed delay between the end and\n    /// start of each task.\n    ///\n    /// - Note: The delay is measured from the completion of one run's returned future to the start of the execution of\n    ///         the next run. For example: If you schedule a task once per second but your task takes two seconds to\n    ///         complete, the time interval between two subsequent runs will actually be three seconds (2s run time plus\n    ///         the 1s delay.)\n    ///\n    /// - Parameters:\n    ///   - initialDelay: The delay after which the first task is executed.\n    ///   - delay: The delay between the end of one task and the start of the next.\n    ///   - maximumAllowableJitter: Exclusive upper bound of jitter range added to the `delay` parameter.\n    ///   - promise: If non-nil, a promise to fulfill when the task is cancelled and all execution is complete.\n    ///   - task: The closure that will be executed. Task will keep repeating regardless of whether the future\n    ///             gets fulfilled with success or error.\n    ///\n    /// - return: `RepeatedTask`\n    @discardableResult\n    public func scheduleRepeatedAsyncTask(\n        initialDelay: TimeAmount,\n        delay: TimeAmount,\n        maximumAllowableJitter: TimeAmount,\n        notifying promise: EventLoopPromise<Void>? = nil,\n        _ task: @escaping @Sendable (RepeatedTask) -> EventLoopFuture<Void>\n    ) -> RepeatedTask {\n        let jitteredInitialDelay = Self._getJitteredDelay(\n            delay: initialDelay,\n            maximumAllowableJitter: maximumAllowableJitter\n        )\n        let jitteredDelay = Self._getJitteredDelay(delay: delay, maximumAllowableJitter: maximumAllowableJitter)\n        return self._scheduleRepeatedAsyncTask(\n            initialDelay: jitteredInitialDelay,\n            delay: jitteredDelay,\n            notifying: promise,\n            task\n        )\n    }\n    typealias ScheduleRepeatedAsyncTaskCallback = @Sendable (RepeatedTask) -> EventLoopFuture<Void>\n\n    func _scheduleRepeatedAsyncTask(\n        initialDelay: TimeAmount,\n        delay: TimeAmount,\n        notifying promise: EventLoopPromise<Void>?,\n        _ task: @escaping ScheduleRepeatedAsyncTaskCallback\n    ) -> RepeatedTask {\n        let repeated = RepeatedTask(interval: delay, eventLoop: self, cancellationPromise: promise, task: task)\n        repeated.begin(in: initialDelay)\n        return repeated\n    }\n\n    /// Adds a random amount of `.nanoseconds` (within `.zero..<maximumAllowableJitter`) to the delay.\n    ///\n    /// - Parameters:\n    ///   - delay: the `TimeAmount` delay to jitter.\n    ///   - maximumAllowableJitter: Exclusive upper bound of jitter range added to the `delay` parameter.\n    /// - Returns: The jittered delay.\n    @inlinable\n    static func _getJitteredDelay(\n        delay: TimeAmount,\n        maximumAllowableJitter: TimeAmount\n    ) -> TimeAmount {\n        let jitter = TimeAmount.nanoseconds(Int64.random(in: .zero..<maximumAllowableJitter.nanoseconds))\n        return delay + jitter\n    }\n\n    /// Returns an `EventLoopIterator` over this `EventLoop`.\n    ///\n    /// - Returns: `EventLoopIterator`\n    public func makeIterator() -> EventLoopIterator {\n        EventLoopIterator([self])\n    }\n\n    /// Asserts that the current thread is the one tied to this `EventLoop`.\n    /// Otherwise, if running in debug mode, the process will be abnormally terminated as per the semantics of\n    /// `preconditionFailure(_:file:line:)`. Never has any effect in release mode.\n    ///\n    /// - Note: This is not a customization point so calls to this function can be fully optimized out in release mode.\n    @inlinable\n    public func assertInEventLoop(file: StaticString = #fileID, line: UInt = #line) {\n        debugOnly {\n            self.preconditionInEventLoop(file: file, line: line)\n        }\n    }\n\n    /// Asserts that the current thread is _not_ the one tied to this `EventLoop`.\n    /// Otherwise, if running in debug mode, the process will be abnormally terminated as per the semantics of\n    /// `preconditionFailure(_:file:line:)`. Never has any effect in release mode.\n    ///\n    /// - Note: This is not a customization point so calls to this function can be fully optimized out in release mode.\n    @inlinable\n    public func assertNotInEventLoop(file: StaticString = #fileID, line: UInt = #line) {\n        debugOnly {\n            self.preconditionNotInEventLoop(file: file, line: line)\n        }\n    }\n\n    /// Checks the necessary condition of currently running on the called `EventLoop` for making forward progress.\n    @inlinable\n    public func preconditionInEventLoop(file: StaticString = #fileID, line: UInt = #line) {\n        precondition(self.inEventLoop, file: file, line: line)\n    }\n\n    /// Checks the necessary condition of currently _not_ running on the called `EventLoop` for making forward progress.\n    @inlinable\n    public func preconditionNotInEventLoop(file: StaticString = #fileID, line: UInt = #line) {\n        precondition(!self.inEventLoop, file: file, line: line)\n    }\n}\n\n/// Provides an endless stream of `EventLoop`s to use.\npublic protocol EventLoopGroup: AnyObject, _NIOPreconcurrencySendable {\n    /// Returns the next `EventLoop` to use, this is useful for load balancing.\n    ///\n    /// The algorithm that is used to select the next `EventLoop` is specific to each `EventLoopGroup`. A common choice\n    /// is _round robin_.\n    ///\n    /// Please note that you should only be using `next()` if you want to load balance over all `EventLoop`s of the\n    /// `EventLoopGroup`. If the actual `EventLoop` does not matter much, `any()` should be preferred because it can\n    /// try to return you the _current_ `EventLoop` which usually is faster because the number of thread switches can\n    /// be reduced.\n    ///\n    /// The rule of thumb is: If you are trying to do _load balancing_, use `next()`. If you just want to create a new\n    /// future or kick off some operation, use `any()`.\n\n    func next() -> EventLoop\n\n    /// Returns any `EventLoop` from the `EventLoopGroup`, a common choice is the current `EventLoop`.\n    ///\n    /// - warning: You cannot rely on the returned `EventLoop` being the current one, not all `EventLoopGroup`s support\n    ///            choosing the current one. Use this method only if you are truly happy with _any_ `EventLoop` of this\n    ///            `EventLoopGroup` instance.\n    ///\n    /// - Note: You will only receive the current `EventLoop` here iff the current `EventLoop` belongs to the\n    ///         `EventLoopGroup` you call `any()` on.\n    ///\n    /// This method is useful having access to an `EventLoopGroup` without the knowledge of which `EventLoop` would be\n    /// the best one to select to create a new `EventLoopFuture`. This commonly happens in libraries where the user\n    /// cannot indicate what `EventLoop` they would like their futures on.\n    ///\n    /// Typically, it is faster to kick off a new operation on the _current_ `EventLoop` because that minimised thread\n    /// switches. Hence, if situations where you don't need precise knowledge of what `EventLoop` some code is running\n    /// on, use `any()` to indicate this.\n    ///\n    /// The rule of thumb is: If you are trying to do _load balancing_, use `next()`. If you just want to create a new\n    /// future or kick off some operation, use `any()`.\n    func any() -> EventLoop\n\n    #if canImport(Dispatch)\n    /// Shuts down the eventloop gracefully. This function is clearly an outlier in that it uses a completion\n    /// callback instead of an EventLoopFuture. The reason for that is that NIO's EventLoopFutures will call back on an event loop.\n    /// The virtue of this function is to shut the event loop down. To work around that we call back on a DispatchQueue\n    /// instead.\n    @preconcurrency func shutdownGracefully(queue: DispatchQueue, _ callback: @Sendable @escaping (Error?) -> Void)\n    #endif\n\n    /// Returns an `EventLoopIterator` over the `EventLoop`s in this `EventLoopGroup`.\n    ///\n    /// - Returns: `EventLoopIterator`\n    func makeIterator() -> EventLoopIterator\n\n    /// Must crash if it's not safe to call `syncShutdownGracefully` in the current context.\n    ///\n    /// This method is a debug hook that can be used to override the behaviour of `syncShutdownGracefully`\n    /// when called. By default it does nothing.\n    func _preconditionSafeToSyncShutdown(file: StaticString, line: UInt)\n}\n\nextension EventLoopGroup {\n    /// The default implementation of `any()` just returns the `next()` EventLoop but it's highly recommended to\n    /// override this and return the current `EventLoop` if possible.\n    public func any() -> EventLoop {\n        self.next()\n    }\n}\n\n#if canImport(Dispatch)\nextension EventLoopGroup {\n    @preconcurrency public func shutdownGracefully(_ callback: @escaping @Sendable (Error?) -> Void) {\n        self.shutdownGracefully(queue: .global(), callback)\n    }\n\n    @available(*, noasync, message: \"this can end up blocking the calling thread\", renamed: \"shutdownGracefully()\")\n    public func syncShutdownGracefully() throws {\n        try self._syncShutdownGracefully()\n    }\n\n    private func _syncShutdownGracefully() throws {\n        self._preconditionSafeToSyncShutdown(file: #fileID, line: #line)\n        let error = NIOLockedValueBox<Error?>(nil)\n        let semaphore = DispatchSemaphore(value: 0)\n        self.shutdownGracefully { shutdownError in\n            if let shutdownError = shutdownError {\n                error.withLockedValue {\n                    $0 = shutdownError\n                }\n            }\n            semaphore.signal()\n        }\n        semaphore.wait()\n        try error.withLockedValue { error in\n            if let error = error {\n                throw error\n            }\n        }\n    }\n\n    public func _preconditionSafeToSyncShutdown(file: StaticString, line: UInt) {\n        return\n    }\n}\n#endif\n\n/// Deprecated.\n///\n/// This type was intended to be used by libraries which use NIO, and offer their users either the option\n/// to `.share` an existing event loop group or create (and manage) a new one (`.createNew`) and let it be\n/// managed by given library and its lifecycle.\n///\n/// Please use a `group: any EventLoopGroup` parameter instead. If you want to default to a global\n/// singleton group instead, consider group: any EventLoopGroup = MultiThreadedEventLoopGroup.singleton` or\n/// similar.\n///\n/// - See also: https://github.com/apple/swift-nio/issues/2142\npublic enum NIOEventLoopGroupProvider {\n    /// Use an `EventLoopGroup` provided by the user.\n    /// The owner of this group is responsible for its lifecycle.\n    case shared(EventLoopGroup)\n\n    /// Deprecated. Create a new `EventLoopGroup` when necessary.\n    /// The library which accepts this provider takes ownership of the created event loop group,\n    /// and must ensure its proper shutdown when the library is being shut down.\n    @available(\n        *,\n        deprecated,\n        message: \"\"\"\n            Please use `.shared(existingGroup)` or use the singleton via \\\n            `.shared(MultiThreadedEventLoopGroup.singleton)` or similar\n            \"\"\"\n    )\n    case createNew\n}\n\nextension NIOEventLoopGroupProvider: Sendable {}\n\n/// Different `Error`s that are specific to `EventLoop` operations / implementations.\npublic enum EventLoopError: Error {\n    /// An operation was executed that is not supported by the `EventLoop`\n    case unsupportedOperation\n\n    /// An scheduled task was cancelled.\n    case cancelled\n\n    /// The `EventLoop` was shutdown already.\n    case shutdown\n\n    /// Shutting down the `EventLoop` failed.\n    case shutdownFailed\n}\n\nextension EventLoopError {\n    @usableFromInline\n    static let _cancelled: any Error = EventLoopError.cancelled\n}\n\nextension EventLoopError: CustomStringConvertible {\n    public var description: String {\n        switch self {\n        case .unsupportedOperation:\n            return \"EventLoopError: the executed operation is not supported by the event loop\"\n        case .cancelled:\n            return \"EventLoopError: the scheduled task was cancelled\"\n        case .shutdown:\n            return \"EventLoopError: the event loop is shutdown\"\n        case .shutdownFailed:\n            return \"EventLoopError: failed to shutdown the event loop\"\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/EventLoopFuture+AssumeIsolated.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A struct wrapping an ``EventLoop`` that ensures all calls to any method on this struct\n/// are coming from the event loop.\n///\n/// This type is explicitly not `Sendable`. It may only be constructed on an event loop,\n/// using ``EventLoop/assumeIsolated()``, and may not subsequently be passed to other isolation\n/// domains.\n///\n/// Using this type relaxes the need to have the closures for ``EventLoop/execute(_:)``,\n/// ``EventLoop/submit(_:)``, ``EventLoop/scheduleTask(in:_:)``,\n/// and ``EventLoop/scheduleCallback(in:handler:)`` to be `@Sendable`.\npublic struct NIOIsolatedEventLoop {\n    @usableFromInline\n    let _wrapped: EventLoop\n\n    @inlinable\n    internal init(_ eventLoop: EventLoop) {\n        self._wrapped = eventLoop\n    }\n\n    /// Submit a given task to be executed by the `EventLoop`\n    @available(*, noasync)\n    @inlinable\n    public func execute(_ task: @escaping () -> Void) {\n        self._wrapped._executeIsolatedUnsafeUnchecked(task)\n    }\n\n    /// Submit a given task to be executed by the `EventLoop`. Once the execution is complete the returned `EventLoopFuture` is notified.\n    ///\n    /// - Parameters:\n    ///   - task: The closure that will be submitted to the `EventLoop` for execution.\n    /// - Returns: `EventLoopFuture` that is notified once the task was executed.\n    @available(*, noasync)\n    @inlinable\n    public func submit<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        self._wrapped._submitIsolatedUnsafeUnchecked(task)\n    }\n\n    /// Schedule a `task` that is executed by this `EventLoop` at the given time.\n    ///\n    /// - Parameters:\n    ///   - deadline: The time at which the task should run.\n    ///   - task: The synchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the completion of the task.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    @discardableResult\n    @available(*, noasync)\n    @inlinable\n    public func scheduleTask<T>(\n        deadline: NIODeadline,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        self._wrapped._scheduleTaskIsolatedUnsafeUnchecked(deadline: deadline, task)\n    }\n\n    /// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.\n    ///\n    /// - Parameters:\n    ///   - delay: The time to wait before running the task.\n    ///   - task: The synchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the completion of the task.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    /// - Note: The `in` value is clamped to a maximum when running on a Darwin-kernel.\n    @discardableResult\n    @available(*, noasync)\n    @inlinable\n    public func scheduleTask<T>(\n        in delay: TimeAmount,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        self._wrapped._scheduleTaskIsolatedUnsafeUnchecked(in: delay, task)\n    }\n\n    /// Schedule a `task` that is executed by this `EventLoop` at the given time.\n    ///\n    /// - Note: The `T` must be `Sendable` since the isolation domains of the event loop future returned from `task` and\n    /// this event loop might differ.\n    ///\n    /// - Parameters:\n    ///   - deadline: The time at which we should run the asynchronous task.\n    ///   - file: The file in which the task is scheduled.\n    ///   - line: The line of the `file` in which the task is scheduled.\n    ///   - task: The asynchronous task to run. As with everything that runs on the `EventLoop`, it must not block.\n    /// - Returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait\n    ///            on the full execution of the task, including its returned `EventLoopFuture`.\n    ///\n    /// - Note: You can only cancel a task before it has started executing.\n    @discardableResult\n    @available(*, noasync)\n    @inlinable\n    public func flatScheduleTask<T: Sendable>(\n        deadline: NIODeadline,\n        file: StaticString = #file,\n        line: UInt = #line,\n        _ task: @escaping () throws -> EventLoopFuture<T>\n    ) -> Scheduled<T> {\n        let promise: EventLoopPromise<T> = self._wrapped.makePromise(file: file, line: line)\n        let scheduled = self.scheduleTask(deadline: deadline, task)\n\n        scheduled.futureResult.whenComplete { result in\n            switch result {\n            case .success(let futureResult):\n                promise.completeWith(futureResult)\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n\n        return .init(promise: promise, cancellationTask: { scheduled.cancel() })\n    }\n\n    /// Schedule a callback at a given time.\n    ///\n    /// - Parameters:\n    ///   - deadline: The instant in time before which the task will not execute.\n    ///   - handler: The handler that defines the behavior of the callback when executed or canceled.\n    /// - Returns: A ``NIOScheduledCallback`` that can be used to cancel the scheduled callback.\n    @discardableResult\n    @available(*, noasync)\n    @inlinable\n    public func scheduleCallback(\n        at deadline: NIODeadline,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback {\n        try self._wrapped._scheduleCallbackIsolatedUnsafeUnchecked(at: deadline, handler: handler)\n    }\n\n    /// Schedule a callback after given time.\n    ///\n    /// - Parameters:\n    ///   - amount: The amount of time before which the task will not execute.\n    ///   - handler: The handler that defines the behavior of the callback when executed or canceled.\n    ///  - Returns: A ``NIOScheduledCallback`` that can be used to cancel the scheduled callback.\n    @discardableResult\n    @available(*, noasync)\n    @inlinable\n    public func scheduleCallback(\n        in amount: TimeAmount,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback {\n        try self._wrapped._scheduleCallbackIsolatedUnsafeUnchecked(in: amount, handler: handler)\n    }\n\n    /// Cancel a scheduled callback.\n    @inlinable\n    @available(*, noasync)\n    public func cancelScheduledCallback(_ scheduledCallback: NIOScheduledCallback) {\n        self._wrapped.preconditionInEventLoop()\n        self._wrapped.cancelScheduledCallback(scheduledCallback)\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is already marked as success. Notifications\n    /// will be done using this `EventLoop` as execution `NIOThread`.\n    ///\n    /// - Parameters:\n    ///   - value: the value that is used by the `EventLoopFuture`.\n    /// - Returns: a succeeded `EventLoopFuture`.\n    @inlinable\n    @available(*, noasync)\n    public func makeSucceededFuture<Success>(_ value: Success) -> EventLoopFuture<Success> {\n        let promise = self._wrapped.makePromise(of: Success.self)\n        promise.assumeIsolatedUnsafeUnchecked().succeed(value)\n        return promise.futureResult\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is already marked as failed. Notifications\n    /// will be done using this `EventLoop`.\n    ///\n    /// - Parameters:\n    ///   - error: the `Error` that is used by the `EventLoopFuture`.\n    /// - Returns: a failed `EventLoopFuture`.\n    @inlinable\n    @available(*, noasync)\n    public func makeFailedFuture<Success>(_ error: Error) -> EventLoopFuture<Success> {\n        let promise = self._wrapped.makePromise(of: Success.self)\n        promise.fail(error)\n        return promise.futureResult\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is marked as succeeded or failed with the\n    /// value held by `result`.\n    ///\n    /// - Parameters:\n    ///   - result: The value that is used by the `EventLoopFuture`\n    /// - Returns: A completed `EventLoopFuture`.\n    @inlinable\n    @available(*, noasync)\n    public func makeCompletedFuture<Success>(_ result: Result<Success, Error>) -> EventLoopFuture<Success> {\n        let promise = self._wrapped.makePromise(of: Success.self)\n        promise.assumeIsolatedUnsafeUnchecked().completeWith(result)\n        return promise.futureResult\n    }\n\n    /// Creates and returns a new `EventLoopFuture` that is marked as succeeded or failed with the\n    /// value returned by `body`.\n    ///\n    /// - Parameters:\n    ///   - body: The function that is used to complete the `EventLoopFuture`\n    /// - Returns: A completed `EventLoopFuture`.\n    @inlinable\n    @available(*, noasync)\n    public func makeCompletedFuture<Success>(\n        withResultOf body: () throws -> Success\n    ) -> EventLoopFuture<Success> {\n        self.makeCompletedFuture(Result(catching: body))\n    }\n\n    /// Returns the wrapped event loop.\n    @inlinable\n    public func nonisolated() -> any EventLoop {\n        self._wrapped\n    }\n}\n\nextension EventLoop {\n    /// Assumes the calling context is isolated to the event loop.\n    @inlinable\n    @available(*, noasync)\n    public func assumeIsolated() -> NIOIsolatedEventLoop {\n        self.preconditionInEventLoop()\n        return NIOIsolatedEventLoop(self)\n    }\n\n    /// Assumes the calling context is isolated to the event loop.\n    ///\n    /// This version of ``EventLoop/assumeIsolated()`` omits the runtime\n    /// isolation check in release builds and doesn't prevent you using it\n    /// from using it in async contexts.\n    @inlinable\n    public func assumeIsolatedUnsafeUnchecked() -> NIOIsolatedEventLoop {\n        self.assertInEventLoop()\n        return NIOIsolatedEventLoop(self)\n    }\n}\n\n@available(*, unavailable)\nextension NIOIsolatedEventLoop: Sendable {}\n\nextension EventLoopFuture {\n    /// A struct wrapping an ``EventLoopFuture`` that ensures all calls to any method on this struct\n    /// are coming from the event loop of the future.\n    ///\n    /// This type is explicitly not `Sendable`. It may only be constructed on an event loop,\n    /// using ``EventLoopFuture/assumeIsolated()``, and may not subsequently be passed to other isolation\n    /// domains.\n    ///\n    /// Using this type relaxes the need to have the closures for the various ``EventLoopFuture``\n    /// callback-attaching functions be `Sendable`.\n    public struct Isolated {\n        @usableFromInline\n        let _wrapped: EventLoopFuture<Value>\n\n        @inlinable\n        init(_wrapped: EventLoopFuture<Value>) {\n            self._wrapped = _wrapped\n        }\n\n        /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback,\n        /// which will provide a new `EventLoopFuture`.\n        ///\n        /// This allows you to dynamically dispatch new asynchronous tasks as phases in a\n        /// longer series of processing steps. Note that you can use the results of the\n        /// current `EventLoopFuture<Value>` when determining how to dispatch the next operation.\n        ///\n        /// This works well when you have APIs that already know how to return `EventLoopFuture`s.\n        /// You can do something with the result of one and just return the next future:\n        ///\n        /// ```\n        /// let d1 = networkRequest(args).future()\n        /// let d2 = d1.flatMap { t -> EventLoopFuture<NewValue> in\n        ///     . . . something with t . . .\n        ///     return netWorkRequest(args)\n        /// }\n        /// d2.whenSuccess { u in\n        ///     NSLog(\"Result of second request: \\(u)\")\n        /// }\n        /// ```\n        ///\n        /// Note that the returned ``EventLoopFuture`` still needs a `Sendable` wrapped value,\n        /// as it may have been created on a different event loop.\n        ///\n        /// Note: In a sense, the `EventLoopFuture<NewValue>` is returned before it's created.\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n        ///         a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the eventual value.\n        @inlinable\n        @available(*, noasync)\n        public func flatMap<NewValue: Sendable>(\n            _ callback: @escaping (Value) -> EventLoopFuture<NewValue>\n        ) -> EventLoopFuture<NewValue>.Isolated {\n            let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let t):\n                    let futureU = callback(t)\n                    if futureU.eventLoop.inEventLoop {\n                        return futureU._addCallback {\n                            next._setValue(value: futureU._value!)\n                        }\n                    } else {\n                        futureU.cascade(to: next)\n                        return CallbackList()\n                    }\n                case .failure(let error):\n                    return next._setValue(value: .failure(error))\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback, which\n        /// performs a synchronous computation and returns a new value of type `NewValue`. The provided\n        /// callback may optionally `throw`.\n        ///\n        /// Operations performed in `flatMapThrowing` should not block, or they will block the entire\n        /// event loop. `flatMapThrowing` is intended for use when you have a data-driven function that\n        /// performs a simple data transformation that can potentially error.\n        ///\n        /// If your callback function throws, the returned `EventLoopFuture` will error.\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n        ///         a new value lifted into a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the eventual value.\n        @inlinable\n        @available(*, noasync)\n        public func flatMapThrowing<NewValue>(\n            _ callback: @escaping (Value) throws -> NewValue\n        ) -> EventLoopFuture<NewValue>.Isolated {\n            let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let t):\n                    do {\n                        let r = try callback(t)\n                        return next._setValue(value: .success(r))\n                    } catch {\n                        return next._setValue(value: .failure(error))\n                    }\n                case .failure(let e):\n                    return next._setValue(value: .failure(e))\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n        /// may recover from the error and returns a new value of type `Value`. The provided callback may optionally `throw`,\n        /// in which case the `EventLoopFuture` will be in a failed state with the new thrown error.\n        ///\n        /// Operations performed in `flatMapErrorThrowing` should not block, or they will block the entire\n        /// event loop. `flatMapErrorThrowing` is intended for use when you have the ability to synchronously\n        /// recover from errors.\n        ///\n        /// If your callback function throws, the returned `EventLoopFuture` will error.\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n        ///         a new value lifted into a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the eventual value or a rethrown error.\n        @inlinable\n        @available(*, noasync)\n        public func flatMapErrorThrowing(\n            _ callback: @escaping (Error) throws -> Value\n        ) -> EventLoopFuture<Value>.Isolated {\n            let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let t):\n                    return next._setValue(value: .success(t))\n                case .failure(let e):\n                    do {\n                        let r = try callback(e)\n                        return next._setValue(value: .success(r))\n                    } catch {\n                        return next._setValue(value: .failure(error))\n                    }\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback, which\n        /// performs a synchronous computation and returns a new value of type `NewValue`.\n        ///\n        /// Operations performed in `map` should not block, or they will block the entire event\n        /// loop. `map` is intended for use when you have a data-driven function that performs\n        /// a simple data transformation that cannot error.\n        ///\n        /// If you have a data-driven function that can throw, you should use `flatMapThrowing`\n        /// instead.\n        ///\n        /// ```\n        /// let future1 = eventually()\n        /// let future2 = future1.map { T -> U in\n        ///     ... stuff ...\n        ///     return u\n        /// }\n        /// let future3 = future2.map { U -> V in\n        ///     ... stuff ...\n        ///     return v\n        /// }\n        /// ```\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n        ///         a new value lifted into a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the eventual value.\n        @inlinable\n        @available(*, noasync)\n        public func map<NewValue>(\n            _ callback: @escaping (Value) -> (NewValue)\n        ) -> EventLoopFuture<NewValue>.Isolated {\n            if NewValue.self == Value.self && NewValue.self == Void.self {\n                self.whenSuccess(callback as! (Value) -> Void)\n                return self as! EventLoopFuture<NewValue>.Isolated\n            } else {\n                let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n                let base = self._wrapped\n                base._whenCompleteIsolated {\n                    next._setValue(value: base._value!.map(callback))\n                }\n                return next.futureResult.assumeIsolatedUnsafeUnchecked()\n            }\n        }\n\n        /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n        /// may recover from the error by returning an `EventLoopFuture<NewValue>`. The callback is intended to potentially\n        /// recover from the error by returning a new `EventLoopFuture` that will eventually contain the recovered\n        /// result.\n        ///\n        /// If the callback cannot recover it should return a failed `EventLoopFuture`.\n        ///\n        /// - Note: The `Value` must be `Sendable` since the isolation domains of this future and the future returned from the callback\n        /// might differ i.e. they might be bound to different event loops.\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n        ///         a new value lifted into a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the recovered value.\n        @inlinable\n        @available(*, noasync)\n        public func flatMapError(\n            _ callback: @escaping (Error) -> EventLoopFuture<Value>\n        ) -> EventLoopFuture<Value>.Isolated where Value: Sendable {\n            let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let t):\n                    return next._setValue(value: .success(t))\n                case .failure(let e):\n                    let t = callback(e)\n                    if t.eventLoop.inEventLoop {\n                        return t._addCallback {\n                            next._setValue(value: t._value!)\n                        }\n                    } else {\n                        t.cascade(to: next)\n                        return CallbackList()\n                    }\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// When the current `EventLoopFuture<Value>.Isolated` is in an error state, run the provided callback, which\n        /// may recover from the error by returning an `EventLoopFuture<NewValue>.Isolated`. The callback is intended to potentially\n        /// recover from the error by returning a new `EventLoopFuture.Isolated` that will eventually contain the recovered\n        /// result.\n        ///\n        /// If the callback cannot recover it should return a failed `EventLoopFuture.Isolated`.\n        ///\n        /// - Note: The `Value` need not be `Sendable` since the isolation domains of this future and the future returned from the callback\n        /// must be the same\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the error value of this `EventLoopFuture.Isolated` and return\n        ///         a new value lifted into a new `EventLoopFuture.Isolated`.\n        /// - Returns: A future that will receive the recovered value.\n        @inlinable\n        @available(*, noasync)\n        public func flatMapError(\n            _ callback: @escaping (Error) -> EventLoopFuture<Value>.Isolated\n        ) -> EventLoopFuture<Value>.Isolated {\n            let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let t):\n                    return next._setValue(value: .success(t))\n                case .failure(let e):\n                    let t = callback(e)\n                    t._wrapped.eventLoop.assertInEventLoop()\n                    return t._wrapped._addCallback {\n                        next._setValue(value: t._wrapped._value!)\n                    }\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback, which\n        /// performs a synchronous computation and returns either a new value (of type `NewValue`) or\n        /// an error depending on the `Result` returned by the closure.\n        ///\n        /// Operations performed in `flatMapResult` should not block, or they will block the entire\n        /// event loop. `flatMapResult` is intended for use when you have a data-driven function that\n        /// performs a simple data transformation that can potentially error.\n        ///\n        ///\n        /// - Parameters:\n        ///   - body: Function that will receive the value of this `EventLoopFuture` and return\n        ///         a new value or error lifted into a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the eventual value.\n        @inlinable\n        @available(*, noasync)\n        public func flatMapResult<NewValue, SomeError: Error>(\n            _ body: @escaping (Value) -> Result<NewValue, SomeError>\n        ) -> EventLoopFuture<NewValue>.Isolated {\n            let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let value):\n                    switch body(value) {\n                    case .success(let newValue):\n                        return next._setValue(value: .success(newValue))\n                    case .failure(let error):\n                        return next._setValue(value: .failure(error))\n                    }\n                case .failure(let e):\n                    return next._setValue(value: .failure(e))\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n        /// can recover from the error and return a new value of type `Value`. The provided callback may not `throw`,\n        /// so this function should be used when the error is always recoverable.\n        ///\n        /// Operations performed in `recover` should not block, or they will block the entire\n        /// event loop. `recover` is intended for use when you have the ability to synchronously\n        /// recover from errors.\n        ///\n        /// - Parameters:\n        ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n        ///         a new value lifted into a new `EventLoopFuture`.\n        /// - Returns: A future that will receive the recovered value.\n        @inlinable\n        @available(*, noasync)\n        public func recover(\n            _ callback: @escaping (Error) -> Value\n        ) -> EventLoopFuture<Value>.Isolated {\n            let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self._wrapped.eventLoop)\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                switch base._value! {\n                case .success(let t):\n                    return next._setValue(value: .success(t))\n                case .failure(let e):\n                    return next._setValue(value: .success(callback(e)))\n                }\n            }\n            return next.futureResult.assumeIsolatedUnsafeUnchecked()\n        }\n\n        /// Adds an observer callback to this `EventLoopFuture` that is called when the\n        /// `EventLoopFuture` has a success result.\n        ///\n        /// An observer callback cannot return a value, meaning that this function cannot be chained\n        /// from. If you are attempting to create a computation pipeline, consider `map` or `flatMap`.\n        /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`\n        /// in the body of this function, consider using `cascade` instead.\n        ///\n        /// - Parameters:\n        ///   - callback: The callback that is called with the successful result of the `EventLoopFuture`.\n        @inlinable\n        @available(*, noasync)\n        public func whenSuccess(_ callback: @escaping (Value) -> Void) {\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                if case .success(let t) = base._value! {\n                    callback(t)\n                }\n                return CallbackList()\n            }\n        }\n\n        /// Adds an observer callback to this `EventLoopFuture` that is called when the\n        /// `EventLoopFuture` has a failure result.\n        ///\n        /// An observer callback cannot return a value, meaning that this function cannot be chained\n        /// from. If you are attempting to create a computation pipeline, consider `recover` or `flatMapError`.\n        /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`\n        /// in the body of this function, consider using `cascade` instead.\n        ///\n        /// - Parameters:\n        ///   - callback: The callback that is called with the failed result of the `EventLoopFuture`.\n        @inlinable\n        @available(*, noasync)\n        public func whenFailure(_ callback: @escaping (Error) -> Void) {\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                if case .failure(let e) = base._value! {\n                    callback(e)\n                }\n                return CallbackList()\n            }\n        }\n\n        /// Adds an observer callback to this `EventLoopFuture` that is called when the\n        /// `EventLoopFuture` has any result.\n        ///\n        /// - Parameters:\n        ///   - callback: The callback that is called when the `EventLoopFuture` is fulfilled.\n        @inlinable\n        @available(*, noasync)\n        public func whenComplete(\n            _ callback: @escaping (Result<Value, Error>) -> Void\n        ) {\n            let base = self._wrapped\n            base._whenCompleteIsolated {\n                callback(base._value!)\n                return CallbackList()\n            }\n        }\n\n        /// Adds an observer callback to this `EventLoopFuture` that is called when the\n        /// `EventLoopFuture` has any result.\n        ///\n        /// - Parameters:\n        ///   - callback: the callback that is called when the `EventLoopFuture` is fulfilled.\n        /// - Returns: the current `EventLoopFuture`\n        @inlinable\n        @available(*, noasync)\n        public func always(\n            _ callback: @escaping (Result<Value, Error>) -> Void\n        ) -> EventLoopFuture<Value>.Isolated {\n            self.whenComplete { result in callback(result) }\n            return self\n        }\n\n        /// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.\n        ///\n        /// Unwraps a future returning a new `EventLoopFuture` with either: the value passed in the `orReplace`\n        /// parameter when the future resolved with value Optional.none, or the same value otherwise. For example:\n        /// ```\n        /// promise.futureResult.unwrap(orReplace: 42).wait()\n        /// ```\n        ///\n        /// - Parameters:\n        ///   - replacement: the value of the returned `EventLoopFuture` when then resolved future's value is `Optional.some()`.\n        /// - Returns: an new `EventLoopFuture` with new type parameter `NewValue` and the value passed in the `orReplace` parameter.\n        @inlinable\n        @available(*, noasync)\n        public func unwrap<NewValue>(\n            orReplace replacement: NewValue\n        ) -> EventLoopFuture<NewValue>.Isolated where Value == NewValue? {\n            self.map { (value) -> NewValue in\n                guard let value = value else {\n                    return replacement\n                }\n                return value\n            }\n        }\n\n        /// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.\n        ///\n        /// Unwraps a future returning a new `EventLoopFuture` with either: the value returned by the closure passed in\n        /// the `orElse` parameter when the future resolved with value Optional.none, or the same value otherwise. For example:\n        /// ```\n        /// var x = 2\n        /// promise.futureResult.unwrap(orElse: { x * 2 }).wait()\n        /// ```\n        ///\n        /// - Parameters:\n        ///   - callback: a closure that returns the value of the returned `EventLoopFuture` when then resolved future's value\n        ///         is `Optional.some()`.\n        /// - Returns: an new `EventLoopFuture` with new type parameter `NewValue` and with the value returned by the closure\n        ///     passed in the `orElse` parameter.\n        @inlinable\n        @available(*, noasync)\n        public func unwrap<NewValue>(\n            orElse callback: @escaping () -> NewValue\n        ) -> EventLoopFuture<NewValue>.Isolated where Value == NewValue? {\n            self.map { (value) -> NewValue in\n                guard let value = value else {\n                    return callback()\n                }\n                return value\n            }\n        }\n\n        /// Returns the wrapped event loop future.\n        @inlinable\n        public func nonisolated() -> EventLoopFuture<Value> {\n            self._wrapped\n        }\n    }\n\n    /// Returns a variant of this ``EventLoopFuture`` with less strict\n    /// `Sendable` requirements. Can only be called from on the\n    /// ``EventLoop`` to which this ``EventLoopFuture`` is bound, will crash\n    /// if that invariant fails to be met.\n    @inlinable\n    @available(*, noasync)\n    public func assumeIsolated() -> Isolated {\n        self.eventLoop.preconditionInEventLoop()\n        return Isolated(_wrapped: self)\n    }\n\n    /// Returns a variant of this ``EventLoopFuture`` with less strict\n    /// `Sendable` requirements. Can only be called from on the\n    /// ``EventLoop`` to which this ``EventLoopFuture`` is bound, will crash\n    /// if that invariant fails to be met in debug builds.\n    ///\n    /// This is an unsafe version of ``EventLoopFuture/assumeIsolated()`` which\n    /// omits the runtime check in release builds.\n    @inlinable\n    @available(*, noasync)\n    public func assumeIsolatedUnsafeUnchecked() -> Isolated {\n        self.eventLoop.assertInEventLoop()\n        return Isolated(_wrapped: self)\n    }\n}\n\n@available(*, unavailable)\nextension EventLoopFuture.Isolated: Sendable {}\n\nextension EventLoopPromise {\n    /// A struct wrapping an ``EventLoopPromise`` that ensures all calls to any method on this struct\n    /// are coming from the event loop of the promise.\n    ///\n    /// This type is explicitly not `Sendable`. It may only be constructed on an event loop,\n    /// using ``EventLoopPromise/assumeIsolated()``, and may not subsequently be passed to other isolation\n    /// domains.\n    ///\n    /// Using this type relaxes the need to have the promise completion functions accept `Sendable`\n    /// values, as this type can only be handled on the ``EventLoop``.\n    ///\n    /// This type does not offer the full suite of completion functions that ``EventLoopPromise``\n    /// does, as many of those functions do not require `Sendable` values already. It only offers\n    /// versions for the functions that do require `Sendable` types. If you have an\n    /// ``EventLoopPromise/Isolated`` but need a regular ``EventLoopPromise``, use\n    /// ``EventLoopPromise/Isolated/nonisolated()`` to unwrap the value.\n    public struct Isolated {\n        @usableFromInline\n        let _wrapped: EventLoopPromise<Value>\n\n        @inlinable\n        init(_wrapped: EventLoopPromise<Value>) {\n            self._wrapped = _wrapped\n        }\n\n        /// Returns the `EventLoopFuture.Isolated` which will be notified once the execution of the scheduled task completes.\n        @inlinable\n        @available(*, noasync)\n        public var futureResult: EventLoopFuture<Value>.Isolated {\n            self._wrapped.futureResult.assumeIsolated()\n        }\n\n        /// Deliver a successful result to the associated `EventLoopFuture<Value>` object.\n        ///\n        /// - Parameters:\n        ///   - value: The successful result of the operation.\n        @inlinable\n        @available(*, noasync)\n        public func succeed(_ value: Value) {\n            self._wrapped._setValue(value: .success(value))._run()\n        }\n\n        /// Complete the promise with the passed in `Result<Value, Error>`.\n        ///\n        /// This method is equivalent to invoking:\n        /// ```\n        /// switch result {\n        /// case .success(let value):\n        ///     promise.succeed(value)\n        /// case .failure(let error):\n        ///     promise.fail(error)\n        /// }\n        /// ```\n        ///\n        /// - Parameters:\n        ///   - result: The result which will be used to succeed or fail this promise.\n        @inlinable\n        @available(*, noasync)\n        public func completeWith(_ result: Result<Value, Error>) {\n            self._wrapped._setValue(value: result)._run()\n        }\n\n        /// Returns the wrapped event loop promise.\n        @inlinable\n        public func nonisolated() -> EventLoopPromise<Value> {\n            self._wrapped\n        }\n    }\n\n    /// Returns a variant of this ``EventLoopPromise`` with less strict\n    /// `Sendable` requirements. Can only be called from on the\n    /// ``EventLoop`` to which this ``EventLoopPromise`` is bound, will crash\n    /// if that invariant fails to be met.\n    @inlinable\n    @available(*, noasync)\n    public func assumeIsolated() -> Isolated {\n        self.futureResult.eventLoop.preconditionInEventLoop()\n        return Isolated(_wrapped: self)\n    }\n\n    /// Returns a variant of this ``EventLoopPromise`` with less strict\n    /// `Sendable` requirements. Can only be called from on the\n    /// ``EventLoop`` to which this ``EventLoopPromise`` is bound, will crash\n    /// if that invariant fails to be met.\n    ///\n    /// This is an unsafe version of ``EventLoopPromise/assumeIsolated()`` which\n    /// omits the runtime check in release builds and doesn't prevent you using it\n    /// from using it in async contexts.\n    @inlinable\n    public func assumeIsolatedUnsafeUnchecked() -> Isolated {\n        self.futureResult.eventLoop.assertInEventLoop()\n        return Isolated(_wrapped: self)\n    }\n}\n\n@available(*, unavailable)\nextension EventLoopPromise.Isolated: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/EventLoopFuture+Deprecated.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension EventLoopFuture {\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func flatMap<NewValue: Sendable>(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ callback: @escaping @Sendable (Value) -> EventLoopFuture<NewValue>\n    ) -> EventLoopFuture<NewValue> {\n        self.flatMap(callback)\n    }\n\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func flatMapThrowing<NewValue: Sendable>(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ callback: @escaping @Sendable (Value) throws -> NewValue\n    ) -> EventLoopFuture<NewValue> {\n        self.flatMapThrowing(callback)\n    }\n\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func flatMapErrorThrowing(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ callback: @escaping @Sendable (Error) throws -> Value\n    ) -> EventLoopFuture<Value> {\n        self.flatMapErrorThrowing(callback)\n    }\n\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func map<NewValue>(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ callback: @escaping @Sendable (Value) -> (NewValue)\n    ) -> EventLoopFuture<NewValue> {\n        self.map(callback)\n    }\n\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func flatMapError(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ callback: @escaping @Sendable (Error) -> EventLoopFuture<Value>\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        self.flatMapError(callback)\n    }\n\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func flatMapResult<NewValue, SomeError: Error>(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ body: @escaping @Sendable (Value) -> Result<NewValue, SomeError>\n    ) -> EventLoopFuture<NewValue> {\n        self.flatMapResult(body)\n    }\n\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func recover(\n        file: StaticString = #fileID,\n        line: UInt = #line,\n        _ callback: @escaping @Sendable (Error) -> Value\n    ) -> EventLoopFuture<Value> {\n        self.recover(callback)\n    }\n\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func and<OtherValue: Sendable>(\n        _ other: EventLoopFuture<OtherValue>,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<(Value, OtherValue)> {\n        self.and(other)\n    }\n\n    @preconcurrency\n    @inlinable\n    @available(*, deprecated, message: \"Please don't pass file:line:, there's no point.\")\n    public func and<OtherValue: Sendable>(\n        value: OtherValue,\n        file: StaticString = #fileID,\n        line: UInt = #line\n    ) -> EventLoopFuture<(Value, OtherValue)> {\n        self.and(value: value)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/EventLoopFuture+WithEventLoop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension EventLoopFuture {\n    /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback,\n    /// which will provide a new `EventLoopFuture` alongside the `EventLoop` associated with this future.\n    ///\n    /// This allows you to dynamically dispatch new asynchronous tasks as phases in a\n    /// longer series of processing steps. Note that you can use the results of the\n    /// current `EventLoopFuture<Value>` when determining how to dispatch the next operation.\n    ///\n    /// This works well when you have APIs that already know how to return `EventLoopFuture`s.\n    /// You can do something with the result of one and just return the next future:\n    ///\n    /// ```\n    /// let d1 = networkRequest(args).future()\n    /// let d2 = d1.flatMapWithEventLoop { t, eventLoop -> EventLoopFuture<NewValue> in\n    ///     eventLoop.makeSucceededFuture(t + 1)\n    /// }\n    /// d2.whenSuccess { u in\n    ///     NSLog(\"Result of second request: \\(u)\")\n    /// }\n    /// ```\n    ///\n    /// Note: In a sense, the `EventLoopFuture<NewValue>` is returned before it's created.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n    ///         a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the eventual value.\n    @inlinable\n    @preconcurrency\n    public func flatMapWithEventLoop<NewValue: Sendable>(\n        _ callback: @escaping @Sendable (Value, EventLoop) -> EventLoopFuture<NewValue>\n    ) -> EventLoopFuture<NewValue> {\n        let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete { [eventLoop = self.eventLoop] in\n            switch self._value! {\n            case .success(let t):\n                let futureU = callback(t, eventLoop)\n                if futureU.eventLoop.inEventLoop {\n                    return futureU._addCallback {\n                        next._setValue(value: futureU._value!)\n                    }\n                } else {\n                    futureU.cascade(to: next)\n                    return CallbackList()\n                }\n            case .failure(let error):\n                return next._setValue(value: .failure(error))\n            }\n        }\n        return next.futureResult\n    }\n\n    /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n    /// may recover from the error by returning an `EventLoopFuture<NewValue>`. The callback is intended to potentially\n    /// recover from the error by returning a new `EventLoopFuture` that will eventually contain the recovered\n    /// result.\n    ///\n    /// If the callback cannot recover it should return a failed `EventLoopFuture`.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n    ///         a new value lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the recovered value.\n    @inlinable\n    @preconcurrency\n    public func flatMapErrorWithEventLoop(\n        _ callback: @escaping @Sendable (Error, EventLoop) -> EventLoopFuture<Value>\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete { [eventLoop = self.eventLoop] in\n            switch self._value! {\n            case .success(let t):\n                return next._setValue(value: .success(t))\n            case .failure(let e):\n                let t = callback(e, eventLoop)\n                if t.eventLoop.inEventLoop {\n                    return t._addCallback {\n                        next._setValue(value: t._value!)\n                    }\n                } else {\n                    t.cascade(to: next)\n                    return CallbackList()\n                }\n            }\n        }\n        return next.futureResult\n    }\n\n    /// Returns a new `EventLoopFuture` that fires only when this `EventLoopFuture` and\n    /// all the provided `futures` complete. It then provides the result of folding the value of this\n    /// `EventLoopFuture` with the values of all the provided `futures`.\n    ///\n    /// This function is suited when you have APIs that already know how to return `EventLoopFuture`s.\n    ///\n    /// The returned `EventLoopFuture` will fail as soon as the a failure is encountered in any of the\n    /// `futures` (or in this one). However, the failure will not occur until all preceding\n    /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent\n    /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once\n    /// a failure is encountered, it will immediately fail the overall EventLoopFuture.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of `EventLoopFuture<NewValue>` to wait for.\n    ///   - combiningFunction: A function that will be used to fold the values of two `EventLoopFuture`s and return a new value wrapped in an `EventLoopFuture`.\n    /// - Returns: A new `EventLoopFuture` with the folded value whose callbacks run on `self.eventLoop`.\n    @inlinable\n    @preconcurrency\n    public func foldWithEventLoop<OtherValue: Sendable>(\n        _ futures: [EventLoopFuture<OtherValue>],\n        with combiningFunction: @escaping @Sendable (Value, OtherValue, EventLoop) -> EventLoopFuture<Value>\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        @Sendable\n        func fold0(eventLoop: EventLoop) -> EventLoopFuture<Value> {\n            let body = futures.reduce(self) {\n                (f1: EventLoopFuture<Value>, f2: EventLoopFuture<OtherValue>) -> EventLoopFuture<Value> in\n                let newFuture = f1.and(f2).flatMap { (args: (Value, OtherValue)) -> EventLoopFuture<Value> in\n                    let (f1Value, f2Value) = args\n                    self.eventLoop.assertInEventLoop()\n                    return combiningFunction(f1Value, f2Value, eventLoop)\n                }\n                assert(newFuture.eventLoop === self.eventLoop)\n                return newFuture\n            }\n            return body\n        }\n\n        if self.eventLoop.inEventLoop {\n            return fold0(eventLoop: self.eventLoop)\n        } else {\n            let promise = self.eventLoop.makePromise(of: Value.self)\n            self.eventLoop.execute { [eventLoop = self.eventLoop] in\n                fold0(eventLoop: eventLoop).cascade(to: promise)\n            }\n            return promise.futureResult\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/EventLoopFuture.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\n/// Internal list of callbacks.\n///\n/// Most of these are closures that pull a value from one future, call a user callback, push the\n/// result into another, then return a list of callbacks from the target future that are now ready to be invoked.\n///\n/// In particular, note that `_run()` here continues to obtain and execute lists of callbacks until it completes.\n/// This eliminates recursion when processing `flatMap()` chains.\n@usableFromInline\ninternal struct CallbackList {\n    @usableFromInline\n    internal typealias Element = Wrapper\n\n    // The compiler is able to better optimize a struct holding a closure than just a raw closure\n    // when used as a generic parameter.\n    @usableFromInline\n    struct Wrapper {\n        @usableFromInline\n        var callback: () -> CallbackList\n\n        @inlinable\n        init(_ callback: @escaping () -> CallbackList) {\n            self.callback = callback\n        }\n    }\n\n    @usableFromInline\n    internal var firstCallback: Optional<Element>\n    @usableFromInline\n    internal var furtherCallbacks: Optional<[Element]>\n\n    @inlinable\n    internal init() {\n        self.firstCallback = nil\n        self.furtherCallbacks = nil\n    }\n\n    @inlinable\n    internal mutating func append(_ callback: @escaping () -> CallbackList) {\n        if self.firstCallback == nil {\n            self.firstCallback = Wrapper(callback)\n        } else {\n            if self.furtherCallbacks != nil {\n                self.furtherCallbacks!.append(Wrapper(callback))\n            } else {\n                self.furtherCallbacks = [Wrapper(callback)]\n            }\n        }\n    }\n\n    @inlinable\n    internal func _allCallbacks() -> CircularBuffer<Element> {\n        switch (self.firstCallback, self.furtherCallbacks) {\n        case (.none, _):\n            return []\n        case (.some(let onlyCallback), .none):\n            return [onlyCallback]\n        default:\n            var array: CircularBuffer<Element> = []\n            self.appendAllCallbacks(&array)\n            return array\n        }\n    }\n\n    @inlinable\n    internal func appendAllCallbacks(_ array: inout CircularBuffer<Element>) {\n        switch (self.firstCallback, self.furtherCallbacks) {\n        case (.none, _):\n            return\n        case (.some(let onlyCallback), .none):\n            array.append(onlyCallback)\n        case (.some(let first), .some(let others)):\n            array.reserveCapacity(array.count + 1 + others.count)\n            array.append(first)\n            array.append(contentsOf: others)\n        }\n    }\n\n    @inlinable\n    internal func _run() {\n        switch (self.firstCallback, self.furtherCallbacks) {\n        case (.none, _):\n            return\n        case (.some(let onlyCallback), .none):\n            var onlyCallback = onlyCallback\n            loop: while true {\n                let cbl = onlyCallback.callback()\n                switch (cbl.firstCallback, cbl.furtherCallbacks) {\n                case (.none, _):\n                    break loop\n                case (.some(let ocb), .none):\n                    onlyCallback = ocb\n                    continue loop\n                case (.some(_), .some(_)):\n                    var pending = cbl._allCallbacks()\n                    while let f = pending.popFirst() {\n                        let next = f.callback()\n                        next.appendAllCallbacks(&pending)\n                    }\n                    break loop\n                }\n            }\n        default:\n            var pending = self._allCallbacks()\n            while let f = pending.popFirst() {\n                let next = f.callback()\n                next.appendAllCallbacks(&pending)\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension CallbackList: Sendable {}\n\n@available(*, unavailable)\nextension CallbackList.Wrapper: Sendable {}\n\n/// Internal error for operations that return results that were not replaced\n@usableFromInline\ninternal struct OperationPlaceholderError: Error {\n    @usableFromInline\n    internal init() {}\n}\n\n/// A promise to provide a result later.\n///\n/// This is the provider API for `EventLoopFuture<Value>`. If you want to return an\n/// unfulfilled `EventLoopFuture<Value>` -- presumably because you are interfacing to\n/// some asynchronous service that will return a real result later, follow this\n/// pattern:\n///\n/// ```\n/// func someAsyncOperation(args) -> EventLoopFuture<ResultType> {\n///     let promise = eventLoop.makePromise(of: ResultType.self)\n///     someAsyncOperationWithACallback(args) { result -> Void in\n///         // when finished...\n///         promise.succeed(result)\n///         // if error...\n///         promise.fail(error)\n///     }\n///     return promise.futureResult\n/// }\n/// ```\n///\n/// Note that the future result is returned before the async process has provided a value.\n///\n/// It's actually not very common to use this directly. Usually, you really want one\n/// of the following:\n///\n/// * If you have an `EventLoopFuture` and want to do something else after it completes,\n///     use `.flatMap()`\n/// * If you already have a value and need an `EventLoopFuture<>` object to plug into\n///     some other API, create an already-resolved object with `eventLoop.makeSucceededFuture(result)`\n///     or `eventLoop.newFailedFuture(error:)`.\n///\n/// - Note: `EventLoopPromise` has reference semantics.\npublic struct EventLoopPromise<Value> {\n    /// The `EventLoopFuture` which is used by the `EventLoopPromise`. You can use it to add callbacks which are notified once the\n    /// `EventLoopPromise` is completed.\n    public let futureResult: EventLoopFuture<Value>\n\n    @inlinable\n    internal static func makeUnleakablePromise(eventLoop: EventLoop, line: UInt = #line) -> EventLoopPromise<Value> {\n        EventLoopPromise<Value>(\n            eventLoop: eventLoop,\n            file: \"\"\"\n                EventLoopGroup shut down with unfulfilled promises remaining. \\\n                This suggests that the EventLoopGroup was shut down with unfinished work outstanding which is \\\n                illegal. Either switch to using the singleton EventLoopGroups or fix the issue by only shutting down \\\n                the EventLoopGroups when all the work associated with them has finished.\n                \"\"\",\n            line: line\n        )\n    }\n\n    /// General initializer\n    ///\n    /// - Parameters:\n    ///   - eventLoop: The event loop this promise is tied to.\n    ///   - file: The file this promise was allocated in, for debugging purposes.\n    ///   - line: The line this promise was allocated on, for debugging purposes.\n    @inlinable\n    internal init(eventLoop: EventLoop, file: StaticString, line: UInt) {\n        self.futureResult = EventLoopFuture<Value>(_eventLoop: eventLoop, file: file, line: line)\n    }\n\n    /// Deliver a successful result to the associated `EventLoopFuture<Value>` object.\n    ///\n    /// - Parameters:\n    ///   - value: The successful result of the operation.\n    @preconcurrency\n    @inlinable\n    public func succeed(_ value: Value) where Value: Sendable {\n        self._resolve(value: .success(value))\n    }\n\n    /// Deliver an error to the associated `EventLoopFuture<Value>` object.\n    ///\n    /// - Parameters:\n    ///      - error: The error from the operation.\n    @inlinable\n    public func fail(_ error: Error) {\n        if self.futureResult.eventLoop.inEventLoop {\n            self.futureResult._setError(error)._run()\n        } else {\n            self.futureResult.eventLoop.execute {\n                self.futureResult._setError(error)._run()\n            }\n        }\n    }\n\n    /// Complete the promise with the passed in `EventLoopFuture<Value>`.\n    ///\n    /// This method is equivalent to invoking `future.cascade(to: promise)`,\n    /// but sometimes may read better than its cascade counterpart.\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of the passed future and this promise might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - future: The future whose value will be used to succeed or fail this promise.\n    /// - seealso: `EventLoopFuture.cascade(to:)`\n    @preconcurrency\n    @inlinable\n    public func completeWith(_ future: EventLoopFuture<Value>) where Value: Sendable {\n        future.cascade(to: self)\n    }\n\n    /// Complete the promise with the passed in `Result<Value, Error>`.\n    ///\n    /// This method is equivalent to invoking:\n    /// ```\n    /// switch result {\n    /// case .success(let value):\n    ///     promise.succeed(value)\n    /// case .failure(let error):\n    ///     promise.fail(error)\n    /// }\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - result: The result which will be used to succeed or fail this promise.\n    @preconcurrency\n    @inlinable\n    public func completeWith(_ result: Result<Value, Error>) where Value: Sendable {\n        self._resolve(value: result)\n    }\n\n    /// Fire the associated `EventLoopFuture` on the appropriate event loop.\n    ///\n    /// This method provides the primary difference between the `EventLoopPromise` and most\n    /// other `Promise` implementations: specifically, all callbacks fire on the `EventLoop`\n    /// that was used to create the promise.\n    ///\n    /// - Parameters:\n    ///   - value: The value to fire the future with.\n    @inlinable\n    internal func _resolve(value: Result<Value, Error>) where Value: Sendable {\n        if self.futureResult.eventLoop.inEventLoop {\n            self._setValue(value: value)._run()\n        } else {\n            self.futureResult.eventLoop.execute {\n                self._setValue(value: value)._run()\n            }\n        }\n    }\n\n    /// Set the future result and get the associated callbacks.\n    ///\n    /// - Parameters:\n    ///   - value: The result of the promise.\n    /// - Returns: The callback list to run.\n    @inlinable\n    internal func _setValue(value: Result<Value, Error>) -> CallbackList {\n        self.futureResult._setValue(value: value)\n    }\n}\n\nextension EventLoopPromise: Equatable {}\n\n/// Holder for a result that will be provided later.\n///\n/// Functions that promise to do work asynchronously can return an `EventLoopFuture<Value>`.\n/// The recipient of such an object can then observe it to be notified when the operation completes.\n///\n/// The provider of a `EventLoopFuture<Value>` can create and return a placeholder object\n/// before the actual result is available. For example:\n///\n/// ```\n/// func getNetworkData(args) -> EventLoopFuture<NetworkResponse> {\n///     let promise = eventLoop.makePromise(of: NetworkResponse.self)\n///     queue.async {\n///         . . . do some work . . .\n///         promise.succeed(response)\n///         . . . if it fails, instead . . .\n///         promise.fail(error)\n///     }\n///     return promise.futureResult\n/// }\n/// ```\n///\n/// Note that this function returns immediately; the promise object will be given a value\n/// later on. This behaviour is common to Future/Promise implementations in many programming\n/// languages. If you are unfamiliar with this kind of object, the following resources may be\n/// helpful:\n///\n/// - [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)\n/// - [Scala](http://docs.scala-lang.org/overviews/core/futures.html)\n/// - [Python](https://docs.google.com/document/d/10WOZgLQaYNpOrag-eTbUm-JUCCfdyfravZ4qSOQPg1M/edit)\n///\n/// If you receive a `EventLoopFuture<Value>` from another function, you have a number of options:\n/// The most common operation is to use `flatMap()` or `map()` to add a function that will be called\n/// with the eventual result.  Both methods returns a new `EventLoopFuture<Value>` immediately\n/// that will receive the return value from your function, but they behave differently. If you have\n/// a function that can return synchronously, the `map` function will transform the result of type\n/// `Value` to a the new result of type `NewValue` and return an `EventLoopFuture<NewValue>`.\n///\n/// ```\n/// let networkData = getNetworkData(args)\n///\n/// // When network data is received, convert it.\n/// let processedResult: EventLoopFuture<Processed> = networkData.map { (n: NetworkResponse) -> Processed in\n///     ... parse network data ....\n///     return processedResult\n/// }\n/// ```\n///\n/// If however you need to do more asynchronous processing, you can call `flatMap()`. The return value of the\n/// function passed to `flatMap` must be a new `EventLoopFuture<NewValue>` object: the return value of `flatMap()` is\n/// a new `EventLoopFuture<NewValue>` that will contain the eventual result of both the original operation and\n/// the subsequent one.\n///\n/// ```\n/// // When converted network data is available, begin the database operation.\n/// let databaseResult: EventLoopFuture<DBResult> = processedResult.flatMap { (p: Processed) -> EventLoopFuture<DBResult> in\n///     return someDatabaseOperation(p)\n/// }\n/// ```\n///\n/// In essence, future chains created via `flatMap()` provide a form of data-driven asynchronous programming\n/// that allows you to dynamically declare data dependencies for your various operations.\n///\n/// `EventLoopFuture` chains created via `flatMap()` are sufficient for most purposes. All of the registered\n/// functions will eventually run in order. If one of those functions throws an error, that error will\n/// bypass the remaining functions. You can use `flatMapError()` to handle and optionally recover from\n/// errors in the middle of a chain.\n///\n/// At the end of an `EventLoopFuture` chain, you can use `whenSuccess()` or `whenFailure()` to add an\n/// observer callback that will be invoked with the result or error at that point. (Note: If you ever\n/// find yourself invoking `promise.succeed()` from inside a `whenSuccess()` callback, you probably should\n/// use `flatMap()` or `cascade(to:)` instead.)\n///\n/// `EventLoopFuture` objects are typically obtained by:\n/// * Using `.flatMap()` on an existing future to create a new future for the next step in a series of operations.\n/// * Initializing an `EventLoopFuture` that already has a value or an error\n///\n/// ### Threading and Futures\n///\n/// One of the major performance advantages of NIO over something like Node.js or Python’s asyncio is that NIO will\n/// by default run multiple event loops at once, on different threads. As most network protocols do not require\n/// blocking operation, at least in their low level implementations, this provides enormous speedups on machines\n/// with many cores such as most modern servers.\n///\n/// However, it can present a challenge at higher levels of abstraction when coordination between those threads\n/// becomes necessary. This is usually the case whenever the events on one connection (that is, one `Channel`) depend\n/// on events on another one. As these `Channel`s may be scheduled on different event loops (and so different threads)\n/// care needs to be taken to ensure that communication between the two loops is done in a thread-safe manner that\n/// avoids concurrent mutation of shared state from multiple loops at once.\n///\n/// The main primitives NIO provides for this use are the `EventLoopPromise` and `EventLoopFuture`. As their names\n/// suggest, these two objects are aware of event loops, and so can help manage the safety and correctness of your\n/// programs. However, understanding the exact semantics of these objects is critical to ensuring the safety of your code.\n///\n/// ####  Callbacks\n///\n/// The most important principle of the `EventLoopPromise` and `EventLoopFuture` is this: all callbacks registered on\n/// an `EventLoopFuture` will execute on the thread corresponding to the event loop that created the `Future`,\n/// *regardless* of what thread succeeds or fails the corresponding `EventLoopPromise`.\n///\n/// This means that if *your code* created the `EventLoopPromise`, you can be extremely confident of what thread the\n/// callback will execute on: after all, you held the event loop in hand when you created the `EventLoopPromise`.\n/// However, if your code is handed an `EventLoopFuture` or `EventLoopPromise`, and you want to register callbacks\n/// on those objects, you cannot be confident that those callbacks will execute on the same `EventLoop` that your\n/// code does.\n///\n/// This presents a problem: how do you ensure thread-safety when registering callbacks on an arbitrary\n/// `EventLoopFuture`? The short answer is that when you are holding an `EventLoopFuture`, you can always obtain a\n/// new `EventLoopFuture` whose callbacks will execute on your event loop. You do this by calling\n/// `EventLoopFuture.hop(to:)`. This function returns a new `EventLoopFuture` whose callbacks are guaranteed\n/// to fire on the provided event loop. As an added bonus, `hopTo` will check whether the provided `EventLoopFuture`\n/// was already scheduled to dispatch on the event loop in question, and avoid doing any work if that was the case.\n///\n/// This means that for any `EventLoopFuture` that your code did not create itself (via\n/// `EventLoopPromise.futureResult`), use of `hopTo` is **strongly encouraged** to help guarantee thread-safety. It\n/// should only be elided when thread-safety is provably not needed.\n///\n/// The \"thread affinity\" of `EventLoopFuture`s is critical to writing safe, performant concurrent code without\n/// boilerplate. It allows you to avoid needing to write or use locks in your own code, instead using the natural\n/// synchronization of the `EventLoop` to manage your thread-safety. In general, if any of your `ChannelHandler`s\n/// or `EventLoopFuture` callbacks need to invoke a lock (either directly or in the form of `DispatchQueue`) this\n/// should be considered a code smell worth investigating: the `EventLoop`-based synchronization guarantees of\n/// `EventLoopFuture` should be sufficient to guarantee thread-safety.\npublic final class EventLoopFuture<Value> {\n    // TODO: Provide a tracing facility.  It would be nice to be able to set '.debugTrace = true' on any EventLoopFuture or EventLoopPromise and have every subsequent chained EventLoopFuture report the success result or failure error.  That would simplify some debugging scenarios.\n    @usableFromInline\n    internal var _value: Optional<Result<Value, Error>>\n\n    /// The `EventLoop` which is tied to the `EventLoopFuture` and is used to notify all registered callbacks.\n    public let eventLoop: EventLoop\n\n    /// Callbacks that should be run when this `EventLoopFuture<Value>` gets a value.\n    /// These callbacks may give values to other `EventLoopFuture`s; if that happens,\n    /// they return any callbacks from those `EventLoopFuture`s so that we can run\n    /// the entire chain from the top without recursing.\n    @usableFromInline\n    internal var _callbacks: CallbackList\n\n    @inlinable\n    internal init(_eventLoop eventLoop: EventLoop, file: StaticString, line: UInt) {\n        self.eventLoop = eventLoop\n        self._value = nil\n        self._callbacks = .init()\n\n        debugOnly {\n            eventLoop._promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier(self), file: file, line: line)\n        }\n    }\n\n    /// A EventLoopFuture<Value> that has already succeeded\n    @inlinable\n    internal init(eventLoop: EventLoop, value: Value) where Value: Sendable {\n        self.eventLoop = eventLoop\n        self._value = .success(value)\n        self._callbacks = .init()\n    }\n\n    /// A EventLoopFuture<Value> that has already succeeded with an isolated (not-necessarily-sendable) value\n    @inlinable\n    internal init(eventLoop: EventLoop, isolatedValue value: Value) {\n        eventLoop.assertInEventLoop()\n\n        self.eventLoop = eventLoop\n        self._value = .success(value)\n        self._callbacks = .init()\n    }\n\n    /// A EventLoopFuture<Value> that has already failed\n    @inlinable\n    internal init(eventLoop: EventLoop, error: Error) {\n        self.eventLoop = eventLoop\n        self._value = .failure(error)\n        self._callbacks = .init()\n    }\n\n    deinit {\n        debugOnly {\n            if let creation = eventLoop._promiseCompleted(futureIdentifier: _NIOEventLoopFutureIdentifier(self)) {\n                if self._value == nil {\n                    fatalError(\"leaking promise created at \\(creation)\", file: creation.file, line: creation.line)\n                }\n            } else {\n                precondition(self._value != nil, \"leaking an unfulfilled Promise\")\n            }\n        }\n    }\n}\n\nextension EventLoopFuture: Equatable {\n    public static func == (lhs: EventLoopFuture, rhs: EventLoopFuture) -> Bool {\n        lhs === rhs\n    }\n}\n\n// MARK: flatMap and map\n\n// 'flatMap' and 'map' implementations. This is really the key of the entire system.\nextension EventLoopFuture {\n    /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback,\n    /// which will provide a new `EventLoopFuture`.\n    ///\n    /// This allows you to dynamically dispatch new asynchronous tasks as phases in a\n    /// longer series of processing steps. Note that you can use the results of the\n    /// current `EventLoopFuture<Value>` when determining how to dispatch the next operation.\n    ///\n    /// This works well when you have APIs that already know how to return `EventLoopFuture`s.\n    /// You can do something with the result of one and just return the next future:\n    ///\n    /// ```\n    /// let d1 = networkRequest(args).future()\n    /// let d2 = d1.flatMap { t -> EventLoopFuture<NewValue> in\n    ///     . . . something with t . . .\n    ///     return netWorkRequest(args)\n    /// }\n    /// d2.whenSuccess { u in\n    ///     NSLog(\"Result of second request: \\(u)\")\n    /// }\n    /// ```\n    ///\n    /// Note: In a sense, the `EventLoopFuture<NewValue>` is returned before it's created.\n    ///\n    /// - Note: The `NewValue` must be `Sendable` since the isolation domains of this future and the future returned from the callback\n    /// might differ i.e. they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n    ///         a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the eventual value.\n    @inlinable\n    @preconcurrency\n    public func flatMap<NewValue: Sendable>(\n        _ callback: @escaping @Sendable (Value) -> EventLoopFuture<NewValue>\n    ) -> EventLoopFuture<NewValue> {\n        self._flatMap(callback)\n    }\n    @usableFromInline typealias FlatMapCallback<NewValue> = @Sendable (Value) -> EventLoopFuture<NewValue>\n\n    @inlinable\n    func _flatMap<NewValue: Sendable>(_ callback: @escaping FlatMapCallback<NewValue>) -> EventLoopFuture<NewValue> {\n        let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete {\n            switch self._value! {\n            case .success(let t):\n                let futureU = callback(t)\n                if futureU.eventLoop.inEventLoop {\n                    return futureU._addCallback {\n                        next._setValue(value: futureU._value!)\n                    }\n                } else {\n                    futureU.cascade(to: next)\n                    return CallbackList()\n                }\n            case .failure(let error):\n                return next._setValue(value: .failure(error))\n            }\n        }\n        return next.futureResult\n    }\n\n    /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback, which\n    /// performs a synchronous computation and returns a new value of type `NewValue`. The provided\n    /// callback may optionally `throw`.\n    ///\n    /// Operations performed in `flatMapThrowing` should not block, or they will block the entire\n    /// event loop. `flatMapThrowing` is intended for use when you have a data-driven function that\n    /// performs a simple data transformation that can potentially error.\n    ///\n    /// If your callback function throws, the returned `EventLoopFuture` will error.\n    ///\n    /// - Note: The `NewValue` must be `Sendable` since the isolation domains of this future and the future returned from the callback\n    /// might differ i.e. they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n    ///         a new value lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the eventual value.\n    @inlinable\n    @preconcurrency\n    public func flatMapThrowing<NewValue>(\n        _ callback: @escaping @Sendable (Value) throws -> NewValue\n    ) -> EventLoopFuture<NewValue> {\n        self._flatMapThrowing(callback)\n    }\n    @usableFromInline typealias FlatMapThrowingCallback<NewValue> = @Sendable (Value) throws -> NewValue\n\n    @inlinable\n    func _flatMapThrowing<NewValue>(\n        _ callback: @escaping FlatMapThrowingCallback<NewValue>\n    ) -> EventLoopFuture<NewValue> {\n        let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete {\n            switch self._value! {\n            case .success(let t):\n                do {\n                    let r = try callback(t)\n                    return next._setValue(value: .success(r))\n                } catch {\n                    return next._setValue(value: .failure(error))\n                }\n            case .failure(let e):\n                return next._setValue(value: .failure(e))\n            }\n        }\n        return next.futureResult\n    }\n\n    /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n    /// may recover from the error and returns a new value of type `Value`. The provided callback may optionally `throw`,\n    /// in which case the `EventLoopFuture` will be in a failed state with the new thrown error.\n    ///\n    /// Operations performed in `flatMapErrorThrowing` should not block, or they will block the entire\n    /// event loop. `flatMapErrorThrowing` is intended for use when you have the ability to synchronously\n    /// recover from errors.\n    ///\n    /// If your callback function throws, the returned `EventLoopFuture` will error.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n    ///         a new value lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the eventual value or a rethrown error.\n    @inlinable\n    @preconcurrency\n    public func flatMapErrorThrowing(\n        _ callback: @escaping @Sendable (Error) throws -> Value\n    ) -> EventLoopFuture<Value> {\n        self._flatMapErrorThrowing(callback)\n    }\n    @usableFromInline typealias FlatMapErrorThrowingCallback = @Sendable (Error) throws -> Value\n\n    @inlinable\n    func _flatMapErrorThrowing(_ callback: @escaping FlatMapErrorThrowingCallback) -> EventLoopFuture<Value> {\n        let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete {\n            switch self._value! {\n            case .success(let t):\n                return next._setValue(value: .success(t))\n            case .failure(let e):\n                do {\n                    let r = try callback(e)\n                    return next._setValue(value: .success(r))\n                } catch {\n                    return next._setValue(value: .failure(error))\n                }\n            }\n        }\n        return next.futureResult\n    }\n\n    /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback, which\n    /// performs a synchronous computation and returns a new value of type `NewValue`.\n    ///\n    /// Operations performed in `map` should not block, or they will block the entire event\n    /// loop. `map` is intended for use when you have a data-driven function that performs\n    /// a simple data transformation that cannot error.\n    ///\n    /// If you have a data-driven function that can throw, you should use `flatMapThrowing`\n    /// instead.\n    ///\n    /// ```\n    /// let future1 = eventually()\n    /// let future2 = future1.map { T -> U in\n    ///     ... stuff ...\n    ///     return u\n    /// }\n    /// let future3 = future2.map { U -> V in\n    ///     ... stuff ...\n    ///     return v\n    /// }\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the value of this `EventLoopFuture` and return\n    ///         a new value lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the eventual value.\n    @inlinable\n    @preconcurrency\n    public func map<NewValue>(\n        _ callback: @escaping @Sendable (Value) -> (NewValue)\n    ) -> EventLoopFuture<NewValue> {\n        self._map(callback)\n    }\n    @usableFromInline typealias MapCallback<NewValue> = @Sendable (Value) -> (NewValue)\n\n    @inlinable\n    func _map<NewValue>(\n        _ callback: @escaping @Sendable (Value) -> (NewValue)\n    ) -> EventLoopFuture<NewValue> {\n        if NewValue.self == Value.self && NewValue.self == Void.self {\n            self.whenSuccess(callback as! @Sendable (Value) -> Void)\n            return self as! EventLoopFuture<NewValue>\n        } else {\n            let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self.eventLoop)\n            self._whenComplete {\n                next._setValue(value: self._value!.map(callback))\n            }\n            return next.futureResult\n        }\n    }\n\n    /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n    /// may recover from the error by returning an `EventLoopFuture<NewValue>`. The callback is intended to potentially\n    /// recover from the error by returning a new `EventLoopFuture` that will eventually contain the recovered\n    /// result.\n    ///\n    /// If the callback cannot recover it should return a failed `EventLoopFuture`.\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of this future and the future returned from the callback\n    /// might differ i.e. they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n    ///         a new value lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the recovered value.\n    @inlinable\n    @preconcurrency\n    public func flatMapError(\n        _ callback: @escaping @Sendable (Error) -> EventLoopFuture<Value>\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete {\n            switch self._value! {\n            case .success(let t):\n                return next._setValue(value: .success(t))\n            case .failure(let e):\n                let t = callback(e)\n                if t.eventLoop.inEventLoop {\n                    return t._addCallback {\n                        next._setValue(value: t._value!)\n                    }\n                } else {\n                    t.cascade(to: next)\n                    return CallbackList()\n                }\n            }\n        }\n        return next.futureResult\n    }\n\n    /// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback, which\n    /// performs a synchronous computation and returns either a new value (of type `NewValue`) or\n    /// an error depending on the `Result` returned by the closure.\n    ///\n    /// Operations performed in `flatMapResult` should not block, or they will block the entire\n    /// event loop. `flatMapResult` is intended for use when you have a data-driven function that\n    /// performs a simple data transformation that can potentially error.\n    ///\n    ///\n    /// - Parameters:\n    ///   - body: Function that will receive the value of this `EventLoopFuture` and return\n    ///         a new value or error lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the eventual value.\n    @inlinable\n    @preconcurrency\n    public func flatMapResult<NewValue, SomeError: Error>(\n        _ body: @escaping @Sendable (Value) -> Result<NewValue, SomeError>\n    ) -> EventLoopFuture<NewValue> {\n        self._flatMapResult(body)\n    }\n    @usableFromInline typealias FlatMapResultCallback<NewValue, SomeError: Error> =\n        @Sendable (Value) -> Result<\n            NewValue, SomeError\n        >\n\n    @inlinable\n    func _flatMapResult<NewValue, SomeError: Error>(\n        _ body: @escaping FlatMapResultCallback<NewValue, SomeError>\n    ) -> EventLoopFuture<NewValue> {\n        let next = EventLoopPromise<NewValue>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete {\n            switch self._value! {\n            case .success(let value):\n                switch body(value) {\n                case .success(let newValue):\n                    return next._setValue(value: .success(newValue))\n                case .failure(let error):\n                    return next._setValue(value: .failure(error))\n                }\n            case .failure(let e):\n                return next._setValue(value: .failure(e))\n            }\n        }\n        return next.futureResult\n    }\n\n    /// When the current `EventLoopFuture<Value>` is in an error state, run the provided callback, which\n    /// can recover from the error and return a new value of type `Value`. The provided callback may not `throw`,\n    /// so this function should be used when the error is always recoverable.\n    ///\n    /// Operations performed in `recover` should not block, or they will block the entire\n    /// event loop. `recover` is intended for use when you have the ability to synchronously\n    /// recover from errors.\n    ///\n    /// - Parameters:\n    ///   - callback: Function that will receive the error value of this `EventLoopFuture` and return\n    ///         a new value lifted into a new `EventLoopFuture`.\n    /// - Returns: A future that will receive the recovered value.\n    @inlinable\n    @preconcurrency\n    public func recover(_ callback: @escaping @Sendable (Error) -> Value) -> EventLoopFuture<Value> {\n        let next = EventLoopPromise<Value>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        self._whenComplete {\n            switch self._value! {\n            case .success(let t):\n                return next._setValue(value: .success(t))\n            case .failure(let e):\n                return next._setValue(value: .success(callback(e)))\n            }\n        }\n        return next.futureResult\n    }\n\n    /// Add a callback.  If there's already a value, invoke it and return the resulting list of new callback functions.\n    @inlinable\n    internal func _addCallback(_ callback: @escaping () -> CallbackList) -> CallbackList {\n        self.eventLoop.assertInEventLoop()\n        if self._value == nil {\n            self._callbacks.append(callback)\n            return CallbackList()\n        }\n        return callback()\n    }\n\n    /// Add a callback.  If there's already a value, run as much of the chain as we can.\n    @inlinable\n    // TODO: We want to remove @preconcurrency but it results in more allocations in 1000_udpconnections\n    @preconcurrency\n    internal func _whenComplete(_ callback: @escaping @Sendable () -> CallbackList) {\n        self._internalWhenComplete(callback)\n    }\n\n    /// Add a callback.  If there's already a value, run as much of the chain as we can.\n    @inlinable\n    internal func _internalWhenComplete(_ callback: @escaping @Sendable () -> CallbackList) {\n        if self.eventLoop.inEventLoop {\n            self._whenCompleteIsolated(callback)\n        } else {\n            self.eventLoop.execute {\n                self._whenCompleteIsolated(callback)\n            }\n        }\n    }\n\n    /// Add a callback.  If there's already a value, run as much of the chain as we can.\n    @inlinable\n    internal func _whenCompleteIsolated(_ callback: @escaping () -> CallbackList) {\n        self.eventLoop.assertInEventLoop()\n        self._addCallback(callback)._run()\n    }\n\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has a success result.\n    ///\n    /// An observer callback cannot return a value, meaning that this function cannot be chained\n    /// from. If you are attempting to create a computation pipeline, consider `map` or `flatMap`.\n    /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`\n    /// in the body of this function, consider using `cascade` instead.\n    ///\n    /// - Parameters:\n    ///   - callback: The callback that is called with the successful result of the `EventLoopFuture`.\n    @inlinable\n    @preconcurrency\n    public func whenSuccess(_ callback: @escaping @Sendable (Value) -> Void) {\n        self._whenComplete {\n            if case .success(let t) = self._value! {\n                callback(t)\n            }\n            return CallbackList()\n        }\n    }\n\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has a failure result.\n    ///\n    /// An observer callback cannot return a value, meaning that this function cannot be chained\n    /// from. If you are attempting to create a computation pipeline, consider `recover` or `flatMapError`.\n    /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`\n    /// in the body of this function, consider using `cascade` instead.\n    ///\n    /// - Parameters:\n    ///   - callback: The callback that is called with the failed result of the `EventLoopFuture`.\n    @inlinable\n    @preconcurrency\n    public func whenFailure(_ callback: @escaping @Sendable (Error) -> Void) {\n        self._whenComplete {\n            if case .failure(let e) = self._value! {\n                callback(e)\n            }\n            return CallbackList()\n        }\n    }\n\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has any result.\n    ///\n    /// - Parameters:\n    ///   - callback: The callback that is called when the `EventLoopFuture` is fulfilled.\n    @inlinable\n    @preconcurrency\n    public func whenComplete(_ callback: @escaping @Sendable (Result<Value, Error>) -> Void) {\n        self._whenComplete {\n            callback(self._value!)\n            return CallbackList()\n        }\n    }\n\n    /// Internal: Set the value and return a list of callbacks that should be invoked as a result.\n    @inlinable\n    internal func _setValue(value: Result<Value, Error>) -> CallbackList {\n        self.eventLoop.assertInEventLoop()\n        if self._value == nil {\n            self._value = value\n            let callbacks = self._callbacks\n            self._callbacks = CallbackList()\n            return callbacks\n        }\n        return CallbackList()\n    }\n\n    /// Internal: Set the value and return a list of callbacks that should be invoked as a result.\n    ///\n    /// We need a separate method for setting the error to avoid Sendable checking of `Value`\n    @inlinable\n    internal func _setError(_ error: Error) -> CallbackList {\n        self.eventLoop.assertInEventLoop()\n        if self._value == nil {\n            self._value = .failure(error)\n            let callbacks = self._callbacks\n            self._callbacks = CallbackList()\n            return callbacks\n        }\n        return CallbackList()\n    }\n}\n\n// MARK: and\n\nextension EventLoopFuture {\n    /// Return a new `EventLoopFuture` that succeeds when this \"and\" another\n    /// provided `EventLoopFuture` both succeed. It then provides the pair\n    /// of results. If either one fails, the combined `EventLoopFuture` will fail with\n    /// the first error encountered.\n    ///\n    /// - Note: The `NewValue` must be `Sendable` since the isolation domains of this future and the other future might differ i.e.\n    /// they might be bound to different event loops.\n    @preconcurrency\n    @inlinable\n    public func and<OtherValue: Sendable>(\n        _ other: EventLoopFuture<OtherValue>\n    ) -> EventLoopFuture<(Value, OtherValue)> {\n        let promise = EventLoopPromise<(Value, OtherValue)>.makeUnleakablePromise(eventLoop: self.eventLoop)\n        let box: UnsafeMutableTransferBox<(t: Value?, u: OtherValue?)> = .init((nil, nil))\n\n        assert(self.eventLoop === promise.futureResult.eventLoop)\n        self._whenComplete { () -> CallbackList in\n            switch self._value! {\n            case .failure(let error):\n                return promise._setValue(value: .failure(error))\n            case .success(let t):\n                if let u = box.wrappedValue.u {\n                    return promise._setValue(value: .success((t, u)))\n                } else {\n                    box.wrappedValue.t = t\n                }\n            }\n            return CallbackList()\n        }\n\n        let hopOver = other.hop(to: self.eventLoop)\n        hopOver._whenComplete { () -> CallbackList in\n            self.eventLoop.assertInEventLoop()\n            switch other._value! {\n            case .failure(let error):\n                return promise._setValue(value: .failure(error))\n            case .success(let u):\n                if let t = box.wrappedValue.t {\n                    return promise._setValue(value: .success((t, u)))\n                } else {\n                    box.wrappedValue.u = u\n                }\n            }\n            return CallbackList()\n        }\n\n        return promise.futureResult\n    }\n\n    /// Return a new EventLoopFuture that contains this \"and\" another value.\n    /// This is just syntactic sugar for `future.and(loop.makeSucceedFuture(value))`.\n    @preconcurrency\n    @inlinable\n    public func and<OtherValue: Sendable>(\n        value: OtherValue  // TODO: This should be transferring\n    ) -> EventLoopFuture<(Value, OtherValue)> {\n        self.and(EventLoopFuture<OtherValue>(eventLoop: self.eventLoop, value: value))\n    }\n}\n\n// MARK: cascade\n\nextension EventLoopFuture {\n    /// Fulfills the given `EventLoopPromise` with the results from this `EventLoopFuture`.\n    ///\n    /// This is useful when allowing users to provide promises for you to fulfill, but\n    /// when you are calling functions that return their own promises. They allow you to\n    /// tidy up your computational pipelines.\n    ///\n    /// For example:\n    /// ```\n    /// doWork().flatMap {\n    ///     doMoreWork($0)\n    /// }.flatMap {\n    ///     doYetMoreWork($0)\n    /// }.flatMapError {\n    ///     maybeRecoverFromError($0)\n    /// }.map {\n    ///     transformData($0)\n    /// }.cascade(to: userPromise)\n    /// ```\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of this future and the promise might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameter promise: The `EventLoopPromise` to fulfill with the results of this future.\n    /// - SeeAlso: `EventLoopPromise.completeWith(_:)`\n    @preconcurrency\n    @inlinable\n    public func cascade(to promise: EventLoopPromise<Value>?) where Value: Sendable {\n        guard let promise = promise else { return }\n        self.whenComplete { result in\n            switch result {\n            case let .success(value): promise.succeed(value)\n            case let .failure(error): promise.fail(error)\n            }\n        }\n    }\n\n    /// Fulfills the given `EventLoopPromise` only when this `EventLoopFuture` succeeds.\n    ///\n    /// If you are doing work that fulfills a type that doesn't match the expected `EventLoopPromise` value, add an\n    /// intermediate `map`.\n    ///\n    /// For example:\n    /// ```\n    /// let boolPromise = eventLoop.makePromise(of: Bool.self)\n    /// doWorkReturningInt().map({ $0 >= 0 }).cascade(to: boolPromise)\n    /// ```\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of this future and the promise might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameter promise: The `EventLoopPromise` to fulfill when a successful result is available.\n    @preconcurrency\n    @inlinable\n    public func cascadeSuccess(to promise: EventLoopPromise<Value>?) where Value: Sendable {\n        guard let promise = promise else { return }\n        self.whenSuccess { promise.succeed($0) }\n    }\n\n    /// Fails the given `EventLoopPromise` with the error from this `EventLoopFuture` if encountered.\n    ///\n    /// This is an alternative variant of `cascade` that allows you to potentially return early failures in\n    /// error cases, while passing the user `EventLoopPromise` onwards.\n    ///\n    ///\n    /// - Parameter promise: The `EventLoopPromise` that should fail with the error of this `EventLoopFuture`.\n    @inlinable\n    public func cascadeFailure<NewValue>(to promise: EventLoopPromise<NewValue>?) {\n        guard let promise = promise else { return }\n        self.whenFailure { promise.fail($0) }\n    }\n}\n\n// MARK: wait\n\nextension EventLoopFuture {\n    /// Wait for the resolution of this `EventLoopFuture` by blocking the current thread until it\n    /// resolves.\n    ///\n    /// If the `EventLoopFuture` resolves with a value, that value is returned from `wait()`. If\n    /// the `EventLoopFuture` resolves with an error, that error will be thrown instead.\n    /// `wait()` will block whatever thread it is called on, so it must not be called on event loop\n    /// threads: it is primarily useful for testing, or for building interfaces between blocking\n    /// and non-blocking code.\n    ///\n    /// This is also forbidden in async contexts: prefer ``EventLoopFuture/get()``.\n    ///\n    /// - Note: The `Value` must be `Sendable` since it is shared outside of the isolation domain of the event loop.\n    ///\n    /// - Returns: The value of the `EventLoopFuture` when it completes.\n    /// - Throws: The error value of the `EventLoopFuture` if it errors.\n    @available(*, noasync, message: \"wait() can block indefinitely, prefer get()\", renamed: \"get()\")\n    @preconcurrency\n    @inlinable\n    public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value where Value: Sendable {\n        #if os(WASI)\n        // NOTE: As of July 22, 2025 `wait()` calling wait() is not supported on WASI platforms.\n        //\n        // This may change down the road if and when true multi-threading evolves. But right now\n        // calling wait here results in the following runtime crash:\n        //\n        // ```\n        // SomeExecutable.wasm:0x123456 Uncaught (in promise) RuntimeError: Atomics.wait cannot be called in this context\n        // ```\n        //\n        // Using the following fatal error here gives wasm runtime users a much more clear error message\n        // to identify the issue.\n        //\n        // If you're running into this error on WASI, refactoring to `get()` instead of `wait()` will\n        // likely solve the issue.\n        fatalError(\n            \"NIO's wait() function should not be called on WASI platforms. It will freeze or crash. Use get() instead.\"\n        )\n        #else\n        try self._blockingWaitForFutureCompletion(file: file, line: line)\n        #endif\n    }\n\n    @inlinable\n    @inline(never)\n    func _blockingWaitForFutureCompletion(file: StaticString, line: UInt) throws -> Value where Value: Sendable {\n        self.eventLoop._preconditionSafeToWait(file: file, line: line)\n\n        let v: UnsafeMutableTransferBox<Result<Value, Error>?> = .init(nil)\n        let lock = ConditionLock(value: 0)\n        self._whenComplete { () -> CallbackList in\n            lock.lock()\n            v.wrappedValue = self._value\n            lock.unlock(withValue: 1)\n            return CallbackList()\n        }\n        lock.lock(whenValue: 1)\n        lock.unlock()\n\n        switch v.wrappedValue! {\n        case .success(let result):\n            return result\n        case .failure(let error):\n            throw error\n        }\n    }\n}\n\n// MARK: fold\n\nextension EventLoopFuture {\n    /// Returns a new `EventLoopFuture` that fires only when this `EventLoopFuture` and\n    /// all the provided `futures` complete. It then provides the result of folding the value of this\n    /// `EventLoopFuture` with the values of all the provided `futures`.\n    ///\n    /// This function is suited when you have APIs that already know how to return `EventLoopFuture`s.\n    ///\n    /// The returned `EventLoopFuture` will fail as soon as the a failure is encountered in any of the\n    /// `futures` (or in this one). However, the failure will not occur until all preceding\n    /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent\n    /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once\n    /// a failure is encountered, it will immediately fail the overall EventLoopFuture.\n    ///\n    /// - Note: The `Value` and `NewValue` must be `Sendable` since the isolation domains of this future and the other futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of `EventLoopFuture<NewValue>` to wait for.\n    ///   - combiningFunction: A function that will be used to fold the values of two `EventLoopFuture`s and return a new value wrapped in an `EventLoopFuture`.\n    /// - Returns: A new `EventLoopFuture` with the folded value whose callbacks run on `self.eventLoop`.\n    @inlinable\n    @preconcurrency\n    public func fold<OtherValue: Sendable>(\n        _ futures: [EventLoopFuture<OtherValue>],\n        with combiningFunction: @escaping @Sendable (Value, OtherValue) -> EventLoopFuture<Value>\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        @Sendable\n        func fold0() -> EventLoopFuture<Value> {\n            let body = futures.reduce(self) {\n                (f1: EventLoopFuture<Value>, f2: EventLoopFuture<OtherValue>) -> EventLoopFuture<Value> in\n                let newFuture = f1.and(f2).flatMap { (args: (Value, OtherValue)) -> EventLoopFuture<Value> in\n                    let (f1Value, f2Value) = args\n                    self.eventLoop.assertInEventLoop()\n                    return combiningFunction(f1Value, f2Value)\n                }\n                assert(newFuture.eventLoop === self.eventLoop)\n                return newFuture\n            }\n            return body\n        }\n\n        if self.eventLoop.inEventLoop {\n            return fold0()\n        } else {\n            let promise = self.eventLoop.makePromise(of: Value.self)\n            self.eventLoop.execute {\n                fold0().cascade(to: promise)\n            }\n            return promise.futureResult\n        }\n    }\n}\n\n// MARK: reduce\n\nextension EventLoopFuture {\n    /// Returns a new `EventLoopFuture` that fires only when all the provided futures complete.\n    /// The new `EventLoopFuture` contains the result of reducing the `initialResult` with the\n    /// values of the `[EventLoopFuture<NewValue>]`.\n    ///\n    /// This function makes copies of the result for each EventLoopFuture, for a version which avoids\n    /// making copies, check out `reduce<NewValue>(into:)`.\n    ///\n    /// The returned `EventLoopFuture` will fail as soon as a failure is encountered in any of the\n    /// `futures`. However, the failure will not occur until all preceding\n    /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent\n    /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once\n    /// a failure is encountered, it will immediately fail the overall `EventLoopFuture`.\n    ///\n    /// - Note: The `Value` and `InputValue` must be `Sendable` since the isolation domains of this future and the other futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - initialResult: An initial result to begin the reduction.\n    ///   - futures: An array of `EventLoopFuture` to wait for.\n    ///   - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will fire.\n    ///   - nextPartialResult: The bifunction used to produce partial results.\n    /// - Returns: A new `EventLoopFuture` with the reduced value.\n    @preconcurrency\n    @inlinable\n    public static func reduce<InputValue: Sendable>(\n        _ initialResult: Value,\n        _ futures: [EventLoopFuture<InputValue>],\n        on eventLoop: EventLoop,\n        _ nextPartialResult: @escaping @Sendable (Value, InputValue) -> Value\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        Self._reduce(initialResult, futures, on: eventLoop, nextPartialResult)\n    }\n    @usableFromInline typealias ReduceCallback<InputValue> = @Sendable (Value, InputValue) -> Value\n\n    @inlinable\n    static func _reduce<InputValue: Sendable>(\n        _ initialResult: Value,\n        _ futures: [EventLoopFuture<InputValue>],\n        on eventLoop: EventLoop,\n        _ nextPartialResult: @escaping ReduceCallback<InputValue>\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        let f0 = eventLoop.makeSucceededFuture(initialResult)\n\n        let body = f0.fold(futures) { (t: Value, u: InputValue) -> EventLoopFuture<Value> in\n            eventLoop.makeSucceededFuture(nextPartialResult(t, u))\n        }\n\n        return body\n    }\n\n    /// Returns a new `EventLoopFuture` that fires only when all the provided futures complete.\n    /// The new `EventLoopFuture` contains the result of combining the `initialResult` with the\n    /// values of the `[EventLoopFuture<NewValue>]`. This function is analogous to the standard library's\n    /// `reduce(into:)`, which does not make copies of the result type for each `EventLoopFuture`.\n    ///\n    /// The returned `EventLoopFuture` will fail as soon as a failure is encountered in any of the\n    /// `futures`. However, the failure will not occur until all preceding\n    /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent\n    /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once\n    /// a failure is encountered, it will immediately fail the overall `EventLoopFuture`.\n    ///\n    /// - Note: The `Value` and `InputValue` must be `Sendable` since the isolation domains of this future and the other futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - initialResult: An initial result to begin the reduction.\n    ///   - futures: An array of `EventLoopFuture` to wait for.\n    ///   - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will fire.\n    ///   - updateAccumulatingResult: The bifunction used to combine partialResults with new elements.\n    /// - Returns: A new `EventLoopFuture` with the combined value.\n    @inlinable\n    @preconcurrency\n    public static func reduce<InputValue: Sendable>(\n        into initialResult: Value,\n        _ futures: [EventLoopFuture<InputValue>],\n        on eventLoop: EventLoop,\n        _ updateAccumulatingResult: @escaping @Sendable (inout Value, InputValue) -> Void\n    ) -> EventLoopFuture<Value> where Value: Sendable {\n        let p0 = eventLoop.makePromise(of: Value.self)\n        let value = NIOLoopBoundBox<Value>(_value: initialResult, uncheckedEventLoop: eventLoop)\n\n        let f0 = eventLoop.makeSucceededFuture(())\n        let future = f0.fold(futures) { (_: (), newValue: InputValue) -> EventLoopFuture<Void> in\n            eventLoop.assertInEventLoop()\n            var v = value.value\n            updateAccumulatingResult(&v, newValue)\n            value.value = v\n            return eventLoop.makeSucceededFuture(())\n        }\n\n        future.whenSuccess {\n            eventLoop.assertInEventLoop()\n            p0.succeed(value.value)\n        }\n        future.whenFailure { (error) in\n            eventLoop.assertInEventLoop()\n            p0.fail(error)\n        }\n        return p0.futureResult\n    }\n}\n\n// MARK: \"fail fast\" reduce\n\nextension EventLoopFuture {\n    /// Returns a new `EventLoopFuture` that succeeds only if all of the provided futures succeed.\n    ///\n    /// This method acts as a successful completion notifier - values fulfilled by each future are discarded.\n    ///\n    /// The returned `EventLoopFuture` fails as soon as any of the provided futures fail.\n    ///\n    /// If it is desired to always succeed, regardless of failures, use `andAllComplete` instead.\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFutures`s to wait for.\n    ///   - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will execute on.\n    /// - Returns: A new `EventLoopFuture` that waits for the other futures to succeed.\n    @inlinable\n    public static func andAllSucceed(\n        _ futures: [EventLoopFuture<Value>],\n        on eventLoop: EventLoop\n    ) -> EventLoopFuture<Void> {\n        let promise = eventLoop.makePromise(of: Void.self)\n        EventLoopFuture.andAllSucceed(futures, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Succeeds the promise if all of the provided futures succeed. If any of the provided\n    /// futures fail then the `promise` will be failed -- even if some futures are yet to complete.\n    ///\n    /// If the results of all futures should be collected use `andAllComplete` instead.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFutures`s to wait for.\n    ///   - promise: The `EventLoopPromise` to complete with the result of this call.\n    @inlinable\n    public static func andAllSucceed(\n        _ futures: [EventLoopFuture<Value>],\n        promise: EventLoopPromise<Void>\n    ) {\n        let eventLoop = promise.futureResult.eventLoop\n\n        if eventLoop.inEventLoop {\n            self._reduceSuccesses0(promise, futures, eventLoop)\n        } else {\n            eventLoop.execute {\n                self._reduceSuccesses0(promise, futures, eventLoop)\n            }\n        }\n    }\n\n    /// Returns a new `EventLoopFuture` that succeeds only if all of the provided futures succeed.\n    /// The new `EventLoopFuture` will contain all of the values fulfilled by the futures.\n    ///\n    /// The returned `EventLoopFuture` will fail as soon as any of the futures fails.\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of the futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFuture`s to wait on for fulfilled values.\n    ///   - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will fire.\n    /// - Returns: A new `EventLoopFuture` with all of the values fulfilled by the provided futures.\n    @preconcurrency\n    public static func whenAllSucceed(\n        _ futures: [EventLoopFuture<Value>],\n        on eventLoop: EventLoop\n    ) -> EventLoopFuture<[Value]> where Value: Sendable {\n        let promise = eventLoop.makePromise(of: [Value].self)\n        EventLoopFuture.whenAllSucceed(futures, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Completes the `promise` with the values of all `futures` if all provided futures succeed. If\n    /// any of the provided futures fail then `promise` will be failed.\n    ///\n    /// If the _results of all futures should be collected use `andAllComplete` instead.\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of the futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFutures`s to wait for.\n    ///   - promise: The `EventLoopPromise` to complete with the result of this call.\n    @preconcurrency\n    public static func whenAllSucceed(\n        _ futures: [EventLoopFuture<Value>],\n        promise: EventLoopPromise<[Value]>\n    ) where Value: Sendable {\n        let eventLoop = promise.futureResult.eventLoop\n        let reduced = eventLoop.makePromise(of: Void.self)\n\n        let results: UnsafeMutableTransferBox<[Value?]> = .init(.init(repeating: nil, count: futures.count))\n        let callback = { @Sendable (index: Int, result: Value) in\n            results.wrappedValue[index] = result\n        }\n\n        if eventLoop.inEventLoop {\n            self._reduceSuccesses0(reduced, futures, eventLoop, onValue: callback)\n        } else {\n            eventLoop.execute {\n                self._reduceSuccesses0(reduced, futures, eventLoop, onValue: callback)\n            }\n        }\n\n        reduced.futureResult.whenComplete { result in\n            switch result {\n            case .success:\n                // verify that all operations have been completed\n                assert(!results.wrappedValue.contains(where: { $0 == nil }))\n                promise.succeed(results.wrappedValue.map { $0! })\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n    }\n\n    /// Loops through the futures array and attaches callbacks to execute `onValue` on the provided `EventLoop` when\n    /// they succeed. The `onValue` will receive the index of the future that fulfilled the provided `Result`.\n    ///\n    /// Once all the futures have succeed, the provided promise will succeed.\n    /// Once any future fails, the provided promise will fail.\n    @inlinable\n    internal static func _reduceSuccesses0<InputValue>(\n        _ promise: EventLoopPromise<Void>,\n        _ futures: [EventLoopFuture<InputValue>],\n        _ eventLoop: EventLoop,\n        onValue: @escaping @Sendable (Int, InputValue) -> Void\n    ) where InputValue: Sendable {\n        eventLoop.assertInEventLoop()\n\n        if futures.count == 0 {\n            promise.succeed(())\n            return\n        }\n\n        let remainingCount = NIOLoopBoundBox(_value: futures.count, uncheckedEventLoop: eventLoop)\n\n        // Sends the result to `onValue` in case of success and succeeds/fails the input promise, if appropriate.\n        @Sendable\n        func processResult(_ index: Int, _ result: Result<InputValue, Error>) {\n            switch result {\n            case .success(let result):\n                onValue(index, result)\n                remainingCount.value -= 1\n\n                if remainingCount.value == 0 {\n                    promise.succeed(())\n                }\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n        // loop through the futures to chain callbacks to execute on the initiating event loop and grab their index\n        // in the \"futures\" to pass their result to the caller\n        for (index, future) in futures.enumerated() {\n            if future.eventLoop.inEventLoop,\n                let result = future._value\n            {\n                // Fast-track already-fulfilled results without the overhead of calling `whenComplete`. This can yield a\n                // ~20% performance improvement in the case of large arrays where all elements are already fulfilled.\n                processResult(index, result)\n                if case .failure = result {\n                    return  // Once the promise is failed, future results do not need to be processed.\n                }\n            } else {\n                future.hop(to: eventLoop)\n                    .whenComplete { result in processResult(index, result) }\n            }\n        }\n    }\n\n    /// Loops through the futures array and attaches callbacks to execute `onValue` on the provided `EventLoop` when\n    /// they succeed. The `onValue` will receive the index of the future that fulfilled the provided `Result`.\n    ///\n    /// Once all the futures have succeed, the provided promise will succeed.\n    /// Once any future fails, the provided promise will fail.\n    @inlinable\n    internal static func _reduceSuccesses0(\n        _ promise: EventLoopPromise<Void>,\n        _ futures: [EventLoopFuture<Value>],\n        _ eventLoop: EventLoop\n    ) {\n        eventLoop.assertInEventLoop()\n\n        if futures.count == 0 {\n            promise.succeed(())\n            return\n        }\n\n        let remainingCount = NIOLoopBoundBox(_value: futures.count, uncheckedEventLoop: eventLoop)\n\n        // Sends the result to `onValue` in case of success and succeeds/fails the input promise, if appropriate.\n        @Sendable\n        func processResult(_ index: Int, _ result: Result<Void, Error>) {\n            switch result {\n            case .success:\n                remainingCount.value -= 1\n\n                if remainingCount.value == 0 {\n                    promise.succeed(())\n                }\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n        // loop through the futures to chain callbacks to execute on the initiating event loop and grab their index\n        // in the \"futures\" to pass their result to the caller\n        for (index, future) in futures.enumerated() {\n            if future.eventLoop.inEventLoop,\n                let result = future._value\n            {\n                // Fast-track already-fulfilled results without the overhead of calling `whenComplete`. This can yield a\n                // ~20% performance improvement in the case of large arrays where all elements are already fulfilled.\n                switch result {\n                case .success:\n                    processResult(index, .success(()))\n                case .failure(let error):\n                    processResult(index, .failure(error))\n                    return\n                }\n            } else {\n                // We have to map to `Void` here to avoid sharing the potentially non-Sendable\n                // value across event loops.\n                future.whenComplete { result in\n                    let voidResult = result.map { _ in }\n                    if eventLoop.inEventLoop {\n                        processResult(index, voidResult)\n                    } else {\n                        eventLoop.execute {\n                            processResult(index, voidResult)\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// MARK: \"fail slow\" reduce\n\nextension EventLoopFuture {\n    /// Returns a new `EventLoopFuture` that succeeds when all of the provided `EventLoopFuture`s complete.\n    ///\n    /// The returned `EventLoopFuture` always succeeds, acting as a completion notification.\n    /// Values fulfilled by each future are discarded.\n    ///\n    /// If the results are needed, use `whenAllComplete` instead.\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFuture`s to wait for.\n    ///   - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will execute on.\n    /// - Returns: A new `EventLoopFuture` that succeeds after all futures complete.\n    @inlinable\n    public static func andAllComplete(\n        _ futures: [EventLoopFuture<Value>],\n        on eventLoop: EventLoop\n    ) -> EventLoopFuture<Void> {\n        let promise = eventLoop.makePromise(of: Void.self)\n        EventLoopFuture.andAllComplete(futures, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Completes a `promise` when all of the provided `EventLoopFuture`s have completed.\n    ///\n    /// The promise will always be succeeded, regardless of the outcome of the individual futures.\n    ///\n    /// If the results are required, use `whenAllComplete` instead.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFuture`s to wait for.\n    ///   - promise: The `EventLoopPromise` to succeed when all futures have completed.\n    @inlinable\n    public static func andAllComplete(\n        _ futures: [EventLoopFuture<Value>],\n        promise: EventLoopPromise<Void>\n    ) {\n        let eventLoop = promise.futureResult.eventLoop\n\n        if eventLoop.inEventLoop {\n            self._reduceCompletions0(promise, futures, eventLoop)\n        } else {\n            eventLoop.execute {\n                self._reduceCompletions0(promise, futures, eventLoop)\n            }\n        }\n    }\n\n    /// Returns a new `EventLoopFuture` that succeeds when all of the provided `EventLoopFuture`s complete.\n    /// The new `EventLoopFuture` will contain an array of results, maintaining ordering for each of the `EventLoopFuture`s.\n    ///\n    /// The returned `EventLoopFuture` always succeeds, regardless of any failures from the waiting futures.\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of the futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// If it is desired to flatten them into a single `EventLoopFuture` that fails on the first `EventLoopFuture` failure,\n    /// use one of the `reduce` methods instead.\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFuture`s to gather results from.\n    ///   - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will fire.\n    /// - Returns: A new `EventLoopFuture` with all the results of the provided futures.\n    @preconcurrency\n    @inlinable\n    public static func whenAllComplete(\n        _ futures: [EventLoopFuture<Value>],\n        on eventLoop: EventLoop\n    ) -> EventLoopFuture<[Result<Value, Error>]> where Value: Sendable {\n        let promise = eventLoop.makePromise(of: [Result<Value, Error>].self)\n        EventLoopFuture.whenAllComplete(futures, promise: promise)\n        return promise.futureResult\n    }\n\n    /// Completes a `promise` with the results of all provided `EventLoopFuture`s.\n    ///\n    /// The promise will always be succeeded, regardless of the outcome of the futures.\n    ///\n    /// - Note: The `Value` must be `Sendable` since the isolation domains of the futures might differ i.e.\n    /// they might be bound to different event loops.\n    ///\n    /// - Parameters:\n    ///   - futures: An array of homogenous `EventLoopFuture`s to gather results from.\n    ///   - promise: The `EventLoopPromise` to complete with the result of the futures.\n    @preconcurrency\n    @inlinable\n    public static func whenAllComplete(\n        _ futures: [EventLoopFuture<Value>],\n        promise: EventLoopPromise<[Result<Value, Error>]>\n    ) where Value: Sendable {\n        let eventLoop = promise.futureResult.eventLoop\n        let reduced = eventLoop.makePromise(of: Void.self)\n\n        let results: UnsafeMutableTransferBox<[Result<Value, Error>]> = .init(\n            .init(repeating: .failure(OperationPlaceholderError()), count: futures.count)\n        )\n        let callback = { @Sendable (index: Int, result: Result<Value, Error>) in\n            results.wrappedValue[index] = result\n        }\n\n        if eventLoop.inEventLoop {\n            self._reduceCompletions0(reduced, futures, eventLoop, onResult: callback)\n        } else {\n            eventLoop.execute {\n                self._reduceCompletions0(reduced, futures, eventLoop, onResult: callback)\n            }\n        }\n\n        reduced.futureResult.whenComplete { result in\n            switch result {\n            case .success:\n                // verify that all operations have been completed\n                assert(\n                    !results.wrappedValue.contains(where: {\n                        guard case let .failure(error) = $0 else { return false }\n                        return error is OperationPlaceholderError\n                    })\n                )\n                promise.succeed(results.wrappedValue)\n\n            case .failure(let error):\n                promise.fail(error)\n            }\n        }\n    }\n\n    /// Loops through the futures array and attaches callbacks to execute `onResult` on the provided `EventLoop` when\n    /// they complete. The `onResult` will receive the index of the future that fulfilled the provided `Result`.\n    ///\n    /// Once all the futures have completed, the provided promise will succeed.\n    @inlinable\n    internal static func _reduceCompletions0<InputValue: Sendable>(\n        _ promise: EventLoopPromise<Void>,\n        _ futures: [EventLoopFuture<InputValue>],\n        _ eventLoop: EventLoop,\n        onResult: @escaping @Sendable (Int, Result<InputValue, Error>) -> Void\n    ) {\n        eventLoop.assertInEventLoop()\n\n        if futures.count == 0 {\n            promise.succeed(())\n            return\n        }\n\n        let remainingCount = NIOLoopBoundBox(_value: futures.count, uncheckedEventLoop: eventLoop)\n\n        // Sends the result to `onResult` in case of success and succeeds the input promise, if appropriate.\n        @Sendable\n        func processResult(_ index: Int, _ result: Result<InputValue, Error>) {\n            onResult(index, result)\n            remainingCount.value -= 1\n\n            if remainingCount.value == 0 {\n                promise.succeed(())\n            }\n        }\n        // loop through the futures to chain callbacks to execute on the initiating event loop and grab their index\n        // in the \"futures\" to pass their result to the caller\n        for (index, future) in futures.enumerated() {\n            if future.eventLoop.inEventLoop,\n                let result = future._value\n            {\n                // Fast-track already-fulfilled results without the overhead of calling `whenComplete`. This can yield a\n                // ~30% performance improvement in the case of large arrays where all elements are already fulfilled.\n                processResult(index, result)\n            } else {\n                future.hop(to: eventLoop)\n                    .whenComplete { result in processResult(index, result) }\n            }\n        }\n    }\n\n    /// Loops through the futures array and attaches callbacks to execute `onResult` on the provided `EventLoop` when\n    /// they complete. The `onResult` will receive the index of the future that fulfilled the provided `Result`.\n    ///\n    /// Once all the futures have completed, the provided promise will succeed.\n    @inlinable\n    internal static func _reduceCompletions0(\n        _ promise: EventLoopPromise<Void>,\n        _ futures: [EventLoopFuture<Value>],\n        _ eventLoop: EventLoop\n    ) {\n        eventLoop.assertInEventLoop()\n\n        if futures.count == 0 {\n            promise.succeed(())\n            return\n        }\n\n        let remainingCount = NIOLoopBoundBox(_value: futures.count, uncheckedEventLoop: eventLoop)\n\n        // Sends the result to `onResult` in case of success and succeeds the input promise, if appropriate.\n        @Sendable\n        func processResult(_ index: Int, _ result: Result<Void, Error>) {\n            remainingCount.value -= 1\n\n            if remainingCount.value == 0 {\n                promise.succeed(())\n            }\n        }\n        // loop through the futures to chain callbacks to execute on the initiating event loop and grab their index\n        // in the \"futures\" to pass their result to the caller\n        for (index, future) in futures.enumerated() {\n            if future.eventLoop.inEventLoop,\n                let result = future._value\n            {\n                // Fast-track already-fulfilled results without the overhead of calling `whenComplete`. This can yield a\n                // ~30% performance improvement in the case of large arrays where all elements are already fulfilled.\n                switch result {\n                case .success:\n                    processResult(index, .success(()))\n                case .failure(let error):\n                    processResult(index, .failure(error))\n                }\n            } else {\n                // We have to map to `Void` here to avoid sharing the potentially non-Sendable\n                // value across event loops.\n                future.whenComplete { result in\n                    let voidResult = result.map { _ in }\n                    if eventLoop.inEventLoop {\n                        processResult(index, voidResult)\n                    } else {\n                        eventLoop.execute {\n                            processResult(index, voidResult)\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// MARK: hop\n\nextension EventLoopFuture {\n    /// Returns an `EventLoopFuture` that fires when this future completes, but executes its callbacks on the\n    /// target event loop instead of the original one.\n    ///\n    /// It is common to want to \"hop\" event loops when you arrange some work: for example, you're closing one channel\n    /// from another, and want to hop back when the close completes. This method lets you spell that requirement\n    /// succinctly. It also contains an optimisation for the case when the loop you're hopping *from* is the same as\n    /// the one you're hopping *to*, allowing you to avoid doing allocations in that case.\n    ///\n    /// - Note: The `Value` must be `Sendable` since it is shared with the isolation domain of the target event loop.\n    ///\n    /// - Parameters:\n    ///   - target: The `EventLoop` that the returned `EventLoopFuture` will run on.\n    /// - Returns: An `EventLoopFuture` whose callbacks run on `target` instead of the original loop.\n    @preconcurrency\n    @inlinable\n    public func hop(to target: EventLoop) -> EventLoopFuture<Value> where Value: Sendable {\n        if target === self.eventLoop {\n            // We're already on that event loop, nothing to do here. Save an allocation.\n            return self\n        }\n        let hoppingPromise = target.makePromise(of: Value.self)\n        self.cascade(to: hoppingPromise)\n        return hoppingPromise.futureResult\n    }\n}\n\n// MARK: always\n\nextension EventLoopFuture {\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has any result.\n    ///\n    /// - Parameters:\n    ///   - callback: the callback that is called when the `EventLoopFuture` is fulfilled.\n    /// - Returns: the current `EventLoopFuture`\n    @inlinable\n    @preconcurrency\n    public func always(_ callback: @escaping @Sendable (Result<Value, Error>) -> Void) -> EventLoopFuture<Value> {\n        self.whenComplete { result in callback(result) }\n        return self\n    }\n}\n\n// MARK: unwrap\n\nextension EventLoopFuture {\n    /// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.\n    ///\n    /// Unwrap a future returning a new `EventLoopFuture`. When the resolved future's value is `Optional.some(...)`\n    /// the new future is created with the identical value. Otherwise the `Error` passed in the `orError` parameter\n    /// is thrown. For example:\n    /// ```\n    /// do {\n    ///     try promise.futureResult.unwrap(orError: ErrorToThrow).wait()\n    /// } catch ErrorToThrow {\n    ///     ...\n    /// }\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - orError: the `Error` that is thrown when then resolved future's value is `Optional.none`.\n    /// - Returns: an new `EventLoopFuture` with new type parameter `NewValue` and the same value as the resolved\n    ///     future.\n    /// - Throws: the `Error` passed in the `orError` parameter when the resolved future's value is `Optional.none`.\n    @inlinable\n    public func unwrap<NewValue>(orError: Error) -> EventLoopFuture<NewValue> where Value == NewValue? {\n        self.flatMapThrowing { (value) throws -> NewValue in\n            guard let value = value else {\n                throw orError\n            }\n            return value\n        }\n    }\n\n    /// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.\n    ///\n    /// Unwraps a future returning a new `EventLoopFuture` with either: the value passed in the `orReplace`\n    /// parameter when the future resolved with value Optional.none, or the same value otherwise. For example:\n    /// ```\n    /// promise.futureResult.unwrap(orReplace: 42).wait()\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - replacement: the value of the returned `EventLoopFuture` when then resolved future's value is `Optional.some()`.\n    /// - Returns: an new `EventLoopFuture` with new type parameter `NewValue` and the value passed in the `replacement` parameter.\n    @preconcurrency\n    @inlinable\n    public func unwrap<NewValue: Sendable>(\n        orReplace replacement: NewValue\n    ) -> EventLoopFuture<NewValue> where Value == NewValue? {\n        self.map { (value) -> NewValue in\n            guard let value = value else {\n                return replacement\n            }\n            return value\n        }\n    }\n\n    /// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.\n    ///\n    /// Unwraps a future returning a new `EventLoopFuture` with either: the value returned by the closure passed in\n    /// the `orElse` parameter when the future resolved with value Optional.none, or the same value otherwise. For example:\n    /// ```\n    /// var x = 2\n    /// promise.futureResult.unwrap(orElse: { x * 2 }).wait()\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - callback: a closure that returns the value of the returned `EventLoopFuture` when then resolved future's value\n    ///         is `Optional.some()`.\n    /// - Returns: an new `EventLoopFuture` with new type parameter `NewValue` and with the value returned by the closure\n    ///     passed in the `callback` parameter.\n    @inlinable\n    @preconcurrency\n    public func unwrap<NewValue>(\n        orElse callback: @escaping @Sendable () -> NewValue\n    ) -> EventLoopFuture<NewValue> where Value == NewValue? {\n        self._unwrap(orElse: callback)\n    }\n    @usableFromInline typealias UnwrapCallback<NewValue> = @Sendable () -> NewValue\n\n    @inlinable\n    func _unwrap<NewValue>(\n        orElse callback: @escaping UnwrapCallback<NewValue>\n    ) -> EventLoopFuture<NewValue> where Value == NewValue? {\n        self.map { (value) -> NewValue in\n            guard let value = value else {\n                return callback()\n            }\n            return value\n        }\n    }\n}\n\n// MARK: may block\n\n#if canImport(Dispatch)\nextension EventLoopFuture {\n    /// Chain an `EventLoopFuture<NewValue>` providing the result of a IO / task that may block. For example:\n    ///\n    ///     promise.futureResult.flatMapBlocking(onto: DispatchQueue.global()) { value in Int\n    ///         blockingTask(value)\n    ///     }\n    ///\n    /// - Note: The `Value` and `NewValue` must be `Sendable` since it is shared between the isolation region queue and the event loop.\n    ///\n    /// - Parameters:\n    ///   - queue: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.\n    ///   - callbackMayBlock: Function that will receive the value of this `EventLoopFuture` and return\n    ///         a new `EventLoopFuture`.\n    @inlinable\n    @preconcurrency\n    public func flatMapBlocking<NewValue: Sendable>(\n        onto queue: DispatchQueue,\n        _ callbackMayBlock: @escaping @Sendable (Value) throws -> NewValue\n    ) -> EventLoopFuture<NewValue> where Value: Sendable {\n        self.flatMap { result in\n            queue.asyncWithFuture(eventLoop: self.eventLoop) { try callbackMayBlock(result) }\n        }\n    }\n\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has a success result. The observer callback is permitted to block.\n    ///\n    /// An observer callback cannot return a value, meaning that this function cannot be chained\n    /// from. If you are attempting to create a computation pipeline, consider `map` or `flatMap`.\n    /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`\n    /// in the body of this function, consider using `cascade` instead.\n    ///\n    /// - Note: The `NewValue` must be `Sendable` since it is shared between the isolation region queue and the event loop.\n    ///\n    /// - Parameters:\n    ///   - queue: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.\n    ///   - callbackMayBlock: The callback that is called with the successful result of the `EventLoopFuture`.\n    @preconcurrency\n    @inlinable\n    public func whenSuccessBlocking(\n        onto queue: DispatchQueue,\n        _ callbackMayBlock: @escaping @Sendable (Value) -> Void\n    ) where Value: Sendable {\n        self.whenSuccess { value in\n            queue.async { callbackMayBlock(value) }\n        }\n    }\n\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has a failure result. The observer callback is permitted to block.\n    ///\n    /// An observer callback cannot return a value, meaning that this function cannot be chained\n    /// from. If you are attempting to create a computation pipeline, consider `recover` or `flatMapError`.\n    /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`\n    /// in the body of this function, consider using `cascade` instead.\n    ///\n    /// - Parameters:\n    ///   - queue: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.\n    ///   - callbackMayBlock: The callback that is called with the failed result of the `EventLoopFuture`.\n    @inlinable\n    @preconcurrency\n    public func whenFailureBlocking(\n        onto queue: DispatchQueue,\n        _ callbackMayBlock: @escaping @Sendable (Error) -> Void\n    ) {\n        self._whenFailureBlocking(onto: queue, callbackMayBlock)\n    }\n    @usableFromInline typealias WhenFailureBlockingCallback = @Sendable (Error) -> Void\n\n    @inlinable\n    func _whenFailureBlocking(onto queue: DispatchQueue, _ callbackMayBlock: @escaping WhenFailureBlockingCallback) {\n        self.whenFailure { err in\n            queue.async { callbackMayBlock(err) }\n        }\n    }\n\n    /// Adds an observer callback to this `EventLoopFuture` that is called when the\n    /// `EventLoopFuture` has any result. The observer callback is permitted to block.\n    ///\n    /// - Note: The `NewValue` must be `Sendable` since it is shared between the isolation region queue and the event loop.\n    ///\n    /// - Parameters:\n    ///   - queue: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.\n    ///   - callbackMayBlock: The callback that is called when the `EventLoopFuture` is fulfilled.\n    @inlinable\n    @preconcurrency\n    public func whenCompleteBlocking(\n        onto queue: DispatchQueue,\n        _ callbackMayBlock: @escaping @Sendable (Result<Value, Error>) -> Void\n    ) where Value: Sendable {\n        self.whenComplete { value in\n            queue.async { callbackMayBlock(value) }\n        }\n    }\n}\n#endif\n\n// MARK: assertion\n\nextension EventLoopFuture {\n    /// Attaches a callback to the `EventLoopFuture` that asserts the original future's success.\n    ///\n    /// If the original future fails, it triggers an assertion failure, causing a runtime error during development.\n    /// The assertion failure will include the file and line of the calling site.\n    ///\n    /// - Parameters:\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @inlinable\n    public func assertSuccess(file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Value> {\n        self.always { result in\n            switch result {\n            case .success:\n                ()\n            case .failure(let error):\n                assertionFailure(\"Expected success, but got failure: \\(error)\", file: file, line: line)\n            }\n        }\n    }\n    /// Attaches a callback to the `EventLoopFuture` that asserts the original future's failure.\n    ///\n    /// If the original future succeeds, it triggers an assertion failure, causing a runtime error during development.\n    /// The assertion failure will include the file and line of the calling site.\n    ///\n    /// - Parameters:\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @inlinable\n    public func assertFailure(file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Value> {\n        self.always { result in\n            switch result {\n            case .success(let value):\n                assertionFailure(\"Expected failure, but got success: \\(value)\", file: file, line: line)\n            case .failure:\n                ()\n            }\n        }\n    }\n\n    /// Attaches a callback to the `EventLoopFuture` that preconditions the original future's success.\n    ///\n    /// If the original future fails, it triggers a precondition failure, causing a runtime error during development.\n    /// The precondition failure will include the file and line of the calling site.\n    ///\n    /// - Parameters:\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @inlinable\n    public func preconditionSuccess(file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Value> {\n        self.always { result in\n            switch result {\n            case .success:\n                ()\n            case .failure(let error):\n                Swift.preconditionFailure(\"Expected success, but got failure: \\(error)\", file: file, line: line)\n            }\n        }\n    }\n\n    /// Attaches a callback to the `EventLoopFuture` that preconditions the original future's failure.\n    ///\n    /// If the original future succeeds, it triggers a precondition failure, causing a runtime error during development.\n    /// The precondition failure will include the file and line of the calling site.\n    ///\n    /// - Parameters:\n    ///   - file: The file this function was called in, for debugging purposes.\n    ///   - line: The line this function was called on, for debugging purposes.\n    @inlinable\n    public func preconditionFailure(file: StaticString = #fileID, line: UInt = #line) -> EventLoopFuture<Value> {\n        self.always { result in\n            switch result {\n            case .success(let value):\n                Swift.preconditionFailure(\"Expected failure, but got success: \\(value)\", file: file, line: line)\n            case .failure:\n                ()\n            }\n        }\n    }\n}\n\n/// An opaque identifier for a specific `EventLoopFuture`.\n///\n/// This is used only when attempting to provide high-fidelity diagnostics of leaked\n/// `EventLoopFuture`s. It is entirely opaque and can only be stored in a simple\n/// tracking data structure.\npublic struct _NIOEventLoopFutureIdentifier: Hashable, Sendable {\n    private var opaqueID: UInt\n\n    @usableFromInline\n    internal init<T>(_ future: EventLoopFuture<T>) {\n        self.opaqueID = _NIOEventLoopFutureIdentifier.obfuscatePointerValue(future: future)\n    }\n\n    private static func obfuscatePointerValue<T>(future: EventLoopFuture<T>) -> UInt {\n        // Note:\n        // 1. 0xbf15ca5d is randomly picked such that it fits into both 32 and 64 bit address spaces\n        // 2. XOR with 0xbf15ca5d so that Memory Graph Debugger and other memory debugging tools\n        // won't see it as a reference.\n        UInt(bitPattern: ObjectIdentifier(future)) ^ 0xbf15_ca5d\n    }\n}\n\n// The future is unchecked Sendable following the below isolation rules this is safe\n//\n// 1. Receiving the value of the future is always done on the EventLoop of the future, hence\n// the value is never transferred out of the event loops isolation domain. It only gets transferred\n// by certain methods such as `hop()` and those methods are annotated with requiring the Value to be\n// Sendable\n// 2. The promise is `Sendable` but fulfilling the promise with a value requires the user to\n// transfer the value to the promise. This ensures that the value is now isolated to the event loops\n// isolation domain. Note: Sendable values can always be transferred\n\nextension EventLoopPromise: Sendable {}\n\nextension EventLoopFuture: @unchecked Sendable {}\n\nextension EventLoopPromise where Value == Void {\n    // Deliver a successful result to the associated `EventLoopFuture<Void>` object.\n    @inlinable\n    public func succeed() {\n        succeed(Void())\n    }\n}\n\nextension Optional {\n    /// Sets or cascades the future result of self to the provided promise, if present.\n    ///\n    /// If `promise` is `nil` then this function is a no-op. Otherwise, if `self` is `nil` then\n    /// `self` is set to `promise`. If `self` isn't `nil` then its `futureResult` will be cascaded\n    /// to `promise`.\n    ///\n    /// - Parameter promise: The promise to set or cascade to.\n    @preconcurrency\n    public mutating func setOrCascade<Value: Sendable>(to promise: EventLoopPromise<Value>?)\n    where Wrapped == EventLoopPromise<Value> {\n        guard let promise = promise else { return }\n\n        switch self {\n        case .none:\n            self = .some(promise)\n        case .some(let existing):\n            existing.futureResult.cascade(to: promise)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/FileDescriptor.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\npublic protocol FileDescriptor {\n\n    /// Will be called with the file descriptor if still open, if not it will\n    /// throw an `IOError`.\n    ///\n    /// The ownership of the file descriptor must not escape the `body` as it's completely managed by the\n    /// implementation of the `FileDescriptor` protocol.\n    ///\n    /// - Parameters:\n    ///   - body: The closure to execute if the `FileDescriptor` is still open.\n    /// - Throws: If either the `FileDescriptor` was closed before or the closure throws by itself.\n    func withUnsafeFileDescriptor<T>(_ body: (CInt) throws -> T) throws -> T\n\n    /// `true` if this `FileDescriptor` is open (which means it was not closed yet).\n    var isOpen: Bool { get }\n\n    /// Close this `FileDescriptor`.\n    func close() throws\n}\n"
  },
  {
    "path": "Sources/NIOCore/FileHandle.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\n\n#if os(Windows)\nimport ucrt\n#elseif canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\nimport CNIOWASI\n#else\n#error(\"The File Handle module was unable to identify your C library.\")\n#endif\n\n#if os(Windows)\npublic typealias NIOPOSIXFileMode = CInt\n#else\npublic typealias NIOPOSIXFileMode = mode_t\n#endif\n\n#if arch(x86_64) || arch(arm64)\n// 64 bit architectures\ntypealias OneUInt32 = UInt32\ntypealias TwoUInt32s = UInt64\n\n// Now we need to make `UInt64` match `DoubleWord`'s API but we can't use a custom\n// type because we need special support by the `swift-atomics` package.\nextension UInt64 {\n    fileprivate init(first: UInt32, second: UInt32) {\n        self = UInt64(first) << 32 | UInt64(second)\n    }\n\n    fileprivate var first: UInt32 {\n        get {\n            UInt32(truncatingIfNeeded: self >> 32)\n        }\n        set {\n            self = (UInt64(newValue) << 32) | UInt64(self.second)\n        }\n    }\n\n    fileprivate var second: UInt32 {\n        get {\n            UInt32(truncatingIfNeeded: self & 0xff_ff_ff_ff)\n        }\n        set {\n            self = (UInt64(self.first) << 32) | UInt64(newValue)\n        }\n    }\n}\n#elseif arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n// 32 bit architectures\n// Note: for testing purposes you can also use these defines for 64 bit platforms, they'll just consume twice as\n// much space, nothing else will go bad.\ntypealias OneUInt32 = UInt\ntypealias TwoUInt32s = DoubleWord\n#else\n#error(\"Unknown architecture\")\n#endif\n\ninternal struct FileDescriptorState {\n    private static let closedValue: OneUInt32 = 0xdead\n    private static let inUseValue: OneUInt32 = 0xbeef\n    private static let openValue: OneUInt32 = 0xcafe\n    internal var rawValue: TwoUInt32s\n\n    internal init(rawValue: TwoUInt32s) {\n        self.rawValue = rawValue\n    }\n\n    internal init(descriptor: CInt) {\n        self.rawValue = TwoUInt32s(\n            first: .init(truncatingIfNeeded: CUnsignedInt(bitPattern: descriptor)),\n            second: Self.openValue\n        )\n    }\n\n    internal var descriptor: CInt {\n        get {\n            CInt(bitPattern: UInt32(truncatingIfNeeded: self.rawValue.first))\n        }\n        set {\n            self.rawValue.first = .init(truncatingIfNeeded: CUnsignedInt(bitPattern: newValue))\n        }\n    }\n\n    internal var isOpen: Bool {\n        self.rawValue.second == Self.openValue\n    }\n\n    internal var isInUse: Bool {\n        self.rawValue.second == Self.inUseValue\n    }\n\n    internal var isClosed: Bool {\n        self.rawValue.second == Self.closedValue\n    }\n\n    mutating func close() {\n        assert(self.isOpen)\n        self.rawValue.second = Self.closedValue\n    }\n\n    mutating func markInUse() {\n        assert(self.isOpen)\n        self.rawValue.second = Self.inUseValue\n    }\n\n    mutating func markNotInUse() {\n        assert(self.rawValue.second == Self.inUseValue)\n        self.rawValue.second = Self.openValue\n    }\n}\n\n/// Deprecated. `NIOFileHandle` is a handle to an open file descriptor.\n///\n/// - warning: The `NIOFileHandle` API is deprecated, do not use going forward. It's not marked as `deprecated` yet such\n///            that users don't get the deprecation warnings affecting their APIs everywhere. For file I/O, please use\n///            the `NIOFileSystem` API.\n///\n/// When creating a `NIOFileHandle` it takes ownership of the underlying file descriptor. When a `NIOFileHandle` is no longer\n/// needed you must `close` it or take back ownership of the file descriptor using `takeDescriptorOwnership`.\n///\n/// - Note: One underlying file descriptor should usually be managed by one `NIOFileHandle` only.\n///\n/// - warning: Failing to manage the lifetime of a `NIOFileHandle` correctly will result in undefined behaviour.\n///\n/// - Note: As of SwiftNIO 2.77.0, `NIOFileHandle` objects are are thread-safe and enforce singular access. If you access the same `NIOFileHandle`\n///         multiple times, it will throw `IOError(errorCode: EBUSY)` for the second access.\npublic final class NIOFileHandle: FileDescriptor & Sendable {\n    private static let descriptorClosed: CInt = CInt.min\n    private let descriptor: UnsafeAtomic<TwoUInt32s>\n\n    public var isOpen: Bool {\n        FileDescriptorState(\n            rawValue: self.descriptor.load(ordering: .sequentiallyConsistent)\n        ).isOpen\n    }\n\n    private static func interpretDescriptorValueThrowIfInUseOrNotOpen(\n        _ descriptor: TwoUInt32s\n    ) throws -> FileDescriptorState {\n        let descriptorState = FileDescriptorState(rawValue: descriptor)\n        if descriptorState.isOpen {\n            return descriptorState\n        } else if descriptorState.isClosed {\n            throw IOError(errnoCode: EBADF, reason: \"can't close file (as it's not open anymore).\")\n        } else {\n            throw IOError(errnoCode: EBUSY, reason: \"file descriptor currently in use\")\n        }\n    }\n\n    private func peekAtDescriptorIfOpen() throws -> FileDescriptorState {\n        let descriptor = self.descriptor.load(ordering: .relaxed)\n        return try Self.interpretDescriptorValueThrowIfInUseOrNotOpen(descriptor)\n    }\n\n    /// Create a `NIOFileHandle` taking ownership of `descriptor`. You must call `NIOFileHandle.close` or `NIOFileHandle.takeDescriptorOwnership` before\n    /// this object can be safely released.\n    @available(\n        *,\n        deprecated,\n        message: \"\"\"\n            Avoid using NIOFileHandle. The type is difficult to hold correctly, \\\n            use NIOFileSystem as a replacement API.\n            \"\"\"\n    )\n    public convenience init(descriptor: CInt) {\n        self.init(_deprecatedTakingOwnershipOfDescriptor: descriptor)\n    }\n\n    /// Create a `NIOFileHandle` taking ownership of `descriptor`. You must call `NIOFileHandle.close` or `NIOFileHandle.takeDescriptorOwnership` before\n    /// this object can be safely released.\n    public init(_deprecatedTakingOwnershipOfDescriptor descriptor: CInt) {\n        self.descriptor = UnsafeAtomic.create(FileDescriptorState(descriptor: descriptor).rawValue)\n    }\n\n    deinit {\n        assert(\n            !self.isOpen,\n            \"leaked open NIOFileHandle(descriptor: \\(self.descriptor)). Call `close()` to close or `takeDescriptorOwnership()` to take ownership and close by some other means.\"\n        )\n        self.descriptor.destroy()\n    }\n\n    #if !os(WASI)\n    /// Duplicates this `NIOFileHandle`. This means that a new `NIOFileHandle` object with a new underlying file descriptor\n    /// is returned. The caller takes ownership of the returned `NIOFileHandle` and is responsible for closing it.\n    ///\n    /// - warning: The returned `NIOFileHandle` is not fully independent, the seek pointer is shared as documented by `dup(2)`.\n    ///\n    /// - Returns: A new `NIOFileHandle` with a fresh underlying file descriptor but shared seek pointer.\n    public func duplicate() throws -> NIOFileHandle {\n        try self.withUnsafeFileDescriptor { fd in\n            NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: try SystemCalls.dup(descriptor: fd))\n        }\n    }\n    #endif\n\n    private func activateDescriptor(as descriptor: CInt) {\n        let desired = FileDescriptorState(descriptor: descriptor)\n        var expected = desired\n        expected.markInUse()\n        let (exchanged, original) = self.descriptor.compareExchange(\n            expected: expected.rawValue,\n            desired: desired.rawValue,\n            ordering: .sequentiallyConsistent\n        )\n        guard exchanged || FileDescriptorState(rawValue: original).isClosed else {\n            fatalError(\"bug in NIO (please report): NIOFileDescritor activate failed \\(original)\")\n        }\n    }\n\n    private func deactivateDescriptor(toClosed: Bool) throws -> CInt {\n        let peekedDescriptor = try self.peekAtDescriptorIfOpen()\n        // Don't worry, the above is just opportunistic. If we lose the race, we re-check below --> `!exchanged`\n        assert(peekedDescriptor.isOpen)\n        var desired = peekedDescriptor\n        if toClosed {\n            desired.close()\n        } else {\n            desired.markInUse()\n        }\n        assert(desired.rawValue != peekedDescriptor.rawValue, \"\\(desired.rawValue) == \\(peekedDescriptor.rawValue)\")\n        let (exchanged, originalDescriptor) = self.descriptor.compareExchange(\n            expected: peekedDescriptor.rawValue,\n            desired: desired.rawValue,\n            ordering: .sequentiallyConsistent\n        )\n\n        if exchanged {\n            assert(peekedDescriptor.rawValue == originalDescriptor)\n            return peekedDescriptor.descriptor\n        } else {\n            // We lost the race above, so this _will_ throw (as we're not closed).\n            let fauxDescriptor = try Self.interpretDescriptorValueThrowIfInUseOrNotOpen(originalDescriptor)\n            // This is impossible, because there are only 4 options in which the exchange above can fail\n            // 1. Descriptor already closed (would've thrown above)\n            // 2. Descriptor in use (would've thrown above)\n            // 3. Descriptor at illegal negative value (would've crashed above)\n            // 4. Descriptor a different, positive value (this is where we're at) --> memory corruption, let's crash\n            fatalError(\n                \"\"\"\n                bug in NIO (please report): \\\n                NIOFileDescriptor illegal state \\\n                (\\(peekedDescriptor), \\(originalDescriptor), \\(fauxDescriptor))\")\n                \"\"\"\n            )\n        }\n    }\n\n    /// Take the ownership of the underlying file descriptor. This is similar to `close()` but the underlying file\n    /// descriptor remains open. The caller is responsible for closing the file descriptor by some other means.\n    ///\n    /// After calling this, the `NIOFileHandle` cannot be used for anything else and all the operations will throw.\n    ///\n    /// - Returns: The underlying file descriptor, now owned by the caller.\n    public func takeDescriptorOwnership() throws -> CInt {\n        try self.deactivateDescriptor(toClosed: true)\n    }\n\n    public func close() throws {\n        let descriptor = try self.deactivateDescriptor(toClosed: true)\n        try SystemCalls.close(descriptor: descriptor)\n    }\n\n    public func withUnsafeFileDescriptor<T>(_ body: (CInt) throws -> T) throws -> T {\n        let descriptor = try self.deactivateDescriptor(toClosed: false)\n        defer {\n            self.activateDescriptor(as: descriptor)\n        }\n        return try body(descriptor)\n    }\n}\n\nextension NIOFileHandle {\n    /// `Mode` represents file access modes.\n    public struct Mode: OptionSet, Sendable {\n        public let rawValue: UInt8\n\n        @inlinable\n        public init(rawValue: UInt8) {\n            self.rawValue = rawValue\n        }\n\n        internal var posixFlags: CInt {\n            switch self {\n            case [.read, .write]:\n                return O_RDWR\n            case .read:\n                return O_RDONLY\n            case .write:\n                return O_WRONLY\n            default:\n                preconditionFailure(\"Unsupported mode value\")\n            }\n        }\n\n        /// Opens file for reading\n        @inlinable\n        public static var read: Mode { Mode(rawValue: 1 << 0) }\n        /// Opens file for writing\n        @inlinable\n        public static var write: NIOFileHandle.Mode { Mode(rawValue: 1 << 1) }\n    }\n\n    /// `Flags` allows to specify additional flags to `Mode`, such as permission for file creation.\n    public struct Flags: Sendable {\n        @usableFromInline\n        internal var posixMode: NIOPOSIXFileMode\n\n        @usableFromInline\n        internal var posixFlags: CInt\n\n        @inlinable\n        internal init(posixMode: NIOPOSIXFileMode, posixFlags: CInt) {\n            self.posixMode = posixMode\n            self.posixFlags = posixFlags\n        }\n\n        public static var `default`: Flags { Flags(posixMode: 0, posixFlags: 0) }\n\n        #if os(Windows)\n        public static let defaultPermissions = _S_IREAD | _S_IWRITE\n        #elseif os(WASI)\n        public static let defaultPermissions = WASILibc.S_IWUSR | WASILibc.S_IRUSR | WASILibc.S_IRGRP | WASILibc.S_IROTH\n        #else\n        public static let defaultPermissions = S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH\n        #endif\n\n        /// Allows file creation when opening file for writing. File owner is set to the effective user ID of the process.\n        ///\n        /// - Parameters:\n        ///   - posixMode: `file mode` applied when file is created. Default permissions are: read and write for fileowner, read for owners group and others.\n        public static func allowFileCreation(posixMode: NIOPOSIXFileMode = defaultPermissions) -> Flags {\n            #if os(WASI)\n            let flags = CNIOWASI_O_CREAT()\n            #else\n            let flags = O_CREAT\n            #endif\n            return Flags(posixMode: posixMode, posixFlags: flags)\n        }\n\n        /// Allows the specification of POSIX flags (e.g. `O_TRUNC`) and mode (e.g. `S_IWUSR`)\n        ///\n        /// - Parameters:\n        ///   - flags: The POSIX open flags (the second parameter for `open(2)`).\n        ///   - mode: The POSIX mode (the third parameter for `open(2)`).\n        /// - Returns: A `NIOFileHandle.Mode` equivalent to the given POSIX flags and mode.\n        public static func posix(flags: CInt, mode: NIOPOSIXFileMode) -> Flags {\n            Flags(posixMode: mode, posixFlags: flags)\n        }\n    }\n\n    /// Open a new `NIOFileHandle`. This operation is blocking.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open. The ownership of the file descriptor is transferred to this `NIOFileHandle` and so it will be closed once `close` is called.\n    ///   - mode: Access mode. Default mode is `.read`.\n    ///   - flags: Additional POSIX flags.\n    @available(\n        *,\n        deprecated,\n        message: \"\"\"\n            Avoid using NIOFileHandle. The type is difficult to hold correctly, \\\n            use NIOFileSystem as a replacement API.\n            \"\"\"\n    )\n    public convenience init(\n        path: String,\n        mode: Mode = .read,\n        flags: Flags = .default\n    ) throws {\n        try self.init(_deprecatedPath: path, mode: mode, flags: flags)\n    }\n\n    /// Open a new `NIOFileHandle`. This operation is blocking.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open. The ownership of the file descriptor is transferred to this `NIOFileHandle` and so it will be closed once `close` is called.\n    ///   - mode: Access mode. Default mode is `.read`.\n    ///   - flags: Additional POSIX flags.\n    @available(*, noasync, message: \"This method may block the calling thread\")\n    public convenience init(\n        _deprecatedPath path: String,\n        mode: Mode = .read,\n        flags: Flags = .default\n    ) throws {\n        #if os(Windows)\n        let fl = mode.posixFlags | flags.posixFlags | _O_NOINHERIT\n        #else\n        let fl = mode.posixFlags | flags.posixFlags | O_CLOEXEC\n        #endif\n        let fd = try SystemCalls.open(file: path, oFlag: fl, mode: flags.posixMode)\n        self.init(_deprecatedTakingOwnershipOfDescriptor: fd)\n    }\n\n    /// Open a new `NIOFileHandle`. This operation is blocking.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open. The ownership of the file descriptor is transferred to this `NIOFileHandle` and so it will be closed once `close` is called.\n    @available(\n        *,\n        deprecated,\n        message: \"\"\"\n            Avoid using NIOFileHandle. The type is difficult to hold correctly, \\\n            use NIOFileSystem as a replacement API.\n            \"\"\"\n    )\n    public convenience init(path: String) throws {\n        try self.init(_deprecatedPath: path)\n    }\n\n    /// Open a new `NIOFileHandle`. This operation is blocking.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open. The ownership of the file descriptor is transferred to this `NIOFileHandle` and so it will be closed once `close` is called.\n    @available(*, noasync, message: \"This method may block the calling thread\")\n    public convenience init(_deprecatedPath path: String) throws {\n        // This function is here because we had a function like this in NIO 2.0, and the one above doesn't quite match. Sadly we can't\n        // really deprecate this either, because it'll be preferred to the one above in many cases.\n        try self.init(_deprecatedPath: path, mode: .read, flags: .default)\n    }\n}\n\nextension NIOFileHandle: CustomStringConvertible {\n    public var description: String {\n        \"FileHandle { descriptor: \\(FileDescriptorState(rawValue: self.descriptor.load(ordering: .relaxed)).descriptor) }\"\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/FileRegion.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#if os(Windows)\nimport ucrt\n#elseif canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"The File Region module was unable to identify your C library.\")\n#endif\n\n/// A `FileRegion` represent a readable portion usually created to be sent over the network.\n///\n/// - warning: The `FileRegion` API is deprecated, do not use going forward. It's not marked as `deprecated` yet such\n///            that users don't get the deprecation warnings affecting their APIs everywhere. For file I/O, please use\n///            the `NIOFileSystem` API.\n///\n/// Usually a `FileRegion` will allow the underlying transport to use `sendfile` to transfer its content and so allows transferring\n/// the file content without copying it into user-space at all. If the actual transport implementation really can make use of sendfile\n/// or if it will need to copy the content to user-space first and use `write` / `writev` is an implementation detail. That said\n///  using `FileRegion` is the recommended way to transfer file content if possible.\n///\n/// One important note, depending your `ChannelPipeline` setup it may not be possible to use a `FileRegion` as a `ChannelHandler` may\n/// need access to the bytes (in a `ByteBuffer`) to transform these.\n///\n/// - Note: It is important to manually manage the lifetime of the ``NIOFileHandle`` used to create a ``FileRegion``.\n/// - Note: As of SwiftNIO 2.77.0, `FileRegion` objects are are thread-safe and the underlying ``NIOFileHandle`` does enforce singular access.\npublic struct FileRegion: Sendable {\n\n    /// The `NIOFileHandle` that is used by this `FileRegion`.\n    public let fileHandle: NIOFileHandle\n\n    private let _endIndex: UInt64\n    private var _readerIndex: _UInt56\n\n    /// The current reader index of this `FileRegion`\n    private(set) public var readerIndex: Int {\n        get {\n            Int(self._readerIndex)\n        }\n        set {\n            self._readerIndex = _UInt56(newValue)\n        }\n    }\n\n    /// The end index of this `FileRegion`.\n    public var endIndex: Int {\n        Int(self._endIndex)\n    }\n\n    /// Create a new `FileRegion` from an open `NIOFileHandle`.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: the `NIOFileHandle` to use.\n    ///   - readerIndex: the index (offset) on which the reading will start.\n    ///   - endIndex: the index which represent the end of the readable portion.\n    public init(fileHandle: NIOFileHandle, readerIndex: Int, endIndex: Int) {\n        precondition(readerIndex <= endIndex, \"readerIndex(\\(readerIndex) must be <= endIndex(\\(endIndex).\")\n\n        self.fileHandle = fileHandle\n        self._readerIndex = _UInt56(readerIndex)\n        self._endIndex = UInt64(endIndex)\n    }\n\n    /// The number of readable bytes within this FileRegion (taking the `readerIndex` and `endIndex` into account).\n    public var readableBytes: Int {\n        endIndex - readerIndex\n    }\n\n    /// Move the readerIndex forward by `offset`.\n    public mutating func moveReaderIndex(forwardBy offset: Int) {\n        let newIndex = self.readerIndex + offset\n        assert(offset >= 0 && newIndex <= endIndex, \"new readerIndex: \\(newIndex), expected: range(0, \\(endIndex))\")\n        self.readerIndex = newIndex\n    }\n}\n\nextension FileRegion {\n    /// Create a new `FileRegion` forming a complete file.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: An open `NIOFileHandle` to the file.\n    public init(fileHandle: NIOFileHandle) throws {\n        let eof = try fileHandle.withUnsafeFileDescriptor { (fd: CInt) throws -> off_t in\n            let eof = try SystemCalls.lseek(descriptor: fd, offset: 0, whence: SEEK_END)\n            try SystemCalls.lseek(descriptor: fd, offset: 0, whence: SEEK_SET)\n            return eof\n        }\n        self.init(fileHandle: fileHandle, readerIndex: 0, endIndex: Int(eof))\n    }\n\n}\n\nextension FileRegion: Equatable {\n    public static func == (lhs: FileRegion, rhs: FileRegion) -> Bool {\n        lhs.fileHandle === rhs.fileHandle && lhs.readerIndex == rhs.readerIndex && lhs.endIndex == rhs.endIndex\n    }\n}\n\nextension FileRegion: CustomStringConvertible {\n    public var description: String {\n        \"FileRegion { handle: \\(self.fileHandle), readerIndex: \\(self.readerIndex), endIndex: \\(self.endIndex) }\"\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/GlobalSingletons.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\n\n#if canImport(Darwin)\nimport Darwin\n#elseif os(Windows)\nimport ucrt\nimport WinSDK\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"Unsupported C library\")\n#endif\n\n/// SwiftNIO provided singleton resources for programs & libraries that don't need full control over all operating\n/// system resources. This type holds sizing (how many loops/threads) suggestions.\n///\n/// Users who need very tight control about the exact threads and resources created may decide to set\n/// `NIOSingletons.singletonsEnabledSuggestion = false`. All singleton-creating facilities should check\n/// this setting and if `false` restrain from creating any global singleton resources. Please note that disabling the\n/// global singletons will lead to a crash if _any_ code attempts to use any of the singletons.\npublic enum NIOSingletons: Sendable {\n}\n\nextension NIOSingletons {\n    /// A suggestion of how many ``EventLoop``s the global singleton ``EventLoopGroup``s are supposed to consist of.\n    ///\n    /// The thread count is ``System/coreCount`` unless the environment variable `NIO_SINGLETON_GROUP_LOOP_COUNT`\n    /// is set or this value was set manually by the user.\n    ///\n    /// Please note that setting this value is a privileged operation which should be performed very early on in the program's lifecycle\n    /// by the main function, or ideally not at all.\n    /// Furthermore, setting the value will only have an effect if the global singleton ``EventLoopGroup`` has not already\n    /// been used.\n    ///\n    /// - Warning: This value can only be set _once_, attempts to set it again will crash the program.\n    /// - Note: This value must be set _before_ any singletons are used and must only be set once.\n    public static var groupLoopCountSuggestion: Int {\n        set {\n            Self.userSetSingletonThreadCount(rawStorage: globalRawSuggestedLoopCount, userValue: newValue)\n        }\n\n        get {\n            Self.getTrustworthyThreadCount(\n                rawStorage: globalRawSuggestedLoopCount,\n                environmentVariable: \"NIO_SINGLETON_GROUP_LOOP_COUNT\"\n            )\n        }\n    }\n\n    /// A suggestion of how many threads the global singleton thread pools that can be used for synchronous, blocking\n    /// functions (such as `NIOThreadPool`) are supposed to consist of\n    ///\n    /// The thread count is ``System/coreCount`` unless the environment variable\n    /// `NIO_SINGLETON_BLOCKING_POOL_THREAD_COUNT` is set or this value was set manually by the user.\n    ///\n    /// Please note that setting this value is a privileged operation which should be performed very early on in the program's lifecycle\n    /// by the main function, or ideally not at all.\n    /// Furthermore, setting the value will only have an effect if the global singleton thread pool has not already\n    /// been used.\n    ///\n    /// - Warning: This value can only be set _once_, attempts to set it again will crash the program.\n    /// - Note: This value must be set _before_ any singletons are used and must only be set once.\n    public static var blockingPoolThreadCountSuggestion: Int {\n        set {\n            Self.userSetSingletonThreadCount(rawStorage: globalRawSuggestedBlockingThreadCount, userValue: newValue)\n        }\n\n        get {\n            Self.getTrustworthyThreadCount(\n                rawStorage: globalRawSuggestedBlockingThreadCount,\n                environmentVariable: \"NIO_SINGLETON_BLOCKING_POOL_THREAD_COUNT\"\n            )\n        }\n    }\n\n    /// A suggestion for whether the global singletons should be enabled. This is `true` unless changed by the user.\n    ///\n    /// This value cannot be changed using an environment variable.\n    ///\n    /// Please note that setting this value is a privileged operation which should be performed very early on in the program's lifecycle\n    /// by the main function, or ideally not at all.\n    ///\n    /// - Warning: This value can only be set _once_, attempts to set it again will crash the program.\n    /// - Note: This value must be set _before_ any singletons are used and must only be set once.\n    public static var singletonsEnabledSuggestion: Bool {\n        get {\n            let (exchanged, original) = globalRawSingletonsEnabled.compareExchange(\n                expected: 0,\n                desired: 1,\n                ordering: .relaxed\n            )\n            if exchanged {\n                // Never been set, we're committing to the default (enabled).\n                assert(original == 0)\n                return true\n            } else {\n                // This has been set before, 1: enabled; -1 disabled.\n                assert(original != 0)\n                assert(original == -1 || original == 1)\n                return original > 0\n            }\n        }\n\n        set {\n            let intRepresentation = newValue ? 1 : -1\n            let (exchanged, _) = globalRawSingletonsEnabled.compareExchange(\n                expected: 0,\n                desired: intRepresentation,\n                ordering: .relaxed\n            )\n            guard exchanged else {\n                fatalError(\n                    \"\"\"\n                    Bug in user code: Global singleton enabled suggestion has been changed after \\\n                    user or has been changed more than once. Either is an error, you must set this value very \\\n                    early and only once.\n                    \"\"\"\n                )\n            }\n        }\n    }\n}\n\n// DO NOT TOUCH THESE DIRECTLY, use `userSetSingletonThreadCount` and `getTrustworthyThreadCount`.\nprivate let globalRawSuggestedLoopCount = ManagedAtomic(0)\nprivate let globalRawSuggestedBlockingThreadCount = ManagedAtomic(0)\nprivate let globalRawSingletonsEnabled = ManagedAtomic(0)\n\nextension NIOSingletons {\n    private static func userSetSingletonThreadCount(rawStorage: ManagedAtomic<Int>, userValue: Int) {\n        precondition(userValue > 0, \"illegal value: needs to be strictly positive\")\n\n        // The user is trying to set it. We can only do this if the value is at 0 and we will set the\n        // negative value. So if the user wants `5`, we will set `-5`. Once it's used (set getter), it'll be upped\n        // to 5.\n        let (exchanged, _) = rawStorage.compareExchange(expected: 0, desired: -userValue, ordering: .relaxed)\n        guard exchanged else {\n            fatalError(\n                \"\"\"\n                Bug in user code: Global singleton suggested loop/thread count has been changed after \\\n                user or has been changed more than once. Either is an error, you must set this value very early \\\n                and only once.\n                \"\"\"\n            )\n        }\n    }\n\n    private static func validateTrustedThreadCount(_ threadCount: Int) {\n        assert(\n            threadCount > 0,\n            \"BUG IN NIO, please report: negative suggested loop/thread count: \\(threadCount)\"\n        )\n        assert(\n            threadCount <= 1024,\n            \"BUG IN NIO, please report: overly big suggested loop/thread count: \\(threadCount)\"\n        )\n    }\n\n    private static func getTrustworthyThreadCount(rawStorage: ManagedAtomic<Int>, environmentVariable: String) -> Int {\n        let returnedValueUnchecked: Int\n\n        let rawSuggestion = rawStorage.load(ordering: .relaxed)\n        switch rawSuggestion {\n        case 0:  // == 0\n            // Not set by user, not yet finalised, let's try to get it from the env var and fall back to\n            // `System.coreCount`.\n            #if os(Windows)\n            let envVarString = Windows.getenv(environmentVariable)\n            #else\n            let envVarString = getenv(environmentVariable).map { String(cString: $0) }\n            #endif\n            returnedValueUnchecked = envVarString.flatMap(Int.init) ?? System.coreCount\n        case .min..<0:  // < 0\n            // Untrusted and unchecked user value. Let's invert and then sanitise/check.\n            returnedValueUnchecked = -rawSuggestion\n        case 1 ... .max:  // > 0\n            // Trustworthy value that has been evaluated and sanitised before.\n            let returnValue = rawSuggestion\n            Self.validateTrustedThreadCount(returnValue)\n            return returnValue\n        default:\n            // Unreachable\n            preconditionFailure()\n        }\n\n        // Can't have fewer than 1, don't want more than 1024.\n        let returnValue = max(1, min(1024, returnedValueUnchecked))\n        Self.validateTrustedThreadCount(returnValue)\n\n        // Store it for next time.\n        let (exchanged, _) = rawStorage.compareExchange(\n            expected: rawSuggestion,\n            desired: returnValue,\n            ordering: .relaxed\n        )\n        if !exchanged {\n            // We lost the race, this must mean it has been concurrently set correctly so we can safely recurse\n            // and try again.\n            return Self.getTrustworthyThreadCount(rawStorage: rawStorage, environmentVariable: environmentVariable)\n        }\n        return returnValue\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/IO.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if os(Windows)\nimport ucrt\nimport func WinSDK.FormatMessageW\nimport func WinSDK.LocalFree\nimport let WinSDK.FORMAT_MESSAGE_ALLOCATE_BUFFER\nimport let WinSDK.FORMAT_MESSAGE_FROM_SYSTEM\nimport let WinSDK.FORMAT_MESSAGE_IGNORE_INSERTS\nimport let WinSDK.LANG_NEUTRAL\nimport let WinSDK.SUBLANG_DEFAULT\nimport typealias WinSDK.DWORD\nimport typealias WinSDK.WCHAR\nimport typealias WinSDK.WORD\n\ninternal func MAKELANGID(_ p: WORD, _ s: WORD) -> DWORD {\n    DWORD((s << 10) | p)\n}\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#elseif canImport(Darwin)\nimport Darwin\n#else\n#error(\"The IO module was unable to identify your C library.\")\n#endif\n\n/// An `Error` for an IO operation.\npublic struct IOError: Swift.Error {\n    @available(*, deprecated, message: \"NIO no longer uses FailureDescription.\")\n    public enum FailureDescription: Sendable {\n        case function(StaticString)\n        case reason(String)\n    }\n\n    /// The actual reason (in an human-readable form) for this `IOError`.\n    private var failureDescription: String\n\n    @available(\n        *,\n        deprecated,\n        message: \"NIO no longer uses FailureDescription, use IOError.description for a human-readable error description\"\n    )\n    public var reason: FailureDescription {\n        .reason(self.failureDescription)\n    }\n\n    private enum Error {\n        #if os(Windows)\n        case windows(DWORD)\n        case winsock(CInt)\n        #endif\n        case errno(CInt)\n    }\n\n    private let error: Error\n\n    /// The `errno` that was set for the operation.\n    public var errnoCode: CInt {\n        switch self.error {\n        case .errno(let code):\n            return code\n        #if os(Windows)\n        default:\n            fatalError(\"IOError domain is not `errno`\")\n        #endif\n        }\n    }\n\n    #if os(Windows)\n    public init(windows code: DWORD, reason: String) {\n        self.error = .windows(code)\n        self.failureDescription = reason\n    }\n\n    public init(winsock code: CInt, reason: String) {\n        self.error = .winsock(code)\n        self.failureDescription = reason\n    }\n    #endif\n\n    /// Creates a new `IOError``\n    ///\n    /// - Parameters:\n    ///   - errnoCode: the `errno` that was set for the operation.\n    ///   - reason: the actual reason (in an human-readable form).\n    public init(errnoCode: CInt, reason: String) {\n        self.error = .errno(errnoCode)\n        self.failureDescription = reason\n    }\n\n    /// Creates a new `IOError``\n    ///\n    /// - Parameters:\n    ///   - errnoCode: the `errno` that was set for the operation.\n    ///   - function: The function the error happened in, the human readable description will be generated automatically when needed.\n    @available(*, deprecated, renamed: \"init(errnoCode:reason:)\")\n    public init(errnoCode: CInt, function: StaticString) {\n        self.error = .errno(errnoCode)\n        self.failureDescription = \"\\(function)\"\n    }\n}\n\n/// Returns a reason to use when constructing a `IOError`.\n///\n/// - Parameters:\n///   - errnoCode: the `errno` that was set for the operation.\n///   - reason: what failed\n/// - Returns: the constructed reason.\nprivate func reasonForError(errnoCode: CInt, reason: String) -> String {\n    #if os(Windows)\n    let errorDesc = Windows.strerror(errnoCode)\n    #else\n    let errorDesc = strerror(errnoCode).flatMap { String(cString: $0) }\n    #endif\n    if let errorDesc {\n        return \"\\(reason): \\(errorDesc)) (errno: \\(errnoCode))\"\n    } else {\n        return \"\\(reason): Broken strerror, unknown error: \\(errnoCode)\"\n    }\n}\n\n#if os(Windows)\nprivate func reasonForWinError(_ code: DWORD) -> String {\n    let dwFlags: DWORD =\n        DWORD(FORMAT_MESSAGE_ALLOCATE_BUFFER)\n        | DWORD(FORMAT_MESSAGE_FROM_SYSTEM)\n        | DWORD(FORMAT_MESSAGE_IGNORE_INSERTS)\n\n    var buffer: UnsafeMutablePointer<WCHAR>?\n    // We use `FORMAT_MESSAGE_ALLOCATE_BUFFER` in flags which means that the\n    // buffer will be allocated by the call to `FormatMessageW`.  The function\n    // expects a `LPWSTR` and expects the user to type-pun in this case.\n    let dwResult: DWORD = withUnsafeMutablePointer(to: &buffer) {\n        $0.withMemoryRebound(to: WCHAR.self, capacity: 2) {\n            FormatMessageW(\n                dwFlags,\n                nil,\n                code,\n                MAKELANGID(WORD(LANG_NEUTRAL), WORD(SUBLANG_DEFAULT)),\n                $0,\n                0,\n                nil\n            )\n        }\n    }\n    guard dwResult > 0, let message = buffer else {\n        return \"unknown error \\(code)\"\n    }\n    defer { LocalFree(buffer) }\n    return String(decodingCString: message, as: UTF16.self)\n}\n#endif\n\nextension IOError: CustomStringConvertible {\n    public var description: String {\n        self.localizedDescription\n    }\n\n    public var localizedDescription: String {\n        #if os(Windows)\n        switch self.error {\n        case .errno(let errno):\n            return reasonForError(errnoCode: errno, reason: self.failureDescription)\n        case .windows(let code):\n            return reasonForWinError(code)\n        case .winsock(let code):\n            return reasonForWinError(DWORD(code))\n        }\n        #else\n        return reasonForError(errnoCode: self.errnoCode, reason: self.failureDescription)\n        #endif\n    }\n}\n\n// FIXME: Duplicated with NIO.\n/// An result for an IO operation that was done on a non-blocking resource.\nenum CoreIOResult<T: Equatable>: Equatable {\n\n    /// Signals that the IO operation could not be completed as otherwise we would need to block.\n    case wouldBlock(T)\n\n    /// Signals that the IO operation was completed.\n    case processed(T)\n}\n\nextension CoreIOResult where T: FixedWidthInteger {\n    var result: T {\n        switch self {\n        case .processed(let value):\n            return value\n        case .wouldBlock(_):\n            fatalError(\"cannot unwrap CoreIOResult\")\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/IOData.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// `IOData` unifies standard SwiftNIO types that are raw bytes of data; currently `ByteBuffer` and `FileRegion`.\n///\n/// - warning: `IOData` is a legacy API, please avoid using it as much as possible.\n///\n/// Many `ChannelHandler`s receive or emit bytes and in most cases this can be either a `ByteBuffer` or a `FileRegion`\n/// from disk. To still form a well-typed `ChannelPipeline` such handlers should receive and emit value of type `IOData`.\npublic enum IOData: Sendable {\n    /// A `ByteBuffer`.\n    case byteBuffer(ByteBuffer)\n\n    /// A `FileRegion`.\n    ///\n    /// - warning: `IOData.fileRegion` is a legacy API, please avoid using it. It cannot work with TLS and `FileRegion`\n    ///            and the underlying `NIOFileHandle` objects are very difficult to hold correctly.\n    ///\n    /// Sending a `FileRegion` through the `ChannelPipeline` using `write` can be useful because some `Channel`s can\n    /// use `sendfile` to send a `FileRegion` more efficiently.\n    case fileRegion(FileRegion)\n}\n\n/// `IOData` objects are comparable just like the values they wrap.\nextension IOData: Equatable {}\n\n/// `IOData` provide a number of readable bytes.\nextension IOData {\n    /// Returns the number of readable bytes in this `IOData`.\n    public var readableBytes: Int {\n        switch self {\n        case .byteBuffer(let buf):\n            return buf.readableBytes\n        case .fileRegion(let region):\n            return region.readableBytes\n        }\n    }\n\n    /// Move the readerIndex forward by `offset`.\n    public mutating func moveReaderIndex(forwardBy: Int) {\n        switch self {\n        case .byteBuffer(var buffer):\n            buffer.moveReaderIndex(forwardBy: forwardBy)\n            self = .byteBuffer(buffer)\n        case .fileRegion(var fileRegion):\n            fileRegion.moveReaderIndex(forwardBy: forwardBy)\n            self = .fileRegion(fileRegion)\n        }\n    }\n}\n\nextension IOData: CustomStringConvertible {\n    public var description: String {\n        switch self {\n        case .byteBuffer(let byteBuffer):\n            return \"IOData { \\(byteBuffer) }\"\n        case .fileRegion(let fileRegion):\n            return \"IOData { \\(fileRegion) }\"\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/IPProtocol.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// In the Internet Protocol version 4 (IPv4) [RFC791] there is a field\n/// called \"Protocol\" to identify the next level protocol.  This is an 8\n/// bit field.  In Internet Protocol version 6 (IPv6) [RFC8200], this field\n/// is called the \"Next Header\" field.\npublic struct NIOIPProtocol: RawRepresentable, Hashable, Sendable {\n    public typealias RawValue = UInt8\n    public var rawValue: RawValue\n\n    @inlinable\n    public init(rawValue: RawValue) {\n        self.rawValue = rawValue\n    }\n}\n\nextension NIOIPProtocol {\n    /// - precondition: `rawValue` must fit into an `UInt8`\n    public init(_ rawValue: Int) {\n        self.init(rawValue: UInt8(rawValue))\n    }\n}\n\n// Subset of https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml with an RFC\nextension NIOIPProtocol {\n    /// IPv6 Hop-by-Hop Option - [RFC8200]\n    @inlinable\n    public static var hopopt: NIOIPProtocol {\n        Self(rawValue: 0)\n    }\n    /// Internet Control Message - [RFC792]\n    @inlinable\n    public static var icmp: NIOIPProtocol {\n        Self(rawValue: 1)\n    }\n    /// Internet Group Management - [RFC1112]\n    @inlinable\n    public static var igmp: NIOIPProtocol {\n        Self(rawValue: 2)\n    }\n    /// Gateway-to-Gateway - [RFC823]\n    @inlinable\n    public static var ggp: NIOIPProtocol {\n        Self(rawValue: 3)\n    }\n    /// IPv4 encapsulation - [RFC2003]\n    @inlinable\n    public static var ipv4: NIOIPProtocol {\n        Self(rawValue: 4)\n    }\n    /// Stream - [RFC1190][RFC1819]\n    @inlinable\n    public static var st: NIOIPProtocol {\n        Self(rawValue: 5)\n    }\n    /// Transmission Control - [RFC9293]\n    @inlinable\n    public static var tcp: NIOIPProtocol {\n        Self(rawValue: 6)\n    }\n    /// Exterior Gateway Protocol - [RFC888][David_Mills]\n    @inlinable\n    public static var egp: NIOIPProtocol {\n        Self(rawValue: 8)\n    }\n    /// Network Voice Protocol - [RFC741][Steve_Casner]\n    @inlinable\n    public static var nvpIi: NIOIPProtocol {\n        Self(rawValue: 11)\n    }\n    /// User Datagram - [RFC768][Jon_Postel]\n    @inlinable\n    public static var udp: NIOIPProtocol {\n        Self(rawValue: 17)\n    }\n    /// Host Monitoring - [RFC869][Bob_Hinden]\n    @inlinable\n    public static var hmp: NIOIPProtocol {\n        Self(rawValue: 20)\n    }\n    /// Reliable Data Protocol - [RFC908][Bob_Hinden]\n    @inlinable\n    public static var rdp: NIOIPProtocol {\n        Self(rawValue: 27)\n    }\n    /// Internet Reliable Transaction - [RFC938][Trudy_Miller]\n    @inlinable\n    public static var irtp: NIOIPProtocol {\n        Self(rawValue: 28)\n    }\n    /// ISO Transport Protocol Class 4 - [RFC905][<mystery contact>]\n    @inlinable\n    public static var isoTp4: NIOIPProtocol {\n        Self(rawValue: 29)\n    }\n    /// Bulk Data Transfer Protocol - [RFC969][David_Clark]\n    @inlinable\n    public static var netblt: NIOIPProtocol {\n        Self(rawValue: 30)\n    }\n    /// Datagram Congestion Control Protocol - [RFC4340]\n    @inlinable\n    public static var dccp: NIOIPProtocol {\n        Self(rawValue: 33)\n    }\n    /// IPv6 encapsulation - [RFC2473]\n    @inlinable\n    public static var ipv6: NIOIPProtocol {\n        Self(rawValue: 41)\n    }\n    /// Reservation Protocol - [RFC2205][RFC3209][Bob_Braden]\n    @inlinable\n    public static var rsvp: NIOIPProtocol {\n        Self(rawValue: 46)\n    }\n    /// Generic Routing Encapsulation - [RFC2784][Tony_Li]\n    @inlinable\n    public static var gre: NIOIPProtocol {\n        Self(rawValue: 47)\n    }\n    /// Dynamic Source Routing Protocol - [RFC4728]\n    @inlinable\n    public static var dsr: NIOIPProtocol {\n        Self(rawValue: 48)\n    }\n    /// Encap Security Payload - [RFC4303]\n    @inlinable\n    public static var esp: NIOIPProtocol {\n        Self(rawValue: 50)\n    }\n    /// Authentication Header - [RFC4302]\n    @inlinable\n    public static var ah: NIOIPProtocol {\n        Self(rawValue: 51)\n    }\n    /// NBMA Address Resolution Protocol - [RFC1735]\n    @inlinable\n    public static var narp: NIOIPProtocol {\n        Self(rawValue: 54)\n    }\n    /// ICMP for IPv6 - [RFC8200]\n    @inlinable\n    public static var ipv6Icmp: NIOIPProtocol {\n        Self(rawValue: 58)\n    }\n    /// No Next Header for IPv6 - [RFC8200]\n    @inlinable\n    public static var ipv6Nonxt: NIOIPProtocol {\n        Self(rawValue: 59)\n    }\n    /// Destination Options for IPv6 - [RFC8200]\n    @inlinable\n    public static var ipv6Opts: NIOIPProtocol {\n        Self(rawValue: 60)\n    }\n    /// EIGRP - [RFC7868]\n    @inlinable\n    public static var eigrp: NIOIPProtocol {\n        Self(rawValue: 88)\n    }\n    /// OSPFIGP - [RFC1583][RFC2328][RFC5340][John_Moy]\n    @inlinable\n    public static var ospfigp: NIOIPProtocol {\n        Self(rawValue: 89)\n    }\n    /// Ethernet-within-IP Encapsulation - [RFC3378]\n    @inlinable\n    public static var etherip: NIOIPProtocol {\n        Self(rawValue: 97)\n    }\n    /// Encapsulation Header - [RFC1241][Robert_Woodburn]\n    @inlinable\n    public static var encap: NIOIPProtocol {\n        Self(rawValue: 98)\n    }\n    /// Protocol Independent Multicast - [RFC7761][Dino_Farinacci]\n    @inlinable\n    public static var pim: NIOIPProtocol {\n        Self(rawValue: 103)\n    }\n    /// IP Payload Compression Protocol - [RFC2393]\n    @inlinable\n    public static var ipcomp: NIOIPProtocol {\n        Self(rawValue: 108)\n    }\n    /// Virtual Router Redundancy Protocol - [RFC5798]\n    @inlinable\n    public static var vrrp: NIOIPProtocol {\n        Self(rawValue: 112)\n    }\n    /// Layer Two Tunneling Protocol - [RFC3931][Bernard_Aboba]\n    @inlinable\n    public static var l2tp: NIOIPProtocol {\n        Self(rawValue: 115)\n    }\n    /// Fibre Channel - [Murali_Rajagopal][RFC6172]\n    @inlinable\n    public static var fc: NIOIPProtocol {\n        Self(rawValue: 133)\n    }\n    /// MANET Protocols - [RFC5498]\n    @inlinable\n    public static var manet: NIOIPProtocol {\n        Self(rawValue: 138)\n    }\n    /// Host Identity Protocol - [RFC7401]\n    @inlinable\n    public static var hip: NIOIPProtocol {\n        Self(rawValue: 139)\n    }\n    /// Shim6 Protocol - [RFC5533]\n    @inlinable\n    public static var shim6: NIOIPProtocol {\n        Self(rawValue: 140)\n    }\n    /// Wrapped Encapsulating Security Payload - [RFC5840]\n    @inlinable\n    public static var wesp: NIOIPProtocol {\n        Self(rawValue: 141)\n    }\n    /// Robust Header Compression - [RFC5858]\n    @inlinable\n    public static var rohc: NIOIPProtocol {\n        Self(rawValue: 142)\n    }\n    /// Ethernet - [RFC8986]\n    @inlinable\n    public static var ethernet: NIOIPProtocol {\n        Self(rawValue: 143)\n    }\n    /// AGGFRAG encapsulation payload for ESP - [RFC-ietf-ipsecme-iptfs-19]\n    @inlinable\n    public static var aggfrag: NIOIPProtocol {\n        Self(rawValue: 144)\n    }\n}\n\nextension NIOIPProtocol: CustomStringConvertible {\n    private var name: String? {\n        switch self {\n        case .hopopt: return \"IPv6 Hop-by-Hop Option\"\n        case .icmp: return \"Internet Control Message\"\n        case .igmp: return \"Internet Group Management\"\n        case .ggp: return \"Gateway-to-Gateway\"\n        case .ipv4: return \"IPv4 encapsulation\"\n        case .st: return \"Stream\"\n        case .tcp: return \"Transmission Control\"\n        case .egp: return \"Exterior Gateway Protocol\"\n        case .nvpIi: return \"Network Voice Protocol\"\n        case .udp: return \"User Datagram\"\n        case .hmp: return \"Host Monitoring\"\n        case .rdp: return \"Reliable Data Protocol\"\n        case .irtp: return \"Internet Reliable Transaction\"\n        case .isoTp4: return \"ISO Transport Protocol Class 4\"\n        case .netblt: return \"Bulk Data Transfer Protocol\"\n        case .dccp: return \"Datagram Congestion Control Protocol\"\n        case .ipv6: return \"IPv6 encapsulation\"\n        case .rsvp: return \"Reservation Protocol\"\n        case .gre: return \"Generic Routing Encapsulation\"\n        case .dsr: return \"Dynamic Source Routing Protocol\"\n        case .esp: return \"Encap Security Payload\"\n        case .ah: return \"Authentication Header\"\n        case .narp: return \"NBMA Address Resolution Protocol\"\n        case .ipv6Icmp: return \"ICMP for IPv6\"\n        case .ipv6Nonxt: return \"No Next Header for IPv6\"\n        case .ipv6Opts: return \"Destination Options for IPv6\"\n        case .eigrp: return \"EIGRP\"\n        case .ospfigp: return \"OSPFIGP\"\n        case .etherip: return \"Ethernet-within-IP Encapsulation\"\n        case .encap: return \"Encapsulation Header\"\n        case .pim: return \"Protocol Independent Multicast\"\n        case .ipcomp: return \"IP Payload Compression Protocol\"\n        case .vrrp: return \"Virtual Router Redundancy Protocol\"\n        case .l2tp: return \"Layer Two Tunneling Protocol\"\n        case .fc: return \"Fibre Channel\"\n        case .manet: return \"MANET Protocols\"\n        case .hip: return \"Host Identity Protocol\"\n        case .shim6: return \"Shim6 Protocol\"\n        case .wesp: return \"Wrapped Encapsulating Security Payload\"\n        case .rohc: return \"Robust Header Compression\"\n        case .ethernet: return \"Ethernet\"\n        case .aggfrag: return \"AGGFRAG encapsulation payload for ESP\"\n        default: return nil\n        }\n    }\n\n    public var description: String {\n        let name = self.name ?? \"Unknown Protocol\"\n        return \"\\(name) - \\(rawValue)\"\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/IntegerBitPacking.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// FIXME: Duplicated in NIO.\n\n@usableFromInline\nenum _IntegerBitPacking: Sendable {}\n\nextension _IntegerBitPacking {\n    @inlinable\n    static func packUU<\n        Left: FixedWidthInteger & UnsignedInteger,\n        Right: FixedWidthInteger & UnsignedInteger,\n        Result: FixedWidthInteger & UnsignedInteger\n    >(\n        _ left: Left,\n        _ right: Right,\n        type: Result.Type = Result.self\n    ) -> Result {\n        assert(MemoryLayout<Left>.size + MemoryLayout<Right>.size <= MemoryLayout<Result>.size)\n\n        let resultLeft = Result(left)\n        let resultRight = Result(right)\n        let result = (resultLeft << Right.bitWidth) | resultRight\n        assert(result.nonzeroBitCount == left.nonzeroBitCount + right.nonzeroBitCount)\n        return result\n    }\n\n    @inlinable\n    static func unpackUU<\n        Input: FixedWidthInteger & UnsignedInteger,\n        Left: FixedWidthInteger & UnsignedInteger,\n        Right: FixedWidthInteger & UnsignedInteger\n    >(\n        _ input: Input,\n        leftType: Left.Type = Left.self,\n        rightType: Right.Type = Right.self\n    ) -> (Left, Right) {\n        assert(MemoryLayout<Left>.size + MemoryLayout<Right>.size <= MemoryLayout<Input>.size)\n\n        let leftMask = Input(Left.max)\n        let rightMask = Input(Right.max)\n        let right = input & rightMask\n        let left = (input >> Right.bitWidth) & leftMask\n\n        assert(input.nonzeroBitCount == left.nonzeroBitCount + right.nonzeroBitCount)\n        return (Left(left), Right(right))\n    }\n}\n\n@usableFromInline\nenum IntegerBitPacking: Sendable {}\n\nextension IntegerBitPacking {\n    @inlinable\n    static func packUInt32UInt16UInt8(_ left: UInt32, _ middle: UInt16, _ right: UInt8) -> UInt64 {\n        _IntegerBitPacking.packUU(\n            _IntegerBitPacking.packUU(right, middle, type: UInt32.self),\n            left\n        )\n    }\n\n    @inlinable\n    static func unpackUInt32UInt16UInt8(_ value: UInt64) -> (UInt32, UInt16, UInt8) {\n        let leftRight = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self)\n        let left = _IntegerBitPacking.unpackUU(leftRight.0, leftType: UInt8.self, rightType: UInt16.self)\n        return (leftRight.1, left.1, left.0)\n    }\n\n    @inlinable\n    static func packUInt8UInt8(_ left: UInt8, _ right: UInt8) -> UInt16 {\n        _IntegerBitPacking.packUU(left, right)\n    }\n\n    @inlinable\n    static func unpackUInt8UInt8(_ value: UInt16) -> (UInt8, UInt8) {\n        _IntegerBitPacking.unpackUU(value)\n    }\n\n    @inlinable\n    static func packUInt16UInt8(_ left: UInt16, _ right: UInt8) -> UInt32 {\n        _IntegerBitPacking.packUU(left, right)\n    }\n\n    @inlinable\n    static func unpackUInt16UInt8(_ value: UInt32) -> (UInt16, UInt8) {\n        _IntegerBitPacking.unpackUU(value)\n    }\n\n    @inlinable\n    static func packUInt32CInt(_ left: UInt32, _ right: CInt) -> UInt64 {\n        _IntegerBitPacking.packUU(left, UInt32(truncatingIfNeeded: right))\n    }\n\n    @inlinable\n    static func unpackUInt32CInt(_ value: UInt64) -> (UInt32, CInt) {\n        let unpacked = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self)\n        return (unpacked.0, CInt(truncatingIfNeeded: unpacked.1))\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/IntegerTypes.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// MARK: _UInt24\n\n// FIXME: Duplicated in NIO.\n\n/// A 24-bit unsigned integer value type.\n@usableFromInline\nstruct _UInt24: Sendable {\n    @usableFromInline var _backing: (UInt16, UInt8)\n\n    @inlinable\n    init(_ value: UInt32) {\n        assert(value & 0xff_00_00_00 == 0, \"value \\(value) too large for _UInt24\")\n        self._backing = IntegerBitPacking.unpackUInt16UInt8(value)\n    }\n\n    @inlinable\n    static var bitWidth: Int { 24 }\n\n    @inlinable\n    static var max: _UInt24 { .init((UInt32(1) << 24) - 1) }\n\n    @inlinable\n    static var min: _UInt24 { .init(0) }\n}\n\nextension UInt32 {\n    @inlinable\n    init(_ value: _UInt24) {\n        self = IntegerBitPacking.packUInt16UInt8(value._backing.0, value._backing.1)\n    }\n}\n\nextension Int {\n    @inlinable\n    init(_ value: _UInt24) {\n        self = Int(UInt32(value))\n    }\n}\n\nextension _UInt24: Equatable {\n    @inlinable\n    public static func == (lhs: _UInt24, rhs: _UInt24) -> Bool {\n        lhs._backing == rhs._backing\n    }\n}\n\nextension _UInt24: CustomStringConvertible {\n    @usableFromInline\n    var description: String {\n        UInt32(self).description\n    }\n}\n\n// MARK: _UInt56\n\n/// A 56-bit unsigned integer value type.\nstruct _UInt56: Sendable {\n    @usableFromInline var _backing: (UInt32, UInt16, UInt8)\n\n    @inlinable init(_ value: UInt64) {\n        self._backing = IntegerBitPacking.unpackUInt32UInt16UInt8(value)\n    }\n\n    @inlinable\n    static var bitWidth: Int { 56 }\n\n    @inlinable\n    static var initializeUInt64: UInt64 { (1 << 56) - 1 }\n    @inlinable\n    static var max: _UInt56 { .init(initializeUInt64) }\n    @inlinable\n    static var min: _UInt56 { .init(0) }\n}\n\nextension _UInt56 {\n    init(_ value: Int) {\n        self.init(UInt64(value))\n    }\n}\n\nextension UInt64 {\n    init(_ value: _UInt56) {\n        self = IntegerBitPacking.packUInt32UInt16UInt8(\n            value._backing.0,\n            value._backing.1,\n            value._backing.2\n        )\n    }\n}\n\nextension Int {\n    init(_ value: _UInt56) {\n        self = Int(UInt64(value))\n    }\n}\n\nextension _UInt56: Equatable {\n    @inlinable\n    public static func == (lhs: _UInt56, rhs: _UInt56) -> Bool {\n        lhs._backing == rhs._backing\n    }\n}\n\nextension _UInt56: CustomStringConvertible {\n    var description: String {\n        UInt64(self).description\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/Interfaces.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#if os(Linux) || os(FreeBSD) || os(Android)\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#endif\nimport CNIOLinux\n#elseif os(OpenBSD)\nimport CNIOOpenBSD\n#elseif canImport(Darwin)\nimport Darwin\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#elseif os(Windows)\nimport let WinSDK.AF_INET\nimport let WinSDK.AF_INET6\n\nimport let WinSDK.INET_ADDRSTRLEN\nimport let WinSDK.INET6_ADDRSTRLEN\n\nimport struct WinSDK.ADDRESS_FAMILY\nimport struct WinSDK.IP_ADAPTER_ADDRESSES\nimport struct WinSDK.IP_ADAPTER_UNICAST_ADDRESS\n\nimport struct WinSDK.sockaddr\nimport struct WinSDK.sockaddr_in\nimport struct WinSDK.sockaddr_in6\nimport struct WinSDK.sockaddr_storage\nimport struct WinSDK.sockaddr_un\n\nimport typealias WinSDK.UINT8\n#else\n#error(\"The Core interfaces module was unable to identify your C library.\")\n#endif\n\n#if !os(Windows) && !os(WASI)\nextension ifaddrs {\n    fileprivate var dstaddr: UnsafeMutablePointer<sockaddr>? {\n        #if os(Linux) || os(Android)\n        return self.ifa_ifu.ifu_dstaddr\n        #elseif canImport(Darwin) || os(OpenBSD)\n        return self.ifa_dstaddr\n        #endif\n    }\n\n    fileprivate var broadaddr: UnsafeMutablePointer<sockaddr>? {\n        #if os(Linux) || os(Android)\n        return self.ifa_ifu.ifu_broadaddr\n        #elseif canImport(Darwin) || os(OpenBSD)\n        return self.ifa_dstaddr\n        #endif\n    }\n}\n#endif\n\n/// A representation of a single network interface on a system.\n@available(*, deprecated, renamed: \"NIONetworkDevice\")\npublic final class NIONetworkInterface: Sendable {\n    // This is a class because in almost all cases this will carry\n    // four structs that are backed by classes, and so will incur 4\n    // refcount operations each time it is copied.\n\n    /// The name of the network interface.\n    public let name: String\n\n    /// The address associated with the given network interface.\n    public let address: SocketAddress\n\n    /// The netmask associated with this address, if any.\n    public let netmask: SocketAddress?\n\n    /// The broadcast address associated with this socket interface, if it has one. Some\n    /// interfaces do not, especially those that have a `pointToPointDestinationAddress`.\n    public let broadcastAddress: SocketAddress?\n\n    /// The address of the peer on a point-to-point interface, if this is one. Some\n    /// interfaces do not have such an address: most of those have a `broadcastAddress`\n    /// instead.\n    public let pointToPointDestinationAddress: SocketAddress?\n\n    /// If the Interface supports Multicast\n    public let multicastSupported: Bool\n\n    /// The index of the interface, as provided by `if_nametoindex`.\n    public let interfaceIndex: Int\n\n    #if os(WASI)\n    @available(*, unavailable)\n    init() { fatalError() }\n    #endif\n\n    #if os(Windows)\n    internal init?(\n        _ pAdapter: UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>,\n        _ pAddress: UnsafeMutablePointer<IP_ADAPTER_UNICAST_ADDRESS>\n    ) {\n        self.name = String(\n            decodingCString: pAdapter.pointee.FriendlyName,\n            as: UTF16.self\n        )\n        guard let address = pAddress.pointee.Address.lpSockaddr.convert() else {\n            return nil\n        }\n        self.address = address\n\n        switch pAddress.pointee.Address.lpSockaddr.pointee.sa_family {\n        case ADDRESS_FAMILY(AF_INET):\n            self.netmask = SocketAddress(ipv4MaskForPrefix: Int(pAddress.pointee.OnLinkPrefixLength))\n            self.interfaceIndex = Int(pAdapter.pointee.IfIndex)\n            break\n        case ADDRESS_FAMILY(AF_INET6):\n            self.netmask = SocketAddress(ipv6MaskForPrefix: Int(pAddress.pointee.OnLinkPrefixLength))\n            self.interfaceIndex = Int(pAdapter.pointee.Ipv6IfIndex)\n            break\n        default:\n            return nil\n        }\n\n        // TODO(compnerd) handle broadcast/ppp/multicast information\n        self.broadcastAddress = nil\n        self.pointToPointDestinationAddress = nil\n        self.multicastSupported = false\n    }\n    #elseif !os(WASI)\n    internal init?(_ caddr: ifaddrs) {\n        self.name = String(cString: caddr.ifa_name!)\n\n        guard caddr.ifa_addr != nil else {\n            return nil\n        }\n\n        guard let address = caddr.ifa_addr!.convert() else {\n            return nil\n        }\n        self.address = address\n\n        if let netmask = caddr.ifa_netmask {\n            self.netmask = netmask.convert()\n        } else {\n            self.netmask = nil\n        }\n\n        if (caddr.ifa_flags & UInt32(IFF_BROADCAST)) != 0, let addr = caddr.broadaddr {\n            self.broadcastAddress = addr.convert()\n            self.pointToPointDestinationAddress = nil\n        } else if (caddr.ifa_flags & UInt32(IFF_POINTOPOINT)) != 0, let addr = caddr.dstaddr {\n            self.broadcastAddress = nil\n            self.pointToPointDestinationAddress = addr.convert()\n        } else {\n            self.broadcastAddress = nil\n            self.pointToPointDestinationAddress = nil\n        }\n\n        if (caddr.ifa_flags & UInt32(IFF_MULTICAST)) != 0 {\n            self.multicastSupported = true\n        } else {\n            self.multicastSupported = false\n        }\n\n        do {\n            self.interfaceIndex = Int(try SystemCalls.if_nametoindex(caddr.ifa_name))\n        } catch {\n            return nil\n        }\n    }\n    #endif\n}\n\n@available(*, deprecated, renamed: \"NIONetworkDevice\")\nextension NIONetworkInterface: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        let baseString = \"Interface \\(self.name): address \\(self.address)\"\n        let maskString = self.netmask != nil ? \" netmask \\(self.netmask!)\" : \"\"\n        return baseString + maskString\n    }\n}\n\n@available(*, deprecated, renamed: \"NIONetworkDevice\")\nextension NIONetworkInterface: Equatable {\n    public static func == (lhs: NIONetworkInterface, rhs: NIONetworkInterface) -> Bool {\n        lhs.name == rhs.name && lhs.address == rhs.address && lhs.netmask == rhs.netmask\n            && lhs.broadcastAddress == rhs.broadcastAddress\n            && lhs.pointToPointDestinationAddress == rhs.pointToPointDestinationAddress\n            && lhs.interfaceIndex == rhs.interfaceIndex\n    }\n}\n\n/// A helper extension for working with sockaddr pointers.\nextension UnsafeMutablePointer where Pointee == sockaddr {\n    /// Converts the `sockaddr` to a `SocketAddress`.\n    fileprivate func convert() -> SocketAddress? {\n        let addressBytes = UnsafeRawPointer(self)\n        switch NIOBSDSocket.AddressFamily(rawValue: CInt(pointee.sa_family)) {\n        case .inet:\n            return SocketAddress(addressBytes.load(as: sockaddr_in.self))\n        case .inet6:\n            return SocketAddress(addressBytes.load(as: sockaddr_in6.self))\n        case .unix:\n            return SocketAddress(addressBytes.load(as: sockaddr_un.self))\n        default:\n            return nil\n        }\n    }\n}\n\n/// A representation of a single network device on a system.\npublic struct NIONetworkDevice {\n    private var backing: Backing\n\n    /// The name of the network device.\n    public var name: String {\n        get {\n            self.backing.name\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.name = newValue\n        }\n    }\n\n    /// The address associated with the given network device.\n    public var address: SocketAddress? {\n        get {\n            self.backing.address\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.address = newValue\n        }\n    }\n\n    /// The netmask associated with this address, if any.\n    public var netmask: SocketAddress? {\n        get {\n            self.backing.netmask\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.netmask = newValue\n        }\n    }\n\n    /// The broadcast address associated with this socket interface, if it has one. Some\n    /// interfaces do not, especially those that have a `pointToPointDestinationAddress`.\n    public var broadcastAddress: SocketAddress? {\n        get {\n            self.backing.broadcastAddress\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.broadcastAddress = newValue\n        }\n    }\n\n    /// The address of the peer on a point-to-point interface, if this is one. Some\n    /// interfaces do not have such an address: most of those have a `broadcastAddress`\n    /// instead.\n    public var pointToPointDestinationAddress: SocketAddress? {\n        get {\n            self.backing.pointToPointDestinationAddress\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.pointToPointDestinationAddress = newValue\n        }\n    }\n\n    /// If the Interface supports Multicast\n    public var multicastSupported: Bool {\n        get {\n            self.backing.multicastSupported\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.multicastSupported = newValue\n        }\n    }\n\n    /// The index of the interface, as provided by `if_nametoindex`.\n    public var interfaceIndex: Int {\n        get {\n            self.backing.interfaceIndex\n        }\n        set {\n            self.uniquifyIfNeeded()\n            self.backing.interfaceIndex = newValue\n        }\n    }\n\n    /// Create a brand new network interface.\n    ///\n    /// This constructor will fail if NIO does not understand the format of the underlying\n    /// socket address family. This is quite common: for example, Linux will return AF_PACKET\n    /// addressed interfaces on most platforms, which NIO does not currently understand.\n    #if os(Windows)\n    internal init?(\n        _ pAdapter: UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>,\n        _ pAddress: UnsafeMutablePointer<IP_ADAPTER_UNICAST_ADDRESS>\n    ) {\n        guard let backing = Backing(pAdapter, pAddress) else {\n            return nil\n        }\n        self.backing = backing\n    }\n    #elseif !os(WASI)\n    internal init?(_ caddr: ifaddrs) {\n        guard let backing = Backing(caddr) else {\n            return nil\n        }\n\n        self.backing = backing\n    }\n    #endif\n\n    #if !os(Windows) && !os(WASI)\n    /// Convert a `NIONetworkInterface` to a `NIONetworkDevice`. As `NIONetworkDevice`s are a superset of `NIONetworkInterface`s,\n    /// it is always possible to perform this conversion.\n    @available(*, deprecated, message: \"This is a compatibility helper, and will be removed in a future release\")\n    public init(_ interface: NIONetworkInterface) {\n        self.backing = Backing(\n            name: interface.name,\n            address: interface.address,\n            netmask: interface.netmask,\n            broadcastAddress: interface.broadcastAddress,\n            pointToPointDestinationAddress: interface.pointToPointDestinationAddress,\n            multicastSupported: interface.multicastSupported,\n            interfaceIndex: interface.interfaceIndex\n        )\n    }\n    #endif\n\n    public init(\n        name: String,\n        address: SocketAddress?,\n        netmask: SocketAddress?,\n        broadcastAddress: SocketAddress?,\n        pointToPointDestinationAddress: SocketAddress,\n        multicastSupported: Bool,\n        interfaceIndex: Int\n    ) {\n        self.backing = Backing(\n            name: name,\n            address: address,\n            netmask: netmask,\n            broadcastAddress: broadcastAddress,\n            pointToPointDestinationAddress: pointToPointDestinationAddress,\n            multicastSupported: multicastSupported,\n            interfaceIndex: interfaceIndex\n        )\n    }\n\n    private mutating func uniquifyIfNeeded() {\n        if !isKnownUniquelyReferenced(&self.backing) {\n            self.backing = Backing(copying: self.backing)\n        }\n    }\n}\n\nextension NIONetworkDevice: @unchecked Sendable {}\n\nextension NIONetworkDevice {\n    fileprivate final class Backing {\n        /// The name of the network interface.\n        var name: String\n\n        /// The address associated with the given network interface.\n        var address: SocketAddress?\n\n        /// The netmask associated with this address, if any.\n        var netmask: SocketAddress?\n\n        /// The broadcast address associated with this socket interface, if it has one. Some\n        /// interfaces do not, especially those that have a `pointToPointDestinationAddress`.\n        var broadcastAddress: SocketAddress?\n\n        /// The address of the peer on a point-to-point interface, if this is one. Some\n        /// interfaces do not have such an address: most of those have a `broadcastAddress`\n        /// instead.\n        var pointToPointDestinationAddress: SocketAddress?\n\n        /// If the Interface supports Multicast\n        var multicastSupported: Bool\n\n        /// The index of the interface, as provided by `if_nametoindex`.\n        var interfaceIndex: Int\n\n        /// Create a brand new network interface.\n        ///\n        /// This constructor will fail if NIO does not understand the format of the underlying\n        /// socket address family. This is quite common: for example, Linux will return AF_PACKET\n        /// addressed interfaces on most platforms, which NIO does not currently understand.\n        #if os(Windows)\n        internal init?(\n            _ pAdapter: UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>,\n            _ pAddress: UnsafeMutablePointer<IP_ADAPTER_UNICAST_ADDRESS>\n        ) {\n            self.name = String(\n                decodingCString: pAdapter.pointee.FriendlyName,\n                as: UTF16.self\n            )\n            self.address = pAddress.pointee.Address.lpSockaddr.convert()\n\n            switch pAddress.pointee.Address.lpSockaddr.pointee.sa_family {\n            case ADDRESS_FAMILY(AF_INET):\n                self.netmask = SocketAddress(ipv4MaskForPrefix: Int(pAddress.pointee.OnLinkPrefixLength))\n                self.interfaceIndex = Int(pAdapter.pointee.IfIndex)\n                break\n            case ADDRESS_FAMILY(AF_INET6):\n                self.netmask = SocketAddress(ipv6MaskForPrefix: Int(pAddress.pointee.OnLinkPrefixLength))\n                self.interfaceIndex = Int(pAdapter.pointee.Ipv6IfIndex)\n                break\n            default:\n                return nil\n            }\n\n            // TODO(compnerd) handle broadcast/ppp/multicast information\n            self.broadcastAddress = nil\n            self.pointToPointDestinationAddress = nil\n            self.multicastSupported = false\n        }\n        #elseif !os(WASI)\n        internal init?(_ caddr: ifaddrs) {\n            self.name = String(cString: caddr.ifa_name!)\n            self.address = caddr.ifa_addr.flatMap { $0.convert() }\n            self.netmask = caddr.ifa_netmask.flatMap { $0.convert() }\n\n            if (caddr.ifa_flags & UInt32(IFF_BROADCAST)) != 0, let addr = caddr.broadaddr {\n                self.broadcastAddress = addr.convert()\n                self.pointToPointDestinationAddress = nil\n            } else if (caddr.ifa_flags & UInt32(IFF_POINTOPOINT)) != 0, let addr = caddr.dstaddr {\n                self.broadcastAddress = nil\n                self.pointToPointDestinationAddress = addr.convert()\n            } else {\n                self.broadcastAddress = nil\n                self.pointToPointDestinationAddress = nil\n            }\n\n            self.multicastSupported = (caddr.ifa_flags & UInt32(IFF_MULTICAST)) != 0\n            do {\n                self.interfaceIndex = Int(try SystemCalls.if_nametoindex(caddr.ifa_name))\n            } catch {\n                return nil\n            }\n        }\n        #endif\n\n        init(copying original: Backing) {\n            self.name = original.name\n            self.address = original.address\n            self.netmask = original.netmask\n            self.broadcastAddress = original.broadcastAddress\n            self.pointToPointDestinationAddress = original.pointToPointDestinationAddress\n            self.multicastSupported = original.multicastSupported\n            self.interfaceIndex = original.interfaceIndex\n        }\n\n        init(\n            name: String,\n            address: SocketAddress?,\n            netmask: SocketAddress?,\n            broadcastAddress: SocketAddress?,\n            pointToPointDestinationAddress: SocketAddress?,\n            multicastSupported: Bool,\n            interfaceIndex: Int\n        ) {\n            self.name = name\n            self.address = address\n            self.netmask = netmask\n            self.broadcastAddress = broadcastAddress\n            self.pointToPointDestinationAddress = pointToPointDestinationAddress\n            self.multicastSupported = multicastSupported\n            self.interfaceIndex = interfaceIndex\n        }\n    }\n}\n\nextension NIONetworkDevice: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        let baseString = \"Device \\(self.name): address \\(String(describing: self.address))\"\n        let maskString = self.netmask != nil ? \" netmask \\(self.netmask!)\" : \"\"\n        return baseString + maskString\n    }\n}\n\n// Sadly, as this is class-backed we cannot synthesise the implementation.\nextension NIONetworkDevice: Equatable {\n    public static func == (lhs: NIONetworkDevice, rhs: NIONetworkDevice) -> Bool {\n        lhs.name == rhs.name && lhs.address == rhs.address && lhs.netmask == rhs.netmask\n            && lhs.broadcastAddress == rhs.broadcastAddress\n            && lhs.pointToPointDestinationAddress == rhs.pointToPointDestinationAddress\n            && lhs.interfaceIndex == rhs.interfaceIndex\n    }\n}\n\nextension NIONetworkDevice: Hashable {\n    public func hash(into hasher: inout Hasher) {\n        hasher.combine(self.name)\n        hasher.combine(self.address)\n        hasher.combine(self.netmask)\n        hasher.combine(self.broadcastAddress)\n        hasher.combine(self.pointToPointDestinationAddress)\n        hasher.combine(self.interfaceIndex)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/Linux.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// This is a companion to System.swift that provides only Linux specials: either things that exist\n// only on Linux, or things that have Linux-specific extensions.\n\n#if os(Linux) || os(Android)\nimport CNIOLinux\n\n#if canImport(Android)\n@preconcurrency import Android\n#endif\n\nenum Linux {\n    static let cfsQuotaPath = \"/sys/fs/cgroup/cpu/cpu.cfs_quota_us\"\n    static let cfsPeriodPath = \"/sys/fs/cgroup/cpu/cpu.cfs_period_us\"\n    static let cfsCpuMaxPath = \"/sys/fs/cgroup/cpu.max\"\n\n    static let cpuSetPathV1 = \"/sys/fs/cgroup/cpuset/cpuset.cpus\"\n    static let cpuSetPathV2: String? = {\n        if let cgroupV2MountPoint = Self.cgroupV2MountPoint {\n            return \"\\(cgroupV2MountPoint)/cpuset.cpus\"\n        }\n        return nil\n    }()\n\n    static let cgroupV2MountPoint: String? = {\n        guard\n            let fd = try? SystemCalls.open(file: \"/proc/self/cgroup\", oFlag: O_RDONLY, mode: NIOPOSIXFileMode(S_IRUSR))\n        else { return nil }\n        defer { try! SystemCalls.close(descriptor: fd) }\n        guard let lines = try? Self.readLines(descriptor: fd) else { return nil }\n\n        // Parse each line looking for cgroup v2 format: \"0::/path\"\n        for line in lines {\n            if let cgroupPath = Self.parseV2CgroupLine(line) {\n                return \"/sys/fs/cgroup\\(cgroupPath)\"\n            }\n        }\n\n        return nil\n    }()\n\n    /// Returns the appropriate cpuset path based on the detected cgroup version\n    static let cpuSetPath: String? = {\n        guard let version = Self.cgroupVersion else { return nil }\n\n        switch version {\n        case .v1:\n            return cpuSetPathV1\n        case .v2:\n            return cpuSetPathV2\n        }\n    }()\n\n    /// Detects whether we're using cgroup v1 or v2\n    static let cgroupVersion: CgroupVersion? = {\n        guard let type = try? SystemCalls.statfs_ftype(\"/sys/fs/cgroup\") else { return nil }\n\n        switch type {\n        case CNIOLinux_TMPFS_MAGIC:\n            return .v1\n        case CNIOLinux_CGROUP2_SUPER_MAGIC:\n            return .v2\n        default:\n            return nil\n        }\n    }()\n\n    enum CgroupVersion {\n        case v1\n        case v2\n    }\n\n    /// Parses a single line from /proc/self/cgroup to extract cgroup v2 path\n    internal static func parseV2CgroupLine(_ line: Substring) -> String? {\n        // Expected format is \"0::/path\"\n        let parts = line.split(separator: \":\", maxSplits: 2, omittingEmptySubsequences: false)\n\n        guard parts.count == 3,\n            parts[0] == \"0\",\n            parts[1] == \"\"\n        else {\n            return nil\n        }\n\n        // Extract the path from parts[2]\n        return String(parts[2])\n    }\n\n    private static func readLines(descriptor: CInt) throws -> [Substring] {\n        // linux doesn't properly report /sys/fs/cgroup/* files lengths so we use a reasonable limit\n        var buf = ByteBufferAllocator().buffer(capacity: 1024)\n        try buf.writeWithUnsafeMutableBytes(minimumWritableBytes: buf.capacity) { ptr in\n            let res = try SystemCalls.read(descriptor: descriptor, pointer: ptr.baseAddress!, size: ptr.count)\n\n            switch res {\n            case .processed(let n):\n                return n\n            case .wouldBlock:\n                preconditionFailure(\"read returned EWOULDBLOCK despite a blocking fd\")\n            }\n        }\n        return String(buffer: buf).split(separator: \"\\n\")\n    }\n\n    private static func firstLineOfFile(path: String) throws -> Substring? {\n        guard let fd = try? SystemCalls.open(file: path, oFlag: O_RDONLY, mode: NIOPOSIXFileMode(S_IRUSR)) else {\n            return nil\n        }\n        defer { try! SystemCalls.close(descriptor: fd) }\n        return try? Self.readLines(descriptor: fd).first\n    }\n\n    private static func countCoreIds(cores: Substring) -> Int {\n        let ids = cores.split(separator: \"-\", maxSplits: 1)\n        guard\n            let first = ids.first.flatMap({ Int($0, radix: 10) }),\n            let last = ids.last.flatMap({ Int($0, radix: 10) }),\n            last >= first\n        else { preconditionFailure(\"cpuset format is incorrect\") }\n        return 1 + last - first\n    }\n\n    static func coreCount(cpuset cpusetPath: String) -> Int? {\n        guard\n            let cpuset = try? firstLineOfFile(path: cpusetPath).flatMap({ $0.split(separator: \",\") }),\n            !cpuset.isEmpty\n        else { return nil }\n        return cpuset.map(countCoreIds).reduce(0, +)\n    }\n\n    /// Get the available core count according to cgroup1 restrictions.\n    /// Round up to the next whole number.\n    static func coreCountCgroup1Restriction(\n        quota quotaPath: String = Linux.cfsQuotaPath,\n        period periodPath: String = Linux.cfsPeriodPath\n    ) -> Int? {\n        guard\n            let quota = try? firstLineOfFile(path: quotaPath).flatMap({ Int($0) }),\n            quota > 0\n        else { return nil }\n        guard\n            let period = try? firstLineOfFile(path: periodPath).flatMap({ Int($0) }),\n            period > 0\n        else { return nil }\n        return (quota - 1 + period) / period  // always round up if fractional CPU quota requested\n    }\n\n    /// Get the available core count according to cgroup2 restrictions.\n    /// Round up to the next whole number.\n    static func coreCountCgroup2Restriction(cpuMaxPath: String = Linux.cfsCpuMaxPath) -> Int? {\n        guard let maxDetails = try? firstLineOfFile(path: cpuMaxPath),\n            let spaceIndex = maxDetails.firstIndex(of: \" \"),\n            let quota = Int(maxDetails[maxDetails.startIndex..<spaceIndex]),\n            let period = Int(maxDetails[maxDetails.index(after: spaceIndex)..<maxDetails.endIndex])\n        else { return nil }\n        return (quota - 1 + period) / period  // always round up if fractional CPU quota requested\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCore/MarkedCircularBuffer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A circular buffer that allows one object at a time to be \"marked\" and easily identified and retrieved later.\n///\n/// This object is used extensively within SwiftNIO to handle flushable buffers. It can be used to store buffered\n/// writes and mark how far through the buffer the user has flushed, and therefore how far through the buffer is\n/// safe to write.\npublic struct MarkedCircularBuffer<Element>: CustomStringConvertible {\n    @usableFromInline internal var _buffer: CircularBuffer<Element>\n    @usableFromInline internal var _markedIndexOffset: Int?  // nil: nothing marked\n\n    /// Create a new instance.\n    ///\n    /// - Parameters:\n    ///   - initialCapacity: The initial capacity of the internal storage.\n    @inlinable\n    public init(initialCapacity: Int) {\n        self._buffer = CircularBuffer(initialCapacity: initialCapacity)\n    }\n\n    // MARK: Forwarding\n\n    /// Appends an entry to the buffer, expanding it if needed.\n    @inlinable\n    public mutating func append(_ value: Element) {\n        self._buffer.append(value)\n    }\n\n    /// Removes the first element from the buffer.\n    @inlinable\n    public mutating func removeFirst() -> Element {\n        assert(self._buffer.count > 0)\n        return self.popFirst()!\n    }\n\n    @inlinable\n    public mutating func popFirst() -> Element? {\n        if let markedIndexOffset = self._markedIndexOffset {\n            if markedIndexOffset > 0 {\n                self._markedIndexOffset = markedIndexOffset - 1\n            } else {\n                self._markedIndexOffset = nil\n            }\n        }\n        return self._buffer.popFirst()\n    }\n\n    /// The first element in the buffer.\n    @inlinable\n    public var first: Element? {\n        self._buffer.first\n    }\n\n    /// If the buffer is empty.\n    @inlinable\n    public var isEmpty: Bool {\n        self._buffer.isEmpty\n    }\n\n    /// The number of elements in the buffer.\n    @inlinable\n    public var count: Int {\n        self._buffer.count\n    }\n\n    @inlinable\n    public var description: String {\n        self._buffer.description\n    }\n\n    // MARK: Marking\n\n    /// Marks the buffer at the current index, making the last index in the buffer marked.\n    @inlinable\n    public mutating func mark() {\n        let count = self._buffer.count\n        if count > 0 {\n            self._markedIndexOffset = count - 1\n        } else {\n            assert(self._markedIndexOffset == nil, \"marked index is \\(self._markedIndexOffset.debugDescription)\")\n        }\n    }\n\n    /// Returns true if the buffer is currently marked at the given index.\n    @inlinable\n    public func isMarked(index: Index) -> Bool {\n        assert(index >= self.startIndex, \"index must not be negative\")\n        precondition(index < self.endIndex, \"index \\(index) out of range (0..<\\(self._buffer.count))\")\n        if let markedIndexOffset = self._markedIndexOffset {\n            return self.index(self.startIndex, offsetBy: markedIndexOffset) == index\n        } else {\n            return false\n        }\n    }\n\n    /// Returns the index of the marked element.\n    @inlinable\n    public var markedElementIndex: Index? {\n        if let markedIndexOffset = self._markedIndexOffset {\n            assert(markedIndexOffset >= 0)\n            return self.index(self.startIndex, offsetBy: markedIndexOffset)\n        } else {\n            return nil\n        }\n    }\n\n    /// Returns the marked element.\n    @inlinable\n    public var markedElement: Element? {\n        self.markedElementIndex.map { self._buffer[$0] }\n    }\n\n    /// Returns true if the buffer has been marked at all.\n    @inlinable\n    public var hasMark: Bool {\n        self._markedIndexOffset != nil\n    }\n}\n\nextension MarkedCircularBuffer: Collection, MutableCollection {\n    public typealias RangeType<Bound> = Range<Bound> where Bound: Strideable, Bound.Stride: SignedInteger\n    public typealias Index = CircularBuffer<Element>.Index\n    public typealias SubSequence = CircularBuffer<Element>\n\n    @inlinable\n    public func index(after i: Index) -> Index {\n        self._buffer.index(after: i)\n    }\n\n    @inlinable\n    public var startIndex: Index { self._buffer.startIndex }\n\n    @inlinable\n    public var endIndex: Index { self._buffer.endIndex }\n\n    /// Retrieves the element at the given index from the buffer, without removing it.\n    @inlinable\n    public subscript(index: Index) -> Element {\n        get {\n            self._buffer[index]\n        }\n        set {\n            self._buffer[index] = newValue\n        }\n    }\n\n    @inlinable\n    public subscript(bounds: Range<Index>) -> SubSequence {\n        get {\n            self._buffer[bounds]\n        }\n        set {\n            var index = bounds.lowerBound\n            var iterator = newValue.makeIterator()\n            while let newElement = iterator.next(), index != bounds.upperBound {\n                self._buffer[index] = newElement\n                formIndex(after: &index)\n            }\n            precondition(iterator.next() == nil && index == bounds.upperBound)\n        }\n    }\n}\n\nextension MarkedCircularBuffer: RandomAccessCollection {\n    @inlinable\n    public func index(_ i: Index, offsetBy distance: Int) -> Index {\n        self._buffer.index(i, offsetBy: distance)\n    }\n\n    @inlinable\n    public func distance(from start: Index, to end: Index) -> Int {\n        self._buffer.distance(from: start, to: end)\n    }\n\n    @inlinable\n    public func index(before i: Index) -> Index {\n        self._buffer.index(before: i)\n    }\n\n}\n\nextension MarkedCircularBuffer: Sendable where Element: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/MulticastChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A `MulticastChannel` is a `Channel` that supports IP multicast operations: that is, a channel that can join multicast\n/// groups.\n///\n/// - Note: As with `Channel`, all operations on a `MulticastChannel` are thread-safe.\npublic protocol MulticastChannel: Channel {\n    /// Request that the `MulticastChannel` join the multicast group given by `group`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    func joinGroup(_ group: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    #if !os(Windows) && !os(WASI)\n    /// Request that the `MulticastChannel` join the multicast group given by `group` on the interface\n    /// given by `interface`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - interface: The interface on which to join the given group, or `nil` to allow the kernel to choose.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    @available(*, deprecated, renamed: \"joinGroup(_:device:promise:)\")\n    func joinGroup(_ group: SocketAddress, interface: NIONetworkInterface?, promise: EventLoopPromise<Void>?)\n    #endif\n\n    /// Request that the `MulticastChannel` join the multicast group given by `group` on the device\n    /// given by `device`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - device: The device on which to join the given group, or `nil` to allow the kernel to choose.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    func joinGroup(_ group: SocketAddress, device: NIONetworkDevice?, promise: EventLoopPromise<Void>?)\n\n    /// Request that the `MulticastChannel` leave the multicast group given by `group`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    func leaveGroup(_ group: SocketAddress, promise: EventLoopPromise<Void>?)\n\n    #if !os(Windows) && !os(WASI)\n    /// Request that the `MulticastChannel` leave the multicast group given by `group` on the interface\n    /// given by `interface`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - interface: The interface on which to leave the given group, or `nil` to allow the kernel to choose.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    @available(*, deprecated, renamed: \"leaveGroup(_:device:promise:)\")\n    func leaveGroup(_ group: SocketAddress, interface: NIONetworkInterface?, promise: EventLoopPromise<Void>?)\n    #endif\n\n    /// Request that the `MulticastChannel` leave the multicast group given by `group` on the device\n    /// given by `device`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - device: The device on which to leave the given group, or `nil` to allow the kernel to choose.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    func leaveGroup(_ group: SocketAddress, device: NIONetworkDevice?, promise: EventLoopPromise<Void>?)\n}\n\n// MARK:- Default implementations for MulticastChannel\nextension MulticastChannel {\n    public func joinGroup(_ group: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.joinGroup(group, device: nil, promise: promise)\n    }\n\n    public func joinGroup(_ group: SocketAddress) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.joinGroup(group, promise: promise)\n        return promise.futureResult\n    }\n\n    #if !os(Windows) && !os(WASI)\n    @available(*, deprecated, renamed: \"joinGroup(_:device:)\")\n    public func joinGroup(_ group: SocketAddress, interface: NIONetworkInterface?) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.joinGroup(group, interface: interface, promise: promise)\n        return promise.futureResult\n    }\n    #endif\n\n    public func joinGroup(_ group: SocketAddress, device: NIONetworkDevice?) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.joinGroup(group, device: device, promise: promise)\n        return promise.futureResult\n    }\n\n    public func leaveGroup(_ group: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.leaveGroup(group, device: nil, promise: promise)\n    }\n\n    public func leaveGroup(_ group: SocketAddress) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.leaveGroup(group, promise: promise)\n        return promise.futureResult\n    }\n\n    #if !os(Windows) && !os(WASI)\n    @available(*, deprecated, renamed: \"leaveGroup(_:device:)\")\n    public func leaveGroup(_ group: SocketAddress, interface: NIONetworkInterface?) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.leaveGroup(group, interface: interface, promise: promise)\n        return promise.futureResult\n    }\n    #endif\n\n    public func leaveGroup(_ group: SocketAddress, device: NIONetworkDevice?) -> EventLoopFuture<Void> {\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.leaveGroup(group, device: device, promise: promise)\n        return promise.futureResult\n    }\n}\n\n// MARK:- API Compatibility shims for MulticastChannel\nextension MulticastChannel {\n    /// Request that the `MulticastChannel` join the multicast group given by `group` on the device\n    /// given by `device`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - device: The device on which to join the given group, or `nil` to allow the kernel to choose.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    public func joinGroup(_ group: SocketAddress, device: NIONetworkDevice?, promise: EventLoopPromise<Void>?) {\n        // We just fail this in the default implementation. Users should override it.\n        promise?.fail(NIOMulticastNotImplementedError())\n    }\n\n    /// Request that the `MulticastChannel` leave the multicast group given by `group` on the device\n    /// given by `device`.\n    ///\n    /// - Parameters:\n    ///   - group: The IP address corresponding to the relevant multicast group.\n    ///   - device: The device on which to leave the given group, or `nil` to allow the kernel to choose.\n    ///   - promise: The `EventLoopPromise` that will be notified once the operation is complete, or\n    ///         `nil` if you are not interested in the result of the operation.\n    public func leaveGroup(_ group: SocketAddress, device: NIONetworkDevice?, promise: EventLoopPromise<Void>?) {\n        // We just fail this in the default implementation. Users should override it.\n        promise?.fail(NIOMulticastNotImplementedError())\n    }\n}\n\n/// Multicast is not supported on this interface.\npublic struct NIOMulticastNotSupportedError: Error {\n    public var device: NIONetworkDevice\n\n    public init(device: NIONetworkDevice) {\n        self.device = device\n    }\n}\n\n/// Multicast has not been properly implemented on this channel.\npublic struct NIOMulticastNotImplementedError: Error {\n    public init() {}\n}\n"
  },
  {
    "path": "Sources/NIOCore/NIOAny.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// `NIOAny` is an opaque container for values of *any* type, similar to Swift's builtin `Any` type. Contrary to\n/// `Any` the overhead of `NIOAny` depends on the the type of the wrapped value. Certain types that are important\n/// for the performance of a SwiftNIO application like `ByteBuffer`, `FileRegion` and `AddressEnvelope<ByteBuffer>` can be expected\n/// to be wrapped almost without overhead. All others will have similar performance as if they were passed as an `Any` as\n/// `NIOAny` just like `Any` will contain them within an existential container.\n///\n/// The most important use-cases for `NIOAny` are values travelling through the `ChannelPipeline` whose type can't\n/// be calculated at compile time. For example:\n///\n///  - the `channelRead` of any `ChannelInboundHandler`\n///  - the `write` method of a `ChannelOutboundHandler`\n///\n/// The abstraction that delivers a `NIOAny` to user code must provide a mechanism to unwrap a `NIOAny` as a\n/// certain type known at run-time. Canonical example:\n///\n///     class SandwichHandler: ChannelInboundHandler {\n///         typealias InboundIn = Bacon /* we expected to be delivered `Bacon` ... */\n///         typealias InboundOut = Sandwich /* ... and we will make and deliver a `Sandwich` from that */\n///\n///         func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n///              /* we receive the `Bacon` as a `NIOAny` as at compile-time the exact configuration of the channel\n///                 pipeline can't be computed. The pipeline can't be computed at compile time as it can change\n///                 dynamically at run-time. Yet, we assert that in any configuration the channel handler before\n///                 `SandwichHandler` does actually send us a stream of `Bacon`.\n///              */\n///              let bacon = Self.unwrapInboundIn(data) /* `Bacon` or crash */\n///              let sandwich = makeSandwich(bacon)\n///              context.fireChannelRead(Self.wrapInboundOut(sandwich)) /* as promised we deliver a wrapped `Sandwich` */\n///         }\n///     }\npublic struct NIOAny {\n    @usableFromInline\n    let _storage: _NIOAny\n\n    /// Wrap a value in a `NIOAny`. In most cases you should not create a `NIOAny` directly using this constructor.\n    /// The abstraction that accepts values of type `NIOAny` must also provide a mechanism to do the wrapping. An\n    /// example is a `ChannelInboundHandler` which provides `Self.wrapInboundOut(aValueOfTypeInboundOut)`.\n    @inlinable\n    public init<T>(_ value: T) {\n        self._storage = _NIOAny(value)\n    }\n\n    @usableFromInline\n    enum _NIOAny {\n        case ioData(IOData)\n        case bufferEnvelope(AddressedEnvelope<ByteBuffer>)\n        case other(Any)\n\n        @inlinable\n        init<T>(_ value: T) {\n            switch value {\n            case let value as ByteBuffer:\n                self = .ioData(.byteBuffer(value))\n            case let value as FileRegion:\n                self = .ioData(.fileRegion(value))\n            case let value as IOData:\n                self = .ioData(value)\n            case let value as AddressedEnvelope<ByteBuffer>:\n                self = .bufferEnvelope(value)\n            default:\n                assert(!(value is NIOAny))\n                self = .other(value)\n            }\n        }\n    }\n\n    /// Try unwrapping the wrapped message as `ByteBuffer`.\n    ///\n    /// - Returns: The wrapped `ByteBuffer` or `nil` if the wrapped message is not a `ByteBuffer`.\n    @inlinable\n    func tryAsByteBuffer() -> ByteBuffer? {\n        if case .ioData(.byteBuffer(let bb)) = self._storage {\n            return bb\n        } else {\n            return nil\n        }\n    }\n\n    /// Force unwrapping the wrapped message as `ByteBuffer`.\n    ///\n    /// - Returns: The wrapped `ByteBuffer` or crash if the wrapped message is not a `ByteBuffer`.\n    @inlinable\n    func forceAsByteBuffer() -> ByteBuffer {\n        if let v = tryAsByteBuffer() {\n            return v\n        } else {\n            fatalError(\n                \"tried to decode as type \\(ByteBuffer.self) but found \\(Mirror(reflecting: Mirror(reflecting: self._storage).children.first!.value).subjectType) with contents \\(self._storage)\"\n            )\n        }\n    }\n\n    /// Try unwrapping the wrapped message as `IOData`.\n    ///\n    /// - Returns: The wrapped `IOData` or `nil` if the wrapped message is not a `IOData`.\n    @inlinable\n    func tryAsIOData() -> IOData? {\n        if case .ioData(let data) = self._storage {\n            return data\n        } else {\n            return nil\n        }\n    }\n\n    /// Force unwrapping the wrapped message as `IOData`.\n    ///\n    /// - Returns: The wrapped `IOData` or crash if the wrapped message is not a `IOData`.\n    @inlinable\n    func forceAsIOData() -> IOData {\n        if let v = tryAsIOData() {\n            return v\n        } else {\n            fatalError(\n                \"tried to decode as type \\(IOData.self) but found \\(Mirror(reflecting: Mirror(reflecting: self._storage).children.first!.value).subjectType) with contents \\(self._storage)\"\n            )\n        }\n    }\n\n    /// Try unwrapping the wrapped message as `FileRegion`.\n    ///\n    /// - Returns: The wrapped `FileRegion` or `nil` if the wrapped message is not a `FileRegion`.\n    @inlinable\n    func tryAsFileRegion() -> FileRegion? {\n        if case .ioData(.fileRegion(let f)) = self._storage {\n            return f\n        } else {\n            return nil\n        }\n    }\n\n    /// Force unwrapping the wrapped message as `FileRegion`.\n    ///\n    /// - Returns: The wrapped `FileRegion` or crash if the wrapped message is not a `FileRegion`.\n    @inlinable\n    func forceAsFileRegion() -> FileRegion {\n        if let v = tryAsFileRegion() {\n            return v\n        } else {\n            fatalError(\n                \"tried to decode as type \\(FileRegion.self) but found \\(Mirror(reflecting: Mirror(reflecting: self._storage).children.first!.value).subjectType) with contents \\(self._storage)\"\n            )\n        }\n    }\n\n    /// Try unwrapping the wrapped message as `AddressedEnvelope<ByteBuffer>`.\n    ///\n    /// - Returns: The wrapped `AddressedEnvelope<ByteBuffer>` or `nil` if the wrapped message is not an `AddressedEnvelope<ByteBuffer>`.\n    @inlinable\n    func tryAsByteEnvelope() -> AddressedEnvelope<ByteBuffer>? {\n        if case .bufferEnvelope(let e) = self._storage {\n            return e\n        } else {\n            return nil\n        }\n    }\n\n    /// Force unwrapping the wrapped message as `AddressedEnvelope<ByteBuffer>`.\n    ///\n    /// - Returns: The wrapped `AddressedEnvelope<ByteBuffer>` or crash if the wrapped message is not an `AddressedEnvelope<ByteBuffer>`.\n    @inlinable\n    func forceAsByteEnvelope() -> AddressedEnvelope<ByteBuffer> {\n        if let e = tryAsByteEnvelope() {\n            return e\n        } else {\n            fatalError(\n                \"tried to decode as type \\(AddressedEnvelope<ByteBuffer>.self) but found \\(Mirror(reflecting: Mirror(reflecting: self._storage).children.first!.value).subjectType) with contents \\(self._storage)\"\n            )\n        }\n    }\n\n    /// Try unwrapping the wrapped message as `T`.\n    ///\n    /// - Returns: The wrapped `T` or `nil` if the wrapped message is not a `T`.\n    @inlinable\n    func tryAsOther<T>(type: T.Type = T.self) -> T? {\n        switch self._storage {\n        case .bufferEnvelope(let v):\n            return v as? T\n        case .ioData(let v):\n            return v as? T\n        case .other(let v):\n            return v as? T\n        }\n    }\n\n    /// Force unwrapping the wrapped message as `T`.\n    ///\n    /// - Returns: The wrapped `T` or crash if the wrapped message is not a `T`.\n    @inlinable\n    func forceAsOther<T>(type: T.Type = T.self) -> T {\n        if let v = tryAsOther(type: type) {\n            return v\n        } else {\n            fatalError(\n                \"tried to decode as type \\(T.self) but found \\(Mirror(reflecting: Mirror(reflecting: self._storage).children.first!.value).subjectType) with contents \\(self._storage)\"\n            )\n        }\n    }\n\n    /// Force unwrapping the wrapped message as `T`.\n    ///\n    /// - Returns: The wrapped `T` or crash if the wrapped message is not a `T`.\n    @inlinable\n    func forceAs<T>(type: T.Type = T.self) -> T {\n        switch T.self {\n        case let t where t == ByteBuffer.self:\n            return self.forceAsByteBuffer() as! T\n        case let t where t == FileRegion.self:\n            return self.forceAsFileRegion() as! T\n        case let t where t == IOData.self:\n            return self.forceAsIOData() as! T\n        case let t where t == AddressedEnvelope<ByteBuffer>.self:\n            return self.forceAsByteEnvelope() as! T\n        default:\n            return self.forceAsOther(type: type)\n        }\n    }\n\n    /// Try unwrapping the wrapped message as `T`.\n    ///\n    /// - Returns: The wrapped `T` or `nil` if the wrapped message is not a `T`.\n    @inlinable\n    func tryAs<T>(type: T.Type = T.self) -> T? {\n        switch T.self {\n        case let t where t == ByteBuffer.self:\n            return self.tryAsByteBuffer() as! T?\n        case let t where t == FileRegion.self:\n            return self.tryAsFileRegion() as! T?\n        case let t where t == IOData.self:\n            return self.tryAsIOData() as! T?\n        case let t where t == AddressedEnvelope<ByteBuffer>.self:\n            return self.tryAsByteEnvelope() as! T?\n        default:\n            return self.tryAsOther(type: type)\n        }\n    }\n\n    /// Unwrap the wrapped message.\n    ///\n    /// - Returns: The wrapped message.\n    @inlinable\n    func asAny() -> Any {\n        switch self._storage {\n        case .ioData(.byteBuffer(let bb)):\n            return bb\n        case .ioData(.fileRegion(let f)):\n            return f\n        case .bufferEnvelope(let e):\n            return e\n        case .other(let o):\n            return o\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIOAny._NIOAny: Sendable {}\n\n@available(*, unavailable)\nextension NIOAny: Sendable {}\n\nextension NIOAny: CustomStringConvertible {\n    public var description: String {\n        \"\\(type(of: self.asAny())): \\(self.asAny())\"\n    }\n}\n\nextension NIOAny: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        \"(\\(self.description))\"\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/NIOCloseOnErrorHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A `ChannelInboundHandler` that closes the channel when an error is caught\npublic final class NIOCloseOnErrorHandler: ChannelInboundHandler, Sendable {\n\n    public typealias InboundIn = NIOAny\n\n    /// Initialize a `NIOCloseOnErrorHandler`\n    public init() {}\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        context.fireErrorCaught(error)\n        context.close(promise: nil)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/NIOCoreSendableMetatype.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if compiler(>=6.2)\npublic typealias _NIOCoreSendableMetatype = SendableMetatype\n#else\npublic typealias _NIOCoreSendableMetatype = Any\n#endif\n"
  },
  {
    "path": "Sources/NIOCore/NIODecodedAsyncSequence.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence where Element == ByteBuffer {\n    /// Decode the `AsyncSequence<ByteBuffer>` into a sequence of `Element`s,\n    /// using the `Decoder`, where `Decoder.InboundOut` matches `Element`.\n    ///\n    /// Usage:\n    /// ```swift\n    /// let myDecoder = MyNIOSingleStepByteToMessageDecoder()\n    /// let baseSequence = MyAsyncSequence<ByteBuffer>(...)\n    /// let decodedSequence = baseSequence.decode(using: myDecoder)\n    ///\n    /// for try await element in decodedSequence {\n    ///     print(\"Decoded an element!\", element)\n    /// }\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - decoder: The `Decoder` to use to decode the ``ByteBuffer``s.\n    ///   - maximumBufferSize: The maximum number of bytes to aggregate in-memory.\n    ///     An error will be thrown if after decoding an element there is more aggregated data than this amount.\n    /// - Returns: A ``NIODecodedAsyncSequence`` that decodes the ``ByteBuffer``s into a sequence of `Element`s.\n    @inlinable\n    public func decode<Decoder: NIOSingleStepByteToMessageDecoder>(\n        using decoder: Decoder,\n        maximumBufferSize: Int? = nil\n    ) -> NIODecodedAsyncSequence<Self, Decoder> {\n        NIODecodedAsyncSequence(\n            asyncSequence: self,\n            decoder: decoder,\n            maximumBufferSize: maximumBufferSize\n        )\n    }\n}\n\n/// A type that decodes an `AsyncSequence<ByteBuffer>` into a sequence of ``Element``s,\n/// using the `Decoder`, where `Decoder.InboundOut` matches ``Element``.\n///\n/// Use `AsyncSequence/decode(using:maximumBufferSize:)` to create a ``NIODecodedAsyncSequence``.\n///\n/// Usage:\n/// ```swift\n/// let myDecoder = MyNIOSingleStepByteToMessageDecoder()\n/// let baseSequence = MyAsyncSequence<ByteBuffer>(...)\n/// let decodedSequence = baseSequence.decode(using: myDecoder)\n///\n/// for try await element in decodedSequence {\n///     print(\"Decoded an element!\", element)\n/// }\n/// ```\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct NIODecodedAsyncSequence<\n    Base: AsyncSequence,\n    Decoder: NIOSingleStepByteToMessageDecoder\n> where Base.Element == ByteBuffer {\n    @usableFromInline\n    var asyncSequence: Base\n    @usableFromInline\n    var decoder: Decoder\n    @usableFromInline\n    var maximumBufferSize: Int?\n\n    @inlinable\n    init(asyncSequence: Base, decoder: Decoder, maximumBufferSize: Int? = nil) {\n        self.asyncSequence = asyncSequence\n        self.decoder = decoder\n        self.maximumBufferSize = maximumBufferSize\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIODecodedAsyncSequence: AsyncSequence {\n    public typealias Element = Decoder.InboundOut\n\n    /// Create an ``AsyncIterator`` for this ``NIODecodedAsyncSequence``.\n    @inlinable\n    public func makeAsyncIterator() -> AsyncIterator {\n        AsyncIterator(base: self)\n    }\n\n    /// An ``AsyncIterator`` over a ``NIODecodedAsyncSequence``.\n    public struct AsyncIterator: AsyncIteratorProtocol {\n        @usableFromInline\n        enum State: Sendable {\n            case canReadFromBaseIterator\n            case baseIteratorIsExhausted\n            case finishedDecoding\n        }\n\n        @usableFromInline\n        var baseIterator: Base.AsyncIterator\n        @usableFromInline\n        var processor: NIOSingleStepByteToMessageProcessor<Decoder>\n        @usableFromInline\n        var state: State\n\n        @inlinable\n        init(base: NIODecodedAsyncSequence) {\n            self.baseIterator = base.asyncSequence.makeAsyncIterator()\n            self.processor = NIOSingleStepByteToMessageProcessor(\n                base.decoder,\n                maximumBufferSize: base.maximumBufferSize\n            )\n            self.state = .canReadFromBaseIterator\n        }\n\n        /// Retrieve the next element from the ``NIODecodedAsyncSequence``.\n        ///\n        /// The same as `next(isolation:)` but not isolated to an actor, which allows\n        /// for less availability restrictions.\n        @inlinable\n        public mutating func next() async throws -> Element? {\n            while true {\n                switch self.state {\n                case .finishedDecoding:\n                    return nil\n                case .canReadFromBaseIterator:\n                    let (decoded, ended) = try self.processor.decodeNext(\n                        decodeMode: .normal,\n                        seenEOF: false\n                    )\n\n                    // We expect `decodeNext()` to only return `ended == true` only if we've notified it\n                    // that we've read the last chunk from the buffer, using `decodeMode: .last`.\n                    assert(!ended)\n\n                    if let decoded {\n                        return decoded\n                    }\n\n                    // Read more data into the buffer so we can decode more messages\n                    guard let nextBuffer = try await self.baseIterator.next() else {\n                        // Ran out of data to read.\n                        self.state = .baseIteratorIsExhausted\n                        continue\n                    }\n                    self.processor.append(nextBuffer)\n                case .baseIteratorIsExhausted:\n                    let (decoded, ended) = try self.processor.decodeNext(\n                        decodeMode: .last,\n                        seenEOF: true\n                    )\n\n                    if ended {\n                        self.state = .finishedDecoding\n                    }\n\n                    return decoded\n                }\n            }\n\n            fatalError(\"Unreachable code\")\n        }\n\n        /// Retrieve the next element from the ``NIODecodedAsyncSequence``.\n        ///\n        /// The same as `next()` but isolated to an actor.\n        @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n        @inlinable\n        public mutating func next(isolation actor: isolated (any Actor)? = #isolation) async throws -> Element? {\n            while true {\n                switch self.state {\n                case .finishedDecoding:\n                    return nil\n                case .canReadFromBaseIterator:\n                    let (decoded, ended) = try self.processor.decodeNext(\n                        decodeMode: .normal,\n                        seenEOF: false\n                    )\n\n                    // We expect `decodeNext()` to only return `ended == true` only if we've notified it\n                    // that we've read the last chunk from the buffer, using `decodeMode: .last`.\n                    assert(!ended)\n\n                    if let decoded {\n                        return decoded\n                    }\n\n                    // Read more data into the buffer so we can decode more messages\n                    guard let nextBuffer = try await self.baseIterator.next(isolation: actor) else {\n                        // Ran out of data to read.\n                        self.state = .baseIteratorIsExhausted\n                        continue\n                    }\n                    self.processor.append(nextBuffer)\n                case .baseIteratorIsExhausted:\n                    let (decoded, ended) = try self.processor.decodeNext(\n                        decodeMode: .last,\n                        seenEOF: true\n                    )\n\n                    if ended {\n                        self.state = .finishedDecoding\n                    }\n\n                    return decoded\n                }\n            }\n\n            fatalError(\"Unreachable code\")\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIODecodedAsyncSequence: Sendable where Base: Sendable, Decoder: Sendable {}\n\n@available(*, unavailable)\nextension NIODecodedAsyncSequence.AsyncIterator: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/NIOLoopBound.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// ``NIOLoopBound`` is an always-`Sendable`, value-typed container allowing you access to ``value`` if and only if\n/// you are accessing it on the right ``EventLoop``.\n///\n/// ``NIOLoopBound`` is useful to transport a value of a non-`Sendable` type that needs to go from one place in\n/// your code to another where you (but not the compiler) know is on one and the same ``EventLoop``. Usually this\n/// involves `@Sendable` closures. This type is safe because it verifies (using ``EventLoop/preconditionInEventLoop(file:line:)-2fxvb``)\n/// that this is actually true.\n///\n/// A ``NIOLoopBound`` can only be constructed, read from or written to when you are provably\n/// (through ``EventLoop/preconditionInEventLoop(file:line:)-2fxvb``) on the ``EventLoop`` associated with the ``NIOLoopBound``. Accessing\n/// or constructing it from any other place will crash your program with a precondition as it would be undefined\n/// behaviour to do so.\npublic struct NIOLoopBound<Value>: @unchecked Sendable {\n    /// The ``EventLoop`` that the value is bound to.\n    public let eventLoop: EventLoop\n\n    @available(*, deprecated, renamed: \"eventLoop\")\n    public var _eventLoop: EventLoop {\n        self.eventLoop\n    }\n\n    @usableFromInline\n    var _value: Value\n\n    /// Initialise a ``NIOLoopBound`` to `value` with the precondition that the code is running on `eventLoop`.\n    @inlinable\n    public init(_ value: Value, eventLoop: EventLoop) {\n        eventLoop.preconditionInEventLoop()\n        self.eventLoop = eventLoop\n        self._value = value\n    }\n\n    /// Access the `value` with the precondition that the code is running on `eventLoop`.\n    ///\n    /// - Note: ``NIOLoopBound`` itself is value-typed, so any writes will only affect the current value.\n    @inlinable\n    public var value: Value {\n        get {\n            self.eventLoop.preconditionInEventLoop()\n            return self._value\n        }\n        _modify {\n            self.eventLoop.preconditionInEventLoop()\n            yield &self._value\n        }\n    }\n}\n\n/// ``NIOLoopBoundBox`` is an always-`Sendable`, reference-typed container allowing you access to ``value`` if and\n/// only if you are accessing it on the right ``EventLoop``.\n///\n/// ``NIOLoopBoundBox`` is useful to transport a value of a non-`Sendable` type that needs to go from one place in\n/// your code to another where you (but not the compiler) know is on one and the same ``EventLoop``. Usually this\n/// involves `@Sendable` closures. This type is safe because it verifies (using ``EventLoop/preconditionInEventLoop(file:line:)-7ukrq``)\n/// that this is actually true.\n///\n/// A ``NIOLoopBoundBox`` can only be read from or written to when you are provably\n/// (through ``EventLoop/preconditionInEventLoop(file:line:)-2fxvb``) on the ``EventLoop`` associated with the ``NIOLoopBoundBox``. Accessing\n/// or constructing it from any other place will crash your program with a precondition as it would be undefined\n/// behaviour to do so.\n///\n/// If constructing a ``NIOLoopBoundBox`` with a `value`, it is also required for the program to already be on `eventLoop`\n/// but if you have a ``NIOLoopBoundBox`` that contains an `Optional` type, you may initialise it _without a value_\n/// whilst off the ``EventLoop`` by using ``NIOLoopBoundBox/makeEmptyBox(valueType:eventLoop:)``. Any read/write access to ``value``\n/// afterwards will require you to be on `eventLoop`.\npublic final class NIOLoopBoundBox<Value>: @unchecked Sendable {\n    /// The ``EventLoop`` that the value is bound to.\n    public let eventLoop: EventLoop\n\n    @available(*, deprecated, renamed: \"eventLoop\")\n    public var _eventLoop: EventLoop {\n        self.eventLoop\n    }\n\n    @usableFromInline\n    var _value: Value\n\n    @inlinable\n    internal init(_value value: Value, uncheckedEventLoop eventLoop: EventLoop) {\n        self.eventLoop = eventLoop\n        self._value = value\n    }\n\n    /// Initialise a ``NIOLoopBoundBox`` to `value` with the precondition that the code is running on `eventLoop`.\n    @inlinable\n    public convenience init(_ value: Value, eventLoop: EventLoop) {\n        // This precondition is absolutely required. If not, it were possible to take a non-Sendable `Value` from\n        // _off_ the ``EventLoop`` and transport it _to_ the ``EventLoop``. That would be illegal.\n        eventLoop.preconditionInEventLoop()\n        self.init(_value: value, uncheckedEventLoop: eventLoop)\n    }\n\n    /// Initialise a ``NIOLoopBoundBox`` that is empty (contains `nil`), this does _not_ require you to be running on `eventLoop`.\n    public static func makeEmptyBox<NonOptionalValue>(\n        valueType: NonOptionalValue.Type = NonOptionalValue.self,\n        eventLoop: EventLoop\n    ) -> NIOLoopBoundBox<Value> where NonOptionalValue? == Value {\n        // Here, we -- possibly surprisingly -- do not precondition being on the EventLoop. This is okay for a few\n        // reasons:\n        // - We write the `Optional.none` value which we know is _not_ a value of the potentially non-Sendable type\n        //   `Value`.\n        // - Because of Swift's Definitive Initialisation (DI), we know that we did write `self._value` before `init`\n        //   returns.\n        // - The only way to ever write (or read indeed) `self._value` is by proving to be inside the `EventLoop`.\n        .init(_value: nil, uncheckedEventLoop: eventLoop)\n    }\n\n    /// Initialise a ``NIOLoopBoundBox`` by sending a `Sendable` value, validly callable off `eventLoop`.\n    ///\n    /// Contrary to ``init(_:eventLoop:)``, this method can be called off `eventLoop` because we know that `value` is `Sendable`.\n    /// So we don't need to protect `value` itself, we just need to protect the ``NIOLoopBoundBox`` against mutations which we do because the ``value``\n    /// accessors are checking that we're on `eventLoop`.\n    public static func makeBoxSendingValue(\n        _ value: Value,\n        as: Value.Type = Value.self,\n        eventLoop: EventLoop\n    ) -> NIOLoopBoundBox<Value> where Value: Sendable {\n        // Here, we -- possibly surprisingly -- do not precondition being on the EventLoop. This is okay for a few\n        // reasons:\n        // - This function only works with `Sendable` values, so we don't need to worry about somebody\n        //   still holding a reference to this.\n        // - Because of Swift's Definitive Initialisation (DI), we know that we did write `self._value` before `init`\n        //   returns.\n        // - The only way to ever write (or read indeed) `self._value` is by proving to be inside the `EventLoop`.\n        .init(_value: value, uncheckedEventLoop: eventLoop)\n    }\n\n    /// Initialise a ``NIOLoopBoundBox`` by sending a  value, validly callable off `eventLoop`.\n    ///\n    /// Contrary to ``init(_:eventLoop:)``, this method can be called off `eventLoop` because `value` is moved into the box and can no longer be accessed outside the box.\n    /// So we don't need to protect `value` itself, we just need to protect the ``NIOLoopBoundBox`` against mutations which we do because the ``value``\n    /// accessors are checking that we're on `eventLoop`.\n    public static func makeBoxSendingValue(\n        _ value: sending Value,\n        as: Value.Type = Value.self,\n        eventLoop: EventLoop\n    ) -> NIOLoopBoundBox<Value> {\n        // Here, we -- possibly surprisingly -- do not precondition being on the EventLoop. This is okay for a few\n        // reasons:\n        // - This function takes its value as `sending` so we don't need to worry about somebody\n        //   still holding a reference to this.\n        // - Because of Swift's Definitive Initialisation (DI), we know that we did write `self._value` before `init`\n        //   returns.\n        // - The only way to ever write (or read indeed) `self._value` is by proving to be inside the `EventLoop`.\n        .init(_value: value, uncheckedEventLoop: eventLoop)\n    }\n\n    /// Access the `value` with the precondition that the code is running on `eventLoop`.\n    ///\n    /// - Note: ``NIOLoopBoundBox`` itself is reference-typed, so any writes will affect anybody sharing this reference.\n    @inlinable\n    public var value: Value {\n        get {\n            self.eventLoop.preconditionInEventLoop()\n            return self._value\n        }\n        _modify {\n            self.eventLoop.preconditionInEventLoop()\n            yield &self._value\n        }\n    }\n\n    /// Safely access and potentially modify the contained value with a closure.\n    ///\n    /// This method provides a way to perform operations on the contained value while ensuring\n    /// thread safety through EventLoop verification. The closure receives an `inout` parameter\n    /// allowing both read and write access to the value.\n    ///\n    /// - Parameter handler: A closure that receives an `inout` reference to the contained value.\n    ///   The closure can read from and write to this value. Any modifications made within the\n    ///   closure will be reflected in the box after the closure completes, even if the closure throws.\n    /// - Returns: The value returned by the `handler` closure.\n    /// - Note: This method is particularly useful when you need to perform read and write operations\n    ///         on the value because it reduces the on EventLoop checks.\n    @inlinable\n    public func withValue<Success, Failure: Error>(\n        _ handler: (inout Value) throws(Failure) -> Success\n    ) throws(Failure) -> Success {\n        self.eventLoop.preconditionInEventLoop()\n        return try handler(&self._value)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/NIOPooledRecvBufferAllocator.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A receive buffer allocator which cycles through a pool of buffers.\n///\n/// Channels can read multiple times per cycle (based on `ChannelOptions.maxMessagesPerRead`), and they reuse\n/// the inbound buffer for each read. If a `ChannelHandler` holds onto this buffer, then CoWing will be needed.\n/// A `NIOPooledRecvBufferAllocator` cycles through preallocated buffers to avoid CoWs during the same read cycle.\npublic struct NIOPooledRecvBufferAllocator: Sendable {\n    // The pool will either use a single buffer (i.e. `buffer`) OR store multiple buffers\n    // in `buffers`. If `buffers` is non-empty then `buffer` MUST be `nil`. If `buffer`\n    // is non-nil then `buffers` MUST be empty.\n    //\n    // The backing storage is changed from `buffer` to `buffers` when a second buffer is\n    // needed (and if capacity allows).\n    @usableFromInline\n    internal var _buffer: Optional<ByteBuffer>\n    @usableFromInline\n    internal var _buffers: [ByteBuffer]\n    /// The index into `buffers` of the index which was last used.\n    @usableFromInline\n    internal var _lastUsedIndex: Int\n\n    /// Maximum number of buffers to store in the pool.\n    public private(set) var capacity: Int\n    /// The receive allocator providing hints for the next buffer size to use.\n    public var recvAllocator: RecvByteBufferAllocator\n\n    /// The return value from the last call to `recvAllocator.record(actualReadBytes:)`.\n    @usableFromInline\n    internal var _mayGrow: Bool\n\n    /// Builds a new instance of `NIOPooledRecvBufferAllocator`\n    ///\n    /// - Parameters:\n    ///   - capacity: Maximum number of buffers to store in the pool.\n    ///   - recvAllocator: The receive allocator providing hints for the next buffer size to use.\n    public init(capacity: Int, recvAllocator: RecvByteBufferAllocator) {\n        precondition(capacity > 0)\n        self.capacity = capacity\n        self._buffer = nil\n        self._buffers = []\n        self._lastUsedIndex = 0\n        self.recvAllocator = recvAllocator\n        self._mayGrow = false\n    }\n\n    /// Returns the number of buffers in the pool.\n    public var count: Int {\n        if self._buffer == nil {\n            // Empty or switched to `buffers` for storage.\n            return self._buffers.count\n        } else {\n            // `buffer` is non-nil; `buffers` must be empty and the count must be 1.\n            assert(self._buffers.isEmpty)\n            return 1\n        }\n    }\n\n    /// Update the capacity of the underlying buffer pool.\n    ///\n    /// - Parameters:\n    ///   - newCapacity: The new capacity for the underlying buffer pool.\n    public mutating func updateCapacity(to newCapacity: Int) {\n        precondition(newCapacity > 0)\n\n        if newCapacity > self.capacity {\n            self.capacity = newCapacity\n            if !self._buffers.isEmpty {\n                self._buffers.reserveCapacity(newCapacity)\n            }\n        } else if newCapacity < self.capacity {\n            self.capacity = newCapacity\n            // Drop buffers if over capacity.\n            while self._buffers.count > self.capacity {\n                self._buffers.removeLast()\n            }\n            // Reset the last used index.\n            if self._lastUsedIndex >= self.capacity {\n                self._lastUsedIndex = 0\n            }\n        }\n    }\n\n    /// Record the number of bytes which were read.\n    ///\n    /// - Parameters:\n    ///   - actualReadBytes: Number of bytes being recorded\n    public mutating func record(actualReadBytes: Int) {\n        self._mayGrow = self.recvAllocator.record(actualReadBytes: actualReadBytes)\n    }\n\n    /// Provides a buffer with enough writable capacity as determined by the underlying\n    /// receive allocator to the given closure.\n    ///\n    /// - Parameters:\n    ///    - allocator: `ByteBufferAllocator` used to construct a new buffer if needed\n    ///    - body: Closure where the caller can use the new or existing buffer\n    /// - Returns: A tuple containing the `ByteBuffer` used and the `Result` yielded by the closure provided.\n    @inlinable\n    public mutating func buffer<Result>(\n        allocator: ByteBufferAllocator,\n        _ body: (inout ByteBuffer) throws -> Result\n    ) rethrows -> (ByteBuffer, Result) {\n        // Reuse an existing buffer if we can do so without CoWing.\n        if let bufferAndResult = try self._reuseExistingBuffer(body) {\n            return bufferAndResult\n        } else {\n            // No available buffers or the allocator does not offer up buffer sizes; directly\n            // allocate a new one.\n            return try self._allocateNewBuffer(using: allocator, body)\n        }\n    }\n\n    @inlinable\n    internal mutating func _reuseExistingBuffer<Result>(\n        _ body: (inout ByteBuffer) throws -> Result\n    ) rethrows -> (ByteBuffer, Result)? {\n        if let nextBufferSize = self.recvAllocator.nextBufferSize() {\n            if let result = try self._buffer?._modifyIfUniquelyOwned(minimumCapacity: nextBufferSize, body) {\n                // `result` can only be non-nil if `buffer` is non-nil.\n                return (self._buffer!, result)\n            } else {\n                // Cycle through the buffers starting at the last used buffer.\n                let resultAndIndex = try self._buffers._loopingFirstIndexWithResult(startingAt: self._lastUsedIndex) {\n                    buffer in\n                    try buffer._modifyIfUniquelyOwned(minimumCapacity: nextBufferSize, body)\n                }\n\n                if let (result, index) = resultAndIndex {\n                    self._lastUsedIndex = index\n                    return (self._buffers[index], result)\n                }\n            }\n        } else if self._buffer != nil, !self._mayGrow {\n            // No hint about the buffer size (so pooling is not being used) and the allocator\n            // indicated that the next buffer will not grow in size so reuse the existing stored\n            // buffer.\n            self._buffer!.clear()\n            let result = try body(&self._buffer!)\n            return (self._buffer!, result)\n        }\n\n        // Couldn't reuse an existing buffer.\n        return nil\n    }\n\n    @inlinable\n    internal mutating func _allocateNewBuffer<Result>(\n        using allocator: ByteBufferAllocator,\n        _ body: (inout ByteBuffer) throws -> Result\n    ) rethrows -> (ByteBuffer, Result) {\n        // Couldn't reuse a buffer; create a new one and store it if there's capacity.\n        var newBuffer = self.recvAllocator.buffer(allocator: allocator)\n\n        if let buffer = self._buffer {\n            assert(self._buffers.isEmpty)\n            // We have a stored buffer, either:\n            // 1. We have capacity to add more and use `buffers` for storage, or\n            // 2. Our capacity is 1; we can't use `buffers` for storage.\n            if self.capacity > 1 {\n                self._buffer = nil\n                self._buffers.reserveCapacity(self.capacity)\n                self._buffers.append(buffer)\n                self._buffers.append(newBuffer)\n                self._lastUsedIndex = self._buffers.index(before: self._buffers.endIndex)\n                return try self._modifyBuffer(atIndex: self._lastUsedIndex, body)\n            } else {\n                let result = try body(&newBuffer)\n                return (newBuffer, result)\n            }\n        } else {\n            // There's no stored buffer which could be due to:\n            // 1. this is the first buffer we allocate (i.e. buffers is empty, we already know\n            //    buffer is nil), or\n            // 2. we've already switched to using buffers for storage and it's not yet full, or\n            // 3. we've already switched to using buffers for storage and it's full.\n            if self._buffers.isEmpty {\n                self._buffer = newBuffer\n                let result = try body(&self._buffer!)\n                return (self._buffer!, result)\n            } else if self._buffers.count < self.capacity {\n                self._buffers.append(newBuffer)\n                self._lastUsedIndex = self._buffers.index(before: self._buffers.endIndex)\n                return try self._modifyBuffer(atIndex: self._lastUsedIndex, body)\n            } else {\n                let result = try body(&newBuffer)\n                return (newBuffer, result)\n            }\n        }\n    }\n\n    @inlinable\n    internal mutating func _modifyBuffer<Result>(\n        atIndex index: Int,\n        _ body: (inout ByteBuffer) throws -> Result\n    ) rethrows -> (ByteBuffer, Result) {\n        let result = try body(&self._buffers[index])\n        return (self._buffers[index], result)\n    }\n}\n\nextension ByteBuffer {\n    @inlinable\n    internal mutating func _modifyIfUniquelyOwned<Result>(\n        minimumCapacity: Int,\n        _ body: (inout ByteBuffer) throws -> Result\n    ) rethrows -> Result? {\n        try self.modifyIfUniquelyOwned { buffer in\n            buffer.clear(minimumCapacity: minimumCapacity)\n            return try body(&buffer)\n        }\n    }\n}\n\nextension Array {\n    /// Iterate over all elements in the array starting at the given index and looping back to the start\n    /// if the end is reached. The `body` is applied to each element and iteration is stopped when\n    /// `body` returns a non-nil value or all elements have been iterated.\n    ///\n    /// - Returns: The result and index of the first element passed to `body` which returned\n    ///   non-nil, or `nil` if no such element exists.\n    @inlinable\n    internal mutating func _loopingFirstIndexWithResult<Result>(\n        startingAt middleIndex: Index,\n        whereNonNil body: (inout Element) throws -> Result?\n    ) rethrows -> (Result, Index)? {\n        if let result = try self._firstIndexWithResult(in: middleIndex..<self.endIndex, whereNonNil: body) {\n            return result\n        }\n\n        return try self._firstIndexWithResult(in: self.startIndex..<middleIndex, whereNonNil: body)\n    }\n\n    @inlinable\n    internal mutating func _firstIndexWithResult<Result>(\n        in indices: Range<Index>,\n        whereNonNil body: (inout Element) throws -> Result?\n    ) rethrows -> (Result, Index)? {\n        for index in indices {\n            if let result = try body(&self[index]) {\n                return (result, index)\n            }\n        }\n        return nil\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/NIOScheduledCallback.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A type that handles callbacks scheduled with `EventLoop.scheduleCallback(at:handler:)`.\n///\n/// - Seealso: `EventLoop.scheduleCallback(at:handler:)`.\npublic protocol NIOScheduledCallbackHandler {\n    /// This function is called at the scheduled time, unless the scheduled callback is cancelled.\n    ///\n    /// - Parameter eventLoop: The event loop on which the callback was scheduled.\n    func handleScheduledCallback(eventLoop: some EventLoop)\n\n    /// This function is called if the scheduled callback is cancelled.\n    ///\n    /// The callback could be cancelled explictily, by the user calling ``NIOScheduledCallback/cancel()``, or\n    /// implicitly, if it was still pending when the event loop was shut down.\n    ///\n    /// - Parameter eventLoop: The event loop on which the callback was scheduled.\n    func didCancelScheduledCallback(eventLoop: some EventLoop)\n}\n\nextension NIOScheduledCallbackHandler {\n    /// Default implementation of `didCancelScheduledCallback(eventLoop:)`: does nothing.\n    public func didCancelScheduledCallback(eventLoop: some EventLoop) {}\n}\n\n/// An opaque handle that can be used to cancel a scheduled callback.\n///\n/// Users should not create an instance of this type; it is returned by `EventLoop.scheduleCallback(at:handler:)`.\n///\n/// - Seealso: `EventLoop.scheduleCallback(at:handler:)`.\npublic struct NIOScheduledCallback: Sendable {\n    @usableFromInline\n    enum Backing: Sendable {\n        /// A task created using `EventLoop.scheduleTask(deadline:_:)` by the default implementation.\n        case `default`(_ task: Scheduled<Void>)\n        /// A custom callback identifier, used by event loops that provide a custom implementation.\n        case custom(id: UInt64)\n    }\n\n    @usableFromInline\n    var eventLoop: any EventLoop\n\n    @usableFromInline\n    var backing: Backing\n\n    /// This initializer is only for the default implementation and is fileprivate to avoid use in EL implementations.\n    fileprivate init(_ eventLoop: any EventLoop, _ task: Scheduled<Void>) {\n        self.eventLoop = eventLoop\n        self.backing = .default(task)\n    }\n\n    /// Create a handle for the scheduled callback with an opaque identifier managed by the event loop.\n    ///\n    /// - NOTE: This initializer is for event loop implementors only, end users should use `EventLoop.scheduleCallback`.\n    ///\n    /// - Seealso: `EventLoop.scheduleCallback(at:handler:)`.\n    @inlinable\n    public init(_ eventLoop: any EventLoop, id: UInt64) {\n        self.eventLoop = eventLoop\n        self.backing = .custom(id: id)\n    }\n\n    /// Cancel the scheduled callback associated with this handle.\n    @inlinable\n    public func cancel() {\n        self.eventLoop.cancelScheduledCallback(self)\n    }\n\n    /// The callback identifier, if the event loop uses a custom scheduled callback implementation; nil otherwise.\n    ///\n    /// - NOTE: This property is for event loop implementors only.\n    @inlinable\n    public var customCallbackID: UInt64? {\n        guard case .custom(let id) = self.backing else { return nil }\n        return id\n    }\n}\n\nextension EventLoop {\n    @preconcurrency\n    /// This method is not part of the public API\n    ///\n    /// Should use `package` not `public` but then it won't compile in\n    /// Xcode 15.4 if you run `swift build --arch x86_64 --arch arm64`.\n    public func _scheduleCallback(\n        at deadline: NIODeadline,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) -> NIOScheduledCallback {\n        let task = self.scheduleTask(deadline: deadline) { handler.handleScheduledCallback(eventLoop: self) }\n        task.futureResult.whenFailure { error in\n            if case .cancelled = error as? EventLoopError {\n                handler.didCancelScheduledCallback(eventLoop: self)\n            }\n        }\n        return NIOScheduledCallback(self, task)\n    }\n\n    /// Default implementation of `scheduleCallback(at deadline:handler:)`: backed by `EventLoop.scheduleTask`.\n    ///\n    /// Ideally the scheduled callback handler should be called exactly once for each call to `scheduleCallback`:\n    /// either the callback handler, or the cancellation handler.\n    ///\n    /// In order to support cancellation in the default implementation, we hook the future of the scheduled task\n    /// backing the scheduled callback. This requires two calls to the event loop: `EventLoop.scheduleTask`, and\n    /// `EventLoopFuture.whenFailure`, both of which queue onto the event loop if called from off the event loop.\n    ///\n    /// This can present a challenge during event loop shutdown, where typically:\n    /// 1. Scheduled work that is past its deadline gets run.\n    /// 2. Scheduled future work gets cancelled.\n    /// 3. New work resulting from (1) and (2) gets handled differently depending on the EL:\n    ///   a. `SelectableEventLoop` runs new work recursively and crashes if not quiesced in some number of ticks.\n    ///   b. `EmbeddedEventLoop` and `NIOAsyncTestingEventLoop` will fail incoming work.\n    ///\n    /// `SelectableEventLoop` has a custom implementation for scheduled callbacks so warrants no further discussion.\n    ///\n    /// As a practical matter, the `EmbeddedEventLoop` is OK because it shares the thread of the caller, but for\n    /// other event loops (including any outside this repo), it's possible that the call to shutdown interleaves\n    /// with the call to create the scheduled task and the call to hook the task future.\n    ///\n    /// Because this API is synchronous and we cannot block the calling thread, users of event loops with this\n    /// default implementation will have cancellation callbacks delivered on a best-effort basis when the event loop\n    /// is shutdown and depends on how the event loop deals with newly scheduled tasks during shutdown.\n    ///\n    /// The implementation of this default conformance has been further factored out so we can use it in\n    /// `NIOAsyncTestingEventLoop`, where the use of `wait()` is _less bad_.\n    @preconcurrency\n    @discardableResult\n    public func scheduleCallback(\n        at deadline: NIODeadline,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) -> NIOScheduledCallback {\n        self._scheduleCallback(at: deadline, handler: handler)\n    }\n\n    /// Default implementation of `scheduleCallback(in amount:handler:)`: calls `scheduleCallback(at deadline:handler:)`.\n    @preconcurrency\n    @discardableResult\n    @inlinable\n    public func scheduleCallback(\n        in amount: TimeAmount,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) throws -> NIOScheduledCallback {\n        try self.scheduleCallback(at: .now() + amount, handler: handler)\n    }\n\n    /// Default implementation of `cancelScheduledCallback(_:)`: only cancels callbacks scheduled by the default implementation of `scheduleCallback`.\n    ///\n    /// - NOTE: Event loops that provide a custom scheduled callback implementation **must** implement _both_\n    ///         `sheduleCallback(at deadline:handler:)` _and_ `cancelScheduledCallback(_:)`. Failure to do so will\n    ///         result in a runtime error.\n    @inlinable\n    public func cancelScheduledCallback(_ scheduledCallback: NIOScheduledCallback) {\n        switch scheduledCallback.backing {\n        case .default(let task):\n            task.cancel()\n        case .custom:\n            preconditionFailure(\"EventLoop missing custom implementation of cancelScheduledCallback(_:)\")\n        }\n    }\n}\n\n@usableFromInline\nstruct LoopBoundScheduledCallbackHandlerWrapper<Handler: NIOScheduledCallbackHandler>:\n    NIOScheduledCallbackHandler, Sendable\n{\n    private let box: NIOLoopBound<Handler>\n\n    @usableFromInline\n    init(wrapping handler: Handler, eventLoop: some EventLoop) {\n        self.box = .init(handler, eventLoop: eventLoop)\n    }\n\n    @usableFromInline\n    func handleScheduledCallback(eventLoop: some EventLoop) {\n        self.box.value.handleScheduledCallback(eventLoop: eventLoop)\n    }\n\n    @usableFromInline\n    func didCancelScheduledCallback(eventLoop: some EventLoop) {\n        self.box.value.didCancelScheduledCallback(eventLoop: eventLoop)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/NIOSendable.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@available(*, deprecated, renamed: \"Sendable\")\npublic typealias NIOSendable = Swift.Sendable\n\n@preconcurrency public protocol _NIOPreconcurrencySendable: Sendable {}\n\n@available(*, deprecated, message: \"use @preconcurrency and Sendable directly\")\npublic typealias NIOPreconcurrencySendable = _NIOPreconcurrencySendable\n\n/// ``UnsafeTransfer`` can be used to make non-`Sendable` values `Sendable`.\n/// As the name implies, the usage of this is unsafe because it disables the sendable checking of the compiler.\n/// It can be used similar to `@unsafe Sendable` but for values instead of types.\n@usableFromInline\npackage struct UnsafeTransfer<Wrapped> {\n    @usableFromInline\n    package var wrappedValue: Wrapped\n\n    @inlinable\n    package init(_ wrappedValue: Wrapped) {\n        self.wrappedValue = wrappedValue\n    }\n}\n\nextension UnsafeTransfer: @unchecked Sendable {}\n\nextension UnsafeTransfer: Equatable where Wrapped: Equatable {}\nextension UnsafeTransfer: Hashable where Wrapped: Hashable {}\n\n/// ``UnsafeMutableTransferBox`` can be used to make non-`Sendable` values `Sendable` and mutable.\n/// It can be used to capture local mutable values in a `@Sendable` closure and mutate them from within the closure.\n/// As the name implies, the usage of this is unsafe because it disables the sendable checking of the compiler and does not add any synchronisation.\n@usableFromInline\npackage final class UnsafeMutableTransferBox<Wrapped> {\n    @usableFromInline\n    package var wrappedValue: Wrapped\n\n    @inlinable\n    package init(_ wrappedValue: Wrapped) {\n        self.wrappedValue = wrappedValue\n    }\n}\n\nextension UnsafeMutableTransferBox: @unchecked Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/NIOSplitLinesMessageDecoder.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence where Element == ByteBuffer {\n    /// Returns the longest possible subsequences of the sequence, in order,\n    /// that are separated by line breaks.\n    ///\n    /// The following Characters are considered line breaks, similar to\n    /// standard library's `String.split(whereSeparator: \\.isNewline)`:\n    /// - \"\\n\" (U+000A): LINE FEED (LF)\n    /// - U+000B: LINE TABULATION (VT)\n    /// - U+000C: FORM FEED (FF)\n    /// - \"\\r\" (U+000D): CARRIAGE RETURN (CR)\n    /// - \"\\r\\n\" (U+000D U+000A): CR-LF\n    ///\n    /// The following Characters are NOT considered line breaks, unlike in\n    /// standard library's `String.split(whereSeparator: \\.isNewline)`:\n    /// - U+0085: NEXT LINE (NEL)\n    /// - U+2028: LINE SEPARATOR\n    /// - U+2029: PARAGRAPH SEPARATOR\n    ///\n    /// This is because these characters would require unicode and data-encoding awareness, which\n    /// are outside swift-nio's scope.\n    ///\n    /// Usage:\n    /// ```swift\n    /// let baseSequence = MyAsyncSequence<ByteBuffer>(...)\n    /// let splitLinesSequence = baseSequence.splitLines()\n    ///\n    /// for try await buffer in splitLinesSequence {\n    ///     print(\"Split by line breaks!\\n\", buffer.hexDump(format: .detailed))\n    /// }\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - omittingEmptySubsequences: If `false`, an empty subsequence is\n    ///     returned in the result for each consecutive line break in the sequence.\n    ///     If `true`, only nonempty subsequences are returned. The default value is `true`.\n    ///   - maximumBufferSize: The maximum number of bytes to aggregate in-memory.\n    ///     An error will be thrown if after decoding an element there is more aggregated data than this amount.\n    /// - Returns: An `AsyncSequence` of ``ByteBuffer``s, split from the this async sequence's bytes.\n    ///\n    /// - Complexity: O(*n*), where *n* is the length of the file.\n    @inlinable\n    public func splitLines(\n        omittingEmptySubsequences: Bool = true,\n        maximumBufferSize: Int? = nil\n    ) -> NIODecodedAsyncSequence<Self, NIOSplitLinesMessageDecoder> {\n        self.decode(\n            using: NIOSplitLinesMessageDecoder(\n                omittingEmptySubsequences: omittingEmptySubsequences\n            ),\n            maximumBufferSize: maximumBufferSize\n        )\n    }\n\n    /// Returns the longest possible `String`s of the sequence, in order,\n    /// that are separated by line breaks.\n    ///\n    /// The following Characters are considered line breaks, similar to\n    /// standard library's `String.split(whereSeparator: \\.isNewline)`:\n    /// - \"\\n\" (U+000A): LINE FEED (LF)\n    /// - U+000B: LINE TABULATION (VT)\n    /// - U+000C: FORM FEED (FF)\n    /// - \"\\r\" (U+000D): CARRIAGE RETURN (CR)\n    /// - \"\\r\\n\" (U+000D U+000A): CR-LF\n    ///\n    /// The following Characters are NOT considered line breaks, unlike in\n    /// standard library's `String.split(whereSeparator: \\.isNewline)`:\n    /// - U+0085: NEXT LINE (NEL)\n    /// - U+2028: LINE SEPARATOR\n    /// - U+2029: PARAGRAPH SEPARATOR\n    ///\n    /// This is because these characters would require unicode and data-encoding awareness, which\n    /// are outside swift-nio's scope.\n    ///\n    /// Usage:\n    /// ```swift\n    /// let baseSequence = MyAsyncSequence<ByteBuffer>(...)\n    /// let splitLinesSequence = baseSequence.splitUTF8Lines()\n    ///\n    /// for try await string in splitLinesSequence {\n    ///     print(\"Split by line breaks!\\n\", string)\n    /// }\n    /// ```\n    ///\n    /// - Parameters:\n    ///   - omittingEmptySubsequences: If `false`, an empty subsequence is\n    ///     returned in the result for each consecutive line break in the sequence.\n    ///     If `true`, only nonempty subsequences are returned. The default value is `true`.\n    ///   - maximumBufferSize: The maximum number of bytes to aggregate in-memory.\n    ///     An error will be thrown if after decoding an element there is more aggregated data than this amount.\n    /// - Returns: An `AsyncSequence` of `String`s, split from the this async sequence's bytes.\n    ///\n    /// - Complexity: O(*n*), where *n* is the length of the file.\n    @inlinable\n    public func splitUTF8Lines(\n        omittingEmptySubsequences: Bool = true,\n        maximumBufferSize: Int? = nil\n    ) -> NIODecodedAsyncSequence<Self, NIOSplitUTF8LinesMessageDecoder> {\n        self.decode(\n            using: NIOSplitUTF8LinesMessageDecoder(\n                omittingEmptySubsequences: omittingEmptySubsequences\n            ),\n            maximumBufferSize: maximumBufferSize\n        )\n    }\n}\n\n// MARK: - SplitMessageDecoder\n\n/// A decoder which splits the data into subsequences that are separated by a given separator.\n/// Similar to standard library's `String.split(separator:maxSplits:omittingEmptySubsequences:)`.\n///\n/// This decoder can be used to introduce a `AsyncSequence/split(omittingEmptySubsequences:maximumBufferSize:whereSeparator:)`\n/// function. We could not come up with valid use-cases for such a function so we held off on introducing it.\n/// See https://github.com/apple/swift-nio/pull/3411 for more info if you need such a function.\n@usableFromInline\nstruct SplitMessageDecoder: NIOSingleStepByteToMessageDecoder {\n    @usableFromInline\n    typealias InboundOut = ByteBuffer\n\n    @usableFromInline\n    let omittingEmptySubsequences: Bool\n    @usableFromInline\n    let isSeparator: (UInt8) -> Bool\n    @usableFromInline\n    var ended: Bool\n    @usableFromInline\n    var bytesWithNoSeparatorsCount: Int\n\n    @inlinable\n    init(\n        omittingEmptySubsequences: Bool = true,\n        whereSeparator isSeparator: @escaping (UInt8) -> Bool\n    ) {\n        self.omittingEmptySubsequences = omittingEmptySubsequences\n        self.isSeparator = isSeparator\n        self.ended = false\n        self.bytesWithNoSeparatorsCount = 0\n    }\n\n    /// Decode the next message from the given buffer.\n    @inlinable\n    mutating func decode(\n        buffer: inout ByteBuffer,\n        hasReceivedLastChunk: Bool\n    ) throws -> (buffer: InboundOut, separator: UInt8?)? {\n        if self.ended { return nil }\n\n        while true {\n            let startIndex = buffer.readerIndex + self.bytesWithNoSeparatorsCount\n            if let separatorIndex = buffer.readableBytesView[startIndex...].firstIndex(where: self.isSeparator) {\n                // Safe to force unwrap. We just found a separator somewhere in the buffer.\n                let slice = buffer.readSlice(length: separatorIndex - buffer.readerIndex)!\n                // Reset for the next search since we found a separator.\n                self.bytesWithNoSeparatorsCount = 0\n\n                if self.omittingEmptySubsequences,\n                    slice.readableBytes == 0\n                {\n                    // Mark the separator itself as read\n                    buffer._moveReaderIndex(forwardBy: 1)\n                    continue\n                }\n\n                // Read the separator itself\n                // Safe to force unwrap. We just found a separator somewhere in the buffer.\n                let separator = buffer.readInteger(as: UInt8.self)!\n\n                return (slice, separator)\n            } else {\n                guard hasReceivedLastChunk else {\n                    // Make sure we don't double-check these no-separator bytes again.\n                    self.bytesWithNoSeparatorsCount = buffer.readableBytes\n                    // Need more data\n                    return nil\n                }\n\n                // At this point, we're ending the decoding process.\n                self.ended = true\n\n                if self.omittingEmptySubsequences,\n                    buffer.readableBytes == 0\n                {\n                    return nil\n                }\n\n                // Just send the whole buffer if we're at the last chunk but we can find no separators\n                // Safe to force unwrap. `buffer.readableBytes` is `0` in the worst case.\n                let slice = buffer.readSlice(length: buffer.readableBytes)!\n\n                return (slice, nil)\n            }\n        }\n    }\n\n    /// Decode the next message separated by the provided separator.\n    /// To be used when we're still receiving data.\n    @inlinable\n    mutating func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n        try self.decode(buffer: &buffer, hasReceivedLastChunk: false)?.buffer\n    }\n\n    /// Decode the next message separated by the provided separator.\n    /// To be used when the last chunk of data has been received.\n    @inlinable\n    mutating func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n        try self.decode(buffer: &buffer, hasReceivedLastChunk: true)?.buffer\n    }\n}\n\n@available(*, unavailable)\nextension SplitMessageDecoder: Sendable {}\n\n// MARK: - NIOSplitLinesMessageDecoder\n\n/// A decoder which splits the data into subsequences that are separated by line breaks.\n///\n/// You can initialize this type directly, or use\n/// `AsyncSequence/splitLines(omittingEmptySubsequences:maximumBufferSize:)` to create a\n/// `NIODecodedAsyncSequence` that uses this decoder.\n///\n/// The following Characters are considered line breaks, similar to\n/// standard library's `String.split(whereSeparator: \\.isNewline)`:\n/// - \"\\n\" (U+000A): LINE FEED (LF)\n/// - U+000B: LINE TABULATION (VT)\n/// - U+000C: FORM FEED (FF)\n/// - \"\\r\" (U+000D): CARRIAGE RETURN (CR)\n/// - \"\\r\\n\" (U+000D U+000A): CR-LF\n///\n/// The following Characters are NOT considered line breaks, unlike in\n/// standard library's `String.split(whereSeparator: \\.isNewline)`:\n/// - U+0085: NEXT LINE (NEL)\n/// - U+2028: LINE SEPARATOR\n/// - U+2029: PARAGRAPH SEPARATOR\n///\n/// This is because these characters would require unicode and data-encoding awareness, which\n/// are outside swift-nio's scope.\n///\n/// Usage:\n/// ```swift\n/// let baseSequence = MyAsyncSequence<ByteBuffer>(...)\n/// let splitLinesSequence = baseSequence.splitLines()\n///\n/// for try await buffer in splitLinesSequence {\n///     print(\"Split by line breaks!\\n\", buffer.hexDump(format: .detailed))\n/// }\n/// ```\npublic struct NIOSplitLinesMessageDecoder: NIOSingleStepByteToMessageDecoder {\n    public typealias InboundOut = ByteBuffer\n\n    @usableFromInline\n    var splitDecoder: SplitMessageDecoder\n    @usableFromInline\n    var previousSeparatorWasCR: Bool\n\n    @inlinable\n    public init(omittingEmptySubsequences: Bool) {\n        self.splitDecoder = SplitMessageDecoder(\n            omittingEmptySubsequences: omittingEmptySubsequences,\n            whereSeparator: Self.isLineBreak\n        )\n        self.previousSeparatorWasCR = false\n    }\n\n    /// - ASCII 10 - \"\\n\" (U+000A): LINE FEED (LF)\n    /// - ASCII 11 - U+000B: LINE TABULATION (VT)\n    /// - ASCII 12 - U+000C: FORM FEED (FF)\n    /// - ASCII 13 - \"\\r\" (U+000D): CARRIAGE RETURN (CR)\n    ///\n    /// \"\\r\\n\" is manually accounted for during the decoding.\n    @inlinable\n    static func isLineBreak(_ byte: UInt8) -> Bool {\n        /// All the 4 ASCII bytes are in range of \\n to \\r.\n        (UInt8(ascii: \"\\n\")...UInt8(ascii: \"\\r\")).contains(byte)\n    }\n\n    /// Decode the next message from the given buffer.\n    @inlinable\n    mutating func decode(buffer: inout ByteBuffer, hasReceivedLastChunk: Bool) throws -> InboundOut? {\n        while true {\n            guard\n                let (slice, separator) = try self.splitDecoder.decode(\n                    buffer: &buffer,\n                    hasReceivedLastChunk: hasReceivedLastChunk\n                )\n            else {\n                return nil\n            }\n\n            // If we are getting rid of empty subsequences then it doesn't matter if we detect\n            // \\r\\n as a CR-LF, or as a CR + a LF. The backing decoder gets rid of the empty subsequence\n            // anyway. Therefore, we can return early right here and skip the rest of the logic.\n            if self.splitDecoder.omittingEmptySubsequences {\n                return slice\n            }\n\n            // \"\\r\\n\" is 2 bytes long, so we need to manually account for it.\n            switch separator {\n            case UInt8(ascii: \"\\n\") where slice.readableBytes == 0:\n                let isCRLF = self.previousSeparatorWasCR\n                self.previousSeparatorWasCR = false\n                if isCRLF {\n                    continue\n                }\n            case UInt8(ascii: \"\\r\"):\n                self.previousSeparatorWasCR = true\n            default:\n                self.previousSeparatorWasCR = false\n            }\n\n            return slice\n        }\n    }\n\n    /// Decode the next message separated by one of the ASCII line breaks.\n    /// To be used when we're still receiving data.\n    @inlinable\n    public mutating func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n        try self.decode(buffer: &buffer, hasReceivedLastChunk: false)\n    }\n\n    /// Decode the next message separated by one of the ASCII line breaks.\n    /// To be used when the last chunk of data has been received.\n    @inlinable\n    public mutating func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n        try self.decode(buffer: &buffer, hasReceivedLastChunk: true)\n    }\n}\n\n@available(*, unavailable)\nextension NIOSplitLinesMessageDecoder: Sendable {}\n\n// MARK: - NIOSplitUTF8LinesMessageDecoder\n\n/// A decoder which splits the data into subsequences that are separated by line breaks.\n///\n/// You can initialize this type directly, or use\n/// `AsyncSequence/splitUTF8Lines(omittingEmptySubsequences:maximumBufferSize:)` to create a\n/// `NIODecodedAsyncSequence` that uses this decoder.\n///\n/// The following Characters are considered line breaks, similar to\n/// standard library's `String.split(whereSeparator: \\.isNewline)`:\n/// - \"\\n\" (U+000A): LINE FEED (LF)\n/// - U+000B: LINE TABULATION (VT)\n/// - U+000C: FORM FEED (FF)\n/// - \"\\r\" (U+000D): CARRIAGE RETURN (CR)\n/// - \"\\r\\n\" (U+000D U+000A): CR-LF\n///\n/// The following Characters are NOT considered line breaks, unlike in\n/// standard library's `String.split(whereSeparator: \\.isNewline)`:\n/// - U+0085: NEXT LINE (NEL)\n/// - U+2028: LINE SEPARATOR\n/// - U+2029: PARAGRAPH SEPARATOR\n///\n/// This is because these characters would require unicode and data-encoding awareness, which\n/// are outside swift-nio's scope.\n///\n/// Usage:\n/// ```swift\n/// let baseSequence = MyAsyncSequence<ByteBuffer>(...)\n/// let splitLinesSequence = baseSequence.splitUTF8Lines()\n///\n/// for try await string in splitLinesSequence {\n///     print(\"Split by line breaks!\\n\", string)\n/// }\n/// ```\npublic struct NIOSplitUTF8LinesMessageDecoder: NIOSingleStepByteToMessageDecoder {\n    public typealias InboundOut = String\n\n    @usableFromInline\n    var splitLinesDecoder: NIOSplitLinesMessageDecoder\n\n    @inlinable\n    public init(omittingEmptySubsequences: Bool) {\n        self.splitLinesDecoder = NIOSplitLinesMessageDecoder(\n            omittingEmptySubsequences: omittingEmptySubsequences\n        )\n    }\n\n    /// Decode the next message separated by one of the ASCII line breaks.\n    /// To be used when we're still receiving data.\n    @inlinable\n    public mutating func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n        try self.splitLinesDecoder.decode(buffer: &buffer, hasReceivedLastChunk: false).map {\n            String(buffer: $0)\n        }\n    }\n\n    /// Decode the next message separated by one of the ASCII line breaks.\n    /// To be used when the last chunk of data has been received.\n    @inlinable\n    public mutating func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n        try self.splitLinesDecoder.decode(buffer: &buffer, hasReceivedLastChunk: true).map {\n            String(buffer: $0)\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIOSplitUTF8LinesMessageDecoder: Sendable {}\n"
  },
  {
    "path": "Sources/NIOCore/NIOTransportAccessibleChannelCore.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A ``ChannelCore`` that provides access to its underlying transport.\n///\n/// This API is only used for ``Channel`` implementations: if you are not implementing a ``Channel``, do not use this\n/// protocol directly. Instead use ``ChannelPipeline/SynchronousOperations/withUnsafeTransportIfAvailable(of:_:)``.\n///\n/// Not all channels are expected to conform to ``NIOTransportAccessibleChannelCore``, but this is determined at runtime, by\n/// ``ChannelPipeline/SynchronousOperations/withUnsafeTransportIfAvailable(of:_:)``.\npublic protocol NIOTransportAccessibleChannelCore<Transport>: ChannelCore {\n    /// The type of the underlying transport.\n    associatedtype Transport\n\n    /// Provides scoped access to the underlying transport.\n    ///\n    /// This is an advanced API for reading or manipulating the underlying transport that backs a channel. Users must\n    /// not close the transport or invalidate any invariants that NIO relies upon for the channel operation.\n    ///\n    /// Users should not attempt to use this API direcly, but should instead use\n    /// ``ChannelPipeline/SynchronousOperations/withUnsafeTransportIfAvailable(of:_:)``.\n    ///\n    /// Not all channels are expected to conform to ``NIOTransportAccessibleChannelCore``. If your channel implementation\n    /// does not support this protocol, do not provide a throwing implementation to indicate this. Instead, simply do\n    /// not conform your channel core to this protocol. Availablity of this functionality is communicated to users by /// ///\n    /// ``ChannelPipeline/SynchronousOperations/withUnsafeTransportIfAvailable(of:_:)``.\n    ///\n    /// - Parameter body: A closure that takes the underlying transport.\n    /// - Returns: The value returned by the closure.\n    /// - Throws: If the underlying transport is unavailable, or rethrows any error thrown by the closure.\n    func withUnsafeTransport<Result>(_ body: (_ transport: Transport) throws -> Result) throws -> Result\n}\n"
  },
  {
    "path": "Sources/NIOCore/RecvByteBufferAllocator.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Allocates `ByteBuffer`s to be used to read bytes from a `Channel` and records the number of the actual bytes that were used.\npublic protocol RecvByteBufferAllocator: _NIOPreconcurrencySendable {\n    /// Allocates a new `ByteBuffer` that will be used to read bytes from a `Channel`.\n    func buffer(allocator: ByteBufferAllocator) -> ByteBuffer\n\n    /// Returns the next size of buffer which should be returned by ``buffer(allocator:)``.\n    func nextBufferSize() -> Int?\n\n    /// Records the actual number of bytes that were read by the last socket call.\n    ///\n    /// - Parameters:\n    ///   - actualReadBytes: The number of bytes that were used by the previous allocated `ByteBuffer`\n    /// - Returns: `true` if the next call to `buffer` may return a bigger buffer then the last call to `buffer`.\n    mutating func record(actualReadBytes: Int) -> Bool\n}\n\nextension RecvByteBufferAllocator {\n    // Default implementation to maintain API compatability.\n    public func nextBufferSize() -> Int? {\n        nil\n    }\n}\n\n/// `RecvByteBufferAllocator` which will always return a `ByteBuffer` with the same fixed size no matter what was recorded.\npublic struct FixedSizeRecvByteBufferAllocator: RecvByteBufferAllocator {\n    public let capacity: Int\n\n    public init(capacity: Int) {\n        precondition(capacity > 0)\n        self.capacity = capacity\n    }\n\n    public mutating func record(actualReadBytes: Int) -> Bool {\n        // Returns false as we always allocate the same size of buffers.\n        false\n    }\n\n    public func buffer(allocator: ByteBufferAllocator) -> ByteBuffer {\n        allocator.buffer(capacity: self.capacity)\n    }\n}\n\nextension FixedSizeRecvByteBufferAllocator {\n    public func nextBufferSize() -> Int? {\n        self.capacity\n    }\n}\n\n/// `RecvByteBufferAllocator` which will gracefully increment or decrement the buffer size on the feedback that was recorded.\npublic struct AdaptiveRecvByteBufferAllocator: RecvByteBufferAllocator {\n    public let minimum: Int\n    public let maximum: Int\n    public let initial: Int\n\n    private var nextReceiveBufferSize: Int\n    private var decreaseNow: Bool\n\n    private static let maximumAllocationSize = 1 << 30\n\n    public init() {\n        self.init(minimum: 64, initial: 2048, maximum: 65536)\n    }\n\n    public init(minimum: Int, initial: Int, maximum: Int) {\n        precondition(minimum >= 0, \"minimum: \\(minimum)\")\n        precondition(initial >= minimum, \"initial: \\(initial)\")\n        precondition(maximum >= initial, \"maximum: \\(maximum)\")\n\n        // We need to round all of these numbers to a power of 2. Initial will be rounded down,\n        // minimum down, and maximum up.\n        self.minimum = min(minimum, AdaptiveRecvByteBufferAllocator.maximumAllocationSize).previousPowerOf2()\n        self.initial = min(initial, AdaptiveRecvByteBufferAllocator.maximumAllocationSize).previousPowerOf2()\n        self.maximum = min(maximum, AdaptiveRecvByteBufferAllocator.maximumAllocationSize).nextPowerOf2()\n\n        self.nextReceiveBufferSize = self.initial\n        self.decreaseNow = false\n    }\n\n    public func buffer(allocator: ByteBufferAllocator) -> ByteBuffer {\n        allocator.buffer(capacity: self.nextReceiveBufferSize)\n    }\n\n    public mutating func record(actualReadBytes: Int) -> Bool {\n        precondition(self.nextReceiveBufferSize % 2 == 0)\n        precondition(self.nextReceiveBufferSize >= self.minimum)\n        precondition(self.nextReceiveBufferSize <= self.maximum)\n\n        var mayGrow = false\n\n        // This right shift is safe: nextReceiveBufferSize can never be negative, so this will stop at 0.\n        let lowerBound = self.nextReceiveBufferSize &>> 1\n\n        // Here we need to be careful with 32-bit systems: if maximum is too large then any shift or multiply will overflow, which\n        // we don't want. Instead we check, and clamp to this current value if we overflow.\n        let upperBoundCandidate = Int(truncatingIfNeeded: Int64(self.nextReceiveBufferSize) &<< 1)\n        let upperBound = upperBoundCandidate <= 0 ? self.nextReceiveBufferSize : upperBoundCandidate\n\n        if actualReadBytes <= lowerBound && lowerBound >= self.minimum {\n            if self.decreaseNow {\n                self.nextReceiveBufferSize = lowerBound\n                self.decreaseNow = false\n            } else {\n                self.decreaseNow = true\n            }\n        } else if actualReadBytes >= self.nextReceiveBufferSize && upperBound <= self.maximum\n            && self.nextReceiveBufferSize != upperBound\n        {\n            self.nextReceiveBufferSize = upperBound\n            self.decreaseNow = false\n            mayGrow = true\n        } else {\n            self.decreaseNow = false\n        }\n\n        return mayGrow\n    }\n}\n\nextension AdaptiveRecvByteBufferAllocator {\n    public func nextBufferSize() -> Int? {\n        self.nextReceiveBufferSize\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/SingleStepByteToMessageDecoder.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A simplified version of `ByteToMessageDecoder` that can generate zero or one messages for each invocation of `decode` or `decodeLast`.\n/// Having `decode` and `decodeLast` return an optional message avoids re-entrancy problems, since the functions relinquish exclusive access\n/// to the `ByteBuffer` when returning. This allows for greatly simplified processing.\n///\n/// Many `ByteToMessageDecoder`'s can trivially be translated to `NIOSingleStepByteToMessageDecoder`'s. You should not implement\n/// `ByteToMessageDecoder`'s `decode` and `decodeLast` methods.\npublic protocol NIOSingleStepByteToMessageDecoder: ByteToMessageDecoder {\n    /// The decoded type this `NIOSingleStepByteToMessageDecoder` decodes to. To conform to `ByteToMessageDecoder` it must be called\n    /// `InboundOut` - see https://bugs.swift.org/browse/SR-11868.\n    associatedtype InboundOut\n\n    /// Decode from a `ByteBuffer`.\n    ///\n    /// This method will be called in a loop until either the input `ByteBuffer` has nothing to read left or `nil` is returned. If non-`nil` is\n    /// returned and the `ByteBuffer` contains more readable bytes, this method will immediately be invoked again, unless `decodeLast` needs\n    /// to be invoked instead.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` from which we decode.\n    /// - Returns: A message if one can be decoded or `nil` if it should be called again once more data is present in the `ByteBuffer`.\n    mutating func decode(buffer: inout ByteBuffer) throws -> InboundOut?\n\n    /// Decode from a `ByteBuffer` when no more data is incoming.\n    ///\n    /// Like with `decode`, this method will be called in a loop until either `nil` is returned from the method or until the input `ByteBuffer`\n    /// has no more readable bytes. If non-`nil` is returned and the `ByteBuffer` contains more readable bytes, this method will immediately\n    /// be invoked again.\n    ///\n    /// Once `nil` is returned, neither `decode` nor `decodeLast` will be called again. If there are no bytes left, `decodeLast` will be called\n    /// once with an empty buffer.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` from which we decode.\n    ///   - seenEOF: `true` if EOF has been seen.\n    /// - Returns: A message if one can be decoded or `nil` if no more messages can be produced.\n    mutating func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut?\n}\n\n// MARK: NIOSingleStepByteToMessageDecoder: ByteToMessageDecoder\nextension NIOSingleStepByteToMessageDecoder {\n    public mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        if let message = try self.decode(buffer: &buffer) {\n            context.fireChannelRead(Self.wrapInboundOut(message))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n\n    public mutating func decodeLast(\n        context: ChannelHandlerContext,\n        buffer: inout ByteBuffer,\n        seenEOF: Bool\n    ) throws -> DecodingState {\n        if let message = try self.decodeLast(buffer: &buffer, seenEOF: seenEOF) {\n            context.fireChannelRead(Self.wrapInboundOut(message))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n}\n\n/// `NIOSingleStepByteToMessageProcessor` uses a `NIOSingleStepByteToMessageDecoder` to produce messages\n/// from a stream of incoming bytes. It works like `ByteToMessageHandler` but may be used outside of the channel pipeline. This allows\n/// processing of wrapped protocols in a general way.\n///\n/// A `NIOSingleStepByteToMessageProcessor` is first initialized with a `NIOSingleStepByteToMessageDecoder`. Then\n/// call `process` as each `ByteBuffer` is received from the stream. The closure is called repeatedly with each message produced by\n/// the decoder.\n///\n/// When your stream ends, call `finishProcessing` to ensure all buffered data is passed to your decoder. This will call `decodeLast`\n/// one or more times with any remaining data.\n///\n/// ### Example\n///\n/// Below is an example of a protocol decoded by `TwoByteStringCodec` that is sent over HTTP. `RawBodyMessageHandler` forwards the headers\n/// and trailers directly and uses `NIOSingleStepByteToMessageProcessor` to send whole decoded messages.\n///\n///     class TwoByteStringCodec: NIOSingleStepByteToMessageDecoder {\n///         typealias InboundOut = String\n///\n///         public func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n///             return buffer.readString(length: 2)\n///         }\n///\n///         public func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n///             return try self.decode(buffer: &buffer)\n///         }\n///     }\n///\n///     class RawBodyMessageHandler: ChannelInboundHandler {\n///         typealias InboundIn = HTTPServerRequestPart // alias for HTTPPart<HTTPRequestHead, ByteBuffer>\n///         // This converts the body from ByteBuffer to String, our message type\n///         typealias InboundOut = HTTPPart<HTTPRequestHead, String>\n///\n///         private var messageProcessor: NIOSingleStepByteToMessageProcessor<TwoByteStringCodec>? = nil\n///\n///         func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n///             let req = Self.unwrapInboundIn(data)\n///             do {\n///                 switch req {\n///                 case .head(let head):\n///                     // simply forward on the head\n///                     context.fireChannelRead(Self.wrapInboundOut(.head(head)))\n///                 case .body(let body):\n///                     if self.messageProcessor == nil {\n///                         self.messageProcessor = NIOSingleStepByteToMessageProcessor(TwoByteStringCodec())\n///                     }\n///                     try self.messageProcessor!.process(buffer: body) { message in\n///                         self.channelReadMessage(context: context, message: message)\n///                     }\n///                 case .end(let trailers):\n///                     // Forward on any remaining messages and the trailers\n///                     try self.messageProcessor?.finishProcessing(seenEOF: false) { message in\n///                         self.channelReadMessage(context: context, message: message)\n///                     }\n///                     context.fireChannelRead(Self.wrapInboundOut(.end(trailers)))\n///                 }\n///             } catch {\n///                 context.fireErrorCaught(error)\n///             }\n///         }\n///\n///         // Forward on the body messages as whole messages\n///         func channelReadMessage(context: ChannelHandlerContext, message: String) {\n///             context.fireChannelRead(Self.wrapInboundOut(.body(message)))\n///         }\n///     }\n///\n///     private class DecodedBodyHTTPHandler: ChannelInboundHandler {\n///         typealias InboundIn = HTTPPart<HTTPRequestHead, String>\n///         typealias OutboundOut = HTTPServerResponsePart\n///\n///         var msgs: [String] = []\n///\n///         func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n///             let message = Self.unwrapInboundIn(data)\n///\n///             switch message {\n///             case .head(let head):\n///                 print(\"head: \\(head)\")\n///             case .body(let msg):\n///                 self.msgs.append(msg)\n///             case .end(let trailers):\n///                 print(\"trailers: \\(trailers)\")\n///                 var responseBuffer = context.channel.allocator.buffer(capacity: 32)\n///                 for msg in msgs {\n///                     responseBuffer.writeString(msg)\n///                     responseBuffer.writeStaticString(\"\\n\")\n///                 }\n///                 var headers = HTTPHeaders()\n///                 headers.add(name: \"content-length\", value: String(responseBuffer.readableBytes))\n///\n///                 context.write(Self.wrapOutboundOut(HTTPServerResponsePart.head(\n///                     HTTPResponseHead(version: .http1_1,\n///                                      status: .ok, headers: headers))), promise: nil)\n///\n///                 context.write(Self.wrapOutboundOut(HTTPServerResponsePart.body(\n///                     .byteBuffer(responseBuffer))), promise: nil)\n///                 context.writeAndFlush(Self.wrapOutboundOut(HTTPServerResponsePart.end(nil)), promise: nil)\n///             }\n///         }\n///     }\n///\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///     let bootstrap = ServerBootstrap(group: group).childChannelInitializer({channel in\n///         channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: true, withErrorHandling: true).flatMap { _ in\n///             channel.pipeline.addHandlers([RawBodyMessageHandler(), DecodedBodyHTTPHandler()])\n///         }\n///     })\n///     let channelFuture = bootstrap.bind(host: \"127.0.0.1\", port: 0)\n///\npublic final class NIOSingleStepByteToMessageProcessor<Decoder: NIOSingleStepByteToMessageDecoder> {\n    @usableFromInline\n    enum DecodeMode: Sendable {\n        /// This is a usual decode, ie. not the last chunk\n        case normal\n        /// Last chunk\n        case last\n    }\n\n    @usableFromInline\n    internal private(set) var decoder: Decoder\n    @usableFromInline\n    let maximumBufferSize: Int?\n    @usableFromInline\n    internal private(set) var _buffer: ByteBuffer?\n\n    /// Initialize a `NIOSingleStepByteToMessageProcessor`.\n    ///\n    /// - Parameters:\n    ///   - decoder: The `NIOSingleStepByteToMessageDecoder` to decode the bytes into message.\n    ///   - maximumBufferSize: The maximum number of bytes to aggregate in-memory.\n    ///     An error will be thrown if after decoding elements there is more aggregated data than this amount.\n    @inlinable\n    public init(_ decoder: Decoder, maximumBufferSize: Int? = nil) {\n        self.decoder = decoder\n        self.maximumBufferSize = maximumBufferSize\n    }\n\n    /// Append a new buffer to this processor.\n    @inlinable\n    func append(_ buffer: ByteBuffer) {\n        if self._buffer == nil || self._buffer!.readableBytes == 0 {\n            self._buffer = buffer\n        } else {\n            var buffer = buffer\n            self._buffer!.writeBuffer(&buffer)\n        }\n    }\n\n    @inlinable\n    func _withNonCoWBuffer(_ body: (inout ByteBuffer) throws -> Decoder.InboundOut?) throws -> Decoder.InboundOut? {\n        guard var buffer = self._buffer else {\n            return nil\n        }\n\n        if buffer.readableBytes == 0 {\n            return nil\n        }\n\n        self._buffer = nil  // To avoid CoW\n        defer { self._buffer = buffer }\n\n        let result = try body(&buffer)\n        return result\n    }\n\n    @inlinable\n    func _decodeLoop(\n        decodeMode: DecodeMode,\n        seenEOF: Bool = false,\n        _ messageReceiver: (Decoder.InboundOut) throws -> Void\n    ) throws {\n        // we want to call decodeLast once with an empty buffer if we have nothing\n        if decodeMode == .last && (self._buffer == nil || self._buffer!.readableBytes == 0) {\n            var emptyBuffer = self._buffer ?? ByteBuffer()\n            if let message = try self.decoder.decodeLast(buffer: &emptyBuffer, seenEOF: seenEOF) {\n                try messageReceiver(message)\n            }\n            return\n        }\n\n        // buffer can only be nil if we're called from finishProcessing which is handled above\n        assert(self._buffer != nil)\n\n        func decodeOnce(buffer: inout ByteBuffer) throws -> Decoder.InboundOut? {\n            if decodeMode == .normal {\n                return try self.decoder.decode(buffer: &buffer)\n            } else {\n                return try self.decoder.decodeLast(buffer: &buffer, seenEOF: seenEOF)\n            }\n        }\n\n        while let message = try self._withNonCoWBuffer(decodeOnce) {\n            try messageReceiver(message)\n        }\n\n        try _postDecodeCheck()\n    }\n\n    /// Decode the next message from the `NIOSingleStepByteToMessageProcessor`\n    ///\n    /// This function is useful to manually decode the next message from the `NIOSingleStepByteToMessageProcessor`.\n    /// It should be used in combination with the `append(_:)` function.\n    /// Whenever you receive a new chunk of data, feed it into the `NIOSingleStepByteToMessageProcessor` using `append(_:)`,\n    /// then call this function to decode the next message.\n    ///\n    /// When you've already received the last chunk of data, call this function with `receivedLastChunk` set to `true`.\n    /// In this case, if the function returns `nil`, you are done decoding and there are no more messages to decode.\n    /// Note that you might need to call `decodeNext` _multiple times_, even if `receivedLastChunk` is true, as there\n    /// might be multiple messages left in the buffer.\n    ///\n    /// If `decodeMode` is `.normal`, this function will never return `ended == true`.\n    ///\n    /// If `decodeMode` is `.last`, this function will try to decode a message even if it means only with an empty buffer.\n    /// It'll then return the decoded message with `ended == true`. When you've received `ended == true`, you should\n    /// simply end the decoding process.\n    ///\n    /// `seenEOF` should only be true if `decodeMode == .last`. Otherwise it'll be ignored.\n    ///\n    /// After a `decoder.decode(buffer:)` or `decoder.decodeLast(buffer:seenEOF:)` returns without throwing,\n    /// the aggregated buffer will have to contain less than or equal to `maximumBufferSize` amount of bytes.\n    /// Otherwise an error will be thrown.\n    ///\n    /// - Parameters:\n    ///   - decodeMode: Either 'normal', or 'last' if the last chunk has been received and appended to the processor.\n    ///   - seenEOF: Whether an EOF was seen on the stream\n    /// - Returns: A tuple containing the decoded message and a boolean indicating whether the decoding has ended.\n    @inlinable\n    func decodeNext(\n        decodeMode: DecodeMode,\n        seenEOF: Bool = false\n    ) throws -> (decoded: Decoder.InboundOut?, ended: Bool) {\n        // we want to call decodeLast once with an empty buffer if we have nothing\n        if decodeMode == .last && (self._buffer == nil || self._buffer!.readableBytes == 0) {\n            var emptyBuffer = self._buffer ?? ByteBuffer()\n            let message = try self.decoder.decodeLast(buffer: &emptyBuffer, seenEOF: seenEOF)\n            return (message, true)\n        }\n\n        if self._buffer == nil {\n            return (nil, false)\n        }\n\n        func decodeOnce(buffer: inout ByteBuffer) throws -> Decoder.InboundOut? {\n            if decodeMode == .normal {\n                return try self.decoder.decode(buffer: &buffer)\n            } else {\n                return try self.decoder.decodeLast(buffer: &buffer, seenEOF: seenEOF)\n            }\n        }\n\n        let message = try self._withNonCoWBuffer(decodeOnce)\n\n        try _postDecodeCheck()\n\n        return (message, false)\n    }\n\n    @inlinable\n    func _postDecodeCheck() throws {\n        if let maximumBufferSize = self.maximumBufferSize, self._buffer!.readableBytes > maximumBufferSize {\n            throw ByteToMessageDecoderError.PayloadTooLargeError()\n        }\n\n        if let readerIndex = self._buffer?.readerIndex, readerIndex > 0,\n            self.decoder.shouldReclaimBytes(buffer: self._buffer!)\n        {\n            self._buffer!.discardReadBytes()\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIOSingleStepByteToMessageProcessor: Sendable {}\n\n// MARK: NIOSingleStepByteToMessageProcessor Public API\nextension NIOSingleStepByteToMessageProcessor {\n    /// The number of bytes that are currently not processed by the ``process(buffer:_:)`` method. Having unprocessed\n    /// bytes may result from receiving only partial messages or from receiving multiple messages at once.\n    public var unprocessedBytes: Int {\n        self._buffer?.readableBytes ?? 0\n    }\n\n    /// Feed data into the `NIOSingleStepByteToMessageProcessor` and process it\n    ///\n    /// This function will decode as many `Decoder.InboundOut` messages from the `NIOSingleStepByteToMessageProcessor` as possible,\n    /// and call the `messageReceiver` closure for each message.\n    ///\n    /// - Parameters:\n    ///   - buffer: The `ByteBuffer` containing the next data in the stream\n    ///   - messageReceiver: A closure called for each message produced by the `Decoder`\n    @inlinable\n    public func process(buffer: ByteBuffer, _ messageReceiver: (Decoder.InboundOut) throws -> Void) throws {\n        self.append(buffer)\n        try self._decodeLoop(decodeMode: .normal, messageReceiver)\n    }\n\n    /// Call when there is no data left in the stream. Calls `Decoder`.`decodeLast` one or more times. If there is no data left\n    /// `decodeLast` will be called one time with an empty `ByteBuffer`.\n    ///\n    /// This function will decode as many `Decoder.InboundOut` messages from the `NIOSingleStepByteToMessageProcessor` as possible,\n    /// and call the `messageReceiver` closure for each message.\n    ///\n    /// - Parameters:\n    ///   - seenEOF: Whether an EOF was seen on the stream.\n    ///   - messageReceiver: A closure called for each message produced by the `Decoder`.\n    @inlinable\n    public func finishProcessing(seenEOF: Bool, _ messageReceiver: (Decoder.InboundOut) throws -> Void) throws {\n        try self._decodeLoop(decodeMode: .last, seenEOF: seenEOF, messageReceiver)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/SocketAddresses.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if os(Windows)\nimport ucrt\n\nimport let WinSDK.AF_INET\nimport let WinSDK.AF_INET6\n\nimport let WinSDK.INET_ADDRSTRLEN\nimport let WinSDK.INET6_ADDRSTRLEN\n\nimport func WinSDK.FreeAddrInfoW\nimport func WinSDK.GetAddrInfoW\n\nimport struct WinSDK.ADDRESS_FAMILY\nimport struct WinSDK.ADDRINFOW\nimport struct WinSDK.IN_ADDR\nimport struct WinSDK.IN6_ADDR\n\nimport struct WinSDK.sockaddr\nimport struct WinSDK.sockaddr_in\nimport struct WinSDK.sockaddr_in6\nimport struct WinSDK.sockaddr_storage\nimport struct WinSDK.sockaddr_un\n\nimport typealias WinSDK.u_short\n\nprivate typealias in_addr = WinSDK.IN_ADDR\nprivate typealias in6_addr = WinSDK.IN6_ADDR\nprivate typealias in_port_t = WinSDK.u_short\nprivate typealias sa_family_t = WinSDK.ADDRESS_FAMILY\n#elseif canImport(Darwin)\nimport Darwin\n#elseif os(Linux) || os(FreeBSD) || os(Android)\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\nimport CNIOLinux\n#elseif os(OpenBSD)\n@preconcurrency import Glibc\nimport CNIOOpenBSD\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"The Socket Addresses module was unable to identify your C library.\")\n#endif\n\n/// Special `Error` that may be thrown if we fail to create a `SocketAddress`.\npublic enum SocketAddressError: Error, Equatable, Hashable {\n    /// The host is unknown (could not be resolved).\n    case unknown(host: String, port: Int)\n    /// The requested `SocketAddress` is not supported.\n    case unsupported\n    /// The requested UDS path is too long.\n    case unixDomainSocketPathTooLong\n    /// Unable to parse a given IP string\n    case failedToParseIPString(String)\n}\n\nextension SocketAddressError {\n    /// Unable to parse a given IP ByteBuffer\n    public struct FailedToParseIPByteBuffer: Error, Hashable {\n        public var address: ByteBuffer\n\n        public init(address: ByteBuffer) {\n            self.address = address\n        }\n    }\n}\n\n/// Represent a socket address to which we may want to connect or bind.\npublic enum SocketAddress: CustomStringConvertible, Sendable {\n\n    /// A single IPv4 address for `SocketAddress`.\n    public struct IPv4Address {\n        private let _storage: Box<(address: sockaddr_in, host: String)>\n\n        /// The libc socket address for an IPv4 address.\n        public var address: sockaddr_in { _storage.value.address }\n\n        /// The host this address is for, if known.\n        public var host: String { _storage.value.host }\n\n        fileprivate init(address: sockaddr_in, host: String) {\n            self._storage = Box((address: address, host: host))\n        }\n    }\n\n    /// A single IPv6 address for `SocketAddress`.\n    public struct IPv6Address {\n        private let _storage: Box<(address: sockaddr_in6, host: String)>\n\n        /// The libc socket address for an IPv6 address.\n        public var address: sockaddr_in6 { _storage.value.address }\n\n        /// The host this address is for, if known.\n        public var host: String { _storage.value.host }\n\n        fileprivate init(address: sockaddr_in6, host: String) {\n            self._storage = Box((address: address, host: host))\n        }\n    }\n\n    /// A single Unix socket address for `SocketAddress`.\n    public struct UnixSocketAddress: Sendable {\n        private let _storage: Box<sockaddr_un>\n\n        /// The libc socket address for a Unix Domain Socket.\n        public var address: sockaddr_un { _storage.value }\n\n        fileprivate init(address: sockaddr_un) {\n            self._storage = Box(address)\n        }\n    }\n\n    /// An IPv4 `SocketAddress`.\n    case v4(IPv4Address)\n\n    /// An IPv6 `SocketAddress`.\n    case v6(IPv6Address)\n\n    /// An UNIX Domain `SocketAddress`.\n    case unixDomainSocket(UnixSocketAddress)\n\n    /// A human-readable description of this `SocketAddress`. Mostly useful for logging.\n    public var description: String {\n        let addressString: String\n        let port: String\n        let host: String?\n        let type: String\n        switch self {\n        case .v4(let addr):\n            host = addr.host.isEmpty ? nil : addr.host\n            type = \"IPv4\"\n            var mutAddr = addr.address.sin_addr\n            // this uses inet_ntop which is documented to only fail if family is not AF_INET or AF_INET6 (or ENOSPC)\n            addressString = try! descriptionForAddress(family: .inet, bytes: &mutAddr, length: Int(INET_ADDRSTRLEN))\n\n            port = \"\\(self.port!)\"\n        case .v6(let addr):\n            host = addr.host.isEmpty ? nil : addr.host\n            type = \"IPv6\"\n            var mutAddr = addr.address.sin6_addr\n            // this uses inet_ntop which is documented to only fail if family is not AF_INET or AF_INET6 (or ENOSPC)\n            addressString = try! descriptionForAddress(family: .inet6, bytes: &mutAddr, length: Int(INET6_ADDRSTRLEN))\n\n            port = \"\\(self.port!)\"\n        case .unixDomainSocket(_):\n            host = nil\n            type = \"UDS\"\n            return \"[\\(type)]\\(self.pathname ?? \"\")\"\n        }\n\n        return \"[\\(type)]\\(host.map { \"\\($0)/\\(addressString):\" } ?? \"\\(addressString):\")\\(port)\"\n    }\n\n    @available(*, deprecated, renamed: \"SocketAddress.protocol\")\n    public var protocolFamily: Int32 {\n        Int32(self.protocol.rawValue)\n    }\n\n    /// Returns the protocol family as defined in `man 2 socket` of this `SocketAddress`.\n    public var `protocol`: NIOBSDSocket.ProtocolFamily {\n        switch self {\n        case .v4:\n            return .inet\n        case .v6:\n            return .inet6\n        case .unixDomainSocket:\n            #if os(WASI)\n            fatalError(\"unix domain sockets are currently not supported by WASILibc\")\n            #else\n            return .unix\n            #endif\n        }\n    }\n\n    /// Get the IP address as a string\n    public var ipAddress: String? {\n        switch self {\n        case .v4(let addr):\n            var mutAddr = addr.address.sin_addr\n            // this uses inet_ntop which is documented to only fail if family is not AF_INET or AF_INET6 (or ENOSPC)\n            return try! descriptionForAddress(family: .inet, bytes: &mutAddr, length: Int(INET_ADDRSTRLEN))\n        case .v6(let addr):\n            var mutAddr = addr.address.sin6_addr\n            // this uses inet_ntop which is documented to only fail if family is not AF_INET or AF_INET6 (or ENOSPC)\n            return try! descriptionForAddress(family: .inet6, bytes: &mutAddr, length: Int(INET6_ADDRSTRLEN))\n        case .unixDomainSocket(_):\n            return nil\n        }\n    }\n    /// Get and set the port associated with the address, if defined.\n    /// When setting to `nil` the port will default to `0` for compatible sockets. The rationale for this is that both `nil` and `0` can\n    /// be interpreted as \"no preference\".\n    /// Setting a non-nil value for a unix domain socket is invalid and will result in a fatal error.\n    public var port: Int? {\n        get {\n            switch self {\n            case .v4(let addr):\n                // looks odd but we need to first convert the endianness as `in_port_t` and then make the result an `Int`.\n                return Int(in_port_t(bigEndian: addr.address.sin_port))\n            case .v6(let addr):\n                // looks odd but we need to first convert the endianness as `in_port_t` and then make the result an `Int`.\n                return Int(in_port_t(bigEndian: addr.address.sin6_port))\n            case .unixDomainSocket:\n                return nil\n            }\n        }\n        set {\n            switch self {\n            case .v4(let addr):\n                var mutAddr = addr.address\n                mutAddr.sin_port = in_port_t(newValue ?? 0).bigEndian\n                self = .v4(.init(address: mutAddr, host: addr.host))\n            case .v6(let addr):\n                var mutAddr = addr.address\n                mutAddr.sin6_port = in_port_t(newValue ?? 0).bigEndian\n                self = .v6(.init(address: mutAddr, host: addr.host))\n            case .unixDomainSocket:\n                precondition(newValue == nil, \"attempting to set a non-nil value to a unix socket is not valid\")\n            }\n        }\n    }\n\n    /// Get the pathname of a UNIX domain socket as a string\n    public var pathname: String? {\n        #if os(WASI)\n        return nil\n        #else\n        switch self {\n        case .v4:\n            return nil\n        case .v6:\n            return nil\n        case .unixDomainSocket(let addr):\n            // This is a static assert that exists just to verify the safety of the assumption below.\n            assert(Swift.type(of: addr.address.sun_path.0) == CChar.self)\n            let pathname: String = withUnsafePointer(to: addr.address.sun_path) { ptr in\n                // Homogeneous tuples are always implicitly also bound to their element type, so this assumption below is safe.\n                let charPtr = UnsafeRawPointer(ptr).assumingMemoryBound(to: CChar.self)\n                return String(cString: charPtr)\n            }\n            return pathname\n        }\n        #endif\n    }\n\n    /// Calls the given function with a pointer to a `sockaddr` structure and the associated size\n    /// of that structure.\n    public func withSockAddr<T>(_ body: (UnsafePointer<sockaddr>, Int) throws -> T) rethrows -> T {\n        switch self {\n        case .v4(let addr):\n            return try addr.address.withSockAddr({ try body($0, $1) })\n        case .v6(let addr):\n            return try addr.address.withSockAddr({ try body($0, $1) })\n        case .unixDomainSocket(let addr):\n            return try addr.address.withSockAddr({ try body($0, $1) })\n        }\n    }\n\n    /// Creates a new IPv4 `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - addr: the `sockaddr_in` that holds the ipaddress and port.\n    ///   - host: the hostname that resolved to the ipaddress.\n    public init(_ addr: sockaddr_in, host: String) {\n        self = .v4(.init(address: addr, host: host))\n    }\n\n    /// Creates a new IPv6 `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - addr: the `sockaddr_in` that holds the ipaddress and port.\n    ///   - host: the hostname that resolved to the ipaddress.\n    public init(_ addr: sockaddr_in6, host: String) {\n        self = .v6(.init(address: addr, host: host))\n    }\n\n    /// Creates a new IPv4 `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - addr: the `sockaddr_in` that holds the ipaddress and port.\n    public init(_ addr: sockaddr_in) {\n        self = .v4(.init(address: addr, host: addr.addressDescription()))\n    }\n\n    /// Creates a new IPv6 `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - addr: the `sockaddr_in` that holds the ipaddress and port.\n    public init(_ addr: sockaddr_in6) {\n        self = .v6(.init(address: addr, host: addr.addressDescription()))\n    }\n\n    /// Creates a new Unix Domain Socket `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - addr: the `sockaddr_un` that holds the socket path.\n    public init(_ addr: sockaddr_un) {\n        self = .unixDomainSocket(.init(address: addr))\n    }\n\n    /// Creates a new UDS `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: the path to use for the `SocketAddress`.\n    /// - Throws: may throw `SocketAddressError.unixDomainSocketPathTooLong` if the path is too long.\n    public init(unixDomainSocketPath: String) throws {\n        guard unixDomainSocketPath.utf8.count <= 103 else {\n            throw SocketAddressError.unixDomainSocketPathTooLong\n        }\n\n        let pathBytes = unixDomainSocketPath.utf8 + [0]\n\n        var addr = sockaddr_un()\n        addr.sun_family = sa_family_t(NIOBSDSocket.AddressFamily.unix.rawValue)\n\n        #if !os(WASI)\n        pathBytes.withUnsafeBytes { srcBuffer in\n            withUnsafeMutableBytes(of: &addr.sun_path) { dstPtr in\n                dstPtr.copyMemory(from: srcBuffer)\n            }\n        }\n        #endif\n\n        self = .unixDomainSocket(.init(address: addr))\n    }\n\n    /// Create a new `SocketAddress` for an IP address in string form.\n    ///\n    /// Supports both IPv4 and IPv6 addresses. IPv6 addresses may include a scope ID\n    /// suffix (e.g., `\"fe80::1%eth0\"`) for link-local addresses; the scope ID will be\n    /// preserved in the resulting `sockaddr_in6.sin6_scope_id`.\n    ///\n    /// - Parameters:\n    ///   - ipAddress: The IP address, in string form.\n    ///   - port: The target port.\n    /// - Throws: may throw `SocketAddressError.failedToParseIPString` if the IP address cannot be parsed.\n    public init(ipAddress: String, port: Int) throws {\n        self = try ipAddress.withCString {\n            do {\n                var ipv4Addr = in_addr()\n                try NIOBSDSocket.inet_pton(addressFamily: .inet, addressDescription: $0, address: &ipv4Addr)\n\n                var addr = sockaddr_in()\n                addr.sin_family = sa_family_t(NIOBSDSocket.AddressFamily.inet.rawValue)\n                addr.sin_port = in_port_t(port).bigEndian\n                addr.sin_addr = ipv4Addr\n\n                return .v4(.init(address: addr, host: \"\"))\n            } catch {\n                // If `inet_pton` fails as an IPv4 address, we will try as an\n                // IPv6 address.\n            }\n\n            // IPv6 addresses with scope IDs (e.g. \"fe80::1%eth0\") are not supported by\n            // inet_pton. Use getaddrinfo with AI_NUMERICHOST which handles %scope and\n            // properly sets sin6_scope_id.\n            if ipAddress.utf8.contains(UInt8(ascii: \"%\")) {\n                #if !os(Windows) && !os(WASI)\n                return try Self._parseScopedIPv6(ipAddress, port: port)\n                #else\n                throw SocketAddressError.failedToParseIPString(ipAddress)\n                #endif\n            }\n\n            do {\n                var ipv6Addr = in6_addr()\n                try NIOBSDSocket.inet_pton(addressFamily: .inet6, addressDescription: $0, address: &ipv6Addr)\n\n                var addr = sockaddr_in6()\n                addr.sin6_family = sa_family_t(NIOBSDSocket.AddressFamily.inet6.rawValue)\n                addr.sin6_port = in_port_t(port).bigEndian\n                addr.sin6_flowinfo = 0\n                addr.sin6_addr = ipv6Addr\n                addr.sin6_scope_id = 0\n                return .v6(.init(address: addr, host: \"\"))\n            } catch {\n                // If `inet_pton` fails as an IPv6 address (and has failed as an\n                // IPv4 address above), we will throw an error below.\n            }\n\n            throw SocketAddressError.failedToParseIPString(ipAddress)\n        }\n    }\n\n    #if !os(Windows) && !os(WASI)\n    /// Parse a scoped IPv6 address (containing `%scope`) using `getaddrinfo` with `AI_NUMERICHOST`.\n    private static func _parseScopedIPv6(_ ipAddress: String, port: Int) throws -> SocketAddress {\n        // Reject empty scope (e.g. \"fe80::1%\") before calling getaddrinfo, because\n        // some platforms (macOS) silently accept it with scope_id == 0.\n        guard let percentIndex = ipAddress.firstIndex(of: \"%\"),\n            ipAddress[ipAddress.index(after: percentIndex)...].isEmpty == false\n        else {\n            throw SocketAddressError.failedToParseIPString(ipAddress)\n        }\n\n        var hints = addrinfo()\n        hints.ai_family = AF_INET6\n        hints.ai_flags = AI_NUMERICHOST\n        var result: UnsafeMutablePointer<addrinfo>?\n        let status = getaddrinfo(ipAddress, String(port), &hints, &result)\n        defer { if result != nil { freeaddrinfo(result) } }\n        guard status == 0, let addrInfo = result, let ai_addr = addrInfo.pointee.ai_addr,\n            ai_addr.pointee.sa_family == sa_family_t(AF_INET6)\n        else {\n            throw SocketAddressError.failedToParseIPString(ipAddress)\n        }\n        let sockaddr = ai_addr.withMemoryRebound(to: sockaddr_in6.self, capacity: 1) { $0.pointee }\n\n        // On macOS, getaddrinfo can succeed even for nonexistent interface names,\n        // silently returning scope_id == 0. A valid scoped address must have a\n        // nonzero scope_id.\n        guard sockaddr.sin6_scope_id != 0 else {\n            throw SocketAddressError.failedToParseIPString(ipAddress)\n        }\n\n        return .v6(.init(address: sockaddr, host: ipAddress))\n    }\n    #endif\n\n    /// Create a new `SocketAddress` for an IP address in ByteBuffer form.\n    ///\n    /// - Parameters:\n    ///   - packedIPAddress: The IP address, in ByteBuffer form.\n    ///   - port: The target port.\n    /// - Throws: may throw `SocketAddressError.failedToParseIPByteBuffer` if the IP address cannot be parsed.\n    public init(packedIPAddress: ByteBuffer, port: Int) throws {\n        let packed = packedIPAddress.readableBytesView\n\n        switch packedIPAddress.readableBytes {\n        case 4:\n            var ipv4Addr = sockaddr_in()\n            ipv4Addr.sin_family = sa_family_t(AF_INET)\n            ipv4Addr.sin_port = in_port_t(port).bigEndian\n            withUnsafeMutableBytes(of: &ipv4Addr.sin_addr) { $0.copyBytes(from: packed) }\n            self = .v4(.init(address: ipv4Addr, host: \"\"))\n        case 16:\n            var ipv6Addr = sockaddr_in6()\n            ipv6Addr.sin6_family = sa_family_t(AF_INET6)\n            ipv6Addr.sin6_port = in_port_t(port).bigEndian\n            withUnsafeMutableBytes(of: &ipv6Addr.sin6_addr) { $0.copyBytes(from: packed) }\n            self = .v6(.init(address: ipv6Addr, host: \"\"))\n        default:\n            throw SocketAddressError.FailedToParseIPByteBuffer(address: packedIPAddress)\n        }\n    }\n\n    /// Creates a new `SocketAddress` corresponding to the netmask for a subnet prefix.\n    ///\n    /// As an example, consider the subnet \"127.0.0.1/8\". The \"subnet prefix\" is \"8\", and the corresponding netmask is \"255.0.0.0\".\n    /// This initializer will produce a `SocketAddress` that contains \"255.0.0.0\".\n    ///\n    /// - Parameters:\n    ///   - prefix: The prefix of the subnet.\n    /// - Returns: A `SocketAddress` containing the associated netmask.\n    internal init(ipv4MaskForPrefix prefix: Int) {\n        precondition((0...32).contains(prefix))\n\n        let packedAddress = (UInt32(0xFFFF_FFFF) << (32 - prefix)).bigEndian\n        var ipv4Addr = sockaddr_in()\n        ipv4Addr.sin_family = sa_family_t(AF_INET)\n        ipv4Addr.sin_port = 0\n        withUnsafeMutableBytes(of: &ipv4Addr.sin_addr) { $0.storeBytes(of: packedAddress, as: UInt32.self) }\n        self = .v4(.init(address: ipv4Addr, host: \"\"))\n    }\n\n    /// Creates a new `SocketAddress` corresponding to the netmask for a subnet prefix.\n    ///\n    /// As an example, consider the subnet \"fe80::/10\". The \"subnet prefix\" is \"10\", and the corresponding netmask is \"ff30::\".\n    /// This initializer will produce a `SocketAddress` that contains \"ff30::\".\n    ///\n    /// - Parameters:\n    ///   - prefix: The prefix of the subnet.\n    /// - Returns: A `SocketAddress` containing the associated netmask.\n    internal init(ipv6MaskForPrefix prefix: Int) {\n        precondition((0...128).contains(prefix))\n\n        // This defends against the possibility of a greater-than-/64 subnet, which would produce a negative shift\n        // operand which is absolutely not what we want.\n        let highShift = min(prefix, 64)\n        let packedAddressHigh = (UInt64(0xFFFF_FFFF_FFFF_FFFF) << (64 - highShift)).bigEndian\n\n        let packedAddressLow = (UInt64(0xFFFF_FFFF_FFFF_FFFF) << (128 - prefix)).bigEndian\n        let packedAddress = (packedAddressHigh, packedAddressLow)\n\n        var ipv6Addr = sockaddr_in6()\n        ipv6Addr.sin6_family = sa_family_t(AF_INET6)\n        ipv6Addr.sin6_port = 0\n        withUnsafeMutableBytes(of: &ipv6Addr.sin6_addr) { $0.storeBytes(of: packedAddress, as: (UInt64, UInt64).self) }\n        self = .v6(.init(address: ipv6Addr, host: \"\"))\n    }\n\n    /// Creates a new `SocketAddress` for the given host (which will be resolved) and port.\n    ///\n    /// - warning: This is a blocking call, so please avoid calling this from an `EventLoop`.\n    ///\n    /// - Parameters:\n    ///   - host: the hostname which should be resolved.\n    ///   - port: the port itself\n    /// - Returns: the `SocketAddress` for the host / port pair.\n    /// - Throws: a `SocketAddressError.unknown` if we could not resolve the `host`, or `SocketAddressError.unsupported` if the address itself is not supported (yet).\n    public static func makeAddressResolvingHost(_ host: String, port: Int) throws -> SocketAddress {\n        #if os(WASI)\n        throw SocketAddressError.unsupported\n        #endif\n\n        #if os(Windows)\n        return try host.withCString(encodedAs: UTF16.self) { wszHost in\n            try String(port).withCString(encodedAs: UTF16.self) { wszPort in\n                var pResult: UnsafeMutablePointer<ADDRINFOW>?\n\n                let result = GetAddrInfoW(wszHost, wszPort, nil, &pResult)\n                guard result == 0 else {\n                    throw SocketAddressError.unknown(host: host, port: port)\n                }\n\n                defer {\n                    FreeAddrInfoW(pResult)\n                }\n\n                if let pResult = pResult, let addressBytes = UnsafeRawPointer(pResult.pointee.ai_addr) {\n                    switch pResult.pointee.ai_family {\n                    case AF_INET:\n                        return .v4(IPv4Address(address: addressBytes.load(as: sockaddr_in.self), host: host))\n                    case AF_INET6:\n                        return .v6(IPv6Address(address: addressBytes.load(as: sockaddr_in6.self), host: host))\n                    default:\n                        break\n                    }\n                }\n\n                throw SocketAddressError.unsupported\n            }\n        }\n        #elseif !os(WASI)\n        var info: UnsafeMutablePointer<addrinfo>?\n\n        // FIXME: this is blocking!\n        if getaddrinfo(host, String(port), nil, &info) != 0 {\n            throw SocketAddressError.unknown(host: host, port: port)\n        }\n\n        defer {\n            if info != nil {\n                freeaddrinfo(info)\n            }\n        }\n\n        if let info = info, let addrPointer = info.pointee.ai_addr {\n            let addressBytes = UnsafeRawPointer(addrPointer)\n            switch NIOBSDSocket.AddressFamily(rawValue: info.pointee.ai_family) {\n            case .inet:\n                return .v4(.init(address: addressBytes.load(as: sockaddr_in.self), host: host))\n            case .inet6:\n                return .v6(.init(address: addressBytes.load(as: sockaddr_in6.self), host: host))\n            default:\n                throw SocketAddressError.unsupported\n            }\n        } else {\n            // this is odd, getaddrinfo returned NULL\n            throw SocketAddressError.unsupported\n        }\n        #endif\n    }\n}\n\n/// We define an extension on `SocketAddress` that gives it an elementwise equatable conformance, using\n/// only the elements defined on the structure in their man pages (excluding lengths).\nextension SocketAddress: Equatable {\n    public static func == (lhs: SocketAddress, rhs: SocketAddress) -> Bool {\n        switch (lhs, rhs) {\n        case (.v4(let addr1), .v4(let addr2)):\n            #if os(Windows)\n            return addr1.address.sin_family == addr2.address.sin_family\n                && addr1.address.sin_port == addr2.address.sin_port\n                && addr1.address.sin_addr.S_un.S_addr == addr2.address.sin_addr.S_un.S_addr\n            #else\n            return addr1.address.sin_family == addr2.address.sin_family\n                && addr1.address.sin_port == addr2.address.sin_port\n                && addr1.address.sin_addr.s_addr == addr2.address.sin_addr.s_addr\n            #endif\n        case (.v6(let addr1), .v6(let addr2)):\n            guard\n                addr1.address.sin6_family == addr2.address.sin6_family\n                    && addr1.address.sin6_port == addr2.address.sin6_port\n                    && addr1.address.sin6_flowinfo == addr2.address.sin6_flowinfo\n                    && addr1.address.sin6_scope_id == addr2.address.sin6_scope_id\n            else {\n                return false\n            }\n\n            var s6addr1 = addr1.address.sin6_addr\n            var s6addr2 = addr2.address.sin6_addr\n            return memcmp(&s6addr1, &s6addr2, MemoryLayout.size(ofValue: s6addr1)) == 0\n        case (.unixDomainSocket(let addr1), .unixDomainSocket(let addr2)):\n            guard addr1.address.sun_family == addr2.address.sun_family else {\n                return false\n            }\n\n            #if os(WASI)\n            return true\n            #else\n            let bufferSize = MemoryLayout.size(ofValue: addr1.address.sun_path)\n\n            // Swift implicitly binds the memory for homogeneous tuples to both the tuple type and the element type.\n            // This allows us to use assumingMemoryBound(to:) for managing the types. However, we add a static assertion here to validate\n            // that the element type _really is_ what we're assuming it to be.\n            assert(Swift.type(of: addr1.address.sun_path.0) == CChar.self)\n            assert(Swift.type(of: addr2.address.sun_path.0) == CChar.self)\n            return withUnsafePointer(to: addr1.address.sun_path) { sunpath1 in\n                withUnsafePointer(to: addr2.address.sun_path) { sunpath2 in\n                    let typedSunpath1 = UnsafeRawPointer(sunpath1).assumingMemoryBound(to: CChar.self)\n                    let typedSunpath2 = UnsafeRawPointer(sunpath2).assumingMemoryBound(to: CChar.self)\n                    return strncmp(typedSunpath1, typedSunpath2, bufferSize) == 0\n                }\n            }\n            #endif\n        case (.v4, _), (.v6, _), (.unixDomainSocket, _):\n            return false\n        }\n    }\n}\n\nextension SocketAddress.IPv4Address: Sendable {}\nextension SocketAddress.IPv6Address: Sendable {}\n\n/// We define an extension on `SocketAddress` that gives it an elementwise hashable conformance, using\n/// only the elements defined on the structure in their man pages (excluding lengths).\nextension SocketAddress: Hashable {\n    public func hash(into hasher: inout Hasher) {\n        switch self {\n        case .unixDomainSocket(let uds):\n            hasher.combine(0)\n            hasher.combine(uds.address.sun_family)\n\n            #if !os(WASI)\n            let pathSize = MemoryLayout.size(ofValue: uds.address.sun_path)\n\n            // Swift implicitly binds the memory of homogeneous tuples to both the tuple type and the element type.\n            // We can therefore use assumingMemoryBound(to:) for pointer type conversion. We add a static assert just to\n            // validate that we are actually right about the element type.\n            assert(Swift.type(of: uds.address.sun_path.0) == CChar.self)\n            withUnsafePointer(to: uds.address.sun_path) { pathPtr in\n                let typedPathPointer = UnsafeRawPointer(pathPtr).assumingMemoryBound(to: CChar.self)\n                let length = strnlen(typedPathPointer, pathSize)\n                let bytes = UnsafeRawBufferPointer(start: UnsafeRawPointer(typedPathPointer), count: length)\n                hasher.combine(bytes: bytes)\n            }\n            #endif\n        case .v4(let v4Addr):\n            hasher.combine(1)\n            hasher.combine(v4Addr.address.sin_family)\n            hasher.combine(v4Addr.address.sin_port)\n            #if os(Windows)\n            hasher.combine(v4Addr.address.sin_addr.S_un.S_addr)\n            #else\n            hasher.combine(v4Addr.address.sin_addr.s_addr)\n            #endif\n        case .v6(let v6Addr):\n            hasher.combine(2)\n            hasher.combine(v6Addr.address.sin6_family)\n            hasher.combine(v6Addr.address.sin6_port)\n            hasher.combine(v6Addr.address.sin6_flowinfo)\n            hasher.combine(v6Addr.address.sin6_scope_id)\n            withUnsafeBytes(of: v6Addr.address.sin6_addr) {\n                hasher.combine(bytes: $0)\n            }\n        }\n    }\n}\n\nextension SocketAddress {\n    /// Whether this `SocketAddress` corresponds to a multicast address.\n    public var isMulticast: Bool {\n        switch self {\n        case .unixDomainSocket:\n            // No multicast on unix sockets.\n            return false\n        case .v4(let v4Addr):\n            // For IPv4 a multicast address is in the range 224.0.0.0/4.\n            // The easy way to check if this is the case is to just mask off\n            // the address.\n            #if os(Windows)\n            let v4WireAddress = v4Addr.address.sin_addr.S_un.S_addr\n            let mask = UInt32(0xF000_0000).bigEndian\n            let subnet = UInt32(0xE000_0000).bigEndian\n            #else\n            let v4WireAddress = v4Addr.address.sin_addr.s_addr\n            let mask = in_addr_t(0xF000_0000 as UInt32).bigEndian\n            let subnet = in_addr_t(0xE000_0000 as UInt32).bigEndian\n            #endif\n            return v4WireAddress & mask == subnet\n        case .v6(let v6Addr):\n            // For IPv6 a multicast address is in the range ff00::/8.\n            // Here we don't need a bitmask, as all the top bits are set,\n            // so we can just ask for equality on the top byte.\n            var v6WireAddress = v6Addr.address.sin6_addr\n            return withUnsafeBytes(of: &v6WireAddress) { $0[0] == 0xff }\n        }\n    }\n}\n\nprotocol SockAddrProtocol {\n    func withSockAddr<R>(_ body: (UnsafePointer<sockaddr>, Int) throws -> R) rethrows -> R\n}\n\n/// Returns a description for the given address.\ninternal func descriptionForAddress(\n    family: NIOBSDSocket.AddressFamily,\n    bytes: UnsafeRawPointer,\n    length byteCount: Int\n) throws -> String {\n    var addressBytes: [Int8] = Array(repeating: 0, count: byteCount)\n    return try addressBytes.withUnsafeMutableBufferPointer {\n        (addressBytesPtr: inout UnsafeMutableBufferPointer<Int8>) -> String in\n        try NIOBSDSocket.inet_ntop(\n            addressFamily: family,\n            addressBytes: bytes,\n            addressDescription: addressBytesPtr.baseAddress!,\n            addressDescriptionLength: socklen_t(byteCount)\n        )\n        return addressBytesPtr.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: byteCount) {\n            addressBytesPtr -> String in\n            String(cString: addressBytesPtr)\n        }\n    }\n}\n\nextension sockaddr_in: SockAddrProtocol {\n    func withSockAddr<R>(_ body: (UnsafePointer<sockaddr>, Int) throws -> R) rethrows -> R {\n        try withUnsafeBytes(of: self) { p in\n            try body(p.baseAddress!.assumingMemoryBound(to: sockaddr.self), p.count)\n        }\n    }\n\n    /// Returns a description of the `sockaddr_in`.\n    func addressDescription() -> String {\n        withUnsafePointer(to: self.sin_addr) { addrPtr in\n            // this uses inet_ntop which is documented to only fail if family is not AF_INET or AF_INET6 (or ENOSPC)\n            try! descriptionForAddress(family: .inet, bytes: addrPtr, length: Int(INET_ADDRSTRLEN))\n        }\n    }\n}\n\nextension sockaddr_in6: SockAddrProtocol {\n    func withSockAddr<R>(_ body: (UnsafePointer<sockaddr>, Int) throws -> R) rethrows -> R {\n        try withUnsafeBytes(of: self) { p in\n            try body(p.baseAddress!.assumingMemoryBound(to: sockaddr.self), p.count)\n        }\n    }\n\n    /// Returns a description of the `sockaddr_in6`.\n    func addressDescription() -> String {\n        withUnsafePointer(to: self.sin6_addr) { addrPtr in\n            // this uses inet_ntop which is documented to only fail if family is not AF_INET or AF_INET6 (or ENOSPC)\n            try! descriptionForAddress(family: .inet6, bytes: addrPtr, length: Int(INET6_ADDRSTRLEN))\n        }\n    }\n}\n\nextension sockaddr_un: SockAddrProtocol {\n    func withSockAddr<R>(_ body: (UnsafePointer<sockaddr>, Int) throws -> R) rethrows -> R {\n        try withUnsafeBytes(of: self) { p in\n            try body(p.baseAddress!.assumingMemoryBound(to: sockaddr.self), p.count)\n        }\n    }\n}\n\nextension sockaddr_storage: SockAddrProtocol {\n    func withSockAddr<R>(_ body: (UnsafePointer<sockaddr>, Int) throws -> R) rethrows -> R {\n        try withUnsafeBytes(of: self) { p in\n            try body(p.baseAddress!.assumingMemoryBound(to: sockaddr.self), p.count)\n        }\n    }\n}\n\n// MARK: Workarounds for SR-14268\n// We need these free functions to expose our extension methods, because otherwise\n// the compiler falls over when we try to access them from test code. As these functions\n// exist purely to make the behaviours accessible from test code, we name them truly awfully.\nfunc __testOnly_addressDescription(_ addr: sockaddr_in) -> String {\n    addr.addressDescription()\n}\n\nfunc __testOnly_addressDescription(_ addr: sockaddr_in6) -> String {\n    addr.addressDescription()\n}\n\nfunc __testOnly_withSockAddr<ReturnType>(\n    _ addr: sockaddr_in,\n    _ body: (UnsafePointer<sockaddr>, Int) throws -> ReturnType\n) rethrows -> ReturnType {\n    try addr.withSockAddr(body)\n}\n\nfunc __testOnly_withSockAddr<ReturnType>(\n    _ addr: sockaddr_in6,\n    _ body: (UnsafePointer<sockaddr>, Int) throws -> ReturnType\n) rethrows -> ReturnType {\n    try addr.withSockAddr(body)\n}\n"
  },
  {
    "path": "Sources/NIOCore/SocketOptionProvider.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#if canImport(Darwin)\nimport Darwin\n#elseif os(Linux) || os(Android)\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#endif\nimport CNIOLinux\n#elseif os(OpenBSD)\n@preconcurrency import Glibc\nimport CNIOOpenBSD\n#elseif os(Windows)\nimport WinSDK\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"The Socket Option provider module was unable to identify your C library.\")\n#endif\n\n/// This protocol defines an object, most commonly a `Channel`, that supports\n/// setting and getting socket options (via `setsockopt`/`getsockopt` or similar).\n/// It provides a strongly typed API that makes working with larger, less-common\n/// socket options easier than the `ChannelOption` API allows.\n///\n/// The API is divided into two portions. For socket options that NIO has prior\n/// knowledge about, the API has strongly and safely typed APIs that only allow\n/// users to use the exact correct type for the socket option. This will ensure\n/// that the API is safe to use, and these are encouraged where possible.\n///\n/// These safe APIs are built on top of an \"unsafe\" API that is also exposed to\n/// users as part of this protocol. The \"unsafe\" API is unsafe in the same way\n/// that `UnsafePointer` is: incorrect use of the API allows all kinds of\n/// memory-unsafe behaviour. This API is necessary for socket options that NIO\n/// does not have prior knowledge of, but wherever possible users are discouraged\n/// from using it.\n///\n/// ### Relationship to SocketOption\n///\n/// All `Channel` objects that implement this protocol should also support the\n/// `SocketOption` `ChannelOption` for simple socket options (those with C `int`\n/// values). These are the most common socket option types, and so this `ChannelOption`\n/// represents a convenient shorthand for using this protocol where the type allows,\n/// as well as avoiding the need to cast to this protocol.\n///\n/// - Note: Like the `Channel` protocol, all methods in this protocol are\n///     thread-safe.\npublic protocol SocketOptionProvider: _NIOPreconcurrencySendable {\n    /// The `EventLoop` which is used by this `SocketOptionProvider` for execution.\n    var eventLoop: EventLoop { get }\n\n    #if !os(Windows)\n    /// Set a socket option for a given level and name to the specified value.\n    ///\n    /// This function is not memory-safe: if you set the generic type parameter incorrectly,\n    /// this function will still execute, and this can cause you to incorrectly interpret memory\n    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of\n    /// the safe functions defined by this protocol.\n    ///\n    /// - Parameters:\n    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.\n    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.\n    ///   - value: The value to set the socket option to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    @preconcurrency\n    func unsafeSetSocketOption<Value: Sendable>(\n        level: SocketOptionLevel,\n        name: SocketOptionName,\n        value: Value\n    ) -> EventLoopFuture<Void>\n    #endif\n\n    /// Set a socket option for a given level and name to the specified value.\n    ///\n    /// This function is not memory-safe: if you set the generic type parameter incorrectly,\n    /// this function will still execute, and this can cause you to incorrectly interpret memory\n    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of\n    /// the safe functions defined by this protocol.\n    ///\n    /// - Parameters:\n    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.\n    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.\n    ///   - value: The value to set the socket option to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    @preconcurrency\n    func unsafeSetSocketOption<Value: Sendable>(\n        level: NIOBSDSocket.OptionLevel,\n        name: NIOBSDSocket.Option,\n        value: Value\n    ) -> EventLoopFuture<Void>\n\n    #if !os(Windows)\n    /// Obtain the value of the socket option for the given level and name.\n    ///\n    /// This function is not memory-safe: if you set the generic type parameter incorrectly,\n    /// this function will still execute, and this can cause you to incorrectly interpret memory\n    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of\n    /// the safe functions defined by this protocol.\n    ///\n    /// - Parameters:\n    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.\n    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    @preconcurrency\n    func unsafeGetSocketOption<Value: Sendable>(\n        level: SocketOptionLevel,\n        name: SocketOptionName\n    ) -> EventLoopFuture<Value>\n    #endif\n\n    /// Obtain the value of the socket option for the given level and name.\n    ///\n    /// This function is not memory-safe: if you set the generic type parameter incorrectly,\n    /// this function will still execute, and this can cause you to incorrectly interpret memory\n    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of\n    /// the safe functions defined by this protocol.\n    ///\n    /// - Parameters:\n    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.\n    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    @preconcurrency\n    func unsafeGetSocketOption<Value: Sendable>(\n        level: NIOBSDSocket.OptionLevel,\n        name: NIOBSDSocket.Option\n    ) -> EventLoopFuture<Value>\n}\n\n#if !os(Windows)\nextension SocketOptionProvider {\n    func unsafeSetSocketOption<Value: Sendable>(\n        level: NIOBSDSocket.OptionLevel,\n        name: NIOBSDSocket.Option,\n        value: Value\n    ) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(\n            level: SocketOptionLevel(level.rawValue),\n            name: SocketOptionName(name.rawValue),\n            value: value\n        )\n    }\n\n    func unsafeGetSocketOption<Value: Sendable>(\n        level: NIOBSDSocket.OptionLevel,\n        name: NIOBSDSocket.Option\n    ) -> EventLoopFuture<Value> {\n        self.unsafeGetSocketOption(level: SocketOptionLevel(level.rawValue), name: SocketOptionName(name.rawValue))\n    }\n}\n#endif\n\nenum SocketOptionProviderError: Swift.Error {\n    case unsupported\n}\n\n#if canImport(WASILibc)\npublic typealias NIOLinger = Never\n#else\npublic typealias NIOLinger = linger\n#endif\n\n// MARK:- Safe helper methods.\n// Hello code reader! All the methods in this extension are \"safe\" wrapper methods that define the correct\n// types for `setSocketOption` and `getSocketOption` and call those methods on behalf of the user. These\n// wrapper methods are memory safe. All of these methods are basically identical, and have been copy-pasted\n// around. As a result, if you change one, you should probably change them all.\n//\n// You are welcome to add more helper methods here, but each helper method you add must be tested.\n//\n// Please note that to work around a Swift compiler issue regarding lookup of the Sendability of\n// libc types across modules, the actual calls to `unsafeSetSocketOption` and `unsafeGetSocketOption`\n// _must_ be made inside non-`public` non-`@inlinable` methods. Otherwise we'll produce crashes\n// in release mode. NIO's integration tests are a good canary for this: if you call your method\n// from an alloc counter test in the integration tests, it'll crash if you messed it up.\nextension SocketOptionProvider {\n    /// Sets the socket option SO_LINGER to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set SO_LINGER to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setSoLinger(_ value: linger) -> EventLoopFuture<Void> {\n        self._setSoLinger(value)\n    }\n\n    /// Gets the value of the socket option SO_LINGER.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getSoLinger() -> EventLoopFuture<NIOLinger> {\n        self._getSoLinger()\n    }\n\n    /// Sets the socket option IP_MULTICAST_IF to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IP_MULTICAST_IF to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {\n        self._setIPMulticastIF(value)\n    }\n\n    /// Gets the value of the socket option IP_MULTICAST_IF.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getIPMulticastIF() -> EventLoopFuture<in_addr> {\n        self._getIPMulticastIF()\n    }\n\n    /// Sets the socket option IP_MULTICAST_TTL to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IP_MULTICAST_TTL to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {\n        self._setIPMulticastTTL(value)\n    }\n\n    /// Gets the value of the socket option IP_MULTICAST_TTL.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {\n        self._getIPMulticastTTL()\n    }\n\n    /// Sets the socket option IP_MULTICAST_LOOP to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IP_MULTICAST_LOOP to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {\n        self._setIPMulticastLoop(value)\n    }\n\n    /// Gets the value of the socket option IP_MULTICAST_LOOP.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {\n        self._getIPMulticastLoop()\n    }\n\n    /// Sets the socket option IPV6_MULTICAST_IF to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IPV6_MULTICAST_IF to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {\n        self._setIPv6MulticastIF(value)\n    }\n\n    /// Gets the value of the socket option IPV6_MULTICAST_IF.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {\n        self._getIPv6MulticastIF()\n    }\n\n    /// Sets the socket option IPV6_MULTICAST_HOPS to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IPV6_MULTICAST_HOPS to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {\n        self._setIPv6MulticastHops(value)\n    }\n\n    /// Gets the value of the socket option IPV6_MULTICAST_HOPS.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getIPv6MulticastHops() -> EventLoopFuture<CInt> {\n        self._getIPv6MulticastHops()\n    }\n\n    /// Sets the socket option IPV6_MULTICAST_LOOP to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IPV6_MULTICAST_LOOP to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    public func setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {\n        self._setIPv6MulticastLoop(value)\n    }\n\n    /// Gets the value of the socket option IPV6_MULTICAST_LOOP.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {\n        self._getIPv6MulticastLoop()\n    }\n\n    #if os(Linux) || os(FreeBSD) || os(Android)\n    /// Gets the value of the socket option TCP_INFO.\n    ///\n    /// This socket option cannot be set.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getTCPInfo() -> EventLoopFuture<tcp_info> {\n        self._getTCPInfo()\n    }\n    #endif\n\n    #if canImport(Darwin)\n    /// Gets the value of the socket option TCP_CONNECTION_INFO.\n    ///\n    /// This socket option cannot be set.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {\n        self._getTCPConnectionInfo()\n    }\n    #endif\n\n    #if os(Linux)\n    /// Gets the value of the socket option MPTCP_INFO.\n    ///\n    /// This socket option cannot be set.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    public func getMPTCPInfo() -> EventLoopFuture<mptcp_info> {\n        self._getMPTCPInfo()\n    }\n    #endif\n\n    // MARK: Non-public non-inlinable actual implementations for the above.\n    //\n    // As discussed above, these are needed to work around a compiler issue\n    // that was present at least up to the 6.0 compiler series. This prevents\n    // the specialization being emitted in the caller code, which is unfortunate,\n    // but it also ensures that we avoid the crash. We should remove these when\n    // they're no longer needed.\n\n    /// Sets the socket option SO_LINGER to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set SO_LINGER to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setSoLinger(_ value: linger) -> EventLoopFuture<Void> {\n        #if os(WASI)\n        self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported)\n        #else\n        self.unsafeSetSocketOption(level: .socket, name: .so_linger, value: value)\n        #endif\n    }\n\n    /// Gets the value of the socket option SO_LINGER.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getSoLinger() -> EventLoopFuture<NIOLinger> {\n        #if os(WASI)\n        self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported)\n        #else\n        self.unsafeGetSocketOption(level: .socket, name: .so_linger)\n        #endif\n    }\n\n    /// Sets the socket option IP_MULTICAST_IF to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IP_MULTICAST_IF to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_if, value: value)\n    }\n\n    /// Gets the value of the socket option IP_MULTICAST_IF.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getIPMulticastIF() -> EventLoopFuture<in_addr> {\n        self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_if)\n    }\n\n    /// Sets the socket option IP_MULTICAST_TTL to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IP_MULTICAST_TTL to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_ttl, value: value)\n    }\n\n    /// Gets the value of the socket option IP_MULTICAST_TTL.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {\n        self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_ttl)\n    }\n\n    /// Sets the socket option IP_MULTICAST_LOOP to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IP_MULTICAST_LOOP to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_loop, value: value)\n    }\n\n    /// Gets the value of the socket option IP_MULTICAST_LOOP.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {\n        self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_loop)\n    }\n\n    /// Sets the socket option IPV6_MULTICAST_IF to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IPV6_MULTICAST_IF to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_if, value: value)\n    }\n\n    /// Gets the value of the socket option IPV6_MULTICAST_IF.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {\n        self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_if)\n    }\n\n    /// Sets the socket option IPV6_MULTICAST_HOPS to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IPV6_MULTICAST_HOPS to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_hops, value: value)\n    }\n\n    /// Gets the value of the socket option IPV6_MULTICAST_HOPS.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getIPv6MulticastHops() -> EventLoopFuture<CInt> {\n        self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_hops)\n    }\n\n    /// Sets the socket option IPV6_MULTICAST_LOOP to `value`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set IPV6_MULTICAST_LOOP to.\n    /// - Returns: An `EventLoopFuture` that fires when the option has been set,\n    ///     or if an error has occurred.\n    private func _setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {\n        self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_loop, value: value)\n    }\n\n    /// Gets the value of the socket option IPV6_MULTICAST_LOOP.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {\n        self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_loop)\n    }\n\n    #if os(Linux) || os(FreeBSD) || os(Android)\n    /// Gets the value of the socket option TCP_INFO.\n    ///\n    /// This socket option cannot be set.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getTCPInfo() -> EventLoopFuture<tcp_info> {\n        self.unsafeGetSocketOption(level: .tcp, name: .tcp_info)\n    }\n    #endif\n\n    #if canImport(Darwin)\n    /// Gets the value of the socket option TCP_CONNECTION_INFO.\n    ///\n    /// This socket option cannot be set.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {\n        self.unsafeGetSocketOption(level: .tcp, name: .tcp_connection_info)\n    }\n    #endif\n\n    #if os(Linux)\n    /// Gets the value of the socket option MPTCP_INFO.\n    ///\n    /// This socket option cannot be set.\n    ///\n    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or\n    ///     any error that occurred while retrieving the socket option.\n    private func _getMPTCPInfo() -> EventLoopFuture<mptcp_info> {\n        self.unsafeGetSocketOption(level: .mptcp, name: .mptcp_info)\n    }\n    #endif\n}\n"
  },
  {
    "path": "Sources/NIOCore/SystemCallHelpers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//  This file contains code that ensures errno is captured correctly when doing syscalls and no ARC traffic can happen inbetween that *could* change the errno\n//  value before we were able to read it.\n//  It's important that all static methods are declared with `@inline(never)` so it's not possible any ARC traffic happens while we need to read errno.\n//\n//  Created by Norman Maurer on 11/10/17.\n//\n// This file arguably shouldn't be here in NIOCore, but due to early design decisions we accidentally exposed a few types that\n// know about system calls into the core API (looking at you, FileHandle). As a result we need support for a small number of system calls.\n#if canImport(Darwin)\nimport Darwin.C\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#elseif os(Windows)\nimport CNIOWindows\n#elseif canImport(Android)\n@preconcurrency import Android\n#else\n#error(\"The system call helpers module was unable to identify your C library.\")\n#endif\n\n#if os(Linux) || os(Android)\nimport CNIOLinux\n#endif\n\n#if os(Windows)\nprivate let sysDup: @convention(c) (CInt) -> CInt = _dup\nprivate let sysClose: @convention(c) (CInt) -> CInt = _close\nprivate let sysLseek: @convention(c) (CInt, off_t, CInt) -> off_t = _lseek\nprivate let sysRead: @convention(c) (CInt, UnsafeMutableRawPointer?, CUnsignedInt) -> CInt = _read\n#else\n#if !os(WASI)\nprivate let sysDup: @convention(c) (CInt) -> CInt = dup\n#endif\nprivate let sysClose: @convention(c) (CInt) -> CInt = close\nprivate let sysOpenWithMode: @convention(c) (UnsafePointer<CChar>, CInt, NIOPOSIXFileMode) -> CInt = open\nprivate let sysLseek: @convention(c) (CInt, off_t, CInt) -> off_t = lseek\nprivate let sysRead: @convention(c) (CInt, UnsafeMutableRawPointer?, size_t) -> size_t = read\n#endif\n\n#if os(Android)\nprivate let sysIfNameToIndex: @convention(c) (UnsafePointer<CChar>) -> CUnsignedInt = if_nametoindex\nprivate let sysGetifaddrs: @convention(c) (UnsafeMutablePointer<UnsafeMutablePointer<ifaddrs>?>) -> CInt = getifaddrs\n#elseif !os(WASI)\nprivate let sysIfNameToIndex: @convention(c) (UnsafePointer<CChar>?) -> CUnsignedInt = if_nametoindex\n#if !os(Windows)\nprivate let sysGetifaddrs: @convention(c) (UnsafeMutablePointer<UnsafeMutablePointer<ifaddrs>?>?) -> CInt = getifaddrs\n#endif\n#endif\n\n@inlinable\ninternal func isUnacceptableErrno(_ code: Int32) -> Bool {\n    switch code {\n    case EFAULT, EBADF:\n        return true\n    default:\n        return false\n    }\n}\n\n@inlinable\ninternal func preconditionIsNotUnacceptableErrno(err: CInt, where function: String) {\n    guard isUnacceptableErrno(err) else {\n        return\n    }\n\n    #if os(Windows)\n    let errorDesc = Windows.strerror(err)\n    #else\n    // strerror is documented to return \"Unknown error: ...\" for illegal value so it won't ever fail\n    let errorDesc = strerror(err).flatMap { String(cString: $0) }\n    #endif\n\n    preconditionFailure(\"unacceptable errno \\(err) \\(errorDesc ?? \"Broken strerror, unknown error\") in \\(function))\")\n}\n\n// Sorry, we really try hard to not use underscored attributes. In this case\n// however we seem to break the inlining threshold which makes a system call\n// take twice the time, ie. we need this exception.\n@inline(__always)\n@discardableResult\ninternal func syscall<T: FixedWidthInteger>(\n    blocking: Bool,\n    where function: String = #function,\n    _ body: () throws -> T\n)\n    throws -> CoreIOResult<T>\n{\n    while true {\n        let res = try body()\n        if res == -1 {\n            #if os(Windows)\n            var err: CInt = 0\n            ucrt._get_errno(&err)\n            #else\n            let err = errno\n            #endif\n            switch (err, blocking) {\n            case (EINTR, _):\n                continue\n            #if !os(WASI)\n            case (EWOULDBLOCK, true):\n                return .wouldBlock(0)\n            #endif\n            default:\n                preconditionIsNotUnacceptableErrno(err: err, where: function)\n                throw IOError(errnoCode: err, reason: function)\n            }\n        }\n        return .processed(res)\n    }\n}\n\nenum SystemCalls {\n    #if !os(WASI)\n    @discardableResult\n    @inline(never)\n    internal static func dup(descriptor: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            sysDup(descriptor)\n        }.result\n    }\n    #endif\n\n    @inline(never)\n    @usableFromInline\n    internal static func close(descriptor: CInt) throws {\n        let res = sysClose(descriptor)\n        if res == -1 {\n            #if os(Windows)\n            var err: CInt = 0\n            ucrt._get_errno(&err)\n            #else\n            let err = errno\n            #endif\n\n            // There is really nothing \"good\" we can do when EINTR was reported on close.\n            // So just ignore it and \"assume\" everything is fine == we closed the file descriptor.\n            //\n            // For more details see:\n            //     - https://bugs.chromium.org/p/chromium/issues/detail?id=269623\n            //     - https://lwn.net/Articles/576478/\n            if err != EINTR {\n                preconditionIsNotUnacceptableErrno(err: err, where: #function)\n                throw IOError(errnoCode: err, reason: \"close\")\n            }\n        }\n    }\n\n    @inline(never)\n    @usableFromInline\n    internal static func open(\n        file: UnsafePointer<CChar>,\n        oFlag: CInt,\n        mode: NIOPOSIXFileMode\n    ) throws -> CInt {\n        #if os(Windows)\n        return try syscall(blocking: false) {\n            var fh: CInt = -1\n            let _ = ucrt._sopen_s(&fh, file, oFlag, _SH_DENYNO, mode)\n            return fh\n        }.result\n        #else\n        return try syscall(blocking: false) {\n            sysOpenWithMode(file, oFlag, mode)\n        }.result\n        #endif\n    }\n\n    @discardableResult\n    @inline(never)\n    @usableFromInline\n    internal static func lseek(descriptor: CInt, offset: off_t, whence: CInt) throws -> off_t {\n        try syscall(blocking: false) {\n            sysLseek(descriptor, offset, whence)\n        }.result\n    }\n\n    #if os(Windows)\n    @inline(never)\n    @usableFromInline\n    internal static func read(\n        descriptor: CInt,\n        pointer: UnsafeMutableRawPointer,\n        size: CUnsignedInt\n    ) throws -> CoreIOResult<CInt> {\n        try syscall(blocking: true) {\n            sysRead(descriptor, pointer, size)\n        }\n    }\n    #elseif !os(WASI)\n    @inline(never)\n    @usableFromInline\n    internal static func read(\n        descriptor: CInt,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t\n    ) throws -> CoreIOResult<ssize_t> {\n        try syscall(blocking: true) {\n            sysRead(descriptor, pointer, size)\n        }\n    }\n    #endif\n\n    #if !os(WASI)\n    @inline(never)\n    @usableFromInline\n    internal static func if_nametoindex(_ name: UnsafePointer<CChar>?) throws -> CUnsignedInt {\n        try syscall(blocking: false) {\n            sysIfNameToIndex(name!)\n        }.result\n    }\n\n    #if !os(Windows)\n    @inline(never)\n    @usableFromInline\n    internal static func getifaddrs(_ addrs: UnsafeMutablePointer<UnsafeMutablePointer<ifaddrs>?>) throws {\n        _ = try syscall(blocking: false) {\n            sysGetifaddrs(addrs)\n        }\n    }\n    #endif\n\n    #if os(Linux) || os(Android)\n    @inline(never)\n    @usableFromInline\n    internal static func statfs_ftype(\n        _ path: UnsafePointer<CChar>\n    ) throws -> f_type_t {\n        try syscall(blocking: false) {\n            CNIOLinux_statfs_ftype(path)\n        }.result\n    }\n    #endif\n\n    #endif  // !os(WASI)\n}\n"
  },
  {
    "path": "Sources/NIOCore/TimeAmount+Duration.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension TimeAmount {\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    /// Creates a new `TimeAmount` for the given `Duration`, truncating and clamping if necessary.\n    ///\n    /// - Returns: `TimeAmount`, truncated to nanosecond precision, and clamped to `Int64.max` nanoseconds.\n    public init(_ duration: Swift.Duration) {\n        self = .nanoseconds(duration.nanosecondsClamped)\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nextension Swift.Duration {\n    /// Construct a `Duration` given a number of nanoseconds represented as a `TimeAmount`.\n    public init(_ timeAmount: TimeAmount) {\n        self = .nanoseconds(timeAmount.nanoseconds)\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nextension Swift.Duration {\n    /// The duration represented as nanoseconds, clamped to maximum expressible value.\n    var nanosecondsClamped: Int64 {\n        let components = self.components\n\n        let secondsComponentNanos = components.seconds.multipliedReportingOverflow(by: 1_000_000_000)\n        let attosCompononentNanos = components.attoseconds / 1_000_000_000\n        let combinedNanos = secondsComponentNanos.partialValue.addingReportingOverflow(attosCompononentNanos)\n\n        guard\n            !secondsComponentNanos.overflow,\n            !combinedNanos.overflow\n        else {\n            return .max\n        }\n\n        return combinedNanos.partialValue\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/TypeAssistedChannelHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// ChannelHandler which will emit data by calling `ChannelHandlerContext.write`.\n///\n/// We _strongly_ advice against implementing this protocol directly. Please implement `ChannelInboundHandler` or / and `ChannelOutboundHandler`.\npublic protocol _EmittingChannelHandler {\n    /// The type of the outbound data which will be forwarded to the next `ChannelOutboundHandler` in the `ChannelPipeline`.\n    associatedtype OutboundOut = Never\n\n    /// Wrap the provided `OutboundOut` that will be passed to the next `ChannelOutboundHandler` by calling `ChannelHandlerContext.write`.\n    @inlinable\n    func wrapOutboundOut(_ value: OutboundOut) -> NIOAny\n}\n\n/// Default implementations for `_EmittingChannelHandler`.\nextension _EmittingChannelHandler {\n    @inlinable\n    public func wrapOutboundOut(_ value: OutboundOut) -> NIOAny {\n        NIOAny(value)\n    }\n\n    @inlinable\n    public static func wrapOutboundOut(_ value: OutboundOut) -> NIOAny {\n        NIOAny(value)\n    }\n}\n\n///  `ChannelHandler` which handles inbound I/O events for a `Channel`.\n///\n/// Please refer to `_ChannelInboundHandler` and `_EmittingChannelHandler` for more details on the provided methods.\npublic protocol ChannelInboundHandler: _ChannelInboundHandler, _EmittingChannelHandler {\n    /// The type of the inbound data which is wrapped in `NIOAny`.\n    associatedtype InboundIn\n\n    /// The type of the inbound data which will be forwarded to the next `ChannelInboundHandler` in the `ChannelPipeline`.\n    associatedtype InboundOut = Never\n\n    /// Unwrap the provided `NIOAny` that was passed to `channelRead`.\n    @inlinable\n    func unwrapInboundIn(_ value: NIOAny) -> InboundIn\n\n    /// Wrap the provided `InboundOut` that will be passed to the next `ChannelInboundHandler` by calling `ChannelHandlerContext.fireChannelRead`.\n    @inlinable\n    func wrapInboundOut(_ value: InboundOut) -> NIOAny\n}\n\n/// Default implementations for `ChannelInboundHandler`.\nextension ChannelInboundHandler {\n    @inlinable\n    public func unwrapInboundIn(_ value: NIOAny) -> InboundIn {\n        value.forceAs()\n    }\n\n    @inlinable\n    public func wrapInboundOut(_ value: InboundOut) -> NIOAny {\n        NIOAny(value)\n    }\n\n    @inlinable\n    public static func unwrapInboundIn(_ value: NIOAny) -> InboundIn {\n        value.forceAs()\n    }\n\n    @inlinable\n    public static func wrapInboundOut(_ value: InboundOut) -> NIOAny {\n        NIOAny(value)\n    }\n}\n\n/// `ChannelHandler` which handles outbound I/O events or intercept an outbound I/O operation for a `Channel`.\n///\n/// Please refer to `_ChannelOutboundHandler` and `_EmittingChannelHandler` for more details on the provided methods.\npublic protocol ChannelOutboundHandler: _ChannelOutboundHandler, _EmittingChannelHandler {\n    /// The type of the outbound data which is wrapped in `NIOAny`.\n    associatedtype OutboundIn\n\n    /// Unwrap the provided `NIOAny` that was passed to `write`.\n    @inlinable\n    func unwrapOutboundIn(_ value: NIOAny) -> OutboundIn\n}\n\n/// Default implementations for `ChannelOutboundHandler`.\nextension ChannelOutboundHandler {\n    @inlinable\n    public func unwrapOutboundIn(_ value: NIOAny) -> OutboundIn {\n        value.forceAs()\n    }\n\n    @inlinable\n    public static func unwrapOutboundIn(_ value: NIOAny) -> OutboundIn {\n        value.forceAs()\n    }\n}\n\n/// A combination of `ChannelInboundHandler` and `ChannelOutboundHandler`.\npublic typealias ChannelDuplexHandler = ChannelInboundHandler & ChannelOutboundHandler\n"
  },
  {
    "path": "Sources/NIOCore/UniversalBootstrapSupport.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// `NIOClientTCPBootstrapProtocol` is implemented by various underlying transport mechanisms. Typically,\n/// this will be the BSD Sockets API implemented by `ClientBootstrap`.\npublic protocol NIOClientTCPBootstrapProtocol {\n    /// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// The connected `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.\n    ///\n    /// - warning: The `handler` closure may be invoked _multiple times_ so it's usually the right choice to instantiate\n    ///            `ChannelHandler`s within `handler`. The reason `handler` may be invoked multiple times is that to\n    ///            successfully set up a connection multiple connections might be setup in the process. Assuming a\n    ///            hostname that resolves to both IPv4 and IPv6 addresses, NIO will follow\n    ///            [_Happy Eyeballs_](https://en.wikipedia.org/wiki/Happy_Eyeballs) and race both an IPv4 and an IPv6\n    ///            connection. It is possible that both connections get fully established before the IPv4 connection\n    ///            will be closed again because the IPv6 connection 'won the race'. Therefore the `channelInitializer`\n    ///            might be called multiple times and it's important not to share stateful `ChannelHandler`s in more\n    ///            than one `Channel`.\n    ///\n    /// - Parameters:\n    ///   - handler: A closure that initializes the provided `Channel`.\n    @preconcurrency\n    func channelInitializer(_ handler: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self\n\n    /// Sets the protocol handlers that will be added to the front of the `ChannelPipeline` right after the\n    /// `channelInitializer` has been called.\n    ///\n    /// Per bootstrap, you can only set the `protocolHandlers` once. Typically, `protocolHandlers` are used for the TLS\n    /// implementation. Most notably, `NIOClientTCPBootstrap`, NIO's \"universal bootstrap\" abstraction, uses\n    /// `protocolHandlers` to add the required `ChannelHandler`s for many TLS implementations.\n    @preconcurrency\n    func protocolHandlers(_ handlers: @escaping @Sendable () -> [ChannelHandler]) -> Self\n\n    /// Specifies a `ChannelOption` to be applied to the `SocketChannel`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    func channelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self\n\n    /// Apply any understood convenience options to the bootstrap, removing them from the set of options if they are consumed.\n    /// Method is optional to implement and should never be directly called by users.\n    /// - Parameters:\n    ///   - options:  The options to try applying - the options applied should be consumed from here.\n    /// - Returns: The updated bootstrap with and options applied.\n    func _applyChannelConvenienceOptions(_ options: inout ChannelOptions.TCPConvenienceOptions) -> Self\n\n    /// - Parameters:\n    ///   - timeout: The timeout that will apply to the connection attempt.\n    func connectTimeout(_ timeout: TimeAmount) -> Self\n\n    /// Specify the `host` and `port` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    func connect(host: String, port: Int) -> EventLoopFuture<Channel>\n\n    /// Specify the `address` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - address: The address to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    func connect(to address: SocketAddress) -> EventLoopFuture<Channel>\n\n    /// Specify the `unixDomainSocket` path to connect to for the UDS `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The _Unix domain socket_ path to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    func connect(unixDomainSocketPath: String) -> EventLoopFuture<Channel>\n}\n\n/// `NIOClientTCPBootstrap` is a bootstrap that allows you to bootstrap client TCP connections using NIO on BSD Sockets,\n/// NIO Transport Services, or other ways.\n///\n/// Usually, to bootstrap a connection with SwiftNIO, you have to match the right `EventLoopGroup`, the right bootstrap,\n/// and the right TLS implementation. Typical choices involve:\n///  - `MultiThreadedEventLoopGroup`, `ClientBootstrap`, and `NIOSSLClientHandler` (from\n///    [`swift-nio-ssl`](https://github.com/apple/swift-nio-ssl)) for NIO on BSD sockets.\n///  - `NIOTSEventLoopGroup`, `NIOTSConnectionBootstrap`, and the Network.framework TLS implementation (all from\n///    [`swift-nio-transport-services`](https://github.com/apple/swift-nio-transport-services).\n///\n/// Bootstrapping connections that way works but is quite tedious for packages that support multiple ways of\n/// bootstrapping. The idea behind `NIOClientTCPBootstrap` is to do all configuration in one place (when you initialize\n/// a `NIOClientTCPBootstrap`) and then have a common API that works for all use-cases.\n///\n/// Example:\n///\n///     // This function combines the right pieces and returns you a \"universal client bootstrap\"\n///     // (`NIOClientTCPBootstrap`). This allows you to bootstrap connections (with or without TLS) using either the\n///     // NIO on sockets (`NIO`) or NIO on Network.framework (`NIOTransportServices`) stacks.\n///     // The remainder of the code should be platform-independent.\n///     func makeUniversalBootstrap(serverHostname: String) throws -> (NIOClientTCPBootstrap, EventLoopGroup) {\n///         func useNIOOnSockets() throws -> (NIOClientTCPBootstrap, EventLoopGroup) {\n///             let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///             let sslContext = try NIOSSLContext(configuration: TLSConfiguration.forClient())\n///             let bootstrap = try NIOClientTCPBootstrap(ClientBootstrap(group: group),\n///                                                       tls: NIOSSLClientTLSProvider(context: sslContext,\n///                                                                                    serverHostname: serverHostname))\n///             return (bootstrap, group)\n///         }\n///\n///         #if canImport(Network)\n///         if #available(macOS 10.14, iOS 12, tvOS 12, watchOS 3, *) {\n///             // We run on a new-enough Darwin so we can use Network.framework\n///\n///             let group = NIOTSEventLoopGroup()\n///             let bootstrap = NIOClientTCPBootstrap(NIOTSConnectionBootstrap(group: group),\n///                                                   tls: NIOTSClientTLSProvider())\n///             return (bootstrap, group)\n///         } else {\n///             // We're on Darwin but not new enough for Network.framework, so we fall back on NIO on BSD sockets.\n///             return try useNIOOnSockets()\n///         }\n///         #else\n///         // We are on a non-Darwin platform, so we'll use BSD sockets.\n///         return try useNIOOnSockets()\n///         #endif\n///     }\n///\n///     let (bootstrap, group) = try makeUniversalBootstrap(serverHostname: \"example.com\")\n///     let connection = try bootstrap\n///             .channelInitializer { channel in\n///                 channel.pipeline.addHandler(PrintEverythingHandler { _ in })\n///             }\n///             .enableTLS()\n///             .connect(host: \"example.com\", port: 443)\n///             .wait()\npublic struct NIOClientTCPBootstrap {\n    public let underlyingBootstrap: NIOClientTCPBootstrapProtocol\n    private let tlsEnablerTypeErased: (NIOClientTCPBootstrapProtocol) -> NIOClientTCPBootstrapProtocol\n\n    /// Initialize a `NIOClientTCPBootstrap` using the underlying `Bootstrap` alongside a compatible `TLS`\n    /// implementation.\n    ///\n    /// - Note: If you do not require `TLS`, you can use `NIOInsecureNoTLS` which supports only plain-text\n    ///         connections. We highly recommend to always use TLS.\n    ///\n    /// - Parameters:\n    ///   - bootstrap: The underlying bootstrap to use.\n    ///   - tls: The TLS implementation to use, needs to be compatible with `Bootstrap`.\n    public init<\n        Bootstrap: NIOClientTCPBootstrapProtocol,\n        TLS: NIOClientTLSProvider\n    >(_ bootstrap: Bootstrap, tls: TLS) where TLS.Bootstrap == Bootstrap {\n        self.underlyingBootstrap = bootstrap\n        self.tlsEnablerTypeErased = { bootstrap in\n            tls.enableTLS(bootstrap as! TLS.Bootstrap)\n        }\n    }\n\n    private init(\n        _ bootstrap: NIOClientTCPBootstrapProtocol,\n        tlsEnabler: @escaping (NIOClientTCPBootstrapProtocol) -> NIOClientTCPBootstrapProtocol\n    ) {\n        self.underlyingBootstrap = bootstrap\n        self.tlsEnablerTypeErased = tlsEnabler\n    }\n\n    internal init(_ original: NIOClientTCPBootstrap, updating underlying: NIOClientTCPBootstrapProtocol) {\n        self.underlyingBootstrap = underlying\n        self.tlsEnablerTypeErased = original.tlsEnablerTypeErased\n    }\n\n    /// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// The connected `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.\n    ///\n    /// - warning: The `handler` closure may be invoked _multiple times_ so it's usually the right choice to instantiate\n    ///            `ChannelHandler`s within `handler`. The reason `handler` may be invoked multiple times is that to\n    ///            successfully set up a connection multiple connections might be setup in the process. Assuming a\n    ///            hostname that resolves to both IPv4 and IPv6 addresses, NIO will follow\n    ///            [_Happy Eyeballs_](https://en.wikipedia.org/wiki/Happy_Eyeballs) and race both an IPv4 and an IPv6\n    ///            connection. It is possible that both connections get fully established before the IPv4 connection\n    ///            will be closed again because the IPv6 connection 'won the race'. Therefore the `channelInitializer`\n    ///            might be called multiple times and it's important not to share stateful `ChannelHandler`s in more\n    ///            than one `Channel`.\n    ///\n    /// - Parameters:\n    ///   - handler: A closure that initializes the provided `Channel`.\n    public func channelInitializer(\n        _ handler: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> NIOClientTCPBootstrap {\n        NIOClientTCPBootstrap(\n            self.underlyingBootstrap.channelInitializer(handler),\n            tlsEnabler: self.tlsEnablerTypeErased\n        )\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the `SocketChannel`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    public func channelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> NIOClientTCPBootstrap {\n        NIOClientTCPBootstrap(\n            self.underlyingBootstrap.channelOption(option, value: value),\n            tlsEnabler: self.tlsEnablerTypeErased\n        )\n    }\n\n    /// - Parameters:\n    ///   - timeout: The timeout that will apply to the connection attempt.\n    public func connectTimeout(_ timeout: TimeAmount) -> NIOClientTCPBootstrap {\n        NIOClientTCPBootstrap(\n            self.underlyingBootstrap.connectTimeout(timeout),\n            tlsEnabler: self.tlsEnablerTypeErased\n        )\n    }\n\n    /// Specify the `host` and `port` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    public func connect(host: String, port: Int) -> EventLoopFuture<Channel> {\n        self.underlyingBootstrap.connect(host: host, port: port)\n    }\n\n    /// Specify the `address` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - address: The address to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    public func connect(to address: SocketAddress) -> EventLoopFuture<Channel> {\n        self.underlyingBootstrap.connect(to: address)\n    }\n\n    /// Specify the `unixDomainSocket` path to connect to for the UDS `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The _Unix domain socket_ path to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    public func connect(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n        self.underlyingBootstrap.connect(unixDomainSocketPath: unixDomainSocketPath)\n    }\n\n    @discardableResult\n    public func enableTLS() -> NIOClientTCPBootstrap {\n        NIOClientTCPBootstrap(\n            self.tlsEnablerTypeErased(self.underlyingBootstrap),\n            tlsEnabler: self.tlsEnablerTypeErased\n        )\n    }\n}\n\n@available(*, unavailable)\nextension NIOClientTCPBootstrap: Sendable {}\n\npublic protocol NIOClientTLSProvider {\n    associatedtype Bootstrap\n\n    func enableTLS(_ bootstrap: Bootstrap) -> Bootstrap\n}\n\npublic struct NIOInsecureNoTLS<Bootstrap: NIOClientTCPBootstrapProtocol>: NIOClientTLSProvider, Sendable {\n    public init() {}\n\n    public func enableTLS(_ bootstrap: Bootstrap) -> Bootstrap {\n        fatalError(\"NIOInsecureNoTLS cannot enable TLS.\")\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCore/Utilities.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#if os(Linux) || os(FreeBSD) || os(Android)\nimport CNIOLinux\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\n#elseif os(OpenBSD)\nimport CNIOOpenBSD\n@preconcurrency import Glibc\n#elseif os(Windows)\nimport ucrt\nimport let WinSDK.RelationProcessorCore\n\nimport let WinSDK.AF_UNSPEC\nimport let WinSDK.ERROR_SUCCESS\n\nimport func WinSDK.GetAdaptersAddresses\nimport func WinSDK.GetLastError\nimport func WinSDK.GetLogicalProcessorInformation\n\nimport struct WinSDK.IP_ADAPTER_ADDRESSES\nimport struct WinSDK.IP_ADAPTER_UNICAST_ADDRESS\nimport struct WinSDK.SYSTEM_LOGICAL_PROCESSOR_INFORMATION\nimport struct WinSDK.ULONG\n\nimport typealias WinSDK.DWORD\n#elseif canImport(Darwin)\nimport Darwin\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#else\n#error(\"The Core utilities module was unable to identify your C library.\")\n#endif\n\n/// A utility function that runs the body code only in debug builds, without\n/// emitting compiler warnings.\n///\n/// This is currently the only way to do this in Swift: see\n/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.\n@inlinable\ninternal func debugOnly(_ body: () -> Void) {\n    // FIXME: duplicated with NIO.\n    assert(\n        {\n            body()\n            return true\n        }()\n    )\n}\n\n/// Allows to \"box\" another value.\nfinal class Box<T> {\n    // FIXME: Duplicated with NIO.\n    let value: T\n    init(_ value: T) { self.value = value }\n}\n\nextension Box: Sendable where T: Sendable {}\n\npublic enum System: Sendable {\n    /// A utility function that returns an estimate of the number of *logical* cores\n    /// on the system available for use.\n    ///\n    /// This value can be used to help provide an estimate of how many threads to use with\n    /// the `MultiThreadedEventLoopGroup`. The exact ratio between this number and the number\n    /// of threads to use is a matter for the programmer, and can be determined based on the\n    /// specific execution behaviour of the program.\n    ///\n    /// On Linux the value returned will take account of cgroup or cpuset restrictions.\n    /// The result will be rounded up to the nearest whole number where fractional CPUs have been assigned.\n    ///\n    /// - Returns: The logical core count on the system.\n    public static var coreCount: Int {\n        #if os(Windows)\n        var dwLength: DWORD = 0\n        _ = GetLogicalProcessorInformation(nil, &dwLength)\n\n        let alignment: Int =\n            MemoryLayout<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>.alignment\n        let pBuffer: UnsafeMutableRawPointer =\n            UnsafeMutableRawPointer.allocate(\n                byteCount: Int(dwLength),\n                alignment: alignment\n            )\n        defer {\n            pBuffer.deallocate()\n        }\n\n        let dwSLPICount: Int =\n            Int(dwLength) / MemoryLayout<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>.stride\n        let pSLPI: UnsafeMutablePointer<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> =\n            pBuffer.bindMemory(\n                to: SYSTEM_LOGICAL_PROCESSOR_INFORMATION.self,\n                capacity: dwSLPICount\n            )\n\n        let bResult: Bool = GetLogicalProcessorInformation(pSLPI, &dwLength)\n        precondition(bResult, \"GetLogicalProcessorInformation: \\(GetLastError())\")\n\n        return UnsafeBufferPointer<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>(\n            start: pSLPI,\n            count: dwSLPICount\n        )\n        .filter { $0.Relationship == RelationProcessorCore }\n        .map { $0.ProcessorMask.nonzeroBitCount }\n        .reduce(0, +)\n        #elseif os(Linux) || os(Android)\n        var cpuSetPath: String?\n\n        switch Linux.cgroupVersion {\n        case .v1:\n            if let quota = Linux.coreCountCgroup1Restriction() {\n                return quota\n            }\n            cpuSetPath = Linux.cpuSetPathV1\n        case .v2:\n            if let quota = Linux.coreCountCgroup2Restriction() {\n                return quota\n            }\n            cpuSetPath = Linux.cpuSetPathV2\n        case .none:\n            break\n        }\n\n        if let cpuSetPath,\n            let cpusetCount = Linux.coreCount(cpuset: cpuSetPath)\n        {\n            return cpusetCount\n        } else {\n            return sysconf(CInt(_SC_NPROCESSORS_ONLN))\n        }\n        #else\n        return sysconf(CInt(_SC_NPROCESSORS_ONLN))\n        #endif\n    }\n\n    #if !os(Windows) && !os(WASI)\n    /// A utility function that enumerates the available network interfaces on this machine.\n    ///\n    /// This function returns values that are true for a brief snapshot in time. These results can\n    /// change, and the returned values will not change to reflect them. This function must be called\n    /// again to get new results.\n    ///\n    /// - Returns: An array of network interfaces available on this machine.\n    /// - Throws: If an error is encountered while enumerating interfaces.\n    @available(*, deprecated, renamed: \"enumerateDevices\")\n    public static func enumerateInterfaces() throws -> [NIONetworkInterface] {\n        var interfaces: [NIONetworkInterface] = []\n        interfaces.reserveCapacity(12)  // Arbitrary choice.\n\n        var interface: UnsafeMutablePointer<ifaddrs>? = nil\n        try SystemCalls.getifaddrs(&interface)\n        let originalInterface = interface\n        defer {\n            freeifaddrs(originalInterface)\n        }\n\n        while let concreteInterface = interface {\n            if let nioInterface = NIONetworkInterface(concreteInterface.pointee) {\n                interfaces.append(nioInterface)\n            }\n            interface = concreteInterface.pointee.ifa_next\n        }\n\n        return interfaces\n    }\n    #endif\n\n    /// A utility function that enumerates the available network devices on this machine.\n    ///\n    /// This function returns values that are true for a brief snapshot in time. These results can\n    /// change, and the returned values will not change to reflect them. This function must be called\n    /// again to get new results.\n    ///\n    /// - Returns: An array of network devices available on this machine.\n    /// - Throws: If an error is encountered while enumerating interfaces.\n    public static func enumerateDevices() throws -> [NIONetworkDevice] {\n        var devices: [NIONetworkDevice] = []\n        devices.reserveCapacity(12)  // Arbitrary choice.\n\n        #if os(Windows)\n        var ulSize: ULONG = 0\n        _ = GetAdaptersAddresses(ULONG(AF_UNSPEC), 0, nil, nil, &ulSize)\n\n        let stride: Int = MemoryLayout<IP_ADAPTER_ADDRESSES>.stride\n        let pBuffer: UnsafeMutableBufferPointer<IP_ADAPTER_ADDRESSES> =\n            UnsafeMutableBufferPointer.allocate(capacity: Int(ulSize) / stride)\n        defer {\n            pBuffer.deallocate()\n        }\n\n        let ulResult: ULONG =\n            GetAdaptersAddresses(\n                ULONG(AF_UNSPEC),\n                0,\n                nil,\n                pBuffer.baseAddress,\n                &ulSize\n            )\n        guard ulResult == ERROR_SUCCESS else {\n            throw IOError(windows: ulResult, reason: \"GetAdaptersAddresses\")\n        }\n\n        var pAdapter: UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>? =\n            UnsafeMutablePointer(pBuffer.baseAddress)\n        while pAdapter != nil {\n            let pUnicastAddresses: UnsafeMutablePointer<IP_ADAPTER_UNICAST_ADDRESS>? =\n                pAdapter!.pointee.FirstUnicastAddress\n            var pUnicastAddress: UnsafeMutablePointer<IP_ADAPTER_UNICAST_ADDRESS>? =\n                pUnicastAddresses\n            while pUnicastAddress != nil {\n                if let device = NIONetworkDevice(pAdapter!, pUnicastAddress!) {\n                    devices.append(device)\n                }\n                pUnicastAddress = pUnicastAddress!.pointee.Next\n            }\n            pAdapter = pAdapter!.pointee.Next\n        }\n        #elseif !os(WASI)\n        var interface: UnsafeMutablePointer<ifaddrs>? = nil\n        try SystemCalls.getifaddrs(&interface)\n        let originalInterface = interface\n        defer {\n            freeifaddrs(originalInterface)\n        }\n\n        while let concreteInterface = interface {\n            if let nioInterface = NIONetworkDevice(concreteInterface.pointee) {\n                devices.append(nioInterface)\n            }\n            interface = concreteInterface.pointee.ifa_next\n        }\n\n        #endif\n        return devices\n    }\n}\n\nextension System {\n    #if os(Linux)\n    /// Returns true if the platform supports `UDP_SEGMENT` (GSO).\n    ///\n    /// The option can be enabled by setting the ``ChannelOptions/Types/DatagramSegmentSize`` channel option.\n    public static let supportsUDPSegmentationOffload: Bool = CNIOLinux_supports_udp_segment()\n    #else\n    /// Returns true if the platform supports `UDP_SEGMENT` (GSO).\n    ///\n    /// The option can be enabled by setting the ``ChannelOptions/Types/DatagramSegmentSize`` channel option.\n    public static let supportsUDPSegmentationOffload: Bool = false\n    #endif\n\n    #if os(Linux)\n    /// Returns true if the platform supports `UDP_GRO`.\n    ///\n    /// The option can be enabled by setting the ``ChannelOptions/Types/DatagramReceiveOffload`` channel option.\n    public static let supportsUDPReceiveOffload: Bool = CNIOLinux_supports_udp_gro()\n    #else\n    /// Returns true if the platform supports `UDP_GRO`.\n    ///\n    /// The option can be enabled by setting the ``ChannelOptions/Types/DatagramReceiveOffload`` channel option.\n    public static let supportsUDPReceiveOffload: Bool = false\n    #endif\n\n    /// Returns `nil`.\n    @available(*, deprecated, message: \"UDP_MAX_SEGMENTS isn't exposed by the Linux kernel\")\n    public static var udpMaxSegments: Int? {\n        nil\n    }\n}\n\n#if os(Windows)\n@usableFromInline\npackage enum Windows {\n    @usableFromInline\n    package static func strerror(_ errnoCode: CInt) -> String? {\n        withUnsafeTemporaryAllocation(of: CChar.self, capacity: 256) { ptr in\n            if strerror_s(ptr.baseAddress, ptr.count, errnoCode) == 0 {\n                return String(cString: UnsafePointer(ptr.baseAddress!))\n            }\n            return nil\n        }\n    }\n\n    package static func getenv(_ env: String) -> String? {\n        var count = 0\n        var ptr: UnsafeMutablePointer<CChar>? = nil\n        withUnsafeMutablePointer(to: &ptr) { buffer in\n            // according to docs only EINVAL and ENOMEM are possible here.\n            _ = _dupenv_s(buffer, &count, env)\n        }\n        defer { if let ptr { free(ptr) } }\n        if count > 0, let ptr {\n            let buffer = UnsafeBufferPointer(start: ptr, count: count)\n            return buffer.withMemoryRebound(to: UInt8.self) {\n                String(decoding: $0, as: Unicode.UTF8.self)\n            }\n        } else {\n            return nil\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTestSuites.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !canImport(Darwin) || os(macOS)\nfunc makeCrashTestSuites() -> [String: Any] {\n    [\n        \"EventLoopCrashTests\": EventLoopCrashTests(),\n        \"ByteBufferCrashTests\": ByteBufferCrashTests(),\n        \"SystemCrashTests\": SystemCrashTests(),\n        \"HTTPCrashTests\": HTTPCrashTests(),\n        \"StrictCrashTests\": StrictCrashTests(),\n        \"LoopBoundTests\": LoopBoundTests(),\n    ]\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTests+ByteBuffer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nstruct ByteBufferCrashTests {\n    #if !canImport(Darwin) || os(macOS)\n    let testMovingReaderIndexPastWriterIndex = CrashTest(\n        regex: #\"Precondition failed: new readerIndex: 1, expected: range\\(0, 0\\)\"#\n    ) {\n        var buffer = ByteBufferAllocator().buffer(capacity: 16)\n        buffer.moveReaderIndex(forwardBy: 1)\n    }\n\n    let testAllocatingNegativeSize = CrashTest(\n        regex: #\"Precondition failed: ByteBuffer capacity must be positive.\"#\n    ) {\n        _ = ByteBufferAllocator().buffer(capacity: -1)\n    }\n    #endif\n}\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTests+EventLoop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !canImport(Darwin) || os(macOS)\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\nprivate let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n\nstruct EventLoopCrashTests {\n    let testMultiThreadedELGCrashesOnZeroThreads = CrashTest(\n        regex: \"Precondition failed: numberOfThreads must be positive\"\n    ) {\n        try? MultiThreadedEventLoopGroup(numberOfThreads: 0).syncShutdownGracefully()\n    }\n\n    let testWaitCrashesWhenOnEL = CrashTest(\n        regex: #\"Precondition failed: BUG DETECTED: wait\\(\\) must not be called when on an EventLoop\"#\n    ) {\n        let promise = group.next().makePromise(of: Void.self)\n        try? group.next().submit {\n            try? promise.futureResult.wait()\n        }.wait()\n    }\n\n    let testAssertInEventLoop = CrashTest(\n        regex: \"Precondition failed\"\n    ) {\n        group.next().assertInEventLoop(file: \"DUMMY\", line: 42)\n    }\n\n    let testPreconditionInEventLoop = CrashTest(\n        regex: \"Precondition failed\"\n    ) {\n        group.next().preconditionInEventLoop(file: \"DUMMY\", line: 42)\n    }\n\n    let testAssertNotInEventLoop = CrashTest(\n        regex: \"Precondition failed\"\n    ) {\n        let el = group.next()\n        try? el.submit {\n            el.assertNotInEventLoop(file: \"DUMMY\", line: 42)\n        }.wait()\n    }\n\n    let testPreconditionNotInEventLoop = CrashTest(\n        regex: \"Precondition failed\"\n    ) {\n        let el = group.next()\n        try? el.submit {\n            el.preconditionNotInEventLoop(file: \"DUMMY\", line: 42)\n        }.wait()\n    }\n\n    let testSchedulingEndlesslyInELShutdown = CrashTest(\n        regex: #\"Precondition failed: EventLoop SelectableEventLoop \\{ .* \\} didn't quiesce after 1000 ticks.\"#\n    ) {\n        let group = MultiThreadedEventLoopGroup.init(numberOfThreads: 1)\n        defer {\n            try? group.syncShutdownGracefully()\n            exit(4)\n        }\n        let el = group.next()\n        el.scheduleTask(in: .hours(7)) {\n            // Will never happen.\n            exit(1)\n        }.futureResult.whenFailure { error in\n            guard case .some(.shutdown) = error as? EventLoopError else {\n                exit(2)\n            }\n            func f() {\n                el.assumeIsolated().scheduleTask(in: .nanoseconds(0)) { [f] in\n                    f()\n                }.futureResult.assumeIsolated().whenFailure { [f] error in\n                    guard case .some(.shutdown) = error as? EventLoopError else {\n                        exit(3)\n                    }\n                    f()\n                }\n            }\n            f()\n        }\n    }\n\n    let testLeakingAPromiseCrashes = CrashTest(\n        regex: #\"Fatal error: leaking promise created at\"#\n    ) {\n        @inline(never)\n        func leaker() {\n            _ = group.next().makePromise(of: Void.self)\n        }\n        leaker()\n        for el in group.makeIterator() {\n            try! el.submit {}.wait()\n        }\n    }\n\n    let testUsingTheSingletonGroupWhenDisabled = CrashTest(\n        regex: #\"Fatal error: Cannot create global singleton MultiThreadedEventLoopGroup because the global singletons\"#\n    ) {\n        NIOSingletons.singletonsEnabledSuggestion = false\n        try? NIOSingletons.posixEventLoopGroup.next().submit {}.wait()\n    }\n\n    let testUsingTheSingletonBlockingPoolWhenDisabled = CrashTest(\n        regex: #\"Fatal error: Cannot create global singleton NIOThreadPool because the global singletons have been\"#\n    ) {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            try? group.syncShutdownGracefully()\n        }\n        NIOSingletons.singletonsEnabledSuggestion = false\n        try? NIOSingletons.posixBlockingThreadPool.runIfActive(eventLoop: group.next(), {}).wait()\n    }\n\n    let testDisablingSingletonsEnabledValueTwice = CrashTest(\n        regex: #\"Fatal error: Bug in user code: Global singleton enabled suggestion has been changed after\"#\n    ) {\n        NIOSingletons.singletonsEnabledSuggestion = false\n        NIOSingletons.singletonsEnabledSuggestion = false\n    }\n\n    let testEnablingSingletonsEnabledValueTwice = CrashTest(\n        regex: #\"Fatal error: Bug in user code: Global singleton enabled suggestion has been changed after\"#\n    ) {\n        NIOSingletons.singletonsEnabledSuggestion = true\n        NIOSingletons.singletonsEnabledSuggestion = true\n    }\n\n    let testEnablingThenDisablingSingletonsEnabledValue = CrashTest(\n        regex: #\"Fatal error: Bug in user code: Global singleton enabled suggestion has been changed after\"#\n    ) {\n        NIOSingletons.singletonsEnabledSuggestion = true\n        NIOSingletons.singletonsEnabledSuggestion = false\n    }\n\n    let testSettingTheSingletonEnabledValueAfterUse = CrashTest(\n        regex: #\"Fatal error: Bug in user code: Global singleton enabled suggestion has been changed after\"#\n    ) {\n        try? MultiThreadedEventLoopGroup.singleton.next().submit({}).wait()\n        NIOSingletons.singletonsEnabledSuggestion = true\n    }\n\n    let testSettingTheSuggestedSingletonGroupCountTwice = CrashTest(\n        regex: #\"Fatal error: Bug in user code: Global singleton suggested loop/thread count has been changed after\"#\n    ) {\n        NIOSingletons.groupLoopCountSuggestion = 17\n        NIOSingletons.groupLoopCountSuggestion = 17\n    }\n\n    let testSettingTheSuggestedSingletonGroupChangeAfterUse = CrashTest(\n        regex: #\"Fatal error: Bug in user code: Global singleton suggested loop/thread count has been changed after\"#\n    ) {\n        try? MultiThreadedEventLoopGroup.singleton.next().submit({}).wait()\n        NIOSingletons.groupLoopCountSuggestion = 17\n    }\n\n    let testSettingTheSuggestedSingletonGroupLoopCountToZero = CrashTest(\n        regex: #\"Precondition failed: illegal value: needs to be strictly positive\"#\n    ) {\n        NIOSingletons.groupLoopCountSuggestion = 0\n    }\n\n    let testSettingTheSuggestedSingletonGroupLoopCountToANegativeValue = CrashTest(\n        regex: #\"Precondition failed: illegal value: needs to be strictly positive\"#\n    ) {\n        NIOSingletons.groupLoopCountSuggestion = -1\n    }\n\n    #if swift(<6.2)  // We only support Concurrency executor take-over on those Swift versions, as versions greater than that have not been properly tested.\n    let testInstallingSingletonMTELGAsConcurrencyExecutorWorksButOnlyOnce = CrashTest(\n        regex: #\"Fatal error: Must be called only once\"#\n    ) {\n        guard NIOSingletons.unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor() else {\n            print(\"Installation failed, that's unexpected -> let's not crash\")\n            return\n        }\n\n        // Yes, this pattern is bad abuse but this is a crash test, we don't mind.\n        let semaphoreAbuse = DispatchSemaphore(value: 0)\n        if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {\n            Task {\n                precondition(MultiThreadedEventLoopGroup.currentEventLoop != nil)\n                try await Task.sleep(nanoseconds: 123)\n                precondition(MultiThreadedEventLoopGroup.currentEventLoop != nil)\n                semaphoreAbuse.signal()\n            }\n        } else {\n            semaphoreAbuse.signal()\n        }\n        semaphoreAbuse.wait()\n        print(\"Okay, worked\")\n\n        // This should crash\n        _ = NIOSingletons.unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor()\n    }\n    #endif  // swift(<6.2)\n}\n#endif  // !canImport(Darwin) || os(macOS)\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTests+HTTP.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#if !canImport(Darwin) || os(macOS)\nimport NIOEmbedded\nimport NIOCore\nimport NIOHTTP1\n\nstruct HTTPCrashTests {\n    let testEncodingChunkedAndContentLengthForRequestsCrashes = CrashTest(\n        regex:\n            \"Assertion failed: illegal HTTP sent: HTTPRequestHead .* contains both a content-length and transfer-encoding:chunked\",\n        {\n            let channel = EmbeddedChannel(handler: HTTPRequestEncoder())\n            _ = try? channel.writeAndFlush(\n                HTTPClientRequestPart.head(\n                    HTTPRequestHead(\n                        version: .http1_1,\n                        method: .POST,\n                        uri: \"/\",\n                        headers: [\n                            \"content-Length\": \"1\",\n                            \"transfer-Encoding\": \"chunked\",\n                        ]\n                    )\n                )\n            ).wait()\n        }\n    )\n\n    let testEncodingChunkedAndContentLengthForResponseCrashes = CrashTest(\n        regex:\n            \"Assertion failed: illegal HTTP sent: HTTPResponseHead .* contains both a content-length and transfer-encoding:chunked\",\n        {\n            let channel = EmbeddedChannel(handler: HTTPResponseEncoder())\n            _ = try? channel.writeAndFlush(\n                HTTPServerResponsePart.head(\n                    HTTPResponseHead(\n                        version: .http1_1,\n                        status: .ok,\n                        headers: [\n                            \"content-Length\": \"1\",\n                            \"transfer-Encoding\": \"chunked\",\n                        ]\n                    )\n                )\n            ).wait()\n        }\n    )\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTests+LoopBound.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\nprivate let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n\nstruct LoopBoundTests {\n    #if !canImport(Darwin) || os(macOS)\n    let testInitChecksEventLoop = CrashTest(\n        regex: \"NIOCore/NIOLoopBound.swift:[0-9]+: Precondition failed\"\n    ) {\n        _ = NIOLoopBound(1, eventLoop: group.any())  // BOOM\n    }\n\n    let testInitOfBoxChecksEventLoop = CrashTest(\n        regex: \"NIOCore/NIOLoopBound.swift:[0-9]+: Precondition failed\"\n    ) {\n        _ = NIOLoopBoundBox(1, eventLoop: group.any())  // BOOM\n    }\n\n    let testGetChecksEventLoop = CrashTest(\n        regex: \"NIOCore/NIOLoopBound.swift:[0-9]+: Precondition failed\"\n    ) {\n        let loop = group.any()\n        let sendable = try? loop.submit {\n            NIOLoopBound(1, eventLoop: loop)\n        }.wait()\n        _ = sendable?.value  // BOOM\n    }\n\n    let testGetOfBoxChecksEventLoop = CrashTest(\n        regex: \"NIOCore/NIOLoopBound.swift:[0-9]+: Precondition failed\"\n    ) {\n        let loop = group.any()\n        let sendable = try? loop.submit {\n            NIOLoopBoundBox(1, eventLoop: loop)\n        }.wait()\n        _ = sendable?.value  // BOOM\n    }\n\n    let testSetChecksEventLoop = CrashTest(\n        regex: \"NIOCore/NIOLoopBound.swift:[0-9]+: Precondition failed\"\n    ) {\n        let loop = group.any()\n        let sendable = try? loop.submit {\n            NIOLoopBound(1, eventLoop: loop)\n        }.wait()\n        var sendableVar = sendable\n        sendableVar?.value = 2\n    }\n\n    let testSetOfBoxChecksEventLoop = CrashTest(\n        regex: \"NIOCore/NIOLoopBound.swift:[0-9]+: Precondition failed\"\n    ) {\n        let loop = group.any()\n        let sendable = try? loop.submit {\n            NIOLoopBoundBox(1, eventLoop: loop)\n        }.wait()\n        sendable?.value = 2\n    }\n    #endif\n}\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTests+Strict.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !canImport(Darwin) || os(macOS)\nimport NIOCore\nimport NIOPosix\n\nstruct StrictCrashTests {\n    let testEventLoopSheduleAfterShutdown = CrashTest(\n        regex: \"Fatal error: Cannot schedule tasks on an EventLoop that has already shut down.\"\n    ) {\n        setenv(\"SWIFTNIO_STRICT\", \"1\", 1)\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = elg.next()\n        try! elg.syncShutdownGracefully()\n        loop.execute {\n            print(\"Crash should happen before this line is printed.\")\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCrashTester/CrashTests+System.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !canImport(Darwin) || os(macOS)\nimport NIOCore\nimport NIOPosix\nimport Foundation\n\nprivate let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n\nstruct SystemCrashTests {\n    let testEBADFIsUnacceptable = CrashTest(\n        regex: \"Precondition failed: unacceptable errno \\(EBADF) Bad file descriptor in\",\n        {\n            _ = try? NIOPipeBootstrap(group: group).takingOwnershipOfDescriptors(input: .max, output: .max - 1).wait()\n        }\n    )\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOCrashTester/OutputGrepper.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOFoundationCompat\nimport NIOPosix\n\nimport class Foundation.Pipe\n\ninternal struct OutputGrepper {\n    internal var result: EventLoopFuture<ProgramOutput>\n    internal var processOutputPipe: NIOFileHandle\n\n    internal static func make(group: EventLoopGroup) -> OutputGrepper {\n        let processToChannel = Pipe()\n\n        let eventLoop = group.next()\n        let outputPromise = eventLoop.makePromise(of: ProgramOutput.self)\n\n        // We gotta `dup` everything because Pipe is bad and closes file descriptors on `deinit` :(\n        let channelFuture = NIOPipeBootstrap(group: group)\n            .channelOption(.allowRemoteHalfClosure, value: true)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandlers([\n                        ByteToMessageHandler(NewlineFramer()),\n                        GrepHandler(promise: outputPromise),\n                    ])\n                }\n            }\n            .takingOwnershipOfDescriptor(input: dup(processToChannel.fileHandleForReading.fileDescriptor))\n        let processOutputPipe = NIOFileHandle(\n            _deprecatedTakingOwnershipOfDescriptor: dup(processToChannel.fileHandleForWriting.fileDescriptor)\n        )\n        processToChannel.fileHandleForReading.closeFile()\n        processToChannel.fileHandleForWriting.closeFile()\n        channelFuture.cascadeFailure(to: outputPromise)\n        return OutputGrepper(\n            result: outputPromise.futureResult,\n            processOutputPipe: processOutputPipe\n        )\n    }\n}\n\ntypealias ProgramOutput = String\n\nprivate final class GrepHandler: ChannelInboundHandler {\n    typealias InboundIn = String\n\n    private let promise: EventLoopPromise<ProgramOutput>\n\n    init(promise: EventLoopPromise<ProgramOutput>) {\n        self.promise = promise\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.promise.fail(error)\n        context.close(promise: nil)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let line = Self.unwrapInboundIn(data)\n        if line.lowercased().contains(\"fatal error\") || line.lowercased().contains(\"precondition failed\")\n            || line.lowercased().contains(\"assertion failed\")\n        {\n            self.promise.succeed(line)\n            context.close(promise: nil)\n        }\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        if case .some(.inputClosed) = event as? ChannelEvent {\n            self.promise.succeed(\"\")\n            context.close(promise: nil)\n        }\n    }\n\n    func handlerRemoved(context: ChannelHandlerContext) {\n        self.promise.fail(ChannelError.alreadyClosed)\n    }\n}\n\nprivate struct NewlineFramer: ByteToMessageDecoder {\n    typealias InboundOut = String\n\n    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        if let firstNewline = buffer.readableBytesView.firstIndex(of: UInt8(ascii: \"\\n\")) {\n            let length = firstNewline - buffer.readerIndex + 1\n            context.fireChannelRead(Self.wrapInboundOut(String(buffer.readString(length: length)!.dropLast())))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOCrashTester/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !canImport(Darwin) || os(macOS)\nimport NIOCore\nimport NIOPosix\nimport class Foundation.Process\nimport struct Foundation.URL\nimport class Foundation.FileHandle\n\nstruct CrashTest {\n    let crashRegex: String\n    let runTest: () -> Void\n\n    init(regex: String, _ runTest: @escaping () -> Void) {\n        self.crashRegex = regex\n        self.runTest = runTest\n    }\n}\n\n// Compatible with Swift on all macOS versions as well as Linux\nextension Process {\n    var binaryPath: String? {\n        get {\n            if #available(macOS 10.13, *) {\n                return self.executableURL?.path\n            } else {\n                return self.launchPath\n            }\n        }\n        set {\n            if #available(macOS 10.13, *) {\n                self.executableURL = newValue.map { URL(fileURLWithPath: $0) }\n            } else {\n                self.launchPath = newValue\n            }\n        }\n    }\n\n    func runProcess() throws {\n        if #available(macOS 10.13, *) {\n            try self.run()\n        } else {\n            self.launch()\n        }\n    }\n}\n\nfunc main() throws {\n    enum RunResult {\n        case signal(Int)\n        case exit(Int)\n    }\n\n    enum InterpretedRunResult {\n        case crashedAsExpected\n        case regexDidNotMatch(regex: String, output: String)\n        case unexpectedRunResult(RunResult)\n        case outputError(String)\n    }\n\n    struct CrashTestNotFound: Error {\n        let suite: String\n        let test: String\n    }\n\n    func allTestsForSuite(_ testSuite: String) -> [(String, CrashTest)] {\n        let crashTestSuites = makeCrashTestSuites()\n        return crashTestSuites[testSuite].map { testSuiteObject in\n            Mirror(reflecting: testSuiteObject)\n                .children\n                .filter { $0.label?.starts(with: \"test\") ?? false }\n                .compactMap { crashTestDescriptor in\n                    crashTestDescriptor.label.flatMap { label in\n                        (crashTestDescriptor.value as? CrashTest).map { crashTest in\n                            (label, crashTest)\n                        }\n                    }\n                }\n        } ?? []\n    }\n\n    func findCrashTest(_ testName: String, suite: String) -> CrashTest? {\n        allTestsForSuite(suite)\n            .first(where: { $0.0 == testName })?\n            .1\n    }\n\n    func interpretOutput(\n        _ result: Result<ProgramOutput, Error>,\n        regex: String,\n        runResult: RunResult\n    ) throws -> InterpretedRunResult {\n        struct NoOutputFound: Error {}\n        #if arch(i386) || arch(x86_64)\n        let expectedSignal = SIGILL\n        #elseif arch(arm) || arch(arm64)\n        let expectedSignal = SIGTRAP\n        #else\n        #error(\"unknown CPU architecture for which we don't know the expected signal for a crash\")\n        #endif\n        guard case .signal(Int(expectedSignal)) = runResult else {\n            return .unexpectedRunResult(runResult)\n        }\n\n        let output = try result.get()\n        if output.range(of: regex, options: .regularExpression) != nil {\n            return .crashedAsExpected\n        } else {\n            return .regexDidNotMatch(regex: regex, output: output)\n        }\n    }\n\n    func usage() {\n        print(\"\\(CommandLine.arguments.first ?? \"NIOCrashTester\") COMMAND [OPTIONS]\")\n        print()\n        print(\"COMMAND is:\")\n        print(\"  run-all                         to run all crash tests\")\n        print(\"  run SUITE TEST-NAME             to run the crash test SUITE.TEST-NAME\")\n        print(\"\")\n        print(\"For debugging purposes, you can also directly run the crash test binary that will crash using\")\n        print(\"  \\(CommandLine.arguments.first ?? \"NIOCrashTester\") _exec SUITE TEST-NAME\")\n    }\n\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        try! group.syncShutdownGracefully()\n    }\n\n    // explicit return type needed due to https://github.com/apple/swift-nio/issues/3180\n    let _: ((Int32) -> Void)? = signal(SIGPIPE, SIG_IGN)\n\n    func runCrashTest(_ name: String, suite: String, binary: String) throws -> InterpretedRunResult {\n        guard let crashTest = findCrashTest(name, suite: suite) else {\n            throw CrashTestNotFound(suite: suite, test: name)\n        }\n\n        let grepper = OutputGrepper.make(group: group)\n\n        let devNull = try FileHandle(forUpdating: URL(fileURLWithPath: \"/dev/null\"))\n        defer {\n            devNull.closeFile()\n        }\n\n        let processOutputPipe = FileHandle(fileDescriptor: try! grepper.processOutputPipe.takeDescriptorOwnership())\n        let process = Process()\n        process.binaryPath = binary\n        process.standardInput = devNull\n        process.standardOutput = devNull\n        process.standardError = processOutputPipe\n\n        process.arguments = [\"_exec\", suite, name]\n        try process.runProcess()\n\n        process.waitUntilExit()\n        processOutputPipe.closeFile()\n        let result: Result<ProgramOutput, Error> = Result {\n            try grepper.result.wait()\n        }\n        return try interpretOutput(\n            result,\n            regex: crashTest.crashRegex,\n            runResult: process.terminationReason == .exit\n                ? .exit(Int(process.terminationStatus)) : .signal(Int(process.terminationStatus))\n        )\n    }\n\n    var failedTests = 0\n    func runAndEval(_ test: String, suite: String) throws {\n        print(\"running crash test \\(suite).\\(test)\", terminator: \" \")\n        switch try runCrashTest(test, suite: suite, binary: CommandLine.arguments.first!) {\n        case .regexDidNotMatch(let regex, let output):\n            print(\n                \"FAILED: regex did not match output\",\n                \"regex: \\(regex)\",\n                \"output: \\(output)\",\n                separator: \"\\n\",\n                terminator: \"\"\n            )\n            failedTests += 1\n        case .unexpectedRunResult(let runResult):\n            print(\"FAILED: unexpected run result: \\(runResult)\")\n            failedTests += 1\n        case .outputError(let description):\n            print(\"FAILED: \\(description)\")\n            failedTests += 1\n        case .crashedAsExpected:\n            print(\"OK\")\n        }\n    }\n\n    switch CommandLine.arguments.dropFirst().first {\n    case .some(\"run-all\"):\n        let crashTestSuites = makeCrashTestSuites()\n        for testSuite in crashTestSuites {\n            for test in allTestsForSuite(testSuite.key) {\n                try runAndEval(test.0, suite: testSuite.key)\n            }\n        }\n    case .some(\"run\"):\n        if let suite = CommandLine.arguments.dropFirst(2).first {\n            for test in CommandLine.arguments.dropFirst(3) {\n                try runAndEval(test, suite: suite)\n            }\n        } else {\n            usage()\n            exit(EXIT_FAILURE)\n        }\n    case .some(\"_exec\"):\n        if let testSuiteName = CommandLine.arguments.dropFirst(2).first,\n            let testName = CommandLine.arguments.dropFirst(3).first,\n            let crashTest = findCrashTest(testName, suite: testSuiteName)\n        {\n            crashTest.runTest()\n        } else {\n            fatalError(\"can't find/create test for \\(Array(CommandLine.arguments.dropFirst(2)))\")\n        }\n    default:\n        usage()\n        exit(EXIT_FAILURE)\n    }\n\n    exit(CInt(failedTests == 0 ? EXIT_SUCCESS : EXIT_FAILURE))\n}\n\ntry main()\n#endif\n"
  },
  {
    "path": "Sources/NIOEchoClient/README.md",
    "content": "# NIOEchoClient\n\nThis sample application provides a simple echo client that will send a single line to an echo server and wait for a response. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOEchoClient  # Connects to a server on ::1, port 9999.\nswift run NIOEchoClient 9899  # Connects to a server on ::1, port 9899\nswift run NIOEchoClient /path/to/unix/socket  # Connects to a server using the given UNIX socket\nswift run NIOEchoClient echo.example.com 9899  # Connects to a server on echo.example.com:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOEchoClient/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOPosix\n\nprint(\"Please enter line to send to the server\")\nlet line = readLine(strippingNewline: true)!\n\nprivate final class EchoHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n    private var sendBytes = 0\n    private var receiveBuffer: ByteBuffer = ByteBuffer()\n\n    public func channelActive(context: ChannelHandlerContext) {\n        print(\"Client connected to \\(context.remoteAddress?.description ?? \"unknown\")\")\n\n        // We are connected. It's time to send the message to the server to initialize the ping-pong sequence.\n        let buffer = context.channel.allocator.buffer(string: line)\n        self.sendBytes = buffer.readableBytes\n        context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var unwrappedInboundData = Self.unwrapInboundIn(data)\n        self.sendBytes -= unwrappedInboundData.readableBytes\n        receiveBuffer.writeBuffer(&unwrappedInboundData)\n\n        if self.sendBytes == 0 {\n            let string = String(buffer: receiveBuffer)\n            print(\"Received: '\\(string)' back from the server, closing channel.\")\n            context.close(promise: nil)\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n}\n\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\nlet bootstrap = ClientBootstrap(group: group)\n    // Enable SO_REUSEADDR.\n    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n    .channelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandler(EchoHandler())\n        }\n    }\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\n// First argument is the program path\nlet arguments = CommandLine.arguments\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\n\nlet defaultHost = \"::1\"\nlet defaultPort: Int = 9999\n\nenum ConnectTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n    case vsock(_: VsockAddress)\n}\n\nlet connectTarget: ConnectTo\nswitch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {\ncase (_, .some(let cid), .some(let port)):\n    // we got two arguments (Int, Int), let's interpret that as vsock cid and port\n    connectTarget = .vsock(\n        VsockAddress(\n            cid: VsockAddress.ContextID(cid),\n            port: VsockAddress.Port(port)\n        )\n    )\ncase (.some(let h), .none, .some(let p)):\n    // we got two arguments (String, Int), let's interpret that as host and port\n    connectTarget = .ip(host: h, port: p)\ncase (.some(let portString), .none, .none):\n    // we got one argument (String), let's interpret that as unix domain socket path\n    connectTarget = .unixDomainSocket(path: portString)\ncase (_, .some(let p), _):\n    // we got one argument (Int), let's interpret that as port on default host\n    connectTarget = .ip(host: defaultHost, port: p)\ndefault:\n    connectTarget = .ip(host: defaultHost, port: defaultPort)\n}\n\nlet channel = try { () -> Channel in\n    switch connectTarget {\n    case .ip(let host, let port):\n        return try bootstrap.connect(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try bootstrap.connect(unixDomainSocketPath: path).wait()\n    case .vsock(let vsockAddress):\n        return try bootstrap.connect(to: vsockAddress).wait()\n    }\n}()\n\n// Will be closed after we echo-ed back to the server.\ntry channel.closeFuture.wait()\n\nprint(\"Client closed\")\n"
  },
  {
    "path": "Sources/NIOEchoServer/README.md",
    "content": "# NIOEchoServer\n\nThis sample application provides a simple echo server that sends clients back whatever data they send it. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOEchoServer  # Binds the server on ::1, port 9999.\nswift run NIOEchoServer 9899  # Binds the server on ::1, port 9899\nswift run NIOEchoServer /path/to/unix/socket  # Binds the server using the given UNIX socket\nswift run NIOEchoServer 192.168.0.5 9899  # Binds the server on 192.168.0.5:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOEchoServer/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOPosix\n\nprivate final class EchoHandler: ChannelInboundHandler {\n    public typealias InboundIn = ByteBuffer\n    public typealias OutboundOut = ByteBuffer\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.write(data, promise: nil)\n    }\n\n    // Flush it out. This can make use of gathering writes if multiple buffers are pending\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        context.flush()\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n}\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\nlet bootstrap = ServerBootstrap(group: group)\n    // Specify backlog and enable SO_REUSEADDR for the server itself\n    .serverChannelOption(.backlog, value: 256)\n    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n    // Set the handlers that are appled to the accepted Channels\n    .childChannelInitializer { channel in\n        // Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandler(BackPressureHandler())\n            try channel.pipeline.syncOperations.addHandler(EchoHandler())\n        }\n    }\n\n    // Enable SO_REUSEADDR for the accepted Channels\n    .childChannelOption(.socketOption(.so_reuseaddr), value: 1)\n    .childChannelOption(.maxMessagesPerRead, value: 16)\n    .childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator())\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\n// First argument is the program path\nlet arguments = CommandLine.arguments\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\n\nlet defaultHost = \"::1\"\nlet defaultPort = 9999\n\nenum BindTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n    case vsock(_: VsockAddress)\n}\n\nlet bindTarget: BindTo\nswitch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {\ncase (_, .some(let cid), .some(let port)):\n    // we got two arguments (Int, Int), let's interpret that as vsock cid and port\n    bindTarget = .vsock(\n        VsockAddress(\n            cid: VsockAddress.ContextID(cid),\n            port: VsockAddress.Port(port)\n        )\n    )\ncase (.some(let h), _, .some(let p)):\n    // we got two arguments (String, Int), let's interpret that as host and port\n    bindTarget = .ip(host: h, port: p)\ncase (.some(let pathString), .none, .none):\n    // we got one argument (String), let's interpret that unix domain socket path\n    bindTarget = .unixDomainSocket(path: pathString)\ncase (_, .some(let p), .none):\n    // we got one argument (Int), let's interpret that as port on default host\n    bindTarget = .ip(host: defaultHost, port: p)\ndefault:\n    bindTarget = .ip(host: defaultHost, port: defaultPort)\n}\n\nlet channel = try { () -> Channel in\n    switch bindTarget {\n    case .ip(let host, let port):\n        return try bootstrap.bind(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try bootstrap.bind(unixDomainSocketPath: path).wait()\n    case .vsock(let vsockAddress):\n        return try bootstrap.bind(to: vsockAddress).wait()\n    }\n}()\n\nswitch bindTarget {\ncase .ip, .unixDomainSocket:\n    print(\"Server started and listening on \\(channel.localAddress!)\")\ncase .vsock(let vsockAddress):\n    print(\"Server started and listening on \\(vsockAddress)\")\n}\n\n// This will never unblock as we don't close the ServerChannel\ntry channel.closeFuture.wait()\n\nprint(\"Server closed\")\n"
  },
  {
    "path": "Sources/NIOEmbedded/AsyncTestingChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Dispatch)\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n/// A `Channel` with fine-grained control for testing.\n///\n/// ``NIOAsyncTestingChannel`` is a `Channel` implementation that does no\n/// actual IO but that does have proper eventing mechanism, albeit one that users can\n/// control. The prime use-case for ``NIOAsyncTestingChannel`` is in unit tests when you\n/// want to feed the inbound events and check the outbound events manually.\n///\n/// Please remember to call ``finish()`` when you are no longer using this\n/// ``NIOAsyncTestingChannel``.\n///\n/// To feed events through an ``NIOAsyncTestingChannel``'s `ChannelPipeline` use\n/// ``NIOAsyncTestingChannel/writeInbound(_:)`` which accepts data of any type. It will then\n/// forward that data through the `ChannelPipeline` and the subsequent\n/// `ChannelInboundHandler` will receive it through the usual `channelRead`\n/// event. The user is responsible for making sure the first\n/// `ChannelInboundHandler` expects data of that type.\n///\n/// Unlike in a regular `ChannelPipeline`, it is expected that the test code will act\n/// as the \"network layer\", using ``readOutbound(as:)`` to observe the data that the\n/// `Channel` has \"written\" to the network, and using ``writeInbound(_:)`` to simulate\n/// receiving data from the network. There are also facilities to make it a bit easier\n/// to handle the logic for `write` and `flush` (using ``writeOutbound(_:)``), and to\n/// extract data that passed the whole way along the channel in `channelRead` (using\n/// ``readOutbound(as:)``. Below is a diagram showing the layout of a `ChannelPipeline`\n/// inside a ``NIOAsyncTestingChannel``, including the functions that can be used to\n/// inject and extract data at each end.\n///\n/// ```\n///\n///            Extract data                         Inject data\n///         using readInbound()                using writeOutbound()\n///                  ▲                                   |\n///  +---------------+-----------------------------------+---------------+\n///  |               |           ChannelPipeline         |               |\n///  |               |                TAIL               ▼               |\n///  |    +---------------------+            +-----------+----------+    |\n///  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |               ▲                                   |               |\n///  |               |                                   ▼               |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |               ▲                                   .               |\n///  |               .                                   .               |\n///  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|\n///  |        [ method call]                       [method call]         |\n///  |               .                                   .               |\n///  |               .                                   ▼               |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |               ▲                                   |               |\n///  |               |                                   ▼               |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |\n///  |    +----------+----------+            +-----------+----------+    |\n///  |               ▲              HEAD                 |               |\n///  +---------------+-----------------------------------+---------------+\n///                  |                                   ▼\n///             Inject data                         Extract data\n///         using writeInbound()                using readOutbound()\n/// ```\n///\n/// - Note: ``NIOAsyncTestingChannel`` is currently only compatible with\n///   ``NIOAsyncTestingEventLoop``s and cannot be used with `SelectableEventLoop`s from\n///   for example `MultiThreadedEventLoopGroup`.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic final class NIOAsyncTestingChannel: Channel {\n    /// ``LeftOverState`` represents any left-over inbound, outbound, and pending outbound events that hit the\n    /// ``NIOAsyncTestingChannel`` and were not consumed when ``finish()`` was called on the ``NIOAsyncTestingChannel``.\n    ///\n    /// ``NIOAsyncTestingChannel`` is most useful in testing and usually in unit tests, you want to consume all inbound and\n    /// outbound data to verify they are what you expect. Therefore, when you ``finish()`` a ``NIOAsyncTestingChannel`` it will\n    /// return if it's either ``LeftOverState/clean`` (no left overs) or that it has ``LeftOverState/leftOvers(inbound:outbound:pendingOutbound:)``.\n    public enum LeftOverState {\n        /// The ``NIOAsyncTestingChannel`` is clean, ie. no inbound, outbound, or pending outbound data left on ``NIOAsyncTestingChannel/finish()``.\n        case clean\n\n        /// The ``NIOAsyncTestingChannel`` has inbound, outbound, or pending outbound data left on ``NIOAsyncTestingChannel/finish()``.\n        case leftOvers(inbound: CircularBuffer<NIOAny>, outbound: CircularBuffer<NIOAny>, pendingOutbound: [NIOAny])\n\n        /// `true` if the ``NIOAsyncTestingChannel`` was `clean` on ``NIOAsyncTestingChannel/finish()``, ie. there is no unconsumed inbound, outbound, or\n        /// pending outbound data left on the `Channel`.\n        public var isClean: Bool {\n            if case .clean = self {\n                return true\n            } else {\n                return false\n            }\n        }\n\n        /// `true` if the ``NIOAsyncTestingChannel`` if there was unconsumed inbound, outbound, or pending outbound data left\n        /// on the `Channel` when it was `finish`ed.\n        public var hasLeftOvers: Bool {\n            !self.isClean\n        }\n    }\n\n    /// ``BufferState`` represents the state of either the inbound, or the outbound ``NIOAsyncTestingChannel`` buffer.\n    ///\n    /// These buffers contain data that travelled the `ChannelPipeline` all the way through..\n    ///\n    /// If the last `ChannelHandler` explicitly (by calling `fireChannelRead`) or implicitly (by not implementing\n    /// `channelRead`) sends inbound data into the end of the ``NIOAsyncTestingChannel``, it will be held in the\n    /// ``NIOAsyncTestingChannel``'s inbound buffer. Similarly for `write` on the outbound side. The state of the respective\n    /// buffer will be returned from ``writeInbound(_:)``/``writeOutbound(_:)`` as a ``BufferState``.\n    public enum BufferState {\n        /// The buffer is empty.\n        case empty\n\n        /// The buffer is non-empty.\n        case full(CircularBuffer<NIOAny>)\n\n        /// Returns `true` is the buffer was empty.\n        public var isEmpty: Bool {\n            if case .empty = self {\n                return true\n            } else {\n                return false\n            }\n        }\n\n        /// Returns `true` if the buffer was non-empty.\n        public var isFull: Bool {\n            !self.isEmpty\n        }\n    }\n\n    /// ``WrongTypeError`` is thrown if you use ``readInbound(as:)`` or ``readOutbound(as:)`` and request a certain type but the first\n    /// item in the respective buffer is of a different type.\n    public struct WrongTypeError: Error, Equatable {\n        /// The type you expected.\n        public let expected: Any.Type\n\n        /// The type of the actual first element.\n        public let actual: Any.Type\n\n        public init(expected: Any.Type, actual: Any.Type) {\n            self.expected = expected\n            self.actual = actual\n        }\n\n        public static func == (lhs: WrongTypeError, rhs: WrongTypeError) -> Bool {\n            lhs.expected == rhs.expected && lhs.actual == rhs.actual\n        }\n    }\n\n    /// Returns `true` if the ``NIOAsyncTestingChannel`` is 'active'.\n    ///\n    /// An active ``NIOAsyncTestingChannel`` can be closed by calling `close` or ``finish()`` on the ``NIOAsyncTestingChannel``.\n    ///\n    /// - Note: An ``NIOAsyncTestingChannel`` starts _inactive_ and can be activated, for example by calling `connect`.\n    public var isActive: Bool { channelcore.isActive }\n\n    /// - see: `ChannelOptions.Types.AllowRemoteHalfClosureOption`\n    public var allowRemoteHalfClosure: Bool {\n        get {\n            channelcore.allowRemoteHalfClosure\n        }\n        set {\n            channelcore.allowRemoteHalfClosure = newValue\n        }\n    }\n\n    /// - see: `Channel.closeFuture`\n    public var closeFuture: EventLoopFuture<Void> { channelcore.closePromise.futureResult }\n\n    /// - see: `Channel.allocator`\n    public let allocator: ByteBufferAllocator = ByteBufferAllocator()\n\n    /// - see: `Channel.eventLoop`\n    public var eventLoop: EventLoop {\n        self.testingEventLoop\n    }\n\n    /// Returns the ``NIOAsyncTestingEventLoop`` that this ``NIOAsyncTestingChannel`` uses. This will return the same instance as\n    /// ``NIOAsyncTestingChannel/eventLoop`` but as the concrete ``NIOAsyncTestingEventLoop`` rather than as `EventLoop` existential.\n    public let testingEventLoop: NIOAsyncTestingEventLoop\n\n    /// `nil` because ``NIOAsyncTestingChannel``s don't have parents.\n    public let parent: Channel? = nil\n\n    // These two variables are only written once, from a single thread, and never written again, so they're _technically_ thread-safe. Most methods cannot safely\n    // be used from multiple threads, but `isActive`, `isOpen`, `eventLoop`, and `closeFuture` can all safely be used from any thread. Just.\n    // `EmbeddedChannelCore`'s localAddress and remoteAddress fields are protected by a lock so they are safe to access.\n    @usableFromInline\n    nonisolated(unsafe) var channelcore: EmbeddedChannelCore!\n    nonisolated(unsafe) private var _pipeline: ChannelPipeline!\n\n    @usableFromInline\n    internal struct State: Sendable {\n        var isWritable: Bool\n\n        @usableFromInline\n        var options: [(option: any ChannelOption, value: any Sendable)]\n    }\n\n    /// Guards any of the getters/setters that can be accessed from any thread.\n    @usableFromInline\n    internal let _stateLock = NIOLockedValueBox(\n        State(isWritable: true, options: [])\n    )\n\n    /// - see: `Channel._channelCore`\n    public var _channelCore: ChannelCore {\n        channelcore\n    }\n\n    /// - see: `Channel.pipeline`\n    public var pipeline: ChannelPipeline {\n        _pipeline\n    }\n\n    /// - see: `Channel.isWritable`\n    public var isWritable: Bool {\n        get {\n            self._stateLock.withLockedValue { $0.isWritable }\n        }\n        set {\n            self._stateLock.withLockedValue {\n                $0.isWritable = newValue\n            }\n        }\n    }\n\n    /// - see: `Channel.localAddress`\n    public var localAddress: SocketAddress? {\n        get {\n            self.channelcore.localAddress\n        }\n        set {\n            self.channelcore.localAddress = newValue\n        }\n    }\n\n    /// - see: `Channel.remoteAddress`\n    public var remoteAddress: SocketAddress? {\n        get {\n            self.channelcore.remoteAddress\n        }\n        set {\n            self.channelcore.remoteAddress = newValue\n        }\n    }\n\n    /// The `ChannelOption`s set on this channel.\n    /// - see: `NIOAsyncTestingChannel.setOption`\n    public var options: [(option: any ChannelOption, value: any Sendable)] {\n        self._stateLock.withLockedValue { $0.options }\n    }\n    /// Create a new instance.\n    ///\n    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.\n    ///\n    /// - Parameters:\n    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.\n    public init(loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()) {\n        self.testingEventLoop = loop\n        self._pipeline = ChannelPipeline(channel: self)\n        self.channelcore = EmbeddedChannelCore(pipeline: self._pipeline, eventLoop: self.eventLoop)\n    }\n\n    /// Create a new instance.\n    ///\n    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.\n    ///\n    /// - Parameters:\n    ///   - handler: The `ChannelHandler` to add to the `ChannelPipeline` before register.\n    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.\n    @preconcurrency\n    public convenience init(\n        handler: ChannelHandler & Sendable,\n        loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()\n    ) async {\n        await self.init(handlers: [handler], loop: loop)\n    }\n\n    /// Create a new instance.\n    ///\n    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.\n    ///\n    /// - Parameters:\n    ///   - handlers: The `ChannelHandler`s to add to the `ChannelPipeline` before register.\n    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.\n    @preconcurrency\n    public convenience init(\n        handlers: [ChannelHandler & Sendable],\n        loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()\n    ) async {\n        try! await self.init(loop: loop) { channel in\n            try channel.pipeline.syncOperations.addHandlers(handlers)\n        }\n    }\n\n    /// Create a new instance.\n    ///\n    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.\n    ///\n    /// - Parameters:\n    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.\n    ///   - channelInitializer: The initialization closure which will be run on the `EventLoop` before registration. This could be used to add handlers using `syncOperations`.\n    public convenience init(\n        loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop(),\n        channelInitializer: @escaping @Sendable (NIOAsyncTestingChannel) throws -> Void\n    ) async throws {\n        self.init(loop: loop)\n        try await loop.submit {\n            try channelInitializer(self)\n        }.get()\n        try await self.register()\n    }\n\n    /// Asynchronously closes the ``NIOAsyncTestingChannel``.\n    ///\n    /// Errors in the ``NIOAsyncTestingChannel`` can be consumed using ``throwIfErrorCaught()``.\n    ///\n    /// - Parameters:\n    ///   - acceptAlreadyClosed: Whether ``finish()`` should throw if the ``NIOAsyncTestingChannel`` has been previously `close`d.\n    /// - Returns: The ``LeftOverState`` of the ``NIOAsyncTestingChannel``. If all the inbound and outbound events have been\n    ///            consumed (using ``readInbound(as:)`` / ``readOutbound(as:)``) and there are no pending outbound events (unflushed\n    ///            writes) this will be ``LeftOverState/clean``. If there are any unconsumed inbound, outbound, or pending outbound\n    ///            events, the ``NIOAsyncTestingChannel`` will returns those as ``LeftOverState/leftOvers(inbound:outbound:pendingOutbound:)``.\n    public func finish(acceptAlreadyClosed: Bool) async throws -> LeftOverState {\n        do {\n            try await self.close().get()\n        } catch let error as ChannelError {\n            guard error == .alreadyClosed && acceptAlreadyClosed else {\n                throw error\n            }\n        }\n\n        // This can never actually throw.\n        try! await self.testingEventLoop.executeInContext {\n            self.testingEventLoop.drainScheduledTasksByRunningAllCurrentlyScheduledTasks()\n        }\n        await self.testingEventLoop.run()\n        try await throwIfErrorCaught()\n\n        // This can never actually throw.\n        return try! await self.testingEventLoop.executeInContext {\n            let c = self.channelcore!\n            if c.outboundBuffer.isEmpty && c.inboundBuffer.isEmpty && c.pendingOutboundBuffer.isEmpty {\n                return .clean\n            } else {\n                return .leftOvers(\n                    inbound: c.inboundBuffer,\n                    outbound: c.outboundBuffer,\n                    pendingOutbound: c.pendingOutboundBuffer.map { $0.0 }\n                )\n            }\n        }\n    }\n\n    /// Asynchronously closes the ``NIOAsyncTestingChannel``.\n    ///\n    /// This method will throw if the `Channel` hit any unconsumed errors or if the `close` fails. Errors in the\n    /// ``NIOAsyncTestingChannel`` can be consumed using ``throwIfErrorCaught()``.\n    ///\n    /// - Returns: The ``LeftOverState`` of the ``NIOAsyncTestingChannel``. If all the inbound and outbound events have been\n    ///            consumed (using ``readInbound(as:)`` / ``readOutbound(as:)``) and there are no pending outbound events (unflushed\n    ///            writes) this will be ``LeftOverState/clean``. If there are any unconsumed inbound, outbound, or pending outbound\n    ///            events, the ``NIOAsyncTestingChannel`` will returns those as ``LeftOverState/leftOvers(inbound:outbound:pendingOutbound:)``.\n    public func finish() async throws -> LeftOverState {\n        try await self.finish(acceptAlreadyClosed: false)\n    }\n\n    /// If available, this method reads one element of type `T` out of the ``NIOAsyncTestingChannel``'s outbound buffer. If the\n    /// first element was of a different type than requested, ``WrongTypeError`` will be thrown, if there\n    /// are no elements in the outbound buffer, `nil` will be returned.\n    ///\n    /// Data hits the ``NIOAsyncTestingChannel``'s outbound buffer when data was written using `write`, then `flush`ed, and\n    /// then travelled the `ChannelPipeline` all the way to the front. For data to hit the outbound buffer, the very\n    /// first `ChannelHandler` must have written and flushed it either explicitly (by calling\n    /// `ChannelHandlerContext.write` and `flush`) or implicitly by not implementing `write`/`flush`.\n    ///\n    /// - Note: Outbound events travel the `ChannelPipeline` _back to front_.\n    /// - Note: ``NIOAsyncTestingChannel/writeOutbound(_:)`` will `write` data through the `ChannelPipeline`, starting with last\n    ///         `ChannelHandler`.\n    @inlinable\n    public func readOutbound<T: Sendable>(as type: T.Type = T.self) async throws -> T? {\n        try await self.testingEventLoop.executeInContext {\n            try self._readFromBuffer(buffer: &self.channelcore.outboundBuffer)\n        }\n    }\n\n    /// This method is similar to ``NIOAsyncTestingChannel/readOutbound(as:)`` but will wait if the outbound buffer is empty.\n    /// If available, this method reads one element of type `T` out of the ``NIOAsyncTestingChannel``'s outbound buffer. If the\n    /// first element was of a different type than requested, ``WrongTypeError`` will be thrown. If the channel has\n    /// already closed or closes before the next pending outbound write, `ChannelError.ioOnClosedChannel` will be\n    /// thrown. If there are no elements in the outbound buffer, this method will wait until there is one, and return\n    /// that element.\n    ///\n    /// Data hits the ``NIOAsyncTestingChannel``'s outbound buffer when data was written using `write`, then `flush`ed, and\n    /// then travelled the `ChannelPipeline` all the way to the front. For data to hit the outbound buffer, the very\n    /// first `ChannelHandler` must have written and flushed it either explicitly (by calling\n    /// `ChannelHandlerContext.write` and `flush`) or implicitly by not implementing `write`/`flush`.\n    ///\n    /// - Note: Outbound events travel the `ChannelPipeline` _back to front_.\n    /// - Note: ``NIOAsyncTestingChannel/writeOutbound(_:)`` will `write` data through the `ChannelPipeline`, starting with last\n    ///         `ChannelHandler`.\n    public func waitForOutboundWrite<T: Sendable>(as type: T.Type = T.self) async throws -> T {\n        try await withCheckedThrowingContinuation { continuation in\n            self.testingEventLoop.execute {\n                do {\n                    if let element: T = try self._readFromBuffer(buffer: &self.channelcore.outboundBuffer) {\n                        continuation.resume(returning: element)\n                        return\n                    }\n                    self.channelcore._enqueueOutboundBufferConsumer { element in\n                        switch element {\n                        case .success(let data):\n                            continuation.resume(with: Result { try self._cast(data) })\n                        case .failure(let failure):\n                            continuation.resume(throwing: failure)\n                        }\n                    }\n                } catch {\n                    continuation.resume(throwing: error)\n                }\n            }\n        }\n    }\n\n    /// If available, this method reads one element of type `T` out of the ``NIOAsyncTestingChannel``'s inbound buffer. If the\n    /// first element was of a different type than requested, ``WrongTypeError`` will be thrown, if there\n    /// are no elements in the outbound buffer, `nil` will be returned.\n    ///\n    /// Data hits the ``NIOAsyncTestingChannel``'s inbound buffer when data was send through the pipeline using `fireChannelRead`\n    /// and then travelled the `ChannelPipeline` all the way to the back. For data to hit the inbound buffer, the\n    /// last `ChannelHandler` must have send the event either explicitly (by calling\n    /// `ChannelHandlerContext.fireChannelRead`) or implicitly by not implementing `channelRead`.\n    ///\n    /// - Note: ``NIOAsyncTestingChannel/writeInbound(_:)`` will fire data through the `ChannelPipeline` using `fireChannelRead`.\n    @inlinable\n    public func readInbound<T: Sendable>(as type: T.Type = T.self) async throws -> T? {\n        try await self.testingEventLoop.executeInContext {\n            try self._readFromBuffer(buffer: &self.channelcore.inboundBuffer)\n        }\n    }\n\n    /// This method is similar to ``NIOAsyncTestingChannel/readInbound(as:)`` but will wait if the inbound buffer is empty.\n    /// If available, this method reads one element of type `T` out of the ``NIOAsyncTestingChannel``'s inbound buffer. If the\n    /// first element was of a different type than requested, ``WrongTypeError`` will be thrown. If the channel has\n    /// already closed or closes before the next pending inbound write, `ChannelError.ioOnClosedChannel` will be thrown.\n    /// If there are no elements in the inbound buffer, this method will wait until there is one, and return that\n    /// element.\n    ///\n    /// Data hits the ``NIOAsyncTestingChannel``'s inbound buffer when data was send through the pipeline using `fireChannelRead`\n    /// and then travelled the `ChannelPipeline` all the way to the back. For data to hit the inbound buffer, the\n    /// last `ChannelHandler` must have send the event either explicitly (by calling\n    /// `ChannelHandlerContext.fireChannelRead`) or implicitly by not implementing `channelRead`.\n    ///\n    /// - Note: ``NIOAsyncTestingChannel/writeInbound(_:)`` will fire data through the `ChannelPipeline` using `fireChannelRead`.\n    public func waitForInboundWrite<T: Sendable>(as type: T.Type = T.self) async throws -> T {\n        try await withCheckedThrowingContinuation { continuation in\n            self.testingEventLoop.execute {\n                do {\n                    if let element: T = try self._readFromBuffer(buffer: &self.channelcore.inboundBuffer) {\n                        continuation.resume(returning: element)\n                        return\n                    }\n                    self.channelcore._enqueueInboundBufferConsumer { element in\n                        switch element {\n                        case .success(let data):\n                            continuation.resume(with: Result { try self._cast(data) })\n                        case .failure(let failure):\n                            continuation.resume(throwing: failure)\n                        }\n                    }\n                } catch {\n                    continuation.resume(throwing: error)\n                }\n            }\n        }\n    }\n\n    /// Sends an inbound `channelRead` event followed by a `channelReadComplete` event through the `ChannelPipeline`.\n    ///\n    /// The immediate effect being that the first `ChannelInboundHandler` will get its `channelRead` method called\n    /// with the data you provide.\n    ///\n    /// - Parameters:\n    ///    - data: The data to fire through the pipeline.\n    /// - Returns: The state of the inbound buffer which contains all the events that travelled the `ChannelPipeline`\n    //             all the way.\n    @inlinable\n    @discardableResult public func writeInbound<T: Sendable>(_ data: T) async throws -> BufferState {\n        try await self.testingEventLoop.executeInContext {\n            self.pipeline.fireChannelRead(data)\n            self.pipeline.fireChannelReadComplete()\n            try self._throwIfErrorCaught()\n            return self.channelcore.inboundBuffer.isEmpty ? .empty : .full(self.channelcore.inboundBuffer)\n        }\n    }\n\n    /// Sends an outbound `writeAndFlush` event through the `ChannelPipeline`.\n    ///\n    /// The immediate effect being that the first `ChannelOutboundHandler` will get its `write` method called\n    /// with the data you provide. Note that the first `ChannelOutboundHandler` in the pipeline is the _last_ handler\n    /// because outbound events travel the pipeline from back to front.\n    ///\n    /// - Parameters:\n    ///    - data: The data to fire through the pipeline.\n    /// - Returns: The state of the outbound buffer which contains all the events that travelled the `ChannelPipeline`\n    //             all the way.\n    @inlinable\n    @discardableResult public func writeOutbound<T: Sendable>(_ data: T) async throws -> BufferState {\n        try await self.writeAndFlush(data)\n\n        return try await self.testingEventLoop.executeInContext {\n            self.channelcore.outboundBuffer.isEmpty ? .empty : .full(self.channelcore.outboundBuffer)\n        }\n    }\n\n    /// This method will throw the error that is stored in the ``NIOAsyncTestingChannel`` if any.\n    ///\n    /// The ``NIOAsyncTestingChannel`` will store an error if some error travels the `ChannelPipeline` all the way past its end.\n    public func throwIfErrorCaught() async throws {\n        try await self.testingEventLoop.executeInContext {\n            try self._throwIfErrorCaught()\n        }\n    }\n\n    @usableFromInline\n    func _throwIfErrorCaught() throws {\n        self.testingEventLoop.preconditionInEventLoop()\n        if let error = self.channelcore.error {\n            self.channelcore.error = nil\n            throw error\n        }\n    }\n\n    @inlinable\n    func _readFromBuffer<T>(buffer: inout CircularBuffer<NIOAny>) throws -> T? {\n        self.testingEventLoop.preconditionInEventLoop()\n\n        if buffer.isEmpty {\n            return nil\n        }\n        return try self._cast(buffer.removeFirst(), to: T.self)\n    }\n\n    @inlinable\n    func _cast<T>(_ element: NIOAny, to: T.Type = T.self) throws -> T {\n        guard let t = self._channelCore.tryUnwrapData(element, as: T.self) else {\n            throw WrongTypeError(\n                expected: T.self,\n                actual: type(of: self._channelCore.tryUnwrapData(element, as: Any.self)!)\n            )\n        }\n        return t\n    }\n\n    /// - see: `Channel.setOption`\n    @inlinable\n    public func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void> {\n        if self.eventLoop.inEventLoop {\n            self.setOptionSync(option, value: value)\n            return self.eventLoop.makeSucceededVoidFuture()\n        } else {\n            return self.eventLoop.submit { self.setOptionSync(option, value: value) }\n        }\n    }\n\n    @inlinable\n    internal func setOptionSync<Option: ChannelOption>(_ option: Option, value: Option.Value) {\n        addOption(option, value: value)\n\n        if option is ChannelOptions.Types.AllowRemoteHalfClosureOption {\n            self.allowRemoteHalfClosure = value as! Bool\n            return\n        }\n    }\n\n    /// - see: `Channel.getOption`\n    @inlinable\n    public func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value> {\n        if self.eventLoop.inEventLoop {\n            return self.eventLoop.makeSucceededFuture(self.getOptionSync(option))\n        } else {\n            return self.eventLoop.submit { self.getOptionSync(option) }\n        }\n    }\n\n    @inlinable\n    internal func getOptionSync<Option: ChannelOption>(_ option: Option) -> Option.Value {\n        if option is ChannelOptions.Types.AutoReadOption {\n            return true as! Option.Value\n        }\n        if option is ChannelOptions.Types.AllowRemoteHalfClosureOption {\n            return self.allowRemoteHalfClosure as! Option.Value\n        }\n        if option is ChannelOptions.Types.BufferedWritableBytesOption {\n            let result = self.channelcore.pendingOutboundBuffer.reduce(0) { partialResult, dataAndPromise in\n                let buffer = self.channelcore.unwrapData(dataAndPromise.0, as: ByteBuffer.self)\n                return partialResult + buffer.readableBytes\n            }\n\n            return result as! Option.Value\n        }\n\n        guard let value = self.optionValue(for: option) else {\n            fatalError(\"option \\(option) not supported\")\n        }\n\n        return value\n    }\n\n    @inlinable\n    internal func optionValue<Option: ChannelOption>(for option: Option) -> Option.Value? {\n        self.options.first(where: { $0.option is Option })?.value as? Option.Value\n    }\n\n    @inlinable\n    internal func addOption<Option: ChannelOption>(_ option: Option, value: Option.Value) {\n        // override the option if it exists\n        self._stateLock.withLockedValue { state in\n            var options = state.options\n            let optionIndex = options.firstIndex(where: { $0.option is Option })\n            if let optionIndex = optionIndex {\n                options[optionIndex] = (option, value)\n            } else {\n                options.append((option, value))\n            }\n            state.options = options\n        }\n    }\n\n    /// Fires the (outbound) `bind` event through the `ChannelPipeline`. If the event hits the ``NIOAsyncTestingChannel`` which\n    /// happens when it travels the `ChannelPipeline` all the way to the front, this will also set the\n    /// ``NIOAsyncTestingChannel``'s ``localAddress``.\n    ///\n    /// - Parameters:\n    ///   - address: The address to fake-bind to.\n    ///   - promise: The `EventLoopPromise` which will be fulfilled when the fake-bind operation has been done.\n    public func bind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        let promise = promise ?? self.testingEventLoop.makePromise()\n        promise.futureResult.whenSuccess {\n            self.localAddress = address\n        }\n        if self.eventLoop.inEventLoop {\n            self.pipeline.bind(to: address, promise: promise)\n        } else {\n            self.eventLoop.execute {\n                self.pipeline.bind(to: address, promise: promise)\n            }\n        }\n    }\n\n    /// Fires the (outbound) `connect` event through the `ChannelPipeline`. If the event hits the ``NIOAsyncTestingChannel``\n    /// which happens when it travels the `ChannelPipeline` all the way to the front, this will also set the\n    /// ``NIOAsyncTestingChannel``'s ``remoteAddress``.\n    ///\n    /// - Parameters:\n    ///   - address: The address to fake-bind to.\n    ///   - promise: The `EventLoopPromise` which will be fulfilled when the fake-bind operation has been done.\n    public func connect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        let promise = promise ?? self.testingEventLoop.makePromise()\n        promise.futureResult.whenSuccess {\n            self.remoteAddress = address\n        }\n        if self.eventLoop.inEventLoop {\n            self.pipeline.connect(to: address, promise: promise)\n        } else {\n            self.eventLoop.execute {\n                self.pipeline.connect(to: address, promise: promise)\n            }\n        }\n    }\n\n    public struct SynchronousOptions: NIOSynchronousChannelOptions {\n        @usableFromInline\n        internal let channel: NIOAsyncTestingChannel\n\n        fileprivate init(channel: NIOAsyncTestingChannel) {\n            self.channel = channel\n        }\n\n        @inlinable\n        public func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n            self.channel.eventLoop.preconditionInEventLoop()\n            self.channel.setOptionSync(option, value: value)\n        }\n\n        @inlinable\n        public func getOption<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n            self.channel.eventLoop.preconditionInEventLoop()\n            return self.channel.getOptionSync(option)\n        }\n    }\n\n    public final var syncOptions: NIOSynchronousChannelOptions? {\n        SynchronousOptions(channel: self)\n    }\n}\n\n// MARK: Unchecked sendable\n//\n// Both of these types are unchecked Sendable because strictly, they aren't. This is\n// because they contain NIOAny, a non-Sendable type. In this instance, we tolerate the moving\n// of this object across threads because in the overwhelming majority of cases the data types\n// in a channel pipeline _are_ `Sendable`, and because these objects only carry NIOAnys in cases\n// where the `Channel` itself no longer holds a reference to these objects.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOAsyncTestingChannel.LeftOverState: @unchecked Sendable {}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOAsyncTestingChannel.BufferState: @unchecked Sendable {}\n\n// Synchronous options are never Sendable.\n@available(*, unavailable)\nextension NIOAsyncTestingChannel.SynchronousOptions: Sendable {}\n\n#endif  // canImport(Dispatch)\n"
  },
  {
    "path": "Sources/NIOEmbedded/AsyncTestingEventLoop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Dispatch)\nimport Atomics\n\n#if canImport(Darwin)\nimport Dispatch\n#else\n@preconcurrency import Dispatch\n#endif\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport _NIODataStructures\n\n/// An `EventLoop` that is thread safe and whose execution is fully controlled\n/// by the user.\n///\n/// Unlike more complex `EventLoop`s, such as `SelectableEventLoop`, the `NIOAsyncTestingEventLoop`\n/// has no proper eventing mechanism. Instead, reads and writes are fully controlled by the\n/// entity that instantiates the `NIOAsyncTestingEventLoop`. This property makes `NIOAsyncTestingEventLoop`\n/// of limited use for many application purposes, but highly valuable for testing and other\n/// kinds of mocking. Unlike `EmbeddedEventLoop`, `NIOAsyncTestingEventLoop` is fully thread-safe and\n/// safe to use from within a Swift concurrency context.\n///\n/// Unlike `EmbeddedEventLoop`, `NIOAsyncTestingEventLoop` does require that user tests appropriately\n/// enforce thread safety. Used carefully it is possible to safely operate the event loop without\n/// explicit synchronization, but it is recommended to use `executeInContext` in any case where it's\n/// necessary to ensure that the event loop is not making progress.\n///\n/// Time is controllable on an `NIOAsyncTestingEventLoop`. It begins at `NIODeadline.uptimeNanoseconds(0)`\n/// and may be advanced by a fixed amount by using `advanceTime(by:)`, or advanced to a point in\n/// time with `advanceTime(to:)`.\n///\n/// If users wish to perform multiple tasks at once on an `NIOAsyncTestingEventLoop`, it is recommended that they\n/// use `executeInContext` to perform the operations. For example:\n///\n/// ```\n/// await loop.executeInContext {\n///     // All three of these will be queued up simultaneously, and no other code can\n///     // get between them.\n///     loop.execute { firstTask() }\n///     loop.execute { secondTask() }\n///     loop.execute { thirdTask() }\n/// }\n/// ```\n///\n/// There is a tricky requirement around waiting for `EventLoopFuture`s when working with this\n/// event loop. Simply calling `.wait()` from the test thread will never complete. This is because\n/// `wait` calls `loop.execute` under the hood, and that callback cannot execute without calling\n/// `loop.run()`.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic final class NIOAsyncTestingEventLoop: EventLoop, @unchecked Sendable {\n    // This type is `@unchecked Sendable` because of the use of `taskNumber`. This\n    // variable is only used from within `queue`, but the compiler cannot see that.\n\n    /// The current \"time\" for this event loop. This is an amount in nanoseconds.\n    /// As we need to access this from any thread, we store this as an atomic.\n    private let _now = ManagedAtomic<UInt64>(0)\n\n    /// The current \"time\" for this event loop. This is an amount in nanoseconds.\n    public var now: NIODeadline {\n        NIODeadline.uptimeNanoseconds(self._now.load(ordering: .relaxed))\n    }\n\n    /// This is used to derive an identifier for this loop.\n    private var thisLoopID: ObjectIdentifier {\n        ObjectIdentifier(self)\n    }\n\n    /// A dispatch specific that we use to determine whether we are on the queue for this\n    /// \"event loop\".\n    private static let inQueueKey = DispatchSpecificKey<ObjectIdentifier>()\n\n    // Our scheduledTaskCounter needs to be an atomic because we're going to access it from\n    // arbitrary threads. This is required by the EventLoop protocol and cannot be avoided.\n    // Specifically, Scheduled<T> creation requires us to be able to define the cancellation\n    // operation, so the task ID has to be created early.\n    private let scheduledTaskCounter = ManagedAtomic<UInt64>(0)\n    private var scheduledTasks = PriorityQueue<EmbeddedScheduledTask>()\n\n    /// Keep track of where promises are allocated to ensure we can identify their source if they leak.\n    private let _promiseCreationStore = PromiseCreationStore()\n\n    // The number of the next task to be created. We track the order so that when we execute tasks\n    // scheduled at the same time, we may do so in the order in which they were submitted for\n    // execution.\n    //\n    // This can only be accessed from `queue`\n    private var taskNumber = UInt64(0)\n\n    /// The queue on which we run all our operations.\n    private let queue = DispatchQueue(label: \"io.swiftnio.AsyncEmbeddedEventLoop\")\n\n    private enum State: Int, AtomicValue { case open, closing, closed }\n    private let state = ManagedAtomic(State.open)\n\n    // This function must only be called on queue.\n    private func nextTaskNumber() -> UInt64 {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n        defer {\n            self.taskNumber += 1\n        }\n        return self.taskNumber\n    }\n\n    /// - see: `EventLoop.inEventLoop`\n    public var inEventLoop: Bool {\n        DispatchQueue.getSpecific(key: Self.inQueueKey) == self.thisLoopID\n    }\n\n    /// Initialize a new `NIOAsyncTestingEventLoop`.\n    public init() {\n        self.queue.setSpecific(key: Self.inQueueKey, value: self.thisLoopID)\n    }\n\n    private func removeTask(taskID: UInt64) {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n        self.scheduledTasks.removeFirst { $0.id == taskID }\n    }\n\n    private func insertTask<ReturnType>(\n        taskID: UInt64,\n        deadline: NIODeadline,\n        promise: EventLoopPromise<ReturnType>?,\n        task: @escaping () throws -> ReturnType\n    ) {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n\n        let task = EmbeddedScheduledTask(\n            id: taskID,\n            readyTime: deadline,\n            insertOrder: self.nextTaskNumber(),\n            task: {\n                do {\n                    // UnsafeUnchecked is acceptable because we know we're in the loop here.\n                    let result = try task()\n                    promise?.assumeIsolatedUnsafeUnchecked().succeed(result)\n                } catch let err {\n                    promise?.fail(err)\n                }\n            },\n            { promise?.fail($0) }\n        )\n\n        self.scheduledTasks.push(task)\n    }\n\n    /// - see: `EventLoop.scheduleTask(deadline:_:)`\n    @discardableResult\n    @preconcurrency\n    public func scheduleTask<T>(\n        deadline: NIODeadline,\n        _ task: @escaping @Sendable () throws -> T\n    ) -> Scheduled<T> {\n        let scheduled: Scheduled<T>\n        switch self._prepareToSchedule(returnType: T.self) {\n        case .doSchedule(let taskID, let promise, let returned):\n            scheduled = returned\n\n            // Ok, actually do it.\n            if self.inEventLoop {\n                self.insertTask(taskID: taskID, deadline: deadline, promise: promise, task: task)\n            } else {\n                self.queue.async {\n                    self.insertTask(taskID: taskID, deadline: deadline, promise: promise, task: task)\n                }\n            }\n\n        case .returnImmediately(let returned):\n            scheduled = returned\n        }\n\n        return scheduled\n    }\n\n    /// - see: `EventLoop.scheduleTask(in:_:)`\n    @discardableResult\n    @preconcurrency\n    public func scheduleTask<T>(in: TimeAmount, _ task: @escaping @Sendable () throws -> T) -> Scheduled<T> {\n        self.scheduleTask(deadline: self.now + `in`, task)\n    }\n\n    @preconcurrency\n    public func scheduleCallback(\n        at deadline: NIODeadline,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) throws -> NIOScheduledCallback {\n        /// The default implementation of `scheduledCallback(at:handler)` makes two calls to the event loop because it\n        /// needs to hook the future of the backing scheduled task, which can lead to lost cancellation callbacks when\n        /// callbacks are scheduled close to event loop shutdown.\n        ///\n        /// We work around this here by using a blocking `wait()` if we are not on the event loop, which would be very\n        /// bad in areal event loop, but _less bad_ for testing.\n        ///\n        /// For more details, see the documentation attached to the default implementation.\n        if self.inEventLoop {\n            return self._scheduleCallback(at: deadline, handler: handler)\n        } else {\n            return try self.submit {\n                self._scheduleCallback(at: deadline, handler: handler)\n            }.wait()\n        }\n    }\n\n    @preconcurrency\n    @discardableResult\n    public func scheduleCallback(\n        in amount: TimeAmount,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) throws -> NIOScheduledCallback {\n        /// Even though this type does not implement a custom `scheduleCallback(at:handler)`, it uses a manual clock so\n        /// it cannot rely on the default implementation of `scheduleCallback(in:handler:)`, which computes the deadline\n        /// as an offset from `NIODeadline.now`. This event loop needs the deadline to be offset from `self.now`.\n        try self.scheduleCallback(at: self.now + amount, handler: handler)\n    }\n\n    /// On an `NIOAsyncTestingEventLoop`, `execute` will simply use `scheduleTask` with a deadline of _now_. Unlike with the other operations, this will\n    /// immediately execute, to eliminate a common class of bugs.\n    @preconcurrency\n    public func execute(_ task: @escaping @Sendable () -> Void) {\n        if self.inEventLoop {\n            self.scheduleTask(deadline: self.now, task)\n        } else {\n            self.queue.async {\n                self.scheduleTask(deadline: self.now, task)\n                self._run()\n            }\n        }\n    }\n\n    /// Run all tasks that have previously been submitted to this `NIOAsyncTestingEventLoop`, either by calling `execute` or\n    /// events that have been enqueued using `scheduleTask`/`scheduleRepeatedTask`/`scheduleRepeatedAsyncTask` and whose\n    /// deadlines have expired.\n    ///\n    /// - seealso: `NIOAsyncTestingEventLoop.advanceTime`.\n    public func run() async {\n        // Execute all tasks that are currently enqueued to be executed *now*.\n        await self.advanceTime(to: self.now)\n    }\n\n    /// Runs the event loop and moves \"time\" forward by the given amount, running any scheduled\n    /// tasks that need to be run.\n    public func advanceTime(by increment: TimeAmount) async {\n        await self.advanceTime(to: self.now + increment)\n    }\n\n    /// Runs the event loop and moves \"time\" forward to the given point in time, running any scheduled\n    /// tasks that need to be run.\n    ///\n    /// - Note: If `deadline` is before the current time, the current time will not be advanced.\n    public func advanceTime(to deadline: NIODeadline) async {\n        await withCheckedContinuation { continuation in\n            self.queue.async {\n                self._advanceTime(to: deadline)\n                continuation.resume()\n            }\n        }\n    }\n\n    internal func _advanceTime(to deadline: NIODeadline) {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n\n        let newTime = max(deadline, self.now)\n\n        var tasks = CircularBuffer<EmbeddedScheduledTask>()\n        while let nextTask = self.scheduledTasks.peek() {\n            guard nextTask.readyTime <= newTime else {\n                break\n            }\n\n            // Now we want to grab all tasks that are ready to execute at the same\n            // time as the first.\n            while let candidateTask = self.scheduledTasks.peek(), candidateTask.readyTime == nextTask.readyTime {\n                tasks.append(candidateTask)\n                self.scheduledTasks.pop()\n            }\n\n            // Set the time correctly before we call into user code, then\n            // call in for all tasks.\n            self._now.store(nextTask.readyTime.uptimeNanoseconds, ordering: .relaxed)\n\n            for task in tasks {\n                task.task()\n            }\n\n            tasks.removeAll(keepingCapacity: true)\n        }\n\n        // Finally ensure we got the time right.\n        self._now.store(newTime.uptimeNanoseconds, ordering: .relaxed)\n    }\n\n    internal func _run() {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n        self._advanceTime(to: self.now)\n    }\n\n    /// Executes the given function in the context of this event loop. This is useful when it's necessary to be confident that an operation\n    /// is \"blocking\" the event loop. As long as you are executing, nothing else can execute in this loop.\n    ///\n    /// While this call is running, no action can take place on the loop. This function can therefore be a good place to schedule a bunch\n    /// of tasks \"at once\", with a guarantee that none of them can progress. It's also useful if you have types that can only be safely\n    /// accessed from the event loop thread and want to be 100% sure of the thread-safety of accessing them.\n    ///\n    /// Be careful not to try to spin the event loop again from within this callback, however. As long as this function is on the call\n    /// stack the `NIOAsyncTestingEventLoop` cannot progress, and so any attempt to progress it will block until this function returns.\n    public func executeInContext<ReturnType: Sendable>(\n        _ task: @escaping @Sendable () throws -> ReturnType\n    ) async throws -> ReturnType {\n        try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<ReturnType, Error>) in\n            self.queue.async {\n                do {\n                    continuation.resume(returning: try task())\n                } catch {\n                    continuation.resume(throwing: error)\n                }\n            }\n        }\n    }\n\n    internal func _cancelRemainingScheduledTasks() {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n        while let task = self.scheduledTasks.pop() {\n            task.fail(EventLoopError.cancelled)\n        }\n    }\n\n    internal func drainScheduledTasksByRunningAllCurrentlyScheduledTasks() {\n        var currentlyScheduledTasks = self.scheduledTasks\n        while let nextTask = currentlyScheduledTasks.pop() {\n            self._now.store(nextTask.readyTime.uptimeNanoseconds, ordering: .relaxed)\n            nextTask.task()\n        }\n        // Just fail all the remaining scheduled tasks. Despite having run all the tasks that were\n        // scheduled when we entered the method this may still contain tasks as running the tasks\n        // may have enqueued more tasks.\n        while let task = self.scheduledTasks.pop() {\n            task.fail(EventLoopError.shutdown)\n        }\n    }\n\n    private func _shutdownGracefully() {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n        self._run()\n        self._cancelRemainingScheduledTasks()\n    }\n\n    /// - see: `EventLoop.shutdownGracefully`\n    @preconcurrency\n    public func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable (Error?) -> Void) {\n        self.queue.async {\n            self._shutdownGracefully()\n            queue.async {\n                callback(nil)\n            }\n        }\n    }\n\n    /// The concurrency-aware equivalent of `shutdownGracefully(queue:_:)`.\n    public func shutdownGracefully() async {\n        await withCheckedContinuation { continuation in\n            self.state.store(.closing, ordering: .releasing)\n            self.queue.async {\n                self._shutdownGracefully()\n                self.state.store(.closed, ordering: .releasing)\n                continuation.resume()\n            }\n        }\n    }\n\n    public func _preconditionSafeToWait(file: StaticString, line: UInt) {\n        dispatchPrecondition(condition: .notOnQueue(self.queue))\n    }\n\n    public func _promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier, file: StaticString, line: UInt) {\n        self._promiseCreationStore.promiseCreated(futureIdentifier: futureIdentifier, file: file, line: line)\n    }\n\n    public func _promiseCompleted(futureIdentifier: _NIOEventLoopFutureIdentifier) -> (file: StaticString, line: UInt)?\n    {\n        self._promiseCreationStore.promiseCompleted(futureIdentifier: futureIdentifier)\n    }\n\n    public func _preconditionSafeToSyncShutdown(file: StaticString, line: UInt) {\n        dispatchPrecondition(condition: .notOnQueue(self.queue))\n    }\n\n    public func _executeIsolatedUnsafeUnchecked(_ task: @escaping () -> Void) {\n        // Call directly to insertTask. That function has a thread-safety check, and\n        // the rest of this method is using thread-safe operations so we don't\n        // need any extra debug-mode checking here.\n        let taskID = self.scheduledTaskCounter.loadThenWrappingIncrement(ordering: .relaxed)\n        self.insertTask(\n            taskID: taskID,\n            deadline: self.now,\n            promise: nil,\n            task: task\n        )\n    }\n\n    public func _submitIsolatedUnsafeUnchecked<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        // Call directly to insertTask. That function has a thread-safety check, and\n        // the rest of this method is using thread-safe operations so we don't\n        // need any extra debug-mode checking here.\n        let promise = self.makePromise(of: T.self)\n        let taskID = self.scheduledTaskCounter.loadThenWrappingIncrement(ordering: .relaxed)\n        self.insertTask(\n            taskID: taskID,\n            deadline: self.now,\n            promise: promise,\n            task: task\n        )\n        return promise.futureResult\n    }\n\n    @discardableResult\n    public func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        deadline: NIODeadline,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        // Call directly to insertTask. That function has a thread-safety check, and\n        // the rest of this method is using thread-safe operations so we don't\n        // need any extra debug-mode checking here.\n        let scheduled: Scheduled<T>\n        switch self._prepareToSchedule(returnType: T.self) {\n        case .doSchedule(let taskID, let promise, let returned):\n            scheduled = returned\n            self.insertTask(taskID: taskID, deadline: deadline, promise: promise, task: task)\n        case .returnImmediately(let returned):\n            scheduled = returned\n        }\n\n        return scheduled\n    }\n\n    @discardableResult\n    public func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        in delay: TimeAmount,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        self._scheduleTaskIsolatedUnsafeUnchecked(deadline: self.now + delay, task)\n    }\n\n    public func preconditionInEventLoop(file: StaticString, line: UInt) {\n        dispatchPrecondition(condition: .onQueue(self.queue))\n    }\n\n    public func preconditionNotInEventLoop(file: StaticString, line: UInt) {\n        dispatchPrecondition(condition: .notOnQueue(self.queue))\n    }\n\n    enum ScheduleCreationResult<TaskReturnType> {\n        case doSchedule(taskID: UInt64, promise: EventLoopPromise<TaskReturnType>, scheduled: Scheduled<TaskReturnType>)\n        case returnImmediately(Scheduled<TaskReturnType>)\n    }\n    private func _prepareToSchedule<ReturnType>(\n        returnType: ReturnType.Type = ReturnType.self\n    ) -> ScheduleCreationResult<ReturnType> {\n        let promise = self.makePromise(of: ReturnType.self)\n\n        switch self.state.load(ordering: .acquiring) {\n        case .open:\n            break\n        case .closing, .closed:\n            // If the event loop is shut down, or shutting down, immediately cancel the task.\n            promise.fail(EventLoopError.cancelled)\n            return .returnImmediately(Scheduled(promise: promise, cancellationTask: {}))\n        }\n\n        let taskID = self.scheduledTaskCounter.loadThenWrappingIncrement(ordering: .relaxed)\n\n        let scheduled = Scheduled(\n            promise: promise,\n            cancellationTask: {\n                if self.inEventLoop {\n                    self.removeTask(taskID: taskID)\n                } else {\n                    self.queue.async {\n                        self.removeTask(taskID: taskID)\n                    }\n                }\n            }\n        )\n        return .doSchedule(\n            taskID: taskID,\n            promise: promise,\n            scheduled: scheduled\n        )\n    }\n\n    deinit {\n        precondition(scheduledTasks.isEmpty, \"NIOAsyncTestingEventLoop freed with unexecuted scheduled tasks!\")\n    }\n}\n\n// MARK: SerialExecutor conformance\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\nextension NIOAsyncTestingEventLoop: NIOSerialEventLoopExecutor {}\n\n/// This is a thread-safe promise creation store.\n///\n/// We use this to keep track of where promises come from in the `NIOAsyncTestingEventLoop`.\nprivate class PromiseCreationStore {\n    private let lock = NIOLock()\n    private var promiseCreationStore: [_NIOEventLoopFutureIdentifier: (file: StaticString, line: UInt)] = [:]\n\n    func promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier, file: StaticString, line: UInt) {\n        precondition(_isDebugAssertConfiguration())\n        self.lock.withLock { () -> Void in\n            self.promiseCreationStore[futureIdentifier] = (file: file, line: line)\n        }\n    }\n\n    func promiseCompleted(futureIdentifier: _NIOEventLoopFutureIdentifier) -> (file: StaticString, line: UInt)? {\n        precondition(_isDebugAssertConfiguration())\n        return self.lock.withLock {\n            self.promiseCreationStore.removeValue(forKey: futureIdentifier)\n        }\n    }\n\n    deinit {\n        // We no longer need the lock here.\n        precondition(self.promiseCreationStore.isEmpty, \"NIOAsyncTestingEventLoop freed with uncompleted promises!\")\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOEmbedded/Embedded.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport DequeModule\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport _NIODataStructures\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#elseif canImport(WinSDK)\n@preconcurrency import WinSDK\n#else\n#error(\"Unknown C library.\")\n#endif\n\nprivate func printError(_ string: StaticString) {\n    string.withUTF8Buffer { buf in\n        var buf = buf\n        while buf.count > 0 {\n            // 2 is stderr\n            #if canImport(WinSDK)\n            let rc = _write(2, buf.baseAddress, UInt32(truncatingIfNeeded: buf.count))\n            let errno = GetLastError()\n            #else\n            let rc = write(2, buf.baseAddress, buf.count)\n            #endif\n            if rc < 0 {\n                let err = errno\n                if err == EINTR { continue }\n                fatalError(\"Unexpected error writing: \\(err)\")\n            }\n            buf = .init(rebasing: buf.dropFirst(Int(rc)))\n        }\n    }\n}\n\ninternal struct EmbeddedScheduledTask {\n    let id: UInt64\n    let task: () -> Void\n    let failFn: (Error) -> Void\n    let readyTime: NIODeadline\n    let insertOrder: UInt64\n\n    init(\n        id: UInt64,\n        readyTime: NIODeadline,\n        insertOrder: UInt64,\n        task: @escaping () -> Void,\n        _ failFn: @escaping (Error) -> Void\n    ) {\n        self.id = id\n        self.readyTime = readyTime\n        self.insertOrder = insertOrder\n        self.task = task\n        self.failFn = failFn\n    }\n\n    func fail(_ error: Error) {\n        self.failFn(error)\n    }\n}\n\nextension EmbeddedScheduledTask: Comparable {\n    static func < (lhs: EmbeddedScheduledTask, rhs: EmbeddedScheduledTask) -> Bool {\n        if lhs.readyTime == rhs.readyTime {\n            return lhs.insertOrder < rhs.insertOrder\n        } else {\n            return lhs.readyTime < rhs.readyTime\n        }\n    }\n\n    static func == (lhs: EmbeddedScheduledTask, rhs: EmbeddedScheduledTask) -> Bool {\n        lhs.id == rhs.id\n    }\n}\n\n/// An `EventLoop` that is embedded in the current running context with no external\n/// control.\n///\n/// Unlike more complex `EventLoop`s, such as `SelectableEventLoop`, the `EmbeddedEventLoop`\n/// has no proper eventing mechanism. Instead, reads and writes are fully controlled by the\n/// entity that instantiates the `EmbeddedEventLoop`. This property makes `EmbeddedEventLoop`\n/// of limited use for many application purposes, but highly valuable for testing and other\n/// kinds of mocking.\n///\n/// Time is controllable on an `EmbeddedEventLoop`. It begins at `NIODeadline.uptimeNanoseconds(0)`\n/// and may be advanced by a fixed amount by using `advanceTime(by:)`, or advanced to a point in\n/// time with `advanceTime(to:)`.\n///\n/// - warning: Unlike `SelectableEventLoop`, `EmbeddedEventLoop` **is not thread-safe**. This\n///     is because it is intended to be run in the thread that instantiated it. Users are\n///     responsible for ensuring they never call into the `EmbeddedEventLoop` in an\n///     unsynchronized fashion.\npublic final class EmbeddedEventLoop: EventLoop, CustomStringConvertible {\n    private var _now: NIODeadline = .uptimeNanoseconds(0)\n    /// The current \"time\" for this event loop. This is an amount in nanoseconds.\n    public var now: NIODeadline { _now }\n\n    private enum State { case open, closing, closed }\n    private var state: State = .open\n\n    private var scheduledTaskCounter: UInt64 = 0\n    private var scheduledTasks = PriorityQueue<EmbeddedScheduledTask>()\n\n    /// Keep track of where promises are allocated to ensure we can identify their source if they leak.\n    private var _promiseCreationStore: [_NIOEventLoopFutureIdentifier: (file: StaticString, line: UInt)] = [:]\n\n    // The number of the next task to be created. We track the order so that when we execute tasks\n    // scheduled at the same time, we may do so in the order in which they were submitted for\n    // execution.\n    private var taskNumber: UInt64 = 0\n\n    public let description = \"EmbeddedEventLoop\"\n\n    #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Android)\n    private let myThread: pthread_t = pthread_self()\n\n    func isCorrectThread() -> Bool {\n        pthread_equal(self.myThread, pthread_self()) != 0\n    }\n    #else\n    func isCorrectThread() -> Bool {\n        true  // let's be conservative\n    }\n    #endif\n\n    private func nextTaskNumber() -> UInt64 {\n        defer {\n            self.taskNumber += 1\n        }\n        return self.taskNumber\n    }\n\n    /// - see: `EventLoop.inEventLoop`\n    public var inEventLoop: Bool {\n        self.checkCorrectThread()\n        return true\n    }\n\n    public func checkCorrectThread() {\n        guard self.isCorrectThread() else {\n            if Self.strictModeEnabled {\n                preconditionFailure(\n                    \"EmbeddedEventLoop is not thread-safe. You can only use it from the thread you created it on.\"\n                )\n            } else {\n                printError(\n                    \"\"\"\n                    ERROR: NIO API misuse: EmbeddedEventLoop is not thread-safe. \\\n                    You can only use it from the thread you created it on. This problem will be upgraded to a forced \\\n                    crash in future versions of SwiftNIO.\n\n                    \"\"\"\n                )\n            }\n            return\n        }\n    }\n\n    /// Initialize a new `EmbeddedEventLoop`.\n    public init() {}\n\n    /// - see: `EventLoop.scheduleTask(deadline:_:)`\n    @discardableResult\n    public func scheduleTask<T>(deadline: NIODeadline, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        self.checkCorrectThread()\n        let promise: EventLoopPromise<T> = makePromise()\n\n        switch self.state {\n        case .open:\n            break\n        case .closing, .closed:\n            // If the event loop is shut down, or shutting down, immediately cancel the task.\n            promise.fail(EventLoopError.cancelled)\n            return Scheduled(promise: promise, cancellationTask: {})\n        }\n\n        self.scheduledTaskCounter += 1\n        let task = EmbeddedScheduledTask(\n            id: self.scheduledTaskCounter,\n            readyTime: deadline,\n            insertOrder: self.nextTaskNumber(),\n            task: {\n                do {\n                    promise.assumeIsolated().succeed(try task())\n                } catch let err {\n                    promise.fail(err)\n                }\n            },\n            promise.fail\n        )\n\n        let taskId = task.id\n        let scheduled = Scheduled(\n            promise: promise,\n            cancellationTask: {\n                self.scheduledTasks.removeFirst { $0.id == taskId }\n            }\n        )\n        scheduledTasks.push(task)\n        return scheduled\n    }\n\n    /// - see: `EventLoop.scheduleTask(in:_:)`\n    @discardableResult\n    public func scheduleTask<T>(in: TimeAmount, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        self.checkCorrectThread()\n        return self.scheduleTask(deadline: self._now + `in`, task)\n    }\n\n    @preconcurrency\n    @discardableResult\n    public func scheduleCallback(\n        in amount: TimeAmount,\n        handler: some (NIOScheduledCallbackHandler & Sendable)\n    ) -> NIOScheduledCallback {\n        self.checkCorrectThread()\n        /// Even though this type does not implement a custom `scheduleCallback(at:handler)`, it uses a manual clock so\n        /// it cannot rely on the default implementation of `scheduleCallback(in:handler:)`, which computes the deadline\n        /// as an offset from `NIODeadline.now`. This event loop needs the deadline to be offset from `self._now`.\n        return self.scheduleCallback(at: self._now + amount, handler: handler)\n    }\n\n    /// On an `EmbeddedEventLoop`, `execute` will simply use `scheduleTask` with a deadline of _now_. This means that\n    /// `task` will be run the next time you call `EmbeddedEventLoop.run`.\n    public func execute(_ task: @escaping () -> Void) {\n        self.checkCorrectThread()\n        self.scheduleTask(deadline: self._now, task)\n    }\n\n    /// Run all tasks that have previously been submitted to this `EmbeddedEventLoop`, either by calling `execute` or\n    /// events that have been enqueued using `scheduleTask`/`scheduleRepeatedTask`/`scheduleRepeatedAsyncTask` and whose\n    /// deadlines have expired.\n    ///\n    /// - seealso: `EmbeddedEventLoop.advanceTime`.\n    public func run() {\n        self.checkCorrectThread()\n        // Execute all tasks that are currently enqueued to be executed *now*.\n        self.advanceTime(to: self._now)\n    }\n\n    /// Runs the event loop and moves \"time\" forward by the given amount, running any scheduled\n    /// tasks that need to be run.\n    public func advanceTime(by increment: TimeAmount) {\n        self.checkCorrectThread()\n        self.advanceTime(to: self._now + increment)\n    }\n\n    /// Runs the event loop and moves \"time\" forward to the given point in time, running any scheduled\n    /// tasks that need to be run.\n    ///\n    /// - Note: If `deadline` is before the current time, the current time will not be advanced.\n    public func advanceTime(to deadline: NIODeadline) {\n        self.checkCorrectThread()\n        let newTime = max(deadline, self._now)\n\n        while let nextTask = self.scheduledTasks.peek() {\n            guard nextTask.readyTime <= newTime else {\n                break\n            }\n\n            // Now we want to grab all tasks that are ready to execute at the same\n            // time as the first.\n            var tasks = [EmbeddedScheduledTask]()\n            while let candidateTask = self.scheduledTasks.peek(), candidateTask.readyTime == nextTask.readyTime {\n                tasks.append(candidateTask)\n                self.scheduledTasks.pop()\n            }\n\n            // Set the time correctly before we call into user code, then\n            // call in for all tasks.\n            self._now = nextTask.readyTime\n\n            for task in tasks {\n                task.task()\n            }\n        }\n\n        // Finally ensure we got the time right.\n        self._now = newTime\n    }\n\n    internal func cancelRemainingScheduledTasks() {\n        self.checkCorrectThread()\n        while let task = self.scheduledTasks.pop() {\n            task.fail(EventLoopError.cancelled)\n        }\n    }\n\n    #if canImport(Dispatch)\n    /// - see: `EventLoop.shutdownGracefully`\n    public func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void) {\n        self.checkCorrectThread()\n        self.state = .closing\n        run()\n        cancelRemainingScheduledTasks()\n        self.state = .closed\n        queue.sync {\n            callback(nil)\n        }\n    }\n    #endif\n\n    public func preconditionInEventLoop(file: StaticString, line: UInt) {\n        self.checkCorrectThread()\n        // Currently, inEventLoop is always true so this always passes.\n    }\n\n    public func preconditionNotInEventLoop(file: StaticString, line: UInt) {\n        // As inEventLoop always returns true, this must always precondition.\n        preconditionFailure(\"Always in EmbeddedEventLoop\", file: file, line: line)\n    }\n\n    public func _preconditionSafeToWait(file: StaticString, line: UInt) {\n        self.checkCorrectThread()\n        // EmbeddedEventLoop always allows a wait, as waiting will essentially always block\n        // wait()\n        return\n    }\n\n    public func _promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier, file: StaticString, line: UInt) {\n        self.checkCorrectThread()\n        precondition(_isDebugAssertConfiguration())\n        self._promiseCreationStore[futureIdentifier] = (file: file, line: line)\n    }\n\n    public func _promiseCompleted(futureIdentifier: _NIOEventLoopFutureIdentifier) -> (file: StaticString, line: UInt)?\n    {\n        self.checkCorrectThread()\n        precondition(_isDebugAssertConfiguration())\n        return self._promiseCreationStore.removeValue(forKey: futureIdentifier)\n    }\n\n    public func _preconditionSafeToSyncShutdown(file: StaticString, line: UInt) {\n        self.checkCorrectThread()\n        // EmbeddedEventLoop always allows a sync shutdown.\n        return\n    }\n\n    public func _executeIsolatedUnsafeUnchecked(_ task: @escaping () -> Void) {\n        // Because of the way EmbeddedEL works, we can just delegate this directly\n        // to execute.\n        self.execute(task)\n    }\n\n    public func _submitIsolatedUnsafeUnchecked<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        // Because of the way EmbeddedEL works, we can delegate this directly to schedule. Note that I didn't\n        // say submit: we don't have an override of submit here.\n        self.scheduleTask(deadline: self._now, task).futureResult\n    }\n\n    @discardableResult\n    public func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        deadline: NIODeadline,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        // Because of the way EmbeddedEL works, we can delegate this directly to schedule.\n        self.scheduleTask(deadline: deadline, task)\n    }\n\n    @discardableResult\n    public func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        in delay: TimeAmount,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        // Because of the way EmbeddedEL works, we can delegate this directly to schedule.\n        self.scheduleTask(in: delay, task)\n    }\n\n    deinit {\n        self.checkCorrectThread()\n        precondition(scheduledTasks.isEmpty, \"Embedded event loop freed with unexecuted scheduled tasks!\")\n    }\n\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    public var executor: any SerialExecutor {\n        fatalError(\n            \"EmbeddedEventLoop is not thread safe and cannot be used as a SerialExecutor. Use NIOAsyncTestingEventLoop instead.\"\n        )\n    }\n\n    static let strictModeEnabled: Bool = {\n        for ciVar in [\"SWIFTNIO_STRICT\", \"SWIFTNIO_CI\", \"SWIFTNIO_STRICT_EMBEDDED\"] {\n            #if os(Windows)\n            let env = Windows.getenv(\"SWIFTNIO_STRICT\")\n            #else\n            let env = getenv(\"SWIFTNIO_STRICT\").flatMap { String(cString: $0) }\n            #endif\n            switch env?.lowercased() {\n            case \"true\", \"y\", \"yes\", \"on\", \"1\":\n                return true\n            default:\n                ()\n            }\n        }\n        return false\n    }()\n}\n\n// EmbeddedEventLoop is extremely _not_ Sendable. However, the EventLoop protocol\n// requires it to be. We are doing some runtime enforcement of correct use, but\n// ultimately we can't have the compiler validating this usage.\nextension EmbeddedEventLoop: @unchecked Sendable {}\n\n@usableFromInline\nclass EmbeddedChannelCore: ChannelCore {\n    var isOpen: Bool {\n        get {\n            self._isOpen.load(ordering: .sequentiallyConsistent)\n        }\n        set {\n            self._isOpen.store(newValue, ordering: .sequentiallyConsistent)\n        }\n    }\n\n    var isActive: Bool {\n        get {\n            self._isActive.load(ordering: .sequentiallyConsistent)\n        }\n        set {\n            self._isActive.store(newValue, ordering: .sequentiallyConsistent)\n        }\n    }\n\n    var allowRemoteHalfClosure: Bool {\n        get {\n            self._allowRemoteHalfClosure.load(ordering: .sequentiallyConsistent)\n        }\n        set {\n            self._allowRemoteHalfClosure.store(newValue, ordering: .sequentiallyConsistent)\n        }\n    }\n\n    var allowOptionsWhenClosed: Bool {\n        get {\n            self._allowOptionsWhenClosed.load(ordering: .sequentiallyConsistent)\n        }\n        set {\n            self._allowOptionsWhenClosed.store(newValue, ordering: .sequentiallyConsistent)\n        }\n    }\n\n    private let _isOpen = ManagedAtomic(true)\n    private let _isActive = ManagedAtomic(false)\n    private let _allowRemoteHalfClosure = ManagedAtomic(false)\n    private let _allowOptionsWhenClosed = ManagedAtomic(true)\n\n    let eventLoop: EventLoop\n    let closePromise: EventLoopPromise<Void>\n    var error: Optional<Error>\n\n    private let pipeline: ChannelPipeline\n\n    init(pipeline: ChannelPipeline, eventLoop: EventLoop) {\n        closePromise = eventLoop.makePromise()\n        self.pipeline = pipeline\n        self.eventLoop = eventLoop\n        self.error = nil\n    }\n\n    deinit {\n        assert(\n            !self.isOpen && !self.isActive,\n            \"leaked an open EmbeddedChannel, maybe forgot to call channel.finish()?\"\n        )\n        isOpen = false\n        closePromise.succeed(())\n    }\n\n    /// Contains the flushed items that went into the `Channel` (and on a regular channel would have hit the network).\n    @usableFromInline\n    var outboundBuffer: CircularBuffer<NIOAny> = CircularBuffer()\n\n    /// Contains observers that want to consume the first element that would be appended to the `outboundBuffer`\n    private var outboundBufferConsumer: Deque<(Result<NIOAny, Error>) -> Void> = []\n\n    /// Contains the unflushed items that went into the `Channel`\n    @usableFromInline\n    var pendingOutboundBuffer: MarkedCircularBuffer<(NIOAny, EventLoopPromise<Void>?)> = MarkedCircularBuffer(\n        initialCapacity: 16\n    )\n\n    /// Contains the items that travelled the `ChannelPipeline` all the way and hit the tail channel handler. On a\n    /// regular `Channel` these items would be lost.\n    @usableFromInline\n    var inboundBuffer: CircularBuffer<NIOAny> = CircularBuffer()\n\n    /// Contains observers that want to consume the first element that would be appended to the `inboundBuffer`\n    private var inboundBufferConsumer: Deque<(Result<NIOAny, Error>) -> Void> = []\n\n    @usableFromInline\n    internal struct Addresses {\n        var localAddress: SocketAddress?\n        var remoteAddress: SocketAddress?\n    }\n\n    @usableFromInline\n    internal let _addresses: NIOLockedValueBox<Addresses> = NIOLockedValueBox(\n        .init(localAddress: nil, remoteAddress: nil)\n    )\n\n    @usableFromInline\n    var localAddress: SocketAddress? {\n        get {\n            self._addresses.withLockedValue { $0.localAddress }\n        }\n        set {\n            self._addresses.withLockedValue { $0.localAddress = newValue }\n        }\n    }\n\n    @usableFromInline\n    var remoteAddress: SocketAddress? {\n        get {\n            self._addresses.withLockedValue { $0.remoteAddress }\n        }\n        set {\n            self._addresses.withLockedValue { $0.remoteAddress = newValue }\n        }\n    }\n\n    @usableFromInline\n    func localAddress0() throws -> SocketAddress {\n        self.eventLoop.preconditionInEventLoop()\n        if let localAddress = self.localAddress {\n            return localAddress\n        } else {\n            throw ChannelError.operationUnsupported\n        }\n    }\n\n    @usableFromInline\n    func remoteAddress0() throws -> SocketAddress {\n        self.eventLoop.preconditionInEventLoop()\n        if let remoteAddress = self.remoteAddress {\n            return remoteAddress\n        } else {\n            throw ChannelError.operationUnsupported\n        }\n    }\n\n    @usableFromInline\n    func close0(error: Error, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        guard self.isOpen else {\n            promise?.fail(ChannelError.alreadyClosed)\n            return\n        }\n        isOpen = false\n        isActive = false\n        promise?.succeed(())\n\n        // Return a `.failure` result containing an error to all pending inbound and outbound consumers.\n        while let consumer = self.inboundBufferConsumer.popFirst() {\n            consumer(.failure(ChannelError.ioOnClosedChannel))\n        }\n        while let consumer = self.outboundBufferConsumer.popFirst() {\n            consumer(.failure(ChannelError.ioOnClosedChannel))\n        }\n\n        // As we called register() in the constructor of EmbeddedChannel we also need to ensure we call unregistered here.\n        self.pipeline.syncOperations.fireChannelInactive()\n        self.pipeline.syncOperations.fireChannelUnregistered()\n\n        let loopBoundSelf = NIOLoopBound(self, eventLoop: self.eventLoop)\n\n        eventLoop.execute {\n            // ensure this is executed in a delayed fashion as the users code may still traverse the pipeline\n            let `self` = loopBoundSelf.value\n            self.removeHandlers(pipeline: self.pipeline)\n            self.closePromise.succeed(())\n        }\n    }\n\n    @usableFromInline\n    func bind0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        promise?.succeed(())\n    }\n\n    @usableFromInline\n    func connect0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        isActive = true\n        promise?.succeed(())\n        self.pipeline.syncOperations.fireChannelActive()\n    }\n\n    @usableFromInline\n    func register0(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        promise?.succeed(())\n        self.pipeline.syncOperations.fireChannelRegistered()\n    }\n\n    @usableFromInline\n    func registerAlreadyConfigured0(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        isActive = true\n        register0(promise: promise)\n        self.pipeline.syncOperations.fireChannelActive()\n    }\n\n    @usableFromInline\n    func write0(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        self.pendingOutboundBuffer.append((data, promise))\n    }\n\n    @usableFromInline\n    func flush0() {\n        self.eventLoop.preconditionInEventLoop()\n        self.pendingOutboundBuffer.mark()\n\n        while self.pendingOutboundBuffer.hasMark, let dataAndPromise = self.pendingOutboundBuffer.popFirst() {\n            self.addToBuffer(\n                buffer: &self.outboundBuffer,\n                consumer: &self.outboundBufferConsumer,\n                data: dataAndPromise.0\n            )\n            dataAndPromise.1?.succeed(())\n        }\n    }\n\n    @usableFromInline\n    func read0() {\n        self.eventLoop.preconditionInEventLoop()\n        // NOOP\n    }\n\n    public final func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.preconditionInEventLoop()\n        promise?.fail(ChannelError.operationUnsupported)\n    }\n\n    @usableFromInline\n    func channelRead0(_ data: NIOAny) {\n        self.eventLoop.preconditionInEventLoop()\n        self.addToBuffer(\n            buffer: &self.inboundBuffer,\n            consumer: &self.inboundBufferConsumer,\n            data: data\n        )\n    }\n\n    public func errorCaught0(error: Error) {\n        self.eventLoop.preconditionInEventLoop()\n        if self.error == nil {\n            self.error = error\n        }\n    }\n\n    private func addToBuffer(\n        buffer: inout CircularBuffer<NIOAny>,\n        consumer: inout Deque<(Result<NIOAny, Error>) -> Void>,\n        data: NIOAny\n    ) {\n        self.eventLoop.preconditionInEventLoop()\n        if let consume = consumer.popFirst() {\n            consume(.success(data))\n        } else {\n            buffer.append(data)\n        }\n    }\n\n    /// Enqueue a consumer closure that will be invoked upon the next pending inbound write.\n    /// - Parameter newElement: The consumer closure to enqueue. Returns a `.failure` result if the channel has already\n    ///   closed.\n    func _enqueueInboundBufferConsumer(_ newElement: @escaping (Result<NIOAny, Error>) -> Void) {\n        self.eventLoop.preconditionInEventLoop()\n\n        // The channel has already closed: there cannot be any further writes. Return a `.failure` result with an error.\n        guard self.isOpen else {\n            newElement(.failure(ChannelError.ioOnClosedChannel))\n            return\n        }\n\n        self.inboundBufferConsumer.append(newElement)\n    }\n\n    /// Enqueue a consumer closure that will be invoked upon the next pending outbound write.\n    /// - Parameter newElement: The consumer closure to enqueue. Returns a `.failure` result if the channel has already\n    ///   closed.\n    func _enqueueOutboundBufferConsumer(_ newElement: @escaping (Result<NIOAny, Error>) -> Void) {\n        self.eventLoop.preconditionInEventLoop()\n\n        // The channel has already closed: there cannot be any further writes. Return a `.failure` result with an error.\n        guard self.isOpen else {\n            newElement(.failure(ChannelError.ioOnClosedChannel))\n            return\n        }\n\n        self.outboundBufferConsumer.append(newElement)\n    }\n}\n\n// ChannelCores are basically never Sendable.\n@available(*, unavailable)\nextension EmbeddedChannelCore: Sendable {}\n\n/// `EmbeddedChannel` is a `Channel` implementation that does neither any\n/// actual IO nor has a proper eventing mechanism. The prime use-case for\n/// `EmbeddedChannel` is in unit tests when you want to feed the inbound events\n/// and check the outbound events manually.\n///\n/// Please remember to call `finish()` when you are no longer using this\n/// `EmbeddedChannel`.\n///\n/// To feed events through an `EmbeddedChannel`'s `ChannelPipeline` use\n/// `EmbeddedChannel.writeInbound` which accepts data of any type. It will then\n/// forward that data through the `ChannelPipeline` and the subsequent\n/// `ChannelInboundHandler` will receive it through the usual `channelRead`\n/// event. The user is responsible for making sure the first\n/// `ChannelInboundHandler` expects data of that type.\n///\n/// `EmbeddedChannel` automatically collects arriving outbound data and makes it\n/// available one-by-one through `readOutbound`.\n///\n/// - Note: `EmbeddedChannel` is currently only compatible with\n///   `EmbeddedEventLoop`s and cannot be used with `SelectableEventLoop`s from\n///   for example `MultiThreadedEventLoopGroup`.\n/// - warning: Unlike other `Channel`s, `EmbeddedChannel` **is not thread-safe**. This\n///     is because it is intended to be run in the thread that instantiated it. Users are\n///     responsible for ensuring they never call into an `EmbeddedChannel` in an\n///     unsynchronized fashion. `EmbeddedEventLoop`s notes also apply as\n///     `EmbeddedChannel` uses an `EmbeddedEventLoop` as its `EventLoop`.\npublic final class EmbeddedChannel: Channel {\n    /// `LeftOverState` represents any left-over inbound, outbound, and pending outbound events that hit the\n    /// `EmbeddedChannel` and were not consumed when `finish` was called on the `EmbeddedChannel`.\n    ///\n    /// `EmbeddedChannel` is most useful in testing and usually in unit tests, you want to consume all inbound and\n    /// outbound data to verify they are what you expect. Therefore, when you `finish` an `EmbeddedChannel` it will\n    /// return if it's either `.clean` (no left overs) or that it has `.leftOvers`.\n    public enum LeftOverState {\n        /// The `EmbeddedChannel` is clean, ie. no inbound, outbound, or pending outbound data left on `finish`.\n        case clean\n\n        /// The `EmbeddedChannel` has inbound, outbound, or pending outbound data left on `finish`.\n        case leftOvers(inbound: [NIOAny], outbound: [NIOAny], pendingOutbound: [NIOAny])\n\n        /// `true` if the `EmbeddedChannel` was `clean` on `finish`, ie. there is no unconsumed inbound, outbound, or\n        /// pending outbound data left on the `Channel`.\n        public var isClean: Bool {\n            if case .clean = self {\n                return true\n            } else {\n                return false\n            }\n        }\n\n        /// `true` if the `EmbeddedChannel` if there was unconsumed inbound, outbound, or pending outbound data left\n        /// on the `Channel` when it was `finish`ed.\n        public var hasLeftOvers: Bool {\n            !self.isClean\n        }\n    }\n\n    /// `BufferState` represents the state of either the inbound, or the outbound `EmbeddedChannel` buffer. These\n    /// buffers contain data that travelled the `ChannelPipeline` all the way.\n    ///\n    /// If the last `ChannelHandler` explicitly (by calling `fireChannelRead`) or implicitly (by not implementing\n    /// `channelRead`) sends inbound data into the end of the `EmbeddedChannel`, it will be held in the\n    /// `EmbeddedChannel`'s inbound buffer. Similarly for `write` on the outbound side. The state of the respective\n    /// buffer will be returned from `writeInbound`/`writeOutbound` as a `BufferState`.\n    public enum BufferState {\n        /// The buffer is empty.\n        case empty\n\n        /// The buffer is non-empty.\n        case full([NIOAny])\n\n        /// Returns `true` is the buffer was empty.\n        public var isEmpty: Bool {\n            if case .empty = self {\n                return true\n            } else {\n                return false\n            }\n        }\n\n        /// Returns `true` if the buffer was non-empty.\n        public var isFull: Bool {\n            !self.isEmpty\n        }\n    }\n\n    /// `WrongTypeError` is throws if you use `readInbound` or `readOutbound` and request a certain type but the first\n    /// item in the respective buffer is of a different type.\n    public struct WrongTypeError: Error, Equatable {\n        /// The type you expected.\n        public let expected: Any.Type\n\n        /// The type of the actual first element.\n        public let actual: Any.Type\n\n        public init(expected: Any.Type, actual: Any.Type) {\n            self.expected = expected\n            self.actual = actual\n        }\n\n        public static func == (lhs: WrongTypeError, rhs: WrongTypeError) -> Bool {\n            lhs.expected == rhs.expected && lhs.actual == rhs.actual\n        }\n    }\n\n    /// Returns `true` if the `EmbeddedChannel` is 'active'.\n    ///\n    /// An active `EmbeddedChannel` can be closed by calling `close` or `finish` on the `EmbeddedChannel`.\n    ///\n    /// - Note: An `EmbeddedChannel` starts _inactive_ and can be activated, for example by calling `connect`.\n    public var isActive: Bool { channelcore.isActive }\n\n    @usableFromInline\n    internal var isOpen: Bool { channelcore.isOpen }\n\n    /// - see: `ChannelOptions.Types.AllowRemoteHalfClosureOption`\n    public var allowRemoteHalfClosure: Bool {\n        get {\n            self.embeddedEventLoop.checkCorrectThread()\n            return channelcore.allowRemoteHalfClosure\n        }\n        set {\n            self.embeddedEventLoop.checkCorrectThread()\n            channelcore.allowRemoteHalfClosure = newValue\n        }\n    }\n\n    public var allowOptionsWhenClosed: Bool {\n        get {\n            self.embeddedEventLoop.checkCorrectThread()\n            return channelcore.allowOptionsWhenClosed\n        }\n        set {\n            self.embeddedEventLoop.checkCorrectThread()\n            channelcore.allowOptionsWhenClosed = newValue\n        }\n    }\n\n    /// - see: `Channel.closeFuture`\n    public var closeFuture: EventLoopFuture<Void> { channelcore.closePromise.futureResult }\n\n    @usableFromInline\n    lazy var channelcore: EmbeddedChannelCore = EmbeddedChannelCore(\n        pipeline: self._pipeline,\n        eventLoop: self.eventLoop\n    )\n\n    /// - see: `Channel._channelCore`\n    public var _channelCore: ChannelCore {\n        self.embeddedEventLoop.checkCorrectThread()\n        return self.channelcore\n    }\n\n    /// - see: `Channel.pipeline`\n    public var pipeline: ChannelPipeline {\n        self.embeddedEventLoop.checkCorrectThread()\n        return self._pipeline\n    }\n\n    /// - see: `Channel.isWritable`\n    public var isWritable: Bool = true\n\n    @usableFromInline\n    internal var _options: [(option: any ChannelOption, value: any Sendable)] = []\n\n    /// The `ChannelOption`s set on this channel.\n    /// - see: `Embedded.setOption`\n    public var options: [(option: any ChannelOption, value: any Sendable)] { self._options }\n\n    /// Synchronously closes the `EmbeddedChannel`.\n    ///\n    /// Errors in the `EmbeddedChannel` can be consumed using `throwIfErrorCaught`.\n    ///\n    /// - Parameters:\n    ///   - acceptAlreadyClosed: Whether `finish` should throw if the `EmbeddedChannel` has been previously `close`d.\n    /// - Returns: The `LeftOverState` of the `EmbeddedChannel`. If all the inbound and outbound events have been\n    ///            consumed (using `readInbound` / `readOutbound`) and there are no pending outbound events (unflushed\n    ///            writes) this will be `.clean`. If there are any unconsumed inbound, outbound, or pending outbound\n    ///            events, the `EmbeddedChannel` will returns those as `.leftOvers(inbound:outbound:pendingOutbound:)`.\n    public func finish(acceptAlreadyClosed: Bool) throws -> LeftOverState {\n        self.embeddedEventLoop.checkCorrectThread()\n        do {\n            try close().wait()\n        } catch let error as ChannelError {\n            guard error == .alreadyClosed && acceptAlreadyClosed else {\n                throw error\n            }\n        }\n        self.embeddedEventLoop.run()\n        self.embeddedEventLoop.cancelRemainingScheduledTasks()\n        try throwIfErrorCaught()\n        let c = self.channelcore\n        if c.outboundBuffer.isEmpty && c.inboundBuffer.isEmpty && c.pendingOutboundBuffer.isEmpty {\n            return .clean\n        } else {\n            return .leftOvers(\n                inbound: Array(c.inboundBuffer),\n                outbound: Array(c.outboundBuffer),\n                pendingOutbound: c.pendingOutboundBuffer.map { $0.0 }\n            )\n        }\n    }\n\n    /// Synchronously closes the `EmbeddedChannel`.\n    ///\n    /// This method will throw if the `Channel` hit any unconsumed errors or if the `close` fails. Errors in the\n    /// `EmbeddedChannel` can be consumed using `throwIfErrorCaught`.\n    ///\n    /// - Returns: The `LeftOverState` of the `EmbeddedChannel`. If all the inbound and outbound events have been\n    ///            consumed (using `readInbound` / `readOutbound`) and there are no pending outbound events (unflushed\n    ///            writes) this will be `.clean`. If there are any unconsumed inbound, outbound, or pending outbound\n    ///            events, the `EmbeddedChannel` will returns those as `.leftOvers(inbound:outbound:pendingOutbound:)`.\n    public func finish() throws -> LeftOverState {\n        self.embeddedEventLoop.checkCorrectThread()\n        return try self.finish(acceptAlreadyClosed: false)\n    }\n\n    private var _pipeline: ChannelPipeline!\n\n    /// - see: `Channel.allocator`\n    public var allocator: ByteBufferAllocator = ByteBufferAllocator()\n\n    /// - see: `Channel.eventLoop`\n    public var eventLoop: EventLoop {\n        self.embeddedEventLoop.checkCorrectThread()\n        return self.embeddedEventLoop\n    }\n\n    /// Returns the `EmbeddedEventLoop` that this `EmbeddedChannel` uses. This will return the same instance as\n    /// `EmbeddedChannel.eventLoop` but as the concrete `EmbeddedEventLoop` rather than as `EventLoop` existential.\n    public var embeddedEventLoop: EmbeddedEventLoop = EmbeddedEventLoop()\n\n    /// - see: `Channel.localAddress`\n    public var localAddress: SocketAddress? {\n        get {\n            self.embeddedEventLoop.checkCorrectThread()\n            return self.channelcore.localAddress\n        }\n        set {\n            self.embeddedEventLoop.checkCorrectThread()\n            self.channelcore.localAddress = newValue\n        }\n    }\n\n    /// - see: `Channel.remoteAddress`\n    public var remoteAddress: SocketAddress? {\n        get {\n            self.embeddedEventLoop.checkCorrectThread()\n            return self.channelcore.remoteAddress\n        }\n        set {\n            self.embeddedEventLoop.checkCorrectThread()\n            self.channelcore.remoteAddress = newValue\n        }\n    }\n\n    /// `nil` because `EmbeddedChannel`s don't have parents.\n    public let parent: Channel? = nil\n\n    /// If available, this method reads one element of type `T` out of the `EmbeddedChannel`'s outbound buffer. If the\n    /// first element was of a different type than requested, `EmbeddedChannel.WrongTypeError` will be thrown, if there\n    /// are no elements in the outbound buffer, `nil` will be returned.\n    ///\n    /// Data hits the `EmbeddedChannel`'s outbound buffer when data was written using `write`, then `flush`ed, and\n    /// then travelled the `ChannelPipeline` all the way too the front. For data to hit the outbound buffer, the very\n    /// first `ChannelHandler` must have written and flushed it either explicitly (by calling\n    /// `ChannelHandlerContext.write` and `flush`) or implicitly by not implementing `write`/`flush`.\n    ///\n    /// - Note: Outbound events travel the `ChannelPipeline` _back to front_.\n    /// - Note: `EmbeddedChannel.writeOutbound` will `write` data through the `ChannelPipeline`, starting with last\n    ///         `ChannelHandler`.\n    @inlinable\n    public func readOutbound<T>(as type: T.Type = T.self) throws -> T? {\n        self.embeddedEventLoop.checkCorrectThread()\n        return try _readFromBuffer(buffer: &channelcore.outboundBuffer)\n    }\n\n    /// If available, this method reads one element of type `T` out of the `EmbeddedChannel`'s inbound buffer. If the\n    /// first element was of a different type than requested, `EmbeddedChannel.WrongTypeError` will be thrown, if there\n    /// are no elements in the outbound buffer, `nil` will be returned.\n    ///\n    /// Data hits the `EmbeddedChannel`'s inbound buffer when data was send through the pipeline using `fireChannelRead`\n    /// and then travelled the `ChannelPipeline` all the way too the back. For data to hit the inbound buffer, the\n    /// last `ChannelHandler` must have send the event either explicitly (by calling\n    /// `ChannelHandlerContext.fireChannelRead`) or implicitly by not implementing `channelRead`.\n    ///\n    /// - Note: `EmbeddedChannel.writeInbound` will fire data through the `ChannelPipeline` using `fireChannelRead`.\n    @inlinable\n    public func readInbound<T>(as type: T.Type = T.self) throws -> T? {\n        self.embeddedEventLoop.checkCorrectThread()\n        return try _readFromBuffer(buffer: &channelcore.inboundBuffer)\n    }\n\n    /// Sends an inbound `channelRead` event followed by a `channelReadComplete` event through the `ChannelPipeline`.\n    ///\n    /// The immediate effect being that the first `ChannelInboundHandler` will get its `channelRead` method called\n    /// with the data you provide.\n    ///\n    /// - Parameters:\n    ///    - data: The data to fire through the pipeline.\n    /// - Returns: The state of the inbound buffer which contains all the events that travelled the `ChannelPipeline`\n    //             all the way.\n    @inlinable\n    @discardableResult public func writeInbound<T>(_ data: T) throws -> BufferState {\n        self.embeddedEventLoop.checkCorrectThread()\n        self.pipeline.syncOperations.fireChannelRead(NIOAny(data))\n        self.pipeline.syncOperations.fireChannelReadComplete()\n        try self.throwIfErrorCaught()\n        return self.channelcore.inboundBuffer.isEmpty ? .empty : .full(Array(self.channelcore.inboundBuffer))\n    }\n\n    /// Sends an outbound `writeAndFlush` event through the `ChannelPipeline`.\n    ///\n    /// The immediate effect being that the first `ChannelOutboundHandler` will get its `write` method called\n    /// with the data you provide. Note that the first `ChannelOutboundHandler` in the pipeline is the _last_ handler\n    /// because outbound events travel the pipeline from back to front.\n    ///\n    /// - Parameters:\n    ///    - data: The data to fire through the pipeline.\n    /// - Returns: The state of the outbound buffer which contains all the events that travelled the `ChannelPipeline`\n    //             all the way.\n    @inlinable\n    @discardableResult public func writeOutbound<T>(_ data: T) throws -> BufferState {\n        self.embeddedEventLoop.checkCorrectThread()\n        try self.writeAndFlush(data).wait()\n        return self.channelcore.outboundBuffer.isEmpty ? .empty : .full(Array(self.channelcore.outboundBuffer))\n    }\n\n    /// This method will throw the error that is stored in the `EmbeddedChannel` if any.\n    ///\n    /// The `EmbeddedChannel` will store an error some error travels the `ChannelPipeline` all the way past its end.\n    public func throwIfErrorCaught() throws {\n        self.embeddedEventLoop.checkCorrectThread()\n        if let error = channelcore.error {\n            self.channelcore.error = nil\n            throw error\n        }\n    }\n\n    @inlinable\n    func _readFromBuffer<T>(buffer: inout CircularBuffer<NIOAny>) throws -> T? {\n        self.embeddedEventLoop.checkCorrectThread()\n        if buffer.isEmpty {\n            return nil\n        }\n        let elem = buffer.removeFirst()\n        guard let t = self._channelCore.tryUnwrapData(elem, as: T.self) else {\n            throw WrongTypeError(\n                expected: T.self,\n                actual: type(of: self._channelCore.tryUnwrapData(elem, as: Any.self)!)\n            )\n        }\n        return t\n    }\n\n    /// Create a new instance.\n    ///\n    /// During creation it will automatically also register itself on the `EmbeddedEventLoop`.\n    ///\n    /// - Parameters:\n    ///   - handler: The `ChannelHandler` to add to the `ChannelPipeline` before register or `nil` if none should be added.\n    ///   - loop: The `EmbeddedEventLoop` to use.\n    public convenience init(handler: ChannelHandler? = nil, loop: EmbeddedEventLoop = EmbeddedEventLoop()) {\n        let handlers = handler.map { [$0] } ?? []\n        self.init(handlers: handlers, loop: loop)\n        self.embeddedEventLoop.checkCorrectThread()\n    }\n\n    /// Create a new instance.\n    ///\n    /// During creation it will automatically also register itself on the `EmbeddedEventLoop`.\n    ///\n    /// - Parameters:\n    ///   - handlers: The `ChannelHandler`s to add to the `ChannelPipeline` before register.\n    ///   - loop: The `EmbeddedEventLoop` to use.\n    public init(handlers: [ChannelHandler], loop: EmbeddedEventLoop = EmbeddedEventLoop()) {\n        self.embeddedEventLoop = loop\n        self._pipeline = ChannelPipeline(channel: self)\n\n        try! self._pipeline.syncOperations.addHandlers(handlers)\n\n        // This will never throw...\n        try! register().wait()\n        self.embeddedEventLoop.checkCorrectThread()\n    }\n\n    /// - see: `Channel.setOption`\n    @inlinable\n    public func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void> {\n        self.embeddedEventLoop.checkCorrectThread()\n        return self.eventLoop.makeCompletedFuture { try self.setOptionSync(option, value: value) }\n    }\n\n    @inlinable\n    internal func setOptionSync<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n        self.embeddedEventLoop.checkCorrectThread()\n\n        guard self.isOpen || self.allowOptionsWhenClosed else {\n            throw ChannelError.alreadyClosed\n        }\n\n        self.addOption(option, value: value)\n\n        if option is ChannelOptions.Types.AllowRemoteHalfClosureOption {\n            self.allowRemoteHalfClosure = value as! Bool\n            return\n        }\n    }\n\n    /// - see: `Channel.getOption`\n    @inlinable\n    public func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value> {\n        self.embeddedEventLoop.checkCorrectThread()\n        return self.eventLoop.makeCompletedFuture { try self.getOptionSync(option) }\n    }\n\n    @inlinable\n    internal func getOptionSync<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n        self.embeddedEventLoop.checkCorrectThread()\n\n        guard self.isOpen || self.allowOptionsWhenClosed else {\n            throw ChannelError.alreadyClosed\n        }\n\n        if option is ChannelOptions.Types.AutoReadOption {\n            return true as! Option.Value\n        }\n        if option is ChannelOptions.Types.AllowRemoteHalfClosureOption {\n            return self.allowRemoteHalfClosure as! Option.Value\n        }\n        if option is ChannelOptions.Types.BufferedWritableBytesOption {\n            let result = self.channelcore.pendingOutboundBuffer.reduce(0) { partialResult, dataAndPromise in\n                let buffer = self.channelcore.unwrapData(dataAndPromise.0, as: ByteBuffer.self)\n                return partialResult + buffer.readableBytes\n            }\n\n            return result as! Option.Value\n        }\n\n        guard let value = optionValue(for: option) else {\n            fatalError(\"option \\(option) not supported\")\n        }\n\n        return value\n    }\n\n    @inlinable\n    internal func addOption<Option: ChannelOption>(_ option: Option, value: Option.Value) {\n        if let optionIndex = self._options.firstIndex(where: { $0.option is Option }) {\n            self._options[optionIndex] = (option: option, value: value)\n        } else {\n            self._options.append((option: option, value: value))\n        }\n    }\n\n    @inlinable\n    internal func optionValue<Option: ChannelOption>(for option: Option) -> Option.Value? {\n        self.options.first(where: { $0.option is Option })?.value as? Option.Value\n    }\n\n    /// Fires the (outbound) `bind` event through the `ChannelPipeline`. If the event hits the `EmbeddedChannel` which\n    /// happens when it travels the `ChannelPipeline` all the way to the front, this will also set the\n    /// `EmbeddedChannel`'s `localAddress`.\n    ///\n    /// - Parameters:\n    ///   - address: The address to fake-bind to.\n    ///   - promise: The `EventLoopPromise` which will be fulfilled when the fake-bind operation has been done.\n    public func bind(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.embeddedEventLoop.checkCorrectThread()\n        let promise = promise ?? self.embeddedEventLoop.makePromise()\n        promise.futureResult.whenSuccess {\n            self.localAddress = address\n        }\n        self.pipeline.bind(to: address, promise: promise)\n    }\n\n    /// Fires the (outbound) `connect` event through the `ChannelPipeline`. If the event hits the `EmbeddedChannel`\n    /// which happens when it travels the `ChannelPipeline` all the way to the front, this will also set the\n    /// `EmbeddedChannel`'s `remoteAddress`.\n    ///\n    /// - Parameters:\n    ///   - address: The address to fake-bind to.\n    ///   - promise: The `EventLoopPromise` which will be fulfilled when the fake-bind operation has been done.\n    public func connect(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.embeddedEventLoop.checkCorrectThread()\n        let promise = promise ?? self.embeddedEventLoop.makePromise()\n        promise.futureResult.whenSuccess {\n            self.remoteAddress = address\n        }\n        self.pipeline.connect(to: address, promise: promise)\n    }\n\n    /// An overload of `Channel.write` that does not require a Sendable type, as ``EmbeddedEventLoop``\n    /// is bound to a single thread.\n    @inlinable\n    public func write<T>(_ data: T, promise: EventLoopPromise<Void>?) {\n        self.embeddedEventLoop.checkCorrectThread()\n        self.pipeline.syncOperations.write(NIOAny(data), promise: promise)\n    }\n\n    /// An overload of `Channel.write` that does not require a Sendable type, as ``EmbeddedEventLoop``\n    /// is bound to a single thread.\n    @inlinable\n    public func write<T>(_ data: T) -> EventLoopFuture<Void> {\n        self.embeddedEventLoop.checkCorrectThread()\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.pipeline.syncOperations.write(NIOAny(data), promise: promise)\n        return promise.futureResult\n    }\n\n    /// An overload of `Channel.writeAndFlush` that does not require a Sendable type, as ``EmbeddedEventLoop``\n    /// is bound to a single thread.\n    @inlinable\n    public func writeAndFlush<T>(_ data: T, promise: EventLoopPromise<Void>?) {\n        self.embeddedEventLoop.checkCorrectThread()\n        self.pipeline.syncOperations.writeAndFlush(NIOAny(data), promise: promise)\n    }\n\n    /// An overload of `Channel.writeAndFlush` that does not require a Sendable type, as ``EmbeddedEventLoop``\n    /// is bound to a single thread.\n    @inlinable\n    public func writeAndFlush<T>(_ data: T) -> EventLoopFuture<Void> {\n        self.embeddedEventLoop.checkCorrectThread()\n        let promise = self.eventLoop.makePromise(of: Void.self)\n        self.pipeline.syncOperations.writeAndFlush(NIOAny(data), promise: promise)\n        return promise.futureResult\n    }\n}\n\nextension EmbeddedChannel {\n    public struct SynchronousOptions: NIOSynchronousChannelOptions {\n        @usableFromInline\n        internal let channel: EmbeddedChannel\n\n        fileprivate init(channel: EmbeddedChannel) {\n            self.channel = channel\n        }\n\n        @inlinable\n        public func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n            try self.channel.setOptionSync(option, value: value)\n        }\n\n        @inlinable\n        public func getOption<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n            try self.channel.getOptionSync(option)\n        }\n    }\n\n    public final var syncOptions: NIOSynchronousChannelOptions? {\n        SynchronousOptions(channel: self)\n    }\n}\n\n// EmbeddedChannel is extremely _not_ Sendable. However, the Channel protocol\n// requires it to be. We are doing some runtime enforcement of correct use, but\n// ultimately we can't have the compiler validating this usage.\nextension EmbeddedChannel: @unchecked Sendable {}\n\n@available(*, unavailable)\nextension EmbeddedChannel.LeftOverState: @unchecked Sendable {}\n\n@available(*, unavailable)\nextension EmbeddedChannel.BufferState: @unchecked Sendable {}\n\n@available(*, unavailable)\nextension EmbeddedChannel.SynchronousOptions: Sendable {}\n"
  },
  {
    "path": "Sources/NIOFS/Array+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension Array where Element == UInt8 {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let byteBuffer = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(maximumSizeAllowed: maximumSizeAllowed)\n        }\n\n        self = Self(buffer: byteBuffer)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOFS/ArraySlice+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ArraySlice where Element == UInt8 {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let bytes = try await Array(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: fileSystem\n        )\n\n        self = Self(bytes)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOFS/BufferedReader.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOCore\n\n/// A reader which maintains a buffer of bytes read from the file.\n///\n/// You can create a reader from a ``ReadableFileHandleProtocol`` by calling\n/// ``ReadableFileHandleProtocol/bufferedReader(startingAtAbsoluteOffset:capacity:)``. Call\n/// ``read(_:)`` to read a fixed number of bytes from the file or ``read(while:)`` to read\n/// from the file while the bytes match a predicate.\n///\n/// You can also read bytes without returning them to caller by calling ``drop(_:)`` and\n/// ``drop(while:)``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct BufferedReader<Handle: ReadableFileHandleProtocol> {\n    /// The handle to read from.\n    private let handle: Handle\n\n    /// The offset for the next read from the file.\n    private var offset: Int64\n\n    /// Whether the reader has read to the end of the file.\n    private var readEOF = false\n\n    /// A buffer containing the read bytes.\n    private var buffer: ByteBuffer\n\n    /// The capacity of the buffer.\n    public let capacity: Int\n\n    /// The number of bytes currently in the buffer.\n    public var count: Int {\n        self.buffer.readableBytes\n    }\n\n    internal init(wrapping readableHandle: Handle, initialOffset: Int64, capacity: Int) {\n        precondition(\n            initialOffset >= 0,\n            \"initialOffset (\\(initialOffset)) must be greater than or equal to zero\"\n        )\n        precondition(capacity > 0, \"capacity (\\(capacity)) must be greater than zero\")\n        self.handle = readableHandle\n        self.offset = initialOffset\n        self.capacity = capacity\n        self.buffer = ByteBuffer()\n    }\n\n    private mutating func readFromFile(_ count: Int) async throws -> ByteBuffer {\n        let bytes = try await self.handle.readChunk(\n            fromAbsoluteOffset: self.offset,\n            length: .bytes(Int64(count))\n        )\n        // Reading short means reading end-of-file.\n        self.readEOF = bytes.readableBytes < count\n        self.offset += Int64(bytes.readableBytes)\n        return bytes\n    }\n\n    /// Read at most `count` bytes from the file; reads short if not enough bytes are available.\n    ///\n    /// - Parameters:\n    ///   - count: The number of bytes to read.\n    /// - Returns: The bytes read from the buffer.\n    public mutating func read(_ count: ByteCount) async throws -> ByteBuffer {\n        let byteCount = Int(count.bytes)\n        guard byteCount > 0 else { return ByteBuffer() }\n\n        if let bytes = self.buffer.readSlice(length: byteCount) {\n            return bytes\n        } else {\n            // Not enough bytes: read enough for the caller and to fill the buffer back to capacity.\n            var buffer = self.buffer\n            self.buffer = ByteBuffer()\n\n            // The bytes to read from the chunk is the difference in what the caller requested\n            // and is already stored in buffer. Note that if we get to the end of the file this\n            // number could be larger than the available number of bytes.\n            let bytesFromChunk = byteCount &- buffer.readableBytes\n            let bytesToRead = bytesFromChunk + self.capacity\n\n            // Read a chunk from the file and store it.\n            let chunk = try await self.readFromFile(bytesToRead)\n            self.buffer.writeImmutableBuffer(chunk)\n\n            // Finally read off the required bytes from the chunk we just read. If we read short\n            // then the chunk we just appended might not less than 'bytesFromChunk', that's fine,\n            // just take what's available.\n            var slice = self.buffer.readSlice(length: min(bytesFromChunk, chunk.readableBytes))!\n            buffer.writeBuffer(&slice)\n\n            return buffer\n        }\n    }\n\n    /// Reads from  the current position in the file until `predicate` returns `false` and returns\n    /// the read bytes.\n    ///\n    /// - Parameters:\n    ///   - predicate: A predicate which evaluates to `true` for all bytes returned.\n    /// - Returns: A tuple containing the bytes read from the file in its first component, and a boolean\n    /// indicating whether we've stopped reading because EOF has been reached, or because the predicate\n    /// condition doesn't hold true anymore.\n    public mutating func read(\n        while predicate: (UInt8) -> Bool\n    ) async throws -> (bytes: ByteBuffer, readEOF: Bool) {\n        // Check if the required bytes are in the buffer already.\n        let view = self.buffer.readableBytesView\n\n        if let index = view.firstIndex(where: { !predicate($0) }) {\n            // Got an index; slice off the front of the buffer.\n            let prefix = view[..<index]\n            let buffer = ByteBuffer(prefix)\n            self.buffer.moveReaderIndex(forwardBy: buffer.readableBytes)\n\n            // If we reached this codepath, it's because at least one element\n            // in the buffer makes the predicate false. This means that we have\n            // stopped reading because the condition doesn't hold true anymore.\n            return (buffer, false)\n        }\n\n        // The predicate holds true for all bytes in the buffer, start consuming chunks from the\n        // iterator.\n        while !self.readEOF {\n            var chunk = try await self.readFromFile(self.capacity)\n            let view = chunk.readableBytesView\n\n            if let index = view.firstIndex(where: { !predicate($0) }) {\n                // Found a byte for which the predicate doesn't hold. Consume the entire buffer and\n                // the front of this slice.\n                let chunkPrefix = view[..<index]\n                self.buffer.writeBytes(chunkPrefix)\n                chunk.moveReaderIndex(forwardBy: chunkPrefix.count)\n\n                let buffer = self.buffer\n                self.buffer = chunk\n\n                // If we reached this codepath, it's because at least one element\n                // in the buffer makes the predicate false. This means that we have\n                // stopped reading because the condition doesn't hold true anymore.\n                return (buffer, false)\n            } else {\n                // Predicate holds for all bytes. Continue reading.\n                self.buffer.writeBuffer(&chunk)\n            }\n        }\n\n        // Read end-of-file and the predicate still holds for all bytes:\n        // clear the buffer and return all bytes.\n        let buffer = self.buffer\n        self.buffer = ByteBuffer()\n        return (buffer, true)\n    }\n\n    /// Reads and discards the given number of bytes.\n    ///\n    /// - Parameter count: The number of bytes to read and discard.\n    public mutating func drop(_ count: Int) async throws {\n        if count > self.buffer.readableBytes {\n            self.offset += Int64(count &- self.buffer.readableBytes)\n            self.buffer.clear()\n        } else {\n            self.buffer.moveReaderIndex(forwardBy: count)\n        }\n    }\n\n    /// Reads and discards bytes until `predicate` returns `false.`\n    ///\n    /// - Parameters:\n    ///   - predicate: A predicate which evaluates to `true` for all dropped bytes.\n    public mutating func drop(while predicate: (UInt8) -> Bool) async throws {\n        let view = self.buffer.readableBytesView\n\n        if let index = view.firstIndex(where: { !predicate($0) }) {\n            let slice = view[..<index]\n            self.buffer.moveReaderIndex(forwardBy: slice.count)\n            return\n        }\n\n        // Didn't hit the predicate for buffered bytes; drop them all and consume the source.\n        self.buffer.clear(minimumCapacity: min(self.buffer.capacity, self.capacity))\n\n        while !self.readEOF {\n            var chunk = try await self.readFromFile(self.capacity)\n            let view = chunk.readableBytesView\n\n            if let index = view.firstIndex(where: { !predicate($0) }) {\n                let slice = view[..<index]\n                chunk.moveReaderIndex(forwardBy: slice.count)\n                self.buffer.writeBuffer(&chunk)\n                return\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ReadableFileHandleProtocol {\n    /// Creates a new ``BufferedReader`` for this file handle.\n    ///\n    /// - Parameters:\n    ///   - initialOffset: The offset to begin reading from, defaults to zero.\n    ///   - capacity: The capacity of the buffer in bytes, as a ``ByteCount``. Defaults to 512 KiB.\n    /// - Returns: A ``BufferedReader``.\n    public func bufferedReader(\n        startingAtAbsoluteOffset initialOffset: Int64 = 0,\n        capacity: ByteCount = .kibibytes(512)\n    ) -> BufferedReader<Self> {\n        BufferedReader(wrapping: self, initialOffset: initialOffset, capacity: Int(capacity.bytes))\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedReader: Sendable where Handle: Sendable {}\n"
  },
  {
    "path": "Sources/NIOFS/BufferedWriter.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// A writer which buffers bytes in memory before writing them to the file system.\n///\n/// You can create a ``BufferedWriter`` by calling\n/// ``WritableFileHandleProtocol/bufferedWriter(startingAtAbsoluteOffset:capacity:)`` on\n/// ``WritableFileHandleProtocol`` and write bytes to it with one of the following methods:\n/// - ``BufferedWriter/write(contentsOf:)-8dhyg``\n/// - ``BufferedWriter/write(contentsOf:)-2i7d9``\n/// - ``BufferedWriter/write(contentsOf:)-1on0y``\n///\n/// If a call to one of the write functions reaches the buffers ``BufferedWriter/capacity`` the\n/// buffer automatically writes its contents to the file.\n///\n/// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n///   configured size.\n///\n/// To write the bytes in the buffer to the file system before the buffer is full\n/// use ``BufferedWriter/flush()``.\n///\n/// - Important: You should you call ``BufferedWriter/flush()`` when you have finished appending\n///   to write any remaining data to the file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct BufferedWriter<Handle: WritableFileHandleProtocol> {\n    private let handle: Handle\n    /// Offset for the next write.\n    private var offset: Int64\n    /// A buffer of bytes to write.\n    private var buffer: [UInt8] = []\n\n    /// The maximum number of bytes to buffer before the buffer is automatically flushed.\n    public let capacity: Int\n\n    /// The number of bytes in the buffer.\n    ///\n    /// You can flush the buffer manually by calling ``flush()``.\n    public var bufferedBytes: Int {\n        self.buffer.count\n    }\n\n    /// The capacity of the buffer.\n    @_spi(Testing)\n    public var bufferCapacity: Int {\n        self.buffer.capacity\n    }\n\n    internal init(wrapping writableHandle: Handle, initialOffset: Int64, capacity: Int) {\n        precondition(\n            initialOffset >= 0,\n            \"initialOffset (\\(initialOffset)) must be greater than or equal to zero\"\n        )\n        precondition(capacity > 0, \"capacity (\\(capacity)) must be greater than zero\")\n        self.handle = writableHandle\n        self.offset = initialOffset\n        self.capacity = capacity\n    }\n\n    /// Write the contents of the collection of bytes to the buffer.\n    ///\n    /// If the number of bytes in the buffer exceeds the size of the buffer then they're\n    /// automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter bytes: The bytes to write to the buffer.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write(contentsOf bytes: some Sequence<UInt8>) async throws -> Int64 {\n        let bufferSize = Int64(self.buffer.count)\n        self.buffer.append(contentsOf: bytes)\n        let bytesWritten = Int64(self.buffer.count) &- bufferSize\n\n        if self.buffer.count >= self.capacity {\n            try await self.flush()\n        }\n\n        return bytesWritten\n    }\n\n    /// Write the contents of the `ByteBuffer` into the buffer.\n    ///\n    /// If the number of bytes in the buffer exceeds the size of the buffer then they're\n    /// automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter bytes: The bytes to write to the buffer.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write(contentsOf bytes: ByteBuffer) async throws -> Int64 {\n        try await self.write(contentsOf: bytes.readableBytesView)\n    }\n\n    /// Write the contents of the `AsyncSequence` of byte chunks to the buffer.\n    ///\n    /// If appending a chunk to the buffer causes it to exceed the capacity of the buffer then the\n    /// contents of the buffer are automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter chunks: The `AsyncSequence` of byte chunks to write to the buffer.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write<Chunks: AsyncSequence>(\n        contentsOf chunks: Chunks\n    ) async throws -> Int64 where Chunks.Element: Sequence<UInt8> {\n        var bytesWritten: Int64 = 0\n        do {\n            for try await chunk in chunks {\n                bytesWritten += try await self.write(contentsOf: chunk)\n            }\n        } catch let error as FileSystemError {\n            // From call to 'write'.\n            throw error\n        } catch let error {\n            // From iterating the async sequence.\n            throw FileSystemError(\n                code: .unknown,\n                message: \"AsyncSequence of bytes threw error while writing to the buffered writer.\",\n                cause: error,\n                location: .here()\n            )\n        }\n        return bytesWritten\n    }\n\n    /// Write the contents of the `AsyncSequence` of `ByteBuffer`s into the buffer.\n    ///\n    /// If appending a chunk to the buffer causes it to exceed the capacity of the buffer then the\n    /// contents of the buffer are automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter chunks: The `AsyncSequence` of `ByteBuffer`s to write.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write<Chunks: AsyncSequence>(\n        contentsOf chunks: Chunks\n    ) async throws -> Int64 where Chunks.Element == ByteBuffer {\n        try await self.write(contentsOf: chunks.map { $0.readableBytesView })\n    }\n\n    /// Write the contents of the `AsyncSequence` of bytes the buffer.\n    ///\n    /// If appending a byte to the buffer causes it to exceed the capacity of the buffer then the\n    /// contents of the buffer are automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter bytes: The `AsyncSequence` of bytes to write to the buffer.\n    @discardableResult\n    public mutating func write<Bytes: AsyncSequence>(\n        contentsOf bytes: Bytes\n    ) async throws -> Int64 where Bytes.Element == UInt8 {\n        try await self.write(contentsOf: bytes.map { CollectionOfOne($0) })\n    }\n\n    /// Flush any buffered bytes to the file system.\n    ///\n    /// - Important: You should you call ``flush()`` when you have finished writing to ensure the\n    ///   buffered writer writes any remaining data to the file system.\n    public mutating func flush() async throws {\n        if self.buffer.isEmpty { return }\n\n        try await self.handle.write(contentsOf: self.buffer, toAbsoluteOffset: self.offset)\n        self.offset += Int64(self.buffer.count)\n\n        // The buffer may grow beyond the specified buffer size. Keep the capacity if it's less than\n        // double the intended size, otherwise reclaim the memory.\n        let keepCapacity = self.buffer.capacity <= (self.capacity * 2)\n        self.buffer.removeAll(keepingCapacity: keepCapacity)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension WritableFileHandleProtocol {\n    /// Creates a new ``BufferedWriter`` for this file handle.\n    ///\n    /// - Parameters:\n    ///   - initialOffset: The offset to begin writing at, defaults to zero.\n    ///   - capacity: The capacity of the buffer in bytes, as a ``ByteCount``. The writer writes the contents of its\n    ///     buffer to the file system when it exceeds this capacity. Defaults to 512 KiB.\n    /// - Returns: A ``BufferedWriter``.\n    public func bufferedWriter(\n        startingAtAbsoluteOffset initialOffset: Int64 = 0,\n        capacity: ByteCount = .kibibytes(512)\n    ) -> BufferedWriter<Self> {\n        BufferedWriter(\n            wrapping: self,\n            initialOffset: initialOffset,\n            capacity: Int(capacity.bytes)\n        )\n    }\n\n    /// Convenience function that creates a buffered reader, executes\n    /// the closure that writes the contents into the buffer and calls 'flush()'.\n    ///\n    /// - Parameters:\n    ///   - initialOffset: The offset to begin writing at, defaults to zero.\n    ///   - capacity: The capacity of the buffer in bytes, as a ``ByteCount``. The writer writes the contents of its\n    ///     buffer to the file system when it exceeds this capacity. Defaults to 512 KiB.\n    ///   - body: The closure that writes the contents to the buffer created in this method.\n    /// - Returns: The result of the executed closure.\n    public func withBufferedWriter<Result>(\n        startingAtAbsoluteOffset initialOffset: Int64 = 0,\n        capacity: ByteCount = .kibibytes(512),\n        execute body: (inout BufferedWriter<Self>) async throws -> Result\n    ) async throws -> Result {\n        var bufferedWriter = self.bufferedWriter(startingAtAbsoluteOffset: initialOffset, capacity: capacity)\n        return try await withUncancellableTearDown {\n            try await body(&bufferedWriter)\n        } tearDown: { _ in\n            try await bufferedWriter.flush()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedWriter: Sendable where Handle: Sendable {}\n"
  },
  {
    "path": "Sources/NIOFS/ByteBuffer+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ByteBuffer {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        self = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(\n                fromAbsoluteOffset: 0,\n                maximumSizeAllowed: maximumSizeAllowed\n            )\n        }\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n\n    /// Writes the readable bytes of the ``ByteBuffer`` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await self.readableBytesView.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: fileSystem\n        )\n    }\n\n    /// Writes the readable bytes of the ``ByteBuffer`` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/ByteCount.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Represents the number of bytes.\npublic struct ByteCount: Hashable, Sendable {\n    /// The number of bytes\n    public var bytes: Int64\n\n    /// Returns a ``ByteCount`` with a given number of bytes\n    /// - Parameter count: The number of bytes\n    public static func bytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of kilobytes\n    ///\n    /// One kilobyte is 1000 bytes.\n    ///\n    /// - Parameter count: The number of kilobytes\n    public static func kilobytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1000 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of megabytes\n    ///\n    /// One megabyte is 1,000,000 bytes.\n    ///\n    /// - Parameter count: The number of megabytes\n    public static func megabytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1000 * 1000 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of gigabytes\n    ///\n    /// One gigabyte is 1,000,000,000 bytes.\n    ///\n    /// - Parameter count: The number of gigabytes\n    public static func gigabytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1000 * 1000 * 1000 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of kibibytes\n    ///\n    /// One kibibyte is 1024 bytes.\n    ///\n    /// - Parameter count: The number of kibibytes\n    public static func kibibytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1024 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of mebibytes\n    ///\n    /// One mebibyte is 10,485,760 bytes.\n    ///\n    /// - Parameter count: The number of mebibytes\n    public static func mebibytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1024 * 1024 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of gibibytes\n    ///\n    /// One gibibyte is 10,737,418,240 bytes.\n    ///\n    /// - Parameter count: The number of gibibytes\n    public static func gibibytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1024 * 1024 * 1024 * count)\n    }\n}\n\nextension ByteCount {\n    /// A ``ByteCount`` for the maximum amount of bytes that can be written to `ByteBuffer`.\n    internal static var byteBufferCapacity: ByteCount {\n        #if arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n        // on 32-bit platforms we can't make use of a whole UInt32.max (as it doesn't fit in an Int)\n        let byteBufferMaxIndex = UInt32(Int.max)\n        #else\n        // on 64-bit platforms we're good\n        let byteBufferMaxIndex = UInt32.max\n        #endif\n\n        return ByteCount(bytes: Int64(byteBufferMaxIndex))\n    }\n\n    /// A ``ByteCount`` for an unlimited amount of bytes.\n    public static var unlimited: ByteCount {\n        ByteCount(bytes: .max)\n    }\n}\n\nextension ByteCount: AdditiveArithmetic {\n    public static var zero: ByteCount { ByteCount(bytes: 0) }\n\n    public static func + (lhs: ByteCount, rhs: ByteCount) -> ByteCount {\n        ByteCount(bytes: lhs.bytes + rhs.bytes)\n    }\n\n    public static func - (lhs: ByteCount, rhs: ByteCount) -> ByteCount {\n        ByteCount(bytes: lhs.bytes - rhs.bytes)\n    }\n}\n\nextension ByteCount: Comparable {\n    public static func < (lhs: ByteCount, rhs: ByteCount) -> Bool {\n        lhs.bytes < rhs.bytes\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Convenience.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\nextension String {\n    /// Writes the UTF8 encoded `String` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the `String` to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await self.utf8.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: fileSystem\n        )\n    }\n\n    /// Writes the UTF8 encoded `String` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the `String` to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n\nextension Sequence<UInt8> where Self: Sendable {\n    /// Writes the contents of the `Sequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await fileSystem.withFileHandle(forWritingAt: path, options: options) { handle in\n            try await handle.write(contentsOf: self, toAbsoluteOffset: offset)\n        }\n    }\n\n    /// Writes the contents of the `Sequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence where Self.Element: Sequence<UInt8>, Self: Sendable {\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await fileSystem.withFileHandle(forWritingAt: path, options: options) { handle in\n            var writer = handle.bufferedWriter(startingAtAbsoluteOffset: offset)\n            let bytesWritten = try await writer.write(contentsOf: self)\n            try await writer.flush()\n            return bytesWritten\n        }\n    }\n\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence where Self.Element == UInt8, Self: Sendable {\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await fileSystem.withFileHandle(forWritingAt: path, options: options) { handle in\n            var writer = handle.bufferedWriter(startingAtAbsoluteOffset: offset)\n            let bytesWritten = try await writer.write(contentsOf: self)\n            try await writer.flush()\n            return bytesWritten\n        }\n    }\n\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: NIOFilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/DirectoryEntries.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIODarwin\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n/// An `AsyncSequence` of entries in a directory.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct DirectoryEntries: AsyncSequence, Sendable {\n    public typealias AsyncIterator = DirectoryIterator\n    public typealias Element = DirectoryEntry\n\n    /// The underlying sequence.\n    private let batchedSequence: Batched\n\n    /// Creates a new ``DirectoryEntries`` sequence.\n    internal init(handle: SystemFileHandle, recursive: Bool) {\n        self.batchedSequence = Batched(handle: handle, recursive: recursive)\n    }\n\n    /// Creates a ``DirectoryEntries`` sequence by wrapping an `AsyncSequence` of _batches_ of\n    /// directory entries.\n    @preconcurrency\n    public init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n    where S.Element == Batched.Element, S.AsyncIterator: NIOFileSystemSendableMetatype {\n        self.batchedSequence = Batched(wrapping: sequence)\n    }\n\n    public func makeAsyncIterator() -> DirectoryIterator {\n        DirectoryIterator(iterator: self.batchedSequence.makeAsyncIterator())\n    }\n\n    /// Returns a sequence of directory entry batches.\n    ///\n    /// The batched sequence has its element type as `Array<DirectoryEntry>` rather\n    /// than `DirectoryEntry`. This can enable better performance by reducing the number of\n    /// executor hops.\n    public func batched() -> Batched {\n        self.batchedSequence\n    }\n\n    /// An `AsyncIteratorProtocol` of `DirectoryEntry`.\n    public struct DirectoryIterator: AsyncIteratorProtocol {\n        /// The batched iterator to consume from.\n        private var iterator: Batched.AsyncIterator\n        /// A slice of the current batch being iterated.\n        private var currentBatch: ArraySlice<DirectoryEntry>\n\n        init(iterator: Batched.AsyncIterator) {\n            self.iterator = iterator\n            self.currentBatch = []\n        }\n\n        public mutating func next() async throws -> DirectoryEntry? {\n            if self.currentBatch.isEmpty {\n                let batch = try await self.iterator.next()\n                self.currentBatch = (batch ?? [])[...]\n            }\n\n            return self.currentBatch.popFirst()\n        }\n    }\n}\n\n@available(*, unavailable)\nextension DirectoryEntries.AsyncIterator: Sendable {}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension DirectoryEntries {\n    /// An `AsyncSequence` of batches of directory entries.\n    ///\n    /// The ``Batched`` sequence uses `Array<DirectoryEntry>` as its element type rather\n    /// than `DirectoryEntry`. This can enable better performance by reducing the number of\n    /// executor hops at the cost of ease-of-use.\n    public struct Batched: AsyncSequence, Sendable {\n        public typealias AsyncIterator = BatchedIterator\n        public typealias Element = [DirectoryEntry]\n\n        private let stream: BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>\n\n        /// Creates a ``DirectoryEntries/Batched`` sequence by wrapping an `AsyncSequence`\n        /// of directory entry batches.\n        @preconcurrency\n        public init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n        where S.Element == Element, S.AsyncIterator: NIOFileSystemSendableMetatype {\n            self.stream = BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>(wrapping: sequence)\n        }\n\n        fileprivate init(handle: SystemFileHandle, recursive: Bool) {\n            // Expanding the batches yields watermarks of 256 and 512 directory entries.\n            let stream = NIOThrowingAsyncSequenceProducer.makeBatchedDirectoryEntryStream(\n                handle: handle,\n                recursive: recursive,\n                entriesPerBatch: 64,\n                lowWatermark: 4,\n                highWatermark: 8\n            )\n\n            self.stream = BufferedOrAnyStream(wrapping: stream)\n        }\n\n        public func makeAsyncIterator() -> BatchedIterator {\n            BatchedIterator(wrapping: self.stream.makeAsyncIterator())\n        }\n\n        /// An `AsyncIteratorProtocol` of `Array<DirectoryEntry>`.\n        public struct BatchedIterator: AsyncIteratorProtocol {\n            private var iterator: BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>.AsyncIterator\n\n            fileprivate init(\n                wrapping iterator: BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>.AsyncIterator\n            ) {\n                self.iterator = iterator\n            }\n\n            public mutating func next() async throws -> [DirectoryEntry]? {\n                try await self.iterator.next()\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension DirectoryEntries.Batched.AsyncIterator: Sendable {}\n\n// MARK: - Internal\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOThrowingAsyncSequenceProducer\nwhere\n    Element == [DirectoryEntry],\n    Failure == (any Error),\n    Strategy == NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n    Delegate == DirectoryEntryProducer\n{\n    fileprivate static func makeBatchedDirectoryEntryStream(\n        handle: SystemFileHandle,\n        recursive: Bool,\n        entriesPerBatch: Int,\n        lowWatermark: Int,\n        highWatermark: Int\n    ) -> NIOThrowingAsyncSequenceProducer<\n        [DirectoryEntry], any Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n        DirectoryEntryProducer\n    > {\n        let producer = DirectoryEntryProducer(\n            handle: handle,\n            recursive: recursive,\n            entriesPerBatch: entriesPerBatch\n        )\n\n        let nioThrowingAsyncSequence = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: [DirectoryEntry].self,\n            backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark(\n                lowWatermark: lowWatermark,\n                highWatermark: highWatermark\n            ),\n            finishOnDeinit: false,\n            delegate: producer\n        )\n\n        producer.setSequenceProducerSource(nioThrowingAsyncSequence.source)\n\n        return nioThrowingAsyncSequence.sequence\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate typealias DirectoryEntrySequenceProducer = NIOThrowingAsyncSequenceProducer<\n    [DirectoryEntry], Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, DirectoryEntryProducer\n>\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate final class DirectoryEntryProducer: NIOAsyncSequenceProducerDelegate {\n    let state: NIOLockedValueBox<DirectoryEnumerator>\n    let entriesPerBatch: Int\n\n    init(handle: SystemFileHandle, recursive: Bool, entriesPerBatch: Int) {\n        let state = DirectoryEnumerator(handle: handle, recursive: recursive)\n        self.state = NIOLockedValueBox(state)\n        self.entriesPerBatch = entriesPerBatch\n    }\n\n    func didTerminate() {\n        guard let threadPool = self.state.withLockedValue({ $0.threadPoolForClosing() }) else {\n            return\n        }\n\n        threadPool.submit { _ in  // always run, even if cancelled\n            self.state.withLockedValue { state in\n                state.closeIfNecessary()\n            }\n        }\n    }\n\n    /// sets the source within the producer state\n    func setSequenceProducerSource(_ sequenceProducerSource: DirectoryEntrySequenceProducer.Source) {\n        self.state.withLockedValue { state in\n            switch state.state {\n            case .idle:\n                state.sequenceProducerSource = sequenceProducerSource\n            case .done:\n                sequenceProducerSource.finish()\n            case .open, .openPausedProducing:\n                fatalError()\n            case .modifying:\n                fatalError()\n            }\n        }\n    }\n\n    func clearSource() {\n        self.state.withLockedValue { state in\n            state.sequenceProducerSource = nil\n        }\n    }\n\n    /// The 'entry point' for producing elements.\n    ///\n    /// Calling this function will start producing directory entries asynchronously by dispatching\n    /// work to the IO executor and feeding the result back to the stream source. On yielding to the\n    /// source it will either produce more or be scheduled to produce more. Stopping production\n    /// is signalled via the stream's 'onTermination' handler.\n    func produceMore() {\n        let threadPool = self.state.withLockedValue { state in\n            state.produceMore()\n        }\n\n        // No thread pool means we're done.\n        guard let threadPool = threadPool else { return }\n\n        threadPool.submit {\n            let result: Result<[DirectoryEntry], Error>\n            switch $0 {\n            case .active:\n                result = Result { try self.nextBatch() }\n            case .cancelled:\n                result = .failure(CancellationError())\n            }\n            self.onNextBatchResult(result)\n        }\n    }\n\n    func pauseProducing() {\n        self.state.withLockedValue { state in\n            state.pauseProducing()\n        }\n    }\n\n    private func nextBatch() throws -> [DirectoryEntry] {\n        try self.state.withLockedValue { state in\n            try state.next(self.entriesPerBatch)\n        }\n    }\n\n    private func onNextBatchResult(_ result: Result<[DirectoryEntry], Error>) {\n        switch result {\n        case let .success(entries):\n            self.onNextBatch(entries)\n        case let .failure(error):\n            // Failed to read more entries: close and notify the stream so consumers receive the\n            // error.\n            self.close()\n            let source = self.state.withLockedValue { state in\n                state.sequenceProducerSource\n            }\n            source?.finish(error)\n            self.clearSource()\n        }\n    }\n\n    private func onNextBatch(_ entries: [DirectoryEntry]) {\n        let source = self.state.withLockedValue { state in\n            state.sequenceProducerSource\n        }\n\n        guard let source else {\n            assertionFailure(\"unexpectedly missing source\")\n            return\n        }\n\n        // No entries were read: this must be the end (as the batch size must be greater than zero).\n        if entries.isEmpty {\n            source.finish()\n            self.clearSource()\n            return\n        }\n\n        // Reading short means reading EOF. The enumerator closes itself in that case.\n        let readEOF = entries.count < self.entriesPerBatch\n\n        // Entries were produced: yield them and maybe produce more.\n        let writeResult = source.yield(contentsOf: CollectionOfOne(entries))\n\n        // Exit early if EOF was read; no use in trying to produce more.\n        if readEOF {\n            source.finish()\n            self.clearSource()\n            return\n        }\n\n        switch writeResult {\n        case .produceMore:\n            self.produceMore()\n        case .stopProducing:\n            self.pauseProducing()\n        case .dropped:\n            // The source is finished; mark ourselves as done.\n            self.close()\n        }\n    }\n\n    private func close() {\n        guard let threadPool = self.state.withLockedValue({ $0.threadPoolForClosing() }) else {\n            return\n        }\n\n        threadPool.submit { _ in  // always run, even if cancelled\n            self.state.withLockedValue { state in\n                state.closeIfNecessary()\n            }\n        }\n    }\n}\n\n/// Enumerates a directory in batches.\n///\n/// Note that this is not a `Sequence` because we allow for errors to be thrown on `next()`.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate struct DirectoryEnumerator: Sendable {\n    internal enum State: @unchecked Sendable {\n        case modifying\n        case idle(SystemFileHandle.SendableView, recursive: Bool)\n        case open(NIOThreadPool, Source, [DirectoryEntry])\n        case openPausedProducing(NIOThreadPool, Source, [DirectoryEntry])\n        case done\n    }\n\n    /// The source of directory entries.\n    internal enum Source {\n        case readdir(CInterop.DirPointer)\n        case fts(CInterop.FTSPointer)\n    }\n\n    /// The current state of enumeration.\n    internal var state: State\n\n    /// The path to the directory being enumerated.\n    private let path: FilePath\n\n    /// The route via which directory entry batches are yielded,\n    /// the sourcing end of the `DirectoryEntrySequenceProducer`\n    internal var sequenceProducerSource: DirectoryEntrySequenceProducer.Source?\n\n    /// Information about an entry returned by FTS. See 'fts(3)'.\n    private enum FTSInfo: Hashable, Sendable {\n        case directoryPreOrder\n        case directoryCausingCycle\n        case ftsDefault\n        case directoryUnreadable\n        case dotFile\n        case directoryPostOrder\n        case error\n        case regularFile\n        case noStatInfoAvailable\n        case noStatInfoRequested\n        case symbolicLink\n        case symbolicLinkToNonExistentTarget\n\n        init?(rawValue: UInt16) {\n            switch Int32(rawValue) {\n            case FTS_D:\n                self = .directoryPreOrder\n            case FTS_DC:\n                self = .directoryCausingCycle\n            case FTS_DEFAULT:\n                self = .ftsDefault\n            case FTS_DNR:\n                self = .directoryUnreadable\n            case FTS_DOT:\n                self = .dotFile\n            case FTS_DP:\n                self = .directoryPostOrder\n            case FTS_ERR:\n                self = .error\n            case FTS_F:\n                self = .regularFile\n            case FTS_NS:\n                self = .noStatInfoAvailable\n            case FTS_NSOK:\n                self = .noStatInfoRequested\n            case FTS_SL:\n                self = .symbolicLink\n            case FTS_SLNONE:\n                self = .symbolicLinkToNonExistentTarget\n            default:\n                return nil\n            }\n        }\n    }\n\n    internal init(handle: SystemFileHandle, recursive: Bool) {\n        self.state = .idle(handle.sendableView, recursive: recursive)\n        self.path = handle.path\n    }\n\n    internal mutating func produceMore() -> NIOThreadPool? {\n        switch self.state {\n        case let .idle(handle, _):\n            return handle.threadPool\n        case let .open(threadPool, _, _):\n            return threadPool\n        case .openPausedProducing(let threadPool, let source, let array):\n            self.state = .open(threadPool, source, array)\n            return threadPool\n        case .done:\n            return nil\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    internal mutating func pauseProducing() {\n        switch self.state {\n        case .open(let threadPool, let source, let array):\n            self.state = .openPausedProducing(threadPool, source, array)\n        case .idle:\n            ()  // we won't apply back pressure until something has been read\n        case .openPausedProducing, .done:\n            ()  // no-op\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    internal func threadPoolForClosing() -> NIOThreadPool? {\n        switch self.state {\n        case .open(let threadPool, _, _), .openPausedProducing(let threadPool, _, _):\n            return threadPool\n        case .idle, .done:\n            // Don't need to close in the idle state: we don't own the handle.\n            return nil\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    /// Returns the next batch of directory entries.\n    internal mutating func next(_ count: Int) throws -> [DirectoryEntry] {\n        while true {\n            switch self.process(count) {\n            case let .yield(result):\n                return try result.get()\n            case .continue:\n                ()\n            }\n        }\n    }\n\n    /// Closes the descriptor, if necessary.\n    internal mutating func closeIfNecessary() {\n        switch self.state {\n        case .idle:\n            // We don't own the handle so don't close it.\n            self.state = .done\n\n        case .open(_, let mode, _), .openPausedProducing(_, let mode, _):\n            self.state = .done\n            switch mode {\n            case .readdir(let dir):\n                _ = Libc.closedir(dir)\n            case .fts(let fts):\n                _ = Libc.ftsClose(fts)\n            }\n\n        case .done:\n            ()\n\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    private enum ProcessResult {\n        case yield(Result<[DirectoryEntry], FileSystemError>)\n        case `continue`\n    }\n\n    private mutating func makeReaddirSource(\n        _ handle: SystemFileHandle.SendableView\n    ) -> Result<Source, FileSystemError> {\n        handle._duplicate().mapError { dupError in\n            FileSystemError(\n                message: \"Unable to open directory stream for '\\(handle.path)'.\",\n                wrapping: dupError\n            )\n        }.flatMap { descriptor in\n            // We own the descriptor and cede ownership if 'opendir' succeeds; if it doesn't we need\n            // to close it.\n            descriptor.opendir().mapError { errno in\n                // Close the descriptor on error.\n                try? descriptor.close()\n                return FileSystemError.fdopendir(errno: errno, path: handle.path, location: .here())\n            }\n        }.map {\n            .readdir($0)\n        }\n    }\n\n    private mutating func makeFTSSource(\n        _ handle: SystemFileHandle.SendableView\n    ) -> Result<Source, FileSystemError> {\n        Libc.ftsOpen(handle.path, options: [.noChangeDir, .physical]).mapError { errno in\n            FileSystemError.open(\"fts_open\", error: errno, path: handle.path, location: .here())\n        }.map {\n            .fts($0)\n        }\n    }\n\n    private mutating func processOpenState(\n        threadPool: NIOThreadPool,\n        dir: CInterop.DirPointer,\n        entries: inout [DirectoryEntry],\n        count: Int\n    ) -> (State, ProcessResult) {\n        entries.removeAll(keepingCapacity: true)\n        entries.reserveCapacity(count)\n\n        while entries.count < count {\n            switch Libc.readdir(dir) {\n            case let .success(.some(entry)):\n                // Skip \".\" and \"..\" (and empty paths)\n                if self.isThisOrParentDirectory(entry.pointee) {\n                    continue\n                }\n\n                let fileType = FileType(direntType: entry.pointee.d_type)\n                let name: FilePath.Component\n                #if canImport(Darwin)\n                // Safe to force unwrap: may be nil if empty, a root, or more than one component.\n                // Empty is checked for above, root can't exist within a directory, and directory\n                // items must be a single path component.\n                name = FilePath.Component(platformString: CNIODarwin_dirent_dname(entry))!\n                #else\n                name = FilePath.Component(platformString: CNIOLinux_dirent_dname(entry))!\n                #endif\n\n                let fullPath = self.path.appending(name)\n                // '!' is okay here: the init returns nil if there is an empty path which we know\n                // isn't the case as 'self.path' is non-empty.\n                entries.append(DirectoryEntry(path: NIOFilePath(fullPath), type: fileType)!)\n\n            case .success(.none):\n                // Nothing we can do on failure so ignore the result.\n                _ = Libc.closedir(dir)\n                return (.done, .yield(.success(entries)))\n\n            case let .failure(errno):\n                // Nothing we can do on failure so ignore the result.\n                _ = Libc.closedir(dir)\n                let error = FileSystemError.readdir(\n                    errno: errno,\n                    path: self.path,\n                    location: .here()\n                )\n                return (.done, .yield(.failure(error)))\n            }\n        }\n\n        // We must have hit our 'count' limit.\n        return (.open(threadPool, .readdir(dir), entries), .yield(.success(entries)))\n    }\n\n    private mutating func processOpenState(\n        threadPool: NIOThreadPool,\n        fts: CInterop.FTSPointer,\n        entries: inout [DirectoryEntry],\n        count: Int\n    ) -> (State, ProcessResult) {\n        entries.removeAll(keepingCapacity: true)\n        entries.reserveCapacity(count)\n\n        while entries.count < count {\n            switch Libc.ftsRead(fts) {\n            case .success(.some(let entry)):\n                let info = FTSInfo(rawValue: entry.pointee.fts_info)\n                switch info {\n                case .directoryPreOrder:\n                    let entry = DirectoryEntry(path: NIOFilePath(entry.path), type: .directory)!\n                    entries.append(entry)\n\n                case .directoryPostOrder:\n                    ()  // Don't visit directories twice.\n\n                case .regularFile:\n                    let entry = DirectoryEntry(path: NIOFilePath(entry.path), type: .regular)!\n                    entries.append(entry)\n\n                case .symbolicLink, .symbolicLinkToNonExistentTarget:\n                    let entry = DirectoryEntry(path: NIOFilePath(entry.path), type: .symlink)!\n                    entries.append(entry)\n\n                case .ftsDefault:\n                    // File type is unknown.\n                    let entry = DirectoryEntry(path: NIOFilePath(entry.path), type: .unknown)!\n                    entries.append(entry)\n\n                case .error:\n                    let errno = Errno(rawValue: entry.pointee.fts_errno)\n                    let error = FileSystemError(\n                        code: .unknown,\n                        message: \"Can't read file system tree.\",\n                        cause: FileSystemError.SystemCallError(systemCall: \"fts_read\", errno: errno),\n                        location: .here()\n                    )\n                    _ = Libc.ftsClose(fts)\n                    return (.done, .yield(.failure(error)))\n\n                case .directoryCausingCycle:\n                    ()  // Cycle found, ignore it and continue.\n                case .directoryUnreadable:\n                    ()  // Can't read directory, ignore it and continue iterating.\n                case .dotFile:\n                    ()  // Ignore \".\" and \"..\"\n                case .noStatInfoAvailable:\n                    ()  // No stat info available so we can't list the entry, ignore it.\n                case .noStatInfoRequested:\n                    ()  // Shouldn't happen.\n\n                case nil:\n                    ()  // Unknown, ignore.\n                }\n\n            case .success(.none):\n                // No entries left to iterate.\n                _ = Libc.ftsClose(fts)\n                return (.done, .yield(.success(entries)))\n\n            case .failure(let errno):\n                // Nothing we can do on failure so ignore the result.\n                _ = Libc.ftsClose(fts)\n                let error = FileSystemError.ftsRead(\n                    errno: errno,\n                    path: self.path,\n                    location: .here()\n                )\n                return (.done, .yield(.failure(error)))\n            }\n        }\n\n        // We must have hit our 'count' limit.\n        return (.open(threadPool, .fts(fts), entries), .yield(.success(entries)))\n    }\n\n    private mutating func process(_ count: Int) -> ProcessResult {\n        switch self.state {\n        case let .idle(handle, recursive):\n            let result: Result<Source, FileSystemError>\n\n            if recursive {\n                result = self.makeFTSSource(handle)\n            } else {\n                result = self.makeReaddirSource(handle)\n            }\n\n            switch result {\n            case let .success(source):\n                self.state = .open(handle.threadPool, source, [])\n                return .continue\n\n            case let .failure(error):\n                self.state = .done\n                return .yield(.failure(error))\n            }\n\n        case .open(let threadPool, let mode, var entries):\n            self.state = .modifying\n\n            switch mode {\n            case .readdir(let dir):\n                let (state, result) = self.processOpenState(\n                    threadPool: threadPool,\n                    dir: dir,\n                    entries: &entries,\n                    count: count\n                )\n                self.state = state\n                return result\n\n            case .fts(let fts):\n                let (state, result) = self.processOpenState(\n                    threadPool: threadPool,\n                    fts: fts,\n                    entries: &entries,\n                    count: count\n                )\n                self.state = state\n                return result\n            }\n\n        case .openPausedProducing:\n            return .yield(.success([]))\n\n        case .done:\n            return .yield(.success([]))\n\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    private func isThisOrParentDirectory(_ entry: CInterop.DirEnt) -> Bool {\n        let dot = CChar(bitPattern: UInt8(ascii: \".\"))\n        switch (entry.d_name.0, entry.d_name.1, entry.d_name.2) {\n        case (0, _, _), (dot, 0, _), (dot, dot, 0):\n            return true\n        default:\n            return false\n        }\n    }\n}\n\nextension UnsafeMutablePointer<CInterop.FTSEnt> {\n    fileprivate var path: FilePath {\n        FilePath(platformString: self.pointee.fts_path!)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/DirectoryEntry.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// Information about an item within a directory.\npublic struct DirectoryEntry: Sendable, Hashable, Equatable {\n    /// The path of the directory entry.\n    ///\n    /// - Precondition: The path must have at least one component.\n    public let path: NIOFilePath\n\n    /// The name of the entry; the final component of the ``path``.\n    ///\n    /// If `path` is \"/Users/tim/path-to-4T.key\" then `name` will be \"path-to-4T.key\".\n    public var name: String {\n        self.path.underlying.lastComponent!.string\n    }\n\n    /// The type of entry.\n    public var type: FileType\n\n    /// Creates a directory entry; returns `nil` if `path` has no components.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory entry which must contain at least one component.\n    ///   - type: The type of entry.\n    public init?(path: NIOFilePath, type: FileType) {\n        if path.underlying.components.isEmpty {\n            return nil\n        }\n\n        self.path = path\n        self.type = type\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Exports.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// These types are used in our public API; expose them to make\n// life easier for users.\n@_exported import enum SystemPackage.CInterop\n@_exported import struct SystemPackage.Errno\n@_exported import struct SystemPackage.FileDescriptor\n@_exported import struct SystemPackage.FilePath\n@_exported import struct SystemPackage.FilePermissions\n"
  },
  {
    "path": "Sources/NIOFS/FileChunks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n/// An `AsyncSequence` of ordered chunks read from a file.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct FileChunks: AsyncSequence, Sendable {\n    enum ChunkRange {\n        case entireFile\n        case partial(Range<Int64>)\n    }\n\n    public typealias Element = ByteBuffer\n\n    /// The underlying buffered stream.\n    private let stream: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>\n\n    /// Create a ``FileChunks`` sequence backed by wrapping an `AsyncSequence`.\n    @preconcurrency\n    public init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n    where S.Element == ByteBuffer, S.AsyncIterator: NIOFileSystemSendableMetatype {\n        self.stream = BufferedOrAnyStream(wrapping: sequence)\n    }\n\n    internal init(\n        handle: SystemFileHandle,\n        chunkLength: ByteCount,\n        range: Range<Int64>\n    ) {\n        let chunkRange: ChunkRange\n        if range.lowerBound == 0, range.upperBound == .max {\n            chunkRange = .entireFile\n        } else {\n            chunkRange = .partial(range)\n        }\n\n        // TODO: choose reasonable watermarks; this should likely be at least somewhat dependent\n        // on the chunk size.\n        let stream = NIOThrowingAsyncSequenceProducer.makeFileChunksStream(\n            of: ByteBuffer.self,\n            handle: handle,\n            chunkLength: chunkLength.bytes,\n            range: chunkRange,\n            lowWatermark: 4,\n            highWatermark: 8\n        )\n\n        self.stream = BufferedOrAnyStream(wrapping: stream)\n    }\n\n    public func makeAsyncIterator() -> FileChunkIterator {\n        FileChunkIterator(wrapping: self.stream.makeAsyncIterator())\n    }\n\n    public struct FileChunkIterator: AsyncIteratorProtocol {\n        private var iterator: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>.AsyncIterator\n\n        fileprivate init(wrapping iterator: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>.AsyncIterator) {\n            self.iterator = iterator\n        }\n\n        public mutating func next() async throws -> ByteBuffer? {\n            try await self.iterator.next()\n        }\n    }\n}\n\n@available(*, unavailable)\nextension FileChunks.FileChunkIterator: Sendable {}\n\n// MARK: - Internal\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate typealias FileChunkSequenceProducer = NIOThrowingAsyncSequenceProducer<\n    ByteBuffer, Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, FileChunkProducer\n>\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOThrowingAsyncSequenceProducer\nwhere\n    Element == ByteBuffer,\n    Failure == Error,\n    Strategy == NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n    Delegate == FileChunkProducer\n{\n    static func makeFileChunksStream(\n        of: Element.Type = Element.self,\n        handle: SystemFileHandle,\n        chunkLength: Int64,\n        range: FileChunks.ChunkRange,\n        lowWatermark: Int,\n        highWatermark: Int\n    ) -> FileChunkSequenceProducer {\n\n        let producer = FileChunkProducer(\n            range: range,\n            handle: handle,\n            chunkLength: chunkLength\n        )\n\n        let nioThrowingAsyncSequence = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: ByteBuffer.self,\n            backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark(\n                lowWatermark: lowWatermark,\n                highWatermark: highWatermark\n            ),\n            finishOnDeinit: false,\n            delegate: producer\n        )\n\n        producer.setSource(nioThrowingAsyncSequence.source)\n\n        return nioThrowingAsyncSequence.sequence\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate final class FileChunkProducer: NIOAsyncSequenceProducerDelegate, Sendable {\n    let state: NIOLockedValueBox<ProducerState>\n\n    let path: FilePath\n    let chunkLength: Int64\n\n    init(range: FileChunks.ChunkRange, handle: SystemFileHandle, chunkLength: Int64) {\n        let state: ProducerState\n        switch range {\n        case .entireFile:\n            state = .init(handle: handle, range: nil)\n        case .partial(let partialRange):\n            state = .init(handle: handle, range: partialRange)\n        }\n\n        self.state = NIOLockedValueBox(state)\n        self.path = handle.path\n        self.chunkLength = chunkLength\n    }\n\n    /// sets the source within the producer state\n    func setSource(_ source: FileChunkSequenceProducer.Source) {\n        self.state.withLockedValue { state in\n            switch state.state {\n            case .producing, .pausedProducing:\n                state.source = source\n            case .done(let emptyRange):\n                if emptyRange {\n                    source.finish()\n                }\n            }\n        }\n    }\n\n    func clearSource() {\n        self.state.withLockedValue { state in\n            state.source = nil\n        }\n    }\n\n    /// The 'entry point' for producing elements.\n    ///\n    /// Calling this function will start producing file chunks asynchronously by dispatching work\n    /// to the IO executor and feeding the result back to the stream source. On yielding to the\n    /// source it will either produce more or be scheduled to produce more. Stopping production\n    /// is signaled via the stream's 'onTermination' handler.\n    func produceMore() {\n        let threadPool = self.state.withLockedValue { state in\n            state.activeThreadPool()\n        }\n        // No thread pool means we're done.\n        guard let threadPool = threadPool else { return }\n\n        threadPool.submit { workItemState in\n            // update state to reflect that we have been requested to perform a read\n            // the read may be performed immediately, queued to be performed later or ignored\n            let requestedReadAction = self.state.withLockedValue { state in\n                state.requestedProduceMore()\n            }\n\n            switch requestedReadAction {\n            case .performRead:\n                let result: Result<ByteBuffer, Error>\n                switch workItemState {\n                case .active:\n                    result = Result { try self.readNextChunk() }\n                case .cancelled:\n                    result = .failure(CancellationError())\n                }\n\n                switch result {\n                case let .success(bytes):\n                    self.didReadNextChunk(bytes)\n                case let .failure(error):\n                    // Failed to read: update our state then notify the stream so consumers receive the\n                    // error.\n                    let source = self.state.withLockedValue { state in\n                        state.done()\n                        return state.source\n                    }\n                    source?.finish(error)\n                    self.clearSource()\n                }\n\n            case .stop:\n                return\n            }\n\n            let performedReadAction = self.state.withLockedValue { state in\n                state.performedProduceMore()\n            }\n\n            switch performedReadAction {\n            case .readMore:\n                self.produceMore()\n            case .stop:\n                return\n            }\n\n        }\n    }\n\n    private func readNextChunk() throws -> ByteBuffer {\n        try self.state.withLockedValue { state in\n            state.fileReadingState()\n        }.flatMap {\n            if let (descriptor, range) = $0 {\n                if let range {\n                    let remainingBytes = range.upperBound - range.lowerBound\n                    let clampedLength = min(self.chunkLength, remainingBytes)\n                    return descriptor.readChunk(\n                        fromAbsoluteOffset: range.lowerBound,\n                        length: clampedLength\n                    ).mapError { error in\n                        .read(usingSyscall: .pread, error: error, path: self.path, location: .here())\n                    }\n                } else {\n                    return descriptor.readChunk(length: self.chunkLength).mapError { error in\n                        .read(usingSyscall: .read, error: error, path: self.path, location: .here())\n                    }\n                }\n            } else {\n                // nil means done: return empty to indicate the stream should finish.\n                return .success(ByteBuffer())\n            }\n        }.get()\n    }\n\n    private func didReadNextChunk(_ buffer: ByteBuffer) {\n        let chunkLength = self.chunkLength\n        assert(buffer.readableBytes <= chunkLength)\n\n        let (source, initialState): (FileChunkSequenceProducer.Source?, ProducerState.State) = self.state\n            .withLockedValue { state in\n                state.didReadBytes(buffer.readableBytes)\n\n                // finishing short indicates the file is done\n                if buffer.readableBytes < chunkLength {\n                    state.state = .done(emptyRange: false)\n                }\n                return (state.source, state.state)\n            }\n\n        guard let source else {\n            return\n        }\n\n        // No bytes were produced, nothing more to do.\n        if buffer.readableBytes == 0 {\n            source.finish()\n            self.clearSource()\n        }\n\n        // Yield bytes and maybe produce more.\n        let yieldResult = source.yield(contentsOf: CollectionOfOne(buffer))\n\n        switch initialState {\n        case .done:\n            source.finish()\n            self.clearSource()\n            return\n        case .producing, .pausedProducing:\n            ()\n        }\n\n        switch yieldResult {\n        case .produceMore:\n            ()\n        case .stopProducing:\n            self.state.withLockedValue { state in state.pauseProducing() }\n        case .dropped:\n            // The source is finished; mark ourselves as done.\n            self.state.withLockedValue { state in state.done() }\n        }\n    }\n\n    func didTerminate() {\n        self.state.withLockedValue { state in\n            state.done()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate struct ProducerState: Sendable {\n    fileprivate struct Producing {\n        /// Possible states for activity relating to performing a read from disk\n        internal enum ActivityState {\n            /// The producer is not currently performing a read from disk\n            case inactive\n            /// The producer is in the critical section for reading from disk\n            case active\n            /// The producer is in the critical section for reading from disk and a further read has been requested.\n            /// This can happen e.g. if a sequence indicates that production should be paused then unpauses and calls\n            /// back into the code before the initial read block has exited.\n            case activeAndQueued\n        }\n\n        /// The handle to read from.\n        var handle: SystemFileHandle.SendableView\n\n        /// An optional range containing the offsets to read from and up to (exclusive)\n        /// The lower bound should be updated after each successful read.\n        /// The upper bound should be used to check if producer should stop.\n        /// If no range is present, then read entire file.\n        var range: Range<Int64>?\n\n        /// Keep track of whether or not we are currently actively engaged in a read\n        /// to protect against re-entrant behavior.\n        var activityState: ActivityState = .inactive\n    }\n\n    internal enum State {\n        /// Can potentially produce values (if the handle is not closed).\n        case producing(Producing)\n        /// Backpressure policy means that we should stop producing new values for now\n        case pausedProducing(Producing)\n        /// Done producing values either by reaching EOF, some error or the stream terminating.\n        case done(emptyRange: Bool)\n    }\n\n    internal var state: State\n\n    /// The route via which file chunks are yielded,\n    /// the sourcing end of the `FileChunkSequenceProducer`\n    internal var source: FileChunkSequenceProducer.Source?\n\n    init(handle: SystemFileHandle, range: Range<Int64>?) {\n        if let range, range.isEmpty {\n            self.state = .done(emptyRange: true)\n        } else {\n            self.state = .producing(.init(handle: handle.sendableView, range: range))\n        }\n    }\n\n    /// Actions which may be taken after 'produce more' is requested.\n    ///\n    /// Either perform the read immediately or (optionally queue the read then) stop.\n    internal enum RequestedProduceMoreAction {\n        case performRead\n        case stop\n    }\n\n    /// Update state to reflect that 'produce more' has been requested.\n    mutating func requestedProduceMore() -> RequestedProduceMoreAction {\n        switch self.state {\n        case .producing(var producingState):\n            switch producingState.activityState {\n            case .inactive:\n                producingState.activityState = .active\n                self.state = .producing(producingState)\n                return .performRead\n            case .active:\n                producingState.activityState = .activeAndQueued\n                self.state = .producing(producingState)\n                return .stop\n            case .activeAndQueued:\n                return .stop\n            }\n\n        case .pausedProducing(var producingState):\n            switch producingState.activityState {\n            case .inactive:\n                producingState.activityState = .active\n                self.state = .producing(producingState)\n                return .performRead\n            case .active:\n                producingState.activityState = .activeAndQueued\n                self.state = .pausedProducing(producingState)\n                return .stop\n            case .activeAndQueued:\n                return .stop\n            }\n\n        case .done:\n            return .stop\n        }\n    }\n\n    /// Actions which may be taken after a more data is produced.\n    ///\n    /// Either go on to read more or stop.\n    internal enum PerformedProduceMoreAction {\n        case readMore\n        case stop\n    }\n\n    /// Update state to reflect that a more data has been produced.\n    mutating func performedProduceMore() -> PerformedProduceMoreAction {\n        switch self.state {\n        case .producing(var producingState):\n            let oldActivityState = producingState.activityState\n\n            producingState.activityState = .inactive\n            self.state = .producing(producingState)\n\n            switch oldActivityState {\n            case .inactive:\n                preconditionFailure()\n            case .active, .activeAndQueued:\n                return .readMore\n            }\n\n        case .pausedProducing(var producingState):\n            let oldActivityState = producingState.activityState\n\n            producingState.activityState = .inactive\n            self.state = .pausedProducing(producingState)\n\n            switch oldActivityState {\n            case .inactive:\n                preconditionFailure()\n            case .active:\n                return .stop\n            case .activeAndQueued:\n                return .readMore\n            }\n\n        case .done:\n            return .stop\n        }\n    }\n\n    mutating func activeThreadPool() -> NIOThreadPool? {\n        switch self.state {\n        case .producing(let producingState), .pausedProducing(let producingState):\n            return producingState.handle.threadPool\n        case .done:\n            return nil\n        }\n    }\n\n    mutating func fileReadingState() -> Result<(FileDescriptor, Range<Int64>?)?, FileSystemError> {\n        switch self.state {\n        case .producing(let producingState), .pausedProducing(let producingState):\n            if let descriptor = producingState.handle.descriptorIfAvailable() {\n                return .success((descriptor, producingState.range))\n            } else {\n                let error = FileSystemError(\n                    code: .closed,\n                    message: \"Cannot read from closed file ('\\(producingState.handle.path)').\",\n                    cause: nil,\n                    location: .here()\n                )\n                return .failure(error)\n            }\n        case .done:\n            return .success(nil)\n        }\n    }\n\n    mutating func didReadBytes(_ count: Int) {\n        switch self.state {\n        case var .producing(state):\n            switch state.updateRangeWithReadBytes(count) {\n            case .moreToRead:\n                self.state = .producing(state)\n            case .cannotReadMore:\n                self.state = .done(emptyRange: false)\n            }\n        case var .pausedProducing(state):\n            switch state.updateRangeWithReadBytes(count) {\n            case .moreToRead:\n                self.state = .pausedProducing(state)\n            case .cannotReadMore:\n                self.state = .done(emptyRange: false)\n            }\n        case .done:\n            ()\n        }\n    }\n\n    mutating func pauseProducing() {\n        switch self.state {\n        case .producing(let state):\n            self.state = .pausedProducing(state)\n        case .pausedProducing, .done:\n            ()\n        }\n    }\n\n    mutating func done() {\n        self.state = .done(emptyRange: false)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ProducerState.Producing {\n    internal enum RangeUpdateOutcome {\n        case moreToRead\n        case cannotReadMore\n    }\n\n    /// Updates the range (the offsets to read from and up to) to reflect the number of bytes which have been read.\n    /// - Parameter count: The number of bytes which have been read.\n    /// - Returns: Returns `.moreToRead` if there are no remaining bytes to read, `.cannotReadMore` otherwise.\n    mutating func updateRangeWithReadBytes(_ count: Int) -> RangeUpdateOutcome {\n        guard let currentRange = self.range else {\n            // we are reading the whole file, just keep going\n            return .moreToRead\n        }\n\n        let newLowerBound = currentRange.lowerBound + Int64(count)\n\n        // we have run out of bytes to read, we are done\n        if newLowerBound >= currentRange.upperBound {\n            self.range = currentRange.upperBound..<currentRange.upperBound\n            return .cannotReadMore\n        }\n\n        // update range, we are not done\n        self.range = newLowerBound..<currentRange.upperBound\n        return .moreToRead\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileHandle.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Provides a ``FileHandle``.\n///\n/// Users should not implement or rely on this protocol; its purpose is to reduce boilerplate\n/// by providing a default implementation of ``FileHandleProtocol`` for types which hold\n/// a ``FileHandle``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol _HasFileHandle: FileHandleProtocol {\n    var fileHandle: FileHandle { get }\n}\n\n// Provides an implementation of `FileHandleProtocol` by calling through to `FileHandle`.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension _HasFileHandle {\n    public func info() async throws -> FileInfo {\n        try await self.fileHandle.info()\n    }\n\n    public func replacePermissions(_ permissions: FilePermissions) async throws {\n        try await self.fileHandle.replacePermissions(permissions)\n    }\n\n    public func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.fileHandle.addPermissions(permissions)\n    }\n\n    public func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.fileHandle.removePermissions(permissions)\n    }\n\n    public func attributeNames() async throws -> [String] {\n        try await self.fileHandle.attributeNames()\n    }\n\n    public func valueForAttribute(_ name: String) async throws -> [UInt8] {\n        try await self.fileHandle.valueForAttribute(name)\n    }\n\n    public func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws {\n        try await self.fileHandle.updateValueForAttribute(bytes, attribute: name)\n    }\n\n    public func removeValueForAttribute(_ name: String) async throws {\n        try await self.fileHandle.removeValueForAttribute(name)\n    }\n\n    public func synchronize() async throws {\n        try await self.fileHandle.synchronize()\n    }\n\n    public func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R {\n        try await self.fileHandle.withUnsafeDescriptor {\n            try execute($0)\n        }\n    }\n\n    public func detachUnsafeFileDescriptor() throws -> FileDescriptor {\n        try self.fileHandle.detachUnsafeFileDescriptor()\n    }\n\n    public func close() async throws {\n        try await self.fileHandle.close()\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``FileHandleProtocol`` by making system calls to interact with the local file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct FileHandle: FileHandleProtocol, Sendable {\n    internal let systemFileHandle: SystemFileHandle\n\n    internal init(wrapping handle: SystemFileHandle) {\n        self.systemFileHandle = handle\n    }\n\n    public func info() async throws -> FileInfo {\n        try await self.systemFileHandle.info()\n    }\n\n    public func replacePermissions(_ permissions: FilePermissions) async throws {\n        try await self.systemFileHandle.replacePermissions(permissions)\n    }\n\n    public func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.systemFileHandle.addPermissions(permissions)\n    }\n\n    public func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.systemFileHandle.removePermissions(permissions)\n    }\n\n    public func attributeNames() async throws -> [String] {\n        try await self.systemFileHandle.attributeNames()\n    }\n\n    public func valueForAttribute(_ name: String) async throws -> [UInt8] {\n        try await self.systemFileHandle.valueForAttribute(name)\n    }\n\n    public func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws {\n        try await self.systemFileHandle.updateValueForAttribute(bytes, attribute: name)\n    }\n\n    public func removeValueForAttribute(_ name: String) async throws {\n        try await self.systemFileHandle.removeValueForAttribute(name)\n    }\n\n    public func synchronize() async throws {\n        try await self.systemFileHandle.synchronize()\n    }\n\n    public func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R {\n        try await self.systemFileHandle.withUnsafeDescriptor {\n            try execute($0)\n        }\n    }\n\n    public func detachUnsafeFileDescriptor() throws -> FileDescriptor {\n        try self.systemFileHandle.detachUnsafeFileDescriptor()\n    }\n\n    public func close() async throws {\n        try await self.systemFileHandle.close()\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``ReadableFileHandleProtocol`` by making system calls to interact with the local\n/// file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct ReadFileHandle: ReadableFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    public func readChunk(\n        fromAbsoluteOffset offset: Int64,\n        length: ByteCount\n    ) async throws -> ByteBuffer {\n        try await self.fileHandle.systemFileHandle.readChunk(\n            fromAbsoluteOffset: offset,\n            length: length\n        )\n    }\n\n    public func readChunks(in range: Range<Int64>, chunkLength: ByteCount) -> FileChunks {\n        self.fileHandle.systemFileHandle.readChunks(in: range, chunkLength: chunkLength)\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``WritableFileHandleProtocol`` by making system calls to interact with the local\n/// file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct WriteFileHandle: WritableFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    @discardableResult\n    public func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.fileHandle.systemFileHandle.write(\n            contentsOf: bytes,\n            toAbsoluteOffset: offset\n        )\n    }\n\n    public func resize(to size: ByteCount) async throws {\n        try await self.fileHandle.systemFileHandle.resize(to: size)\n    }\n\n    public func close(makeChangesVisible: Bool) async throws {\n        try await self.fileHandle.systemFileHandle.close(makeChangesVisible: makeChangesVisible)\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``ReadableAndWritableFileHandleProtocol`` by making system calls to interact with the\n/// local file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct ReadWriteFileHandle: ReadableAndWritableFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    public func readChunk(\n        fromAbsoluteOffset offset: Int64,\n        length: ByteCount\n    ) async throws -> ByteBuffer {\n        try await self.fileHandle.systemFileHandle.readChunk(\n            fromAbsoluteOffset: offset,\n            length: length\n        )\n    }\n\n    public func readChunks(in offset: Range<Int64>, chunkLength: ByteCount) -> FileChunks {\n        self.fileHandle.systemFileHandle.readChunks(in: offset, chunkLength: chunkLength)\n    }\n\n    @discardableResult\n    public func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.fileHandle.systemFileHandle.write(\n            contentsOf: bytes,\n            toAbsoluteOffset: offset\n        )\n    }\n\n    public func resize(to size: ByteCount) async throws {\n        try await self.fileHandle.systemFileHandle.resize(to: size)\n    }\n\n    public func close(makeChangesVisible: Bool) async throws {\n        try await self.fileHandle.systemFileHandle.close(makeChangesVisible: makeChangesVisible)\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``DirectoryFileHandleProtocol`` by making system calls to interact with the local\n/// file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct DirectoryFileHandle: DirectoryFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    public func listContents(recursive: Bool) -> DirectoryEntries {\n        self.fileHandle.systemFileHandle.listContents(recursive: recursive)\n    }\n\n    public func openFile(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openFile(\n            forReadingAt: path,\n            options: options\n        )\n        return ReadFileHandle(wrapping: systemFileHandle)\n    }\n\n    public func openFile(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openFile(\n            forWritingAt: path,\n            options: options\n        )\n        return WriteFileHandle(wrapping: systemFileHandle)\n    }\n\n    public func openFile(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openFile(\n            forReadingAndWritingAt: path,\n            options: options\n        )\n        return ReadWriteFileHandle(wrapping: systemFileHandle)\n    }\n\n    public func openDirectory(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory\n    ) async throws -> DirectoryFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openDirectory(\n            atPath: path,\n            options: options\n        )\n        return DirectoryFileHandle(wrapping: systemFileHandle)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileHandleProtocol.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport SystemPackage\n\n/// A handle for a file system object.\n///\n/// There is a hierarchy of file handle protocols which allow for different functionality. All\n/// file handle protocols refine the base ``FileHandleProtocol`` protocol.\n///\n/// ```\n///                                      ┌────────────────────┐\n///                                      │ FileHandleProtocol │\n///                                      │     [Protocol]     │\n///                                      └────────────────────┘\n///                                                ▲\n///                 ┌──────────────────────────────┼────────────────────────────────┐\n///                 │                              │                                │\n/// ┌────────────────────────────┐   ┌────────────────────────────┐  ┌─────────────────────────────┐\n/// │ ReadableFileHandleProtocol │   │ WritableFileHandleProtocol │  │ DirectoryFileHandleProtocol │\n/// │          [Protocol]        │   │         [Protocol]         │  │          [Protocol]         │\n/// └────────────────────────────┘   └────────────────────────────┘  └─────────────────────────────┘\n/// ```\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol FileHandleProtocol {\n    /// Returns information about the file.\n    ///\n    /// Information is typically gathered by calling `fstat(2)` on the file.\n    ///\n    /// - Returns: Information about the open file.\n    func info() async throws -> FileInfo\n\n    /// Replaces the permissions set on the file.\n    ///\n    /// Permissions are typically set using `fchmod(2)`.\n    ///\n    /// - Parameters:\n    ///   - permissions: The permissions to set on the file.\n    func replacePermissions(_ permissions: FilePermissions) async throws\n\n    /// Adds permissions to the existing permissions set for the file.\n    ///\n    /// This is equivalent to retrieving the permissions, merging them with the provided\n    /// permissions and then replacing the permissions on the file.\n    ///\n    /// - Parameters:\n    ///   - permissions: The permissions to add to the file.\n    /// - Returns: The updated permissions.\n    @discardableResult\n    func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions\n\n    /// Remove permissions from the existing permissions set for the file.\n    ///\n    /// This is equivalent to retrieving the permissions, subtracting any of the provided\n    /// permissions and then replacing the permissions on the file.\n    ///\n    /// - Parameters:\n    ///   - permissions: The permissions to remove from the file.\n    /// - Returns: The updated permissions.\n    @discardableResult\n    func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions\n\n    /// Returns an array containing the names of all extended attributes set on the file.\n    ///\n    /// Attributes names are typically fetched using `flistxattr(2)`.\n    func attributeNames() async throws -> [String]\n\n    /// Returns the value for the named attribute if it exists; `nil` otherwise.\n    ///\n    /// Attribute values are typically fetched using `fgetxattr(2)`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the attribute.\n    /// - Returns: The bytes of the value set for the attribute. If no value is set an empty array\n    ///     is returned.\n    func valueForAttribute(_ name: String) async throws -> [UInt8]\n\n    /// Replaces the value for the named attribute, creating it if it didn't already exist.\n    ///\n    /// Attribute values are typically replaced using `fsetxattr(2)`.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to set as the value for the attribute.\n    ///   - name: The name of the attribute.\n    func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws\n\n    /// Removes the value for the named attribute if it exists.\n    ///\n    /// Attribute values are typically removed using `fremovexattr(2)`.\n    ///\n    /// - Parameter name: The name of the attribute to remove.\n    func removeValueForAttribute(_ name: String) async throws\n\n    /// Synchronize modified data and metadata to a permanent storage device.\n    ///\n    /// This is typically achieved using `fsync(2)`.\n    func synchronize() async throws\n\n    /// Runs the provided callback with the file descriptor for this handle.\n    ///\n    /// This function should be used with caution: the `FileDescriptor` must not be escaped from\n    /// the closure nor should it be closed. Where possible make use of the methods defined\n    /// on ``FileHandleProtocol`` instead; this function is intended as an escape hatch.\n    ///\n    /// Note that `execute` is not run if the handle has already been closed.\n    ///\n    /// - Parameter execute: A closure to run.\n    /// - Returns: The result of the closure.\n    func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R\n\n    /// Detaches and returns the file descriptor from the handle.\n    ///\n    /// After detaching the file descriptor the handle is rendered invalid. All methods will throw\n    /// an appropriate error if called. Detaching the descriptor yields ownerships to the caller.\n    ///\n    /// - Returns: The detached `FileDescriptor`\n    func detachUnsafeFileDescriptor() throws -> FileDescriptor\n\n    /// Closes the file handle.\n    ///\n    /// It is important to close a handle once it has been finished with to avoid leaking\n    /// resources. Prefer using APIs which provided scoped access to a file handle which\n    /// manage lifecycles on your behalf. Note that if the handle has been detached via\n    /// ``detachUnsafeFileDescriptor()`` then it is not necessary to close the handle.\n    ///\n    /// After closing the handle calls to other functions will throw an appropriate error.\n    func close() async throws\n\n    /// Sets the file's last access and last data modification times to the given values.\n    ///\n    /// If **either** time is `nil`, the current value will not be changed.\n    /// If **both** times are `nil`, then both times will be set to the current time.\n    ///\n    /// > Important: Times are only considered valid if their nanoseconds components are one of the following:\n    /// > - `UTIME_NOW` (you can use ``FileInfo/Timespec/now`` to get a Timespec set to this value),\n    /// > - `UTIME_OMIT` (you can use ``FileInfo/Timespec/omit`` to get a Timespec set to this value),\n    /// > - Greater than zero and no larger than 1000 million: if outside of this range, the value will be clamped to the closest valid value.\n    /// > The seconds component must also be positive: if it's not, zero will be used as the value instead.\n    ///\n    /// - Parameters:\n    ///   - lastAccess: The new value of the file's last access time, as time elapsed since the Epoch.\n    ///   - lastDataModification: The new value of the file's last data modification time, as time elapsed since the Epoch.\n    ///\n    /// - Throws: If there's an error updating the times. If this happens, the original values won't be modified.\n    func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws\n}\n\n// MARK: - Readable\n\n/// A handle for reading data from an open file.\n///\n/// ``ReadableFileHandleProtocol`` refines ``FileHandleProtocol`` to add requirements for reading data from a file.\n///\n/// There are two requirements for implementing this protocol:\n/// 1. ``readChunk(fromAbsoluteOffset:length:)``, and\n/// 2. ``readChunks(chunkLength:)\n///\n/// A number of overloads are provided which provide sensible defaults.\n///\n/// Conformance to ``ReadableFileHandleProtocol`` also provides\n/// ``readToEnd(fromAbsoluteOffset:maximumSizeAllowed:)`` (and various overloads with sensible\n/// defaults) for reading the contents of a file into memory.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol ReadableFileHandleProtocol: FileHandleProtocol {\n    /// Returns a slice of bytes read from the file.\n    ///\n    /// The length of the slice to read indicates the largest size in bytes that the returned slice\n    /// may be. The slice may be shorter than the given `length` if there are fewer bytes from the\n    /// `offset` to the end of the file.\n    ///\n    /// - Parameters:\n    ///   - offset: The absolute offset into the file to read from.\n    ///   - length: The maximum number of bytes to read as a ``ByteCount``.\n    /// - Returns: The bytes read from the file.\n    func readChunk(fromAbsoluteOffset offset: Int64, length: ByteCount) async throws -> ByteBuffer\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: The absolute offsets into the file to read.\n    ///   - chunkLength: The maximum length of the chunk to read as a ``ByteCount``.\n    /// - Returns: A sequence of chunks read from the file.\n    func readChunks(in range: Range<Int64>, chunkLength: ByteCount) -> FileChunks\n}\n\n// MARK: - Read chunks with default chunk length\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ReadableFileHandleProtocol {\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: ClosedRange<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: Range(range), chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: Range<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: range, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: PartialRangeFrom<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        let newRange = range.lowerBound..<Int64.max\n        return self.readChunks(in: newRange, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: PartialRangeThrough<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        let newRange = 0...range.upperBound\n        return self.readChunks(in: newRange, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: PartialRangeUpTo<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        let newRange = 0..<range.upperBound\n        return self.readChunks(in: newRange, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: UnboundedRange,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: 0..<Int64.max, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: ..., chunkLength: chunkLength)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ReadableFileHandleProtocol {\n    /// Returns the contents of a file by loading it into memory.\n    ///\n    /// - Important: This method checks whether the file is seekable or not (i.e., whether it's a socket,\n    /// pipe or FIFO), and will throw ``FileSystemError/Code-swift.struct/unsupported`` if\n    /// an offset other than zero is passed.\n    ///\n    /// - Parameters:\n    ///   - offset: The absolute offset into the file to read from. Defaults to zero.\n    ///   - maximumSizeAllowed: The maximum size of file to read, as a ``ByteCount``.\n    /// - Returns: The bytes read from the file.\n    /// - Throws: ``FileSystemError`` with code ``FileSystemError/Code-swift.struct/resourceExhausted``\n    /// if `maximumSizeAllowed` is more than can be written to `ByteBuffer`. Or if there are more bytes to read than\n    /// `maximumBytesAllowed`.\n    public func readToEnd(\n        fromAbsoluteOffset offset: Int64 = 0,\n        maximumSizeAllowed: ByteCount\n    ) async throws -> ByteBuffer {\n        let maximumSizeAllowed = maximumSizeAllowed == .unlimited ? .byteBufferCapacity : maximumSizeAllowed\n        let info = try await self.info()\n        let fileSize = Int64(info.size)\n        let readSize = max(Int(fileSize - offset), 0)\n\n        if maximumSizeAllowed > .byteBufferCapacity {\n            throw FileSystemError(\n                code: .resourceExhausted,\n                message: \"\"\"\n                    The maximum size allowed (\\(maximumSizeAllowed)) is more than the maximum \\\n                    amount of bytes that can be written to ByteBuffer \\\n                    (\\(ByteCount.byteBufferCapacity)). You can read the file in smaller chunks by \\\n                    calling readChunks().\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n        }\n\n        if readSize > maximumSizeAllowed.bytes {\n            throw FileSystemError(\n                code: .resourceExhausted,\n                message: \"\"\"\n                    There are more bytes to read (\\(readSize)) than the maximum size allowed \\\n                    (\\(maximumSizeAllowed)). Read the file in chunks or increase the maximum size \\\n                    allowed.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n        }\n\n        let isSeekable = !(info.type == .fifo || info.type == .socket)\n        if isSeekable {\n            // Limit the size of single shot reads. If the system is busy then avoid slowing down other\n            // work by blocking an I/O executor thread while doing a large read. The limit is somewhat\n            // arbitrary.\n            let singleShotReadLimit = 64 * 1024 * 1024\n\n            // If the file size isn't 0 but the read size is, then it means that\n            // we are intending to read an empty fragment: we can just return\n            // fast and skip any reads.\n            // If the file size is 0, we can't conclude anything about the size\n            // of the file, as `stat` will return 0 for unbounded files.\n            // If this happens, just read in chunks to make sure the whole file\n            // is read (up to `maximumSizeAllowed` bytes).\n            var forceChunkedRead = false\n            if fileSize > 0 {\n                if readSize == 0 {\n                    return ByteBuffer()\n                }\n            } else {\n                forceChunkedRead = true\n            }\n\n            if !forceChunkedRead, readSize <= singleShotReadLimit {\n                return try await self.readChunk(\n                    fromAbsoluteOffset: offset,\n                    length: .bytes(Int64(readSize))\n                )\n            } else {\n                var accumulator = ByteBuffer()\n                accumulator.reserveCapacity(readSize)\n\n                for try await chunk in self.readChunks(in: offset..., chunkLength: .mebibytes(8)) {\n                    accumulator.writeImmutableBuffer(chunk)\n                    if accumulator.readableBytes > maximumSizeAllowed.bytes {\n                        throw FileSystemError(\n                            code: .resourceExhausted,\n                            message: \"\"\"\n                                There are more bytes to read than the maximum size allowed \\\n                                (\\(maximumSizeAllowed)). Read the file in chunks or increase the maximum size \\\n                                allowed.\n                                \"\"\",\n                            cause: nil,\n                            location: .here()\n                        )\n                    }\n                }\n\n                return accumulator\n            }\n        } else {\n            guard offset == 0 else {\n                throw FileSystemError(\n                    code: .unsupported,\n                    message: \"File is unseekable.\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n            var accumulator = ByteBuffer()\n            accumulator.reserveCapacity(readSize)\n\n            for try await chunk in self.readChunks(in: ..., chunkLength: .mebibytes(8)) {\n                accumulator.writeImmutableBuffer(chunk)\n                if accumulator.readableBytes > maximumSizeAllowed.bytes {\n                    throw FileSystemError(\n                        code: .resourceExhausted,\n                        message: \"\"\"\n                            There are more bytes to read than the maximum size allowed \\\n                            (\\(maximumSizeAllowed)). Read the file in chunks or increase the maximum size \\\n                            allowed.\n                            \"\"\",\n                        cause: nil,\n                        location: .here()\n                    )\n                }\n            }\n\n            return accumulator\n        }\n    }\n}\n\n// MARK: - Writable\n\n/// A file handle suitable for writing.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol WritableFileHandleProtocol: FileHandleProtocol {\n    /// Write the given bytes to the open file.\n    ///\n    /// - Important: This method checks whether the file is seekable or not (i.e., whether it's a socket,\n    /// pipe or FIFO), and will throw ``FileSystemError/Code-swift.struct/unsupported``\n    /// if an offset other than zero is passed.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to write.\n    ///   - offset: The absolute offset into the file to write the bytes.\n    /// - Returns: The number of bytes written.\n    /// - Throws: ``FileSystemError/Code-swift.struct/unsupported`` if file is\n    /// unseekable and `offset` is not 0.\n    @discardableResult\n    func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64\n\n    /// Resizes a file to the given size.\n    ///\n    /// - Parameters:\n    ///   - size: The number of bytes to resize the file to as a ``ByteCount``.\n    func resize(\n        to size: ByteCount\n    ) async throws\n\n    /// Closes the file handle.\n    ///\n    /// It is important to close a handle once it has been finished with to avoid leaking\n    /// resources. Prefer using APIs which provided scoped access to a file handle which\n    /// manage lifecycles on your behalf. Note that if the handle has been detached via\n    /// ``FileHandleProtocol/detachUnsafeFileDescriptor()`` then it is not necessary to close\n    /// the handle.\n    ///\n    /// After closing the handle calls to other functions will throw an appropriate error.\n    ///\n    /// - Parameters:\n    ///   - makeChangesVisible: Whether the changes made to the file will be made visibile. This\n    ///       parameter is ignored unless ``OpenOptions/NewFile/transactionalCreation`` was\n    ///       set to `true`. When `makeChangesVisible` is `true`, the file will be created on the\n    ///       filesystem with the expected name, otherwise no file will be created or the original\n    ///       file won't be modified (if one existed).\n    func close(makeChangesVisible: Bool) async throws\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension WritableFileHandleProtocol {\n    /// Write the readable bytes of the `ByteBuffer` to the open file.\n    ///\n    /// - Important: This method checks whether the file is seekable or not (i.e., whether it's a socket,\n    /// pipe or FIFO), and will throw ``FileSystemError/Code-swift.struct/unsupported``\n    /// if an offset other than zero is passed.\n    ///\n    /// - Parameters:\n    ///   - buffer: The bytes to write.\n    ///   - offset: The absolute offset into the file to write the bytes.\n    /// - Returns: The number of bytes written.\n    /// - Throws: ``FileSystemError/Code-swift.struct/unsupported`` if file is\n    /// unseekable and `offset` is not 0.\n    @discardableResult\n    public func write(\n        contentsOf buffer: ByteBuffer,\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.write(contentsOf: buffer.readableBytesView, toAbsoluteOffset: offset)\n    }\n}\n\n// MARK: - File times modifiers\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileHandleProtocol {\n    /// Sets the file's last access time to the given time.\n    ///\n    /// - Parameter time: The time to which the file's last access time should be set.\n    ///\n    /// - Throws: If there's an error updating the time. If this happens, the original value won't be modified.\n    public func setLastAccessTime(to time: FileInfo.Timespec) async throws {\n        try await self.setTimes(lastAccess: time, lastDataModification: nil)\n    }\n\n    /// Sets the file's last data modification time to the given time.\n    ///\n    /// - Parameter time: The time to which the file's last data modification time should be set.\n    ///\n    /// - Throws: If there's an error updating the time. If this happens, the original value won't be modified.\n    public func setLastDataModificationTime(to time: FileInfo.Timespec) async throws {\n        try await self.setTimes(lastAccess: nil, lastDataModification: time)\n    }\n\n    /// Sets the file's last access and last data modification times to the current time.\n    ///\n    /// - Throws: If there's an error updating the times. If this happens, the original values won't be modified.\n    public func touch() async throws {\n        try await self.setTimes(lastAccess: nil, lastDataModification: nil)\n    }\n}\n\n/// A file handle which is suitable for reading and writing.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic typealias ReadableAndWritableFileHandleProtocol = ReadableFileHandleProtocol\n    & WritableFileHandleProtocol\n\n// MARK: - Directory\n\n/// A handle suitable for directories.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol DirectoryFileHandleProtocol: FileHandleProtocol {\n    /// The type of ``ReadableFileHandleProtocol`` to return when opening files for reading.\n    associatedtype ReadFileHandle: ReadableFileHandleProtocol\n\n    /// The type of ``WritableFileHandleProtocol`` to return when opening files for writing.\n    associatedtype WriteFileHandle: WritableFileHandleProtocol\n\n    /// The type of ``ReadableAndWritableFileHandleProtocol`` to return when opening files for reading and writing.\n    associatedtype ReadWriteFileHandle: ReadableAndWritableFileHandleProtocol\n\n    /// Returns an `AsyncSequence` of entries in the open directory.\n    ///\n    /// You can recurse into and list the contents of any subdirectories by setting `recursive`\n    /// to `true`. The current (\".\") and parent (\"..\") directory entries are not included. The order\n    /// of entries is arbitrary and shouldn't be relied upon.\n    ///\n    /// - Parameter recursive: Whether subdirectories should be recursively visited.\n    /// - Returns: An `AsyncSequence` of directory entries.\n    func listContents(recursive: Bool) -> DirectoryEntries\n\n    /// Opens the file at `path` for reading and returns a handle to it.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle. The file being\n    /// opened must already exist otherwise this function will throw a ``FileSystemError`` with\n    /// code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open relative to the open file.\n    ///   - options: How the file should be opened.\n    /// - Returns: A read-only handle to the opened file.\n    func openFile(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle\n\n    /// Opens the file at `path` for writing and returns a handle to it.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    /// - Returns: A write-only handle to the opened file.\n    func openFile(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle\n\n    /// Opens the file at `path` for reading and writing and returns a handle to it.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    func openFile(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle\n\n    /// Opens the directory at `path` and returns a handle to it.\n    ///\n    /// The directory being opened must already exist otherwise this function will throw an error.\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A handle to the opened directory.\n    func openDirectory(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory\n    ) async throws -> Self\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension DirectoryFileHandleProtocol {\n    /// Returns an `AsyncSequence` of entries in the open directory.\n    ///\n    /// The current (\".\") and parent (\"..\") directory entries are not included. The order of entries\n    /// is arbitrary and should not be relied upon.\n    public func listContents() -> DirectoryEntries {\n        self.listContents(recursive: false)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension DirectoryFileHandleProtocol {\n    /// Opens the file at the given path and provides scoped read access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns. Files may also be opened in write-only and read-write\n    /// mode by calling ``DirectoryFileHandleProtocol/withFileHandle(forWritingAt:options:execute:)``\n    /// and ``DirectoryFileHandleProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)``,\n    /// respectively.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle. The file being\n    /// opened must already exist otherwise this function will throw a ``FileSystemError`` with\n    /// code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - body: A closure which provides read-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read = OpenOptions.Read(),\n        execute body: (_ read: ReadFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAt: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped write access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns. Files may also be opened in read-only or read-write\n    /// mode by calling ``DirectoryFileHandleProtocol/withFileHandle(forReadingAt:options:execute:)`` and\n    /// ``DirectoryFileHandleProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)``,\n    /// respectively.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - body: A closure which provides write-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute body: (_ write: WriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forWritingAt: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { result in\n            switch result {\n            case .success:\n                try await handle.close(makeChangesVisible: true)\n            case .failure:\n                try await handle.close(makeChangesVisible: false)\n            }\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped read-write access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns. Files may also be opened in read-only or write-only\n    /// mode by calling ``DirectoryFileHandleProtocol/withFileHandle(forReadingAt:options:execute:)`` and\n    /// ``DirectoryFileHandleProtocol/withFileHandle(forWritingAt:options:execute:)``, respectively.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading and writing.\n    ///   - options: How the file should be opened.\n    ///   - body: A closure which provides access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute body: (_ readWrite: ReadWriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAndWritingAt: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { result in\n            switch result {\n            case .success:\n                try await handle.close(makeChangesVisible: true)\n            case .failure:\n                try await handle.close(makeChangesVisible: false)\n            }\n        }\n    }\n\n    /// Opens the directory at the given path and provides scoped access to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the directory should be opened.\n    ///   - body: A closure which provides access to the directory.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withDirectoryHandle<Result>(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory = OpenOptions.Directory(),\n        execute body: (_ directory: Self) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openDirectory(atPath: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileInfo.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n/// Information about a file system object.\n///\n/// The information available for a file depends on the platform, ``FileInfo`` provides\n/// convenient access to a common subset of properties. Using these properties ensures that\n/// code is portable. If available, the platform specific information is made available via\n/// ``FileInfo/platformSpecificStatus``. However users should take care to ensure their\n/// code uses the correct platform checks when using it to ensure their code is portable.\npublic struct FileInfo: Hashable, Sendable {\n    /// Wraps `CInterop.Stat` providing `Hashable` and `Equatable` conformance.\n    private var _platformSpecificStatus: Stat?\n\n    /// The information about the file returned from the filesystem, if available.\n    ///\n    /// This value is platform specific: you should be careful when using\n    /// it as some of its fields vary across platforms. In most cases prefer\n    /// using other properties on this type instead.\n    ///\n    /// See also: the manual pages for 'stat' (`man 2 stat`)\n    public var platformSpecificStatus: CInterop.Stat? {\n        get { self._platformSpecificStatus?.stat }\n        set { self._platformSpecificStatus = newValue.map { Stat($0) } }\n    }\n\n    /// The type of the file.\n    public var type: FileType\n\n    /// Permissions currently set on the file.\n    public var permissions: FilePermissions\n\n    /// The size of the file in bytes.\n    public var size: Int64\n\n    /// User ID of the file.\n    public var userID: UserID\n\n    /// Group ID of the file.\n    public var groupID: GroupID\n\n    /// The last time the file was accessed.\n    public var lastAccessTime: Timespec\n\n    /// The last time the files data was last changed.\n    public var lastDataModificationTime: Timespec\n\n    /// The last time the status of the file was changed.\n    public var lastStatusChangeTime: Timespec\n\n    /// Creates a ``FileInfo`` by deriving values from a platform-specific value.\n    public init(platformSpecificStatus: CInterop.Stat) {\n        self._platformSpecificStatus = Stat(platformSpecificStatus)\n        self.type = FileType(platformSpecificMode: CInterop.Mode(platformSpecificStatus.st_mode))\n        self.permissions = FilePermissions(masking: CInterop.Mode(platformSpecificStatus.st_mode))\n        self.size = Int64(platformSpecificStatus.st_size)\n        self.userID = UserID(rawValue: platformSpecificStatus.st_uid)\n        self.groupID = GroupID(rawValue: platformSpecificStatus.st_gid)\n\n        #if canImport(Darwin)\n        self.lastAccessTime = Timespec(platformSpecificStatus.st_atimespec)\n        self.lastDataModificationTime = Timespec(platformSpecificStatus.st_mtimespec)\n        self.lastStatusChangeTime = Timespec(platformSpecificStatus.st_ctimespec)\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        self.lastAccessTime = Timespec(platformSpecificStatus.st_atim)\n        self.lastDataModificationTime = Timespec(platformSpecificStatus.st_mtim)\n        self.lastStatusChangeTime = Timespec(platformSpecificStatus.st_ctim)\n        #endif\n    }\n\n    /// Creates a ``FileInfo`` from the provided values.\n    ///\n    /// If you have a platform specific status value prefer calling\n    /// ``init(platformSpecificStatus:)``.\n    public init(\n        type: FileType,\n        permissions: FilePermissions,\n        size: Int64,\n        userID: UserID,\n        groupID: GroupID,\n        lastAccessTime: Timespec,\n        lastDataModificationTime: Timespec,\n        lastStatusChangeTime: Timespec\n    ) {\n        self._platformSpecificStatus = nil\n        self.type = type\n        self.permissions = permissions\n        self.size = size\n        self.userID = userID\n        self.groupID = groupID\n        self.lastAccessTime = lastAccessTime\n        self.lastDataModificationTime = lastDataModificationTime\n        self.lastStatusChangeTime = lastStatusChangeTime\n    }\n}\n\nextension FileInfo {\n    /// The numeric ID of a user.\n    public struct UserID: Hashable, Sendable, CustomStringConvertible {\n        public var rawValue: UInt32\n\n        public init(rawValue: UInt32) {\n            self.rawValue = rawValue\n        }\n\n        public var description: String {\n            String(describing: self.rawValue)\n        }\n    }\n\n    /// The numeric ID of a group.\n    public struct GroupID: Hashable, Sendable, CustomStringConvertible {\n        public var rawValue: UInt32\n\n        public init(rawValue: UInt32) {\n            self.rawValue = rawValue\n        }\n\n        public var description: String {\n            String(describing: self.rawValue)\n        }\n    }\n\n    /// A time interval consisting of whole seconds and nanoseconds.\n    public struct Timespec: Hashable, Sendable {\n        #if canImport(Darwin)\n        private static let utimeOmit = Int(UTIME_OMIT)\n        private static let utimeNow = Int(UTIME_NOW)\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        private static let utimeOmit = Int(CNIOLinux_UTIME_OMIT)\n        private static let utimeNow = Int(CNIOLinux_UTIME_NOW)\n        #endif\n\n        /// A timespec where the seconds are set to zero and the nanoseconds set to `UTIME_OMIT`.\n        /// In syscalls such as `futimens`, this means the time component set to this value will be ignored.\n        public static let omit = Self(\n            seconds: 0,\n            nanoseconds: Self.utimeOmit\n        )\n\n        /// A timespec where the seconds are set to zero and the nanoseconds set to `UTIME_NOW`.\n        /// In syscalls such as `futimens`, this means the time component set to this value will be\n        /// be set to the current time or the largest value supported by the platform, whichever is smaller.\n        public static let now = Self(\n            seconds: 0,\n            nanoseconds: Self.utimeNow\n        )\n\n        /// The number of seconds.\n        public var seconds: Int\n\n        /// The number of nanoseconds.\n        public var nanoseconds: Int\n\n        init(_ timespec: timespec) {\n            self.seconds = timespec.tv_sec\n            self.nanoseconds = timespec.tv_nsec\n        }\n\n        public init(seconds: Int, nanoseconds: Int) {\n            self.seconds = seconds\n            self.nanoseconds = nanoseconds\n        }\n    }\n}\n\n/// A wrapper providing `Hashable` and `Equatable` conformance for `CInterop.Stat`.\nprivate struct Stat: Hashable {\n    var stat: CInterop.Stat\n\n    init(_ stat: CInterop.Stat) {\n        self.stat = stat\n    }\n\n    func hash(into hasher: inout Hasher) {\n        let stat = self.stat\n        // Different platforms have different underlying values; these are\n        // common between Darwin and Glibc.\n        hasher.combine(stat.st_dev)\n        hasher.combine(stat.st_mode)\n        hasher.combine(stat.st_nlink)\n        hasher.combine(stat.st_ino)\n        hasher.combine(stat.st_uid)\n        hasher.combine(stat.st_gid)\n        hasher.combine(stat.st_rdev)\n        hasher.combine(stat.st_size)\n        hasher.combine(stat.st_blocks)\n        hasher.combine(stat.st_blksize)\n\n        #if canImport(Darwin)\n        hasher.combine(FileInfo.Timespec(stat.st_atimespec))\n        hasher.combine(FileInfo.Timespec(stat.st_mtimespec))\n        hasher.combine(FileInfo.Timespec(stat.st_ctimespec))\n        hasher.combine(FileInfo.Timespec(stat.st_birthtimespec))\n        hasher.combine(stat.st_flags)\n        hasher.combine(stat.st_gen)\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        hasher.combine(FileInfo.Timespec(stat.st_atim))\n        hasher.combine(FileInfo.Timespec(stat.st_mtim))\n        hasher.combine(FileInfo.Timespec(stat.st_ctim))\n        #endif\n\n    }\n\n    static func == (lhs: Stat, rhs: Stat) -> Bool {\n        let lStat = lhs.stat\n        let rStat = rhs.stat\n\n        // Different platforms have different underlying values; these are\n        // common between Darwin and Glibc.\n        var isEqual = lStat.st_dev == rStat.st_dev\n        isEqual = isEqual && lStat.st_mode == rStat.st_mode\n        isEqual = isEqual && lStat.st_nlink == rStat.st_nlink\n        isEqual = isEqual && lStat.st_ino == rStat.st_ino\n        isEqual = isEqual && lStat.st_uid == rStat.st_uid\n        isEqual = isEqual && lStat.st_gid == rStat.st_gid\n        isEqual = isEqual && lStat.st_rdev == rStat.st_rdev\n        isEqual = isEqual && lStat.st_size == rStat.st_size\n        isEqual = isEqual && lStat.st_blocks == rStat.st_blocks\n        isEqual = isEqual && lStat.st_blksize == rStat.st_blksize\n\n        #if canImport(Darwin)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_atimespec) == FileInfo.Timespec(rStat.st_atimespec)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_mtimespec) == FileInfo.Timespec(rStat.st_mtimespec)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_ctimespec) == FileInfo.Timespec(rStat.st_ctimespec)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_birthtimespec)\n                == FileInfo.Timespec(rStat.st_birthtimespec)\n        isEqual = isEqual && lStat.st_flags == rStat.st_flags\n        isEqual = isEqual && lStat.st_gen == rStat.st_gen\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        isEqual = isEqual && FileInfo.Timespec(lStat.st_atim) == FileInfo.Timespec(rStat.st_atim)\n        isEqual = isEqual && FileInfo.Timespec(lStat.st_mtim) == FileInfo.Timespec(rStat.st_mtim)\n        isEqual = isEqual && FileInfo.Timespec(lStat.st_ctim) == FileInfo.Timespec(rStat.st_ctim)\n        #endif\n\n        return isEqual\n    }\n}\n\nextension FilePermissions {\n    internal init(masking rawValue: CInterop.Mode) {\n        self = .init(rawValue: rawValue & ~S_IFMT)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#endif\n\n/// A file system which interacts with the local system. The file system uses a thread pool to\n/// perform system calls.\n///\n/// ### Creating a `FileSystem`\n///\n/// You should prefer using the `shared` instance of the file system. The `shared` instance uses two\n/// threads unless the `SWIFT_FILE_SYSTEM_THREAD_COUNT` environment variable is set.\n///\n/// If you require more granular control you can create a ``FileSystem`` with the required number of\n/// threads by calling ``withFileSystem(numberOfThreads:_:)`` or by using ``init(threadPool:)``.\n///\n/// ### Errors\n///\n/// Errors thrown by ``FileSystem`` will be of type:\n/// - ``FileSystemError`` if it wasn't possible to complete the operation, or\n/// - `CancellationError` if the `Task` was cancelled.\n///\n/// ``FileSystemError`` implements `CustomStringConvertible`. The output from the `description`\n/// contains basic information including the error code, message and underlying error. You can get\n/// more information about the error by calling ``FileSystemError/detailedDescription()`` which\n/// returns a structured multi-line string containing information about the error.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct FileSystem: Sendable, FileSystemProtocol {\n    /// Returns a shared global instance of the ``FileSystem``.\n    ///\n    /// The file system executes blocking work in a thread pool which defaults to having two\n    /// threads. This can be modified by `blockingPoolThreadCountSuggestion` or by setting the\n    /// `NIO_SINGLETON_BLOCKING_POOL_THREAD_COUNT` environment variable.\n    public static var shared: FileSystem { globalFileSystem }\n\n    private let threadPool: NIOThreadPool\n    private let ownsThreadPool: Bool\n\n    fileprivate func shutdown() async {\n        if self.ownsThreadPool {\n            try? await self.threadPool.shutdownGracefully()\n        }\n    }\n\n    /// Creates a new ``FileSystem`` using the provided thread pool.\n    ///\n    /// - Parameter threadPool: A started thread pool to execute blocking system calls on. The\n    ///     ``FileSystem`` doesn't take ownership of the thread pool and you remain responsible for\n    ///     shutting it down when necessary.\n    public init(threadPool: NIOThreadPool) {\n        self.init(threadPool: threadPool, ownsThreadPool: false)\n    }\n\n    fileprivate init(threadPool: NIOThreadPool, ownsThreadPool: Bool) {\n        self.threadPool = threadPool\n        self.ownsThreadPool = ownsThreadPool\n    }\n\n    fileprivate init(numberOfThreads: Int) async {\n        let threadPool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        threadPool.start()\n        // Wait for the thread pool to start.\n        try? await threadPool.runIfActive {}\n        self.init(threadPool: threadPool, ownsThreadPool: true)\n    }\n\n    /// Open the file at `path` for reading.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A readable handle to the opened file.\n    public func openFile(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openFile(forReadingAt: path.underlying, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Open the file at `path` for writing.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/permissionDenied`` if you have insufficient\n    ///   permissions to create the file.\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist and `options`\n    ///   weren't set to create a file.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A writable handle to the opened file.\n    public func openFile(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openFile(forWritingAt: path.underlying, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Open the file at `path` for reading and writing.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/permissionDenied`` if you have insufficient\n    ///   permissions to create the file.\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist and `options`\n    ///   weren't set to create a file.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A readable and writable handle to the opened file.\n    public func openFile(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openFile(forReadingAndWritingAt: path.underlying, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Open the directory at `path`.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the directory should be opened.\n    /// - Returns: A handle to the opened directory.\n    public func openDirectory(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory\n    ) async throws -> DirectoryFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openDirectory(at: path.underlying, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Create a directory at the given path.\n    ///\n    /// If a directory (or file) already exists at `path` a ``FileSystemError`` with code\n    /// ``FileSystemError/Code-swift.struct/fileAlreadyExists`` is thrown.\n    ///\n    /// If the parent directory of the directory to created does not exist a ``FileSystemError``\n    /// with ``FileSystemError/Code-swift.struct/invalidArgument`` is thrown. Missing directories\n    /// can be created by passing `true` to `createIntermediateDirectories`.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if a file or directory already\n    ///   exists .\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if a component in the `path` prefix\n    ///   does not exist and `createIntermediateDirectories` is `false`.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `mkdir(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The directory to create.\n    ///   - createIntermediateDirectories: Whether intermediate directories should be created.\n    ///   - permissions: The permissions to set on the new directory; default permissions will be\n    ///       used if not specified.\n    public func createDirectory(\n        at path: NIOFilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions?\n    ) async throws {\n        try await self.createDirectory(\n            at: path,\n            withIntermediateDirectories: createIntermediateDirectories,\n            permissions: permissions,\n            idempotent: true\n        )\n    }\n\n    private func createDirectory(\n        at path: NIOFilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions?,\n        idempotent: Bool\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._createDirectory(\n                at: path.underlying,\n                withIntermediateDirectories: createIntermediateDirectories,\n                permissions: permissions ?? .defaultsForDirectory,\n                idempotent: idempotent\n            ).get()\n        }\n    }\n\n    /// Create a temporary directory at the given path, using a template.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if the template doesn't end in at\n    ///   least 3 'X's.\n    /// - ``FileSystemError/Code-swift.struct/permissionDenied`` if the user doesn't have permission\n    ///  to create a directory at the path specified in the template.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `mkdir(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - template: The template for the path of the temporary directory.\n    /// - Returns:\n    ///   - The path to the new temporary directory.\n    public func createTemporaryDirectory(\n        template: NIOFilePath\n    ) async throws -> NIOFilePath {\n        try await self.threadPool.runIfActive {\n            NIOFilePath(try self._createTemporaryDirectory(template: template.underlying).get())\n        }\n    }\n\n    /// Returns information about the file at `path` if it exists; nil otherwise.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses `lstat(2)` if `infoAboutSymbolicLink` is `true`, `stat(2)` otherwise.\n    ///\n    /// - Parameters:\n    ///    - path: The path of the file.\n    ///    - infoAboutSymbolicLink: If the file is a symbolic link and this parameter is `true`,\n    ///        then information about the link will be returned. Otherwise, information about the\n    ///        destination of the symbolic link is returned.\n    /// - Returns: Information about the file at the given path or `nil` if no file exists.\n    public func info(\n        forFileAt path: NIOFilePath,\n        infoAboutSymbolicLink: Bool\n    ) async throws -> FileInfo? {\n        try await self.threadPool.runIfActive {\n            try self._info(forFileAt: path.underlying, infoAboutSymbolicLink: infoAboutSymbolicLink).get()\n        }\n    }\n\n    // MARK: - File copying, removal, and moving\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The item to be copied must be a:\n    /// - regular file,\n    /// - symbolic link, or\n    /// - directory.\n    ///\n    /// `shouldCopyItem` can be used to ignore objects not part of this set.\n    ///\n    /// #### Errors\n    ///\n    /// In addition to the already documented errors these may be thrown\n    /// - ``FileSystemError/Code-swift.struct/unsupported`` if an item to be copied is not a regular\n    ///   file, symbolic link or directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// This function is platform dependent. On Darwin the `copyfile(2)` system call is used and\n    /// items are cloned where possible. On Linux the `sendfile(2)` system call is used.\n    ///\n    /// When `replaceExisting` is `true`, regular files are atomically replaced using `COPYFILE_UNLINK`\n    /// on Darwin or a temporary file followed by `renameat2(2)` on Linux. Symbolic links are\n    /// atomically replaced using a temporary symlink followed by `renamex_np(2)` on Darwin or\n    /// `renameat2(2)` on Linux.\n    ///\n    /// Note that `replaceExisting` is ignored for directories and implemented only for regular\n    /// files and symbolic links.\n    public func copyItem(\n        at sourcePath: NIOFilePath,\n        to destinationPath: NIOFilePath,\n        strategy copyStrategy: CopyStrategy,\n        replaceExisting: Bool,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: NIOFilePath\n            ) async -> Bool\n    ) async throws {\n        guard let info = try await self.info(forFileAt: sourcePath, infoAboutSymbolicLink: true)\n        else {\n            throw FileSystemError(\n                code: .notFound,\n                message: \"Unable to copy '\\(sourcePath)', it does not exist.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n\n        // By doing this before looking at the type, we allow callers to decide whether\n        // unanticipated kinds of entries can be safely ignored without needing changes upstream.\n        if await shouldCopyItem(.init(path: sourcePath, type: info.type)!, destinationPath) {\n            switch info.type {\n            case .regular:\n                try await self.copyRegularFile(\n                    from: sourcePath.underlying,\n                    to: destinationPath.underlying,\n                    replaceExisting: replaceExisting\n                )\n\n            case .symlink:\n                try await self.copySymbolicLink(\n                    from: sourcePath.underlying,\n                    to: destinationPath.underlying,\n                    replaceExisting: replaceExisting\n                )\n\n            case .directory:\n                try await self.copyDirectory(\n                    from: sourcePath.underlying,\n                    to: destinationPath.underlying,\n                    strategy: copyStrategy,\n                    shouldProceedAfterError: shouldProceedAfterError\n                ) { source, destination in\n                    await shouldCopyItem(source, .init(destination))\n                }\n\n            default:\n                throw FileSystemError(\n                    code: .unsupported,\n                    message: \"\"\"\n                        Can't copy '\\(sourcePath)' of type '\\(info.type)'; only regular files, \\\n                        symbolic links and directories can be copied.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    /// See ``FileSystemProtocol/removeItem(at:strategy:recursively:)``\n    ///\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// Only regular files, symbolic links and directories may be removed. If the file at `path` is\n    /// a directory then its contents and all of its subdirectories will be removed recursively.\n    /// Symbolic links are also removed (but their targets are not deleted). If no file exists at\n    /// `path` this function returns zero.\n    ///\n    /// #### Errors\n    ///\n    /// Errors codes thrown by this function include:\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if the item is not a regular file,\n    ///   symbolic link or directory. This also applies to items within the directory being removed.\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item being removed is a directory\n    ///   which isn't empty and `removeItemRecursively` is false.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `remove(3)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removalStrategy: Whether to delete files sequentially (one-by-one), or perform a\n    ///       concurrent scan of the tree at `path` and delete files when they are found.\n    ///   - removeItemRecursively: Whether or not to remove items recursively.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: NIOFilePath,\n        strategy removalStrategy: RemovalStrategy,\n        recursively removeItemRecursively: Bool\n    ) async throws -> Int {\n        // Try to remove the item: we might just get lucky.\n        let result = try await self.threadPool.runIfActive { Libc.remove(path.underlying) }\n\n        switch result {\n        case .success:\n            // Great; we removed an entire item.\n            return 1\n\n        case .failure(.noSuchFileOrDirectory):\n            // Nothing to delete.\n            return 0\n\n        case .failure(.directoryNotEmpty):\n            guard removeItemRecursively else {\n                throw FileSystemError(\n                    code: .notEmpty,\n                    message: \"\"\"\n                        Can't remove directory at path '\\(path)', it isn't empty and \\\n                        'removeItemRecursively' is false. Remove items from the directory first or \\\n                        set 'removeItemRecursively' to true when calling \\\n                        'removeItem(at:recursively:)'.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n\n            switch removalStrategy.wrapped {\n            case .sequential:\n                return try await self.removeItemSequentially(at: path.underlying)\n            case let .parallel(maxDescriptors):\n                return try await self.removeConcurrently(at: path.underlying, maxDescriptors)\n            }\n\n        case let .failure(errno):\n            throw FileSystemError.remove(errno: errno, path: path.underlying, location: .here())\n        }\n    }\n\n    @discardableResult\n    private func removeItemSequentially(\n        at path: FilePath\n    ) async throws -> Int {\n        var (subdirectories, filesRemoved) = try await self.withDirectoryHandle(\n            atPath: NIOFilePath(path)\n        ) { directory in\n            var subdirectories = [FilePath]()\n            var filesRemoved = 0\n\n            for try await batch in directory.listContents().batched() {\n                for entry in batch {\n                    switch entry.type {\n                    case .directory:\n                        subdirectories.append(entry.path.underlying)\n\n                    default:\n                        filesRemoved += try await self.removeOneItem(at: entry.path.underlying)\n                    }\n                }\n            }\n\n            return (subdirectories, filesRemoved)\n        }\n\n        for subdirectory in subdirectories {\n            filesRemoved += try await self.removeItemSequentially(at: subdirectory)\n        }\n\n        // The directory should be empty now. Remove ourself.\n        filesRemoved += try await self.removeOneItem(at: path)\n\n        return filesRemoved\n\n    }\n\n    private func removeConcurrently(\n        at path: FilePath,\n        _ maxDescriptors: Int\n    ) async throws -> Int {\n        let bucket: TokenBucket = .init(tokens: maxDescriptors)\n        return try await self.discoverAndRemoveItemsInTree(at: path, bucket)\n    }\n\n    /// Moves the named file or directory to a new location.\n    ///\n    /// Only regular files, symbolic links and directories may be moved. If the item to be is a\n    /// symbolic link then only the link is moved; the target of the link is not moved.\n    ///\n    /// If the file is moved within to a different logical partition then the file is copied to the\n    /// new partition before being removed from old partition. If removing the item fails the copied\n    /// file will not be removed.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if an item at `destinationPath`\n    ///   already exists.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `rename(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to move.\n    ///   - destinationPath: The path at which to place the item.\n    public func moveItem(at sourcePath: NIOFilePath, to destinationPath: NIOFilePath) async throws {\n        let result = try await self.threadPool.runIfActive {\n            try self._moveItem(at: sourcePath.underlying, to: destinationPath.underlying).get()\n        }\n\n        switch result {\n        case .moved:\n            ()\n        case .differentLogicalDevices:\n            // Fall back to copy and remove.\n            try await self.copyItem(at: sourcePath, to: destinationPath)\n            try await self.removeItem(at: sourcePath, strategy: .platformDefault)\n        }\n    }\n\n    /// Replaces the item at `destinationPath` with the item at `existingPath`.\n    ///\n    /// Only regular files, symbolic links and directories may replace the item at the existing\n    /// path. The file at the destination path isn't required to exist. If it does exist it does not\n    /// have to match the type of the file it is being replaced with.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `existingPath` does not\n    ///   exist.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `rename(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - destinationPath: The path of the file or directory to replace.\n    ///   - existingPath: The path of the existing file or directory.\n    public func replaceItem(\n        at destinationPath: NIOFilePath,\n        withItemAt existingPath: NIOFilePath\n    ) async throws {\n        do {\n            try await self.removeItem(at: destinationPath, strategy: .platformDefault)\n            try await self.moveItem(at: existingPath, to: destinationPath)\n            try await self.removeItem(at: existingPath, strategy: .platformDefault)\n        } catch let error as FileSystemError {\n            throw FileSystemError(\n                message: \"Can't replace '\\(destinationPath)' with '\\(existingPath)'.\",\n                wrapping: error\n            )\n        }\n    }\n\n    // MARK: - Symbolic links\n\n    /// Creates a symbolic link between two files.\n    ///\n    /// A link is created at `linkPath` which points to `destinationPath`. The destination of a\n    /// symbolic link can be read with ``destinationOfSymbolicLink(at:)``.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if a file exists at\n    ///   `destinationPath`.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `link(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - linkPath: The path at which to create the symbolic link.\n    ///   - destinationPath: The path that contains the item that the symbolic link points to.`\n    public func createSymbolicLink(\n        at linkPath: NIOFilePath,\n        withDestination destinationPath: NIOFilePath\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._createSymbolicLink(at: linkPath.underlying, withDestination: destinationPath.underlying).get()\n        }\n    }\n\n    /// Returns the path of the item pointed to by a symbolic link.\n    ///\n    /// The destination of the symbolic link is not guaranteed to be a valid path, nor is it\n    /// guaranteed to be an absolute path. If you need to open a file which is the destination of a\n    /// symbolic link then the appropriate `open` function:\n    /// - ``openFile(forReadingAt:)``\n    /// - ``openFile(forWritingAt:options:)``\n    /// - ``openFile(forReadingAndWritingAt:options:)``\n    /// - ``openDirectory(atPath:options:)``\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` does not exist.\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if the file at `path` is not a\n    ///   symbolic link.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `readlink(2)` system call.\n    ///\n    /// - Parameter path: The path of a file or directory.\n    /// - Returns: The path of the file or directory to which the symbolic link points to.\n    public func destinationOfSymbolicLink(\n        at path: NIOFilePath\n    ) async throws -> NIOFilePath {\n        try await self.threadPool.runIfActive {\n            NIOFilePath(try self._destinationOfSymbolicLink(at: path.underlying).get())\n        }\n    }\n\n    /// Returns the path of the current working directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `getcwd(2)` system call.\n    ///\n    /// - Returns: The path to the current working directory.\n    public var currentWorkingDirectory: NIOFilePath {\n        get async throws {\n            let result = try await self.threadPool.runIfActive {\n                try Libc.getcwd().mapError { errno in\n                    FileSystemError.getcwd(errno: errno, location: .here())\n                }.get()\n            }\n            return .init(result)\n        }\n    }\n\n    /// Returns the path of the current user's home directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// This function first checks the `HOME` environment variable (and `USERPROFILE` on Windows).\n    /// If not set, on Darwin/Linux/Android it uses `getpwuid_r(3)` to query the password database.\n    ///\n    /// Note: `getpwuid_r` can potentially block on I/O (e.g., when using NIS or LDAP),\n    /// which is why this property is async when falling back to the password database.\n    ///\n    /// - Returns: The path to the current user's home directory.\n    public var homeDirectory: NIOFilePath {\n        get async throws {\n            if let path = Libc.homeDirectoryFromEnvironment() {\n                return NIOFilePath(path)\n            }\n\n            #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n            return try await self.threadPool.runIfActive {\n                NIOFilePath(\n                    try Libc.homeDirectoryFromPasswd().mapError { errno in\n                        FileSystemError.getpwuid_r(errno: errno, location: .here())\n                    }.get()\n                )\n            }\n            #else\n            throw FileSystemError.getpwuid_r(errno: .noSuchFileOrDirectory, location: .here())\n            #endif\n        }\n    }\n\n    /// Returns a path to a temporary directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// On all platforms, this function first attempts to read the `TMPDIR` environment variable and returns that path, omitting trailing slashes.\n    /// If that fails:\n    /// - On Darwin this function uses `confstr(3)` and gets the value of `_CS_DARWIN_USER_TEMP_DIR`;\n    ///   the users temporary directory. Typically items are removed after three days if they are not\n    ///   accessed.\n    /// - On Android this returns \"/data/local/tmp\".\n    /// - On other platforms this returns \"/tmp\".\n    ///\n    /// - Returns: The path to a temporary directory.\n    public var temporaryDirectory: NIOFilePath {\n        get async throws {\n            if let tmpdir = getenv(\"TMPDIR\") {\n                return NIOFilePath(String(cString: tmpdir))\n            }\n\n            #if canImport(Darwin)\n            return try await self.threadPool.runIfActive {\n                let result = Libc.constr(_CS_DARWIN_USER_TEMP_DIR)\n                switch result {\n                case .success(let path):\n                    return NIOFilePath(path)\n                case .failure(_):\n                    return NIOFilePath(\"/tmp\")\n                }\n            }\n            #elseif os(Android)\n            return NIOFilePath(\"/data/local/tmp\")\n            #else\n            return NIOFilePath(\"/tmp\")\n            #endif\n        }\n    }\n}\n\n// MARK: - Creating FileSystems\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate let globalFileSystem: FileSystem = {\n    guard NIOSingletons.singletonsEnabledSuggestion else {\n        fatalError(\n            \"\"\"\n            Cannot create global singleton FileSystem thread pool because the global singletons \\\n            have been disabled by setting `NIOSingletons.singletonsEnabledSuggestion = false`\n            \"\"\"\n        )\n    }\n    return FileSystem(threadPool: NIOSingletons.posixBlockingThreadPool, ownsThreadPool: false)\n}()\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOSingletons {\n    /// Returns a shared global instance of the ``FileSystem``.\n    ///\n    /// The file system executes blocking work in a thread pool. See\n    /// `blockingPoolThreadCountSuggestion` for the default behaviour and ways to control it.\n    public static var fileSystem: FileSystem { globalFileSystem }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemProtocol where Self == FileSystem {\n    /// A global shared instance of ``FileSystem``.\n    public static var shared: FileSystem {\n        FileSystem.shared\n    }\n}\n\n/// Provides temporary scoped access to a ``FileSystem`` with the given number of threads.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic func withFileSystem<Result>(\n    numberOfThreads: Int,\n    _ body: (FileSystem) async throws -> Result\n) async throws -> Result {\n    let fileSystem = await FileSystem(numberOfThreads: numberOfThreads)\n    return try await withUncancellableTearDown {\n        try await body(fileSystem)\n    } tearDown: { _ in\n        await fileSystem.shutdown()\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    /// Opens `path` for reading and returns ``ReadFileHandle`` or ``FileSystemError``.\n    private func _openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) -> Result<ReadFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .readOnly,\n            options: options.descriptorOptions,\n            permissions: nil,\n            transactionalIfPossible: false,\n            threadPool: self.threadPool\n        ).map {\n            ReadFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Opens `path` for writing and returns ``WriteFileHandle`` or ``FileSystemError``.\n    private func _openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) -> Result<WriteFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .writeOnly,\n            options: options.descriptorOptions,\n            permissions: options.permissionsForRegularFile,\n            transactionalIfPossible: options.newFile?.transactionalCreation ?? false,\n            threadPool: self.threadPool\n        ).map {\n            WriteFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Opens `path` for reading and writing and returns ``ReadWriteFileHandle`` or\n    /// ``FileSystemError``.\n    private func _openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) -> Result<ReadWriteFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .readWrite,\n            options: options.descriptorOptions,\n            permissions: options.permissionsForRegularFile,\n            transactionalIfPossible: options.newFile?.transactionalCreation ?? false,\n            threadPool: self.threadPool\n        ).map {\n            ReadWriteFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Opens the directory at `path` and returns ``DirectoryFileHandle`` or ``FileSystemError``.\n    private func _openDirectory(\n        at path: FilePath,\n        options: OpenOptions.Directory\n    ) -> Result<DirectoryFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .readOnly,\n            options: options.descriptorOptions,\n            permissions: nil,\n            transactionalIfPossible: false,\n            threadPool: self.threadPool\n        ).map {\n            DirectoryFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Creates a directory at `fullPath`, potentially creating other directories along the way.\n    private func _createDirectory(\n        at fullPath: FilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions,\n        idempotent: Bool = true\n    ) -> Result<Void, FileSystemError> {\n        // We assume that we will be creating intermediate directories:\n        // - Try creating the directory. If it fails with ENOENT (no such file or directory), then\n        //   drop the last component and append it to a buffer.\n        // - Repeat until the path is empty. This means we cannot create the directory or we\n        //   succeed, in which case we can build up our original path and create directories one at\n        //   a time.\n        var droppedComponents: [FilePath.Component] = []\n        var path = fullPath\n\n        // Normalize the path to remove any superflous '..'.\n        path.lexicallyNormalize()\n\n        if path.isEmpty {\n            let error = FileSystemError(\n                code: .invalidArgument,\n                message: \"Path of directory to create must not be empty.\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        loop: while true {\n            switch Syscall.mkdir(at: path, permissions: permissions) {\n            case .success:\n                break loop\n\n            case let .failure(errno):\n                if errno == .fileExists {\n                    if idempotent {\n                        switch self._info(forFileAt: path, infoAboutSymbolicLink: false) {\n                        case let .success(maybeInfo):\n                            if let info = maybeInfo, info.type == .directory {\n                                break loop\n                            } else {\n                                // A file exists at this path.\n                                return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                            }\n                        case .failure:\n                            // Unable to determine what exists at this path.\n                            return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                        }\n                    } else {\n                        return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                    }\n                }\n                guard createIntermediateDirectories, errno == .noSuchFileOrDirectory else {\n                    return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                }\n\n                // Drop the last component and loop around.\n                if let component = path.lastComponent {\n                    path.removeLastComponent()\n                    droppedComponents.append(component)\n                } else {\n                    // Should only happen if the path is empty or contains just the root.\n                    return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                }\n            }\n        }\n\n        // Successfully made a directory, construct its children.\n        while let subdirectory = droppedComponents.popLast() {\n            path.append(subdirectory)\n            switch Syscall.mkdir(at: path, permissions: permissions) {\n            case .success:\n                continue\n            case let .failure(errno):\n                return .failure(.mkdir(errno: errno, path: path, location: .here()))\n            }\n        }\n\n        return .success(())\n    }\n\n    /// Returns info about the file at `path`.\n    private func _info(\n        forFileAt path: FilePath,\n        infoAboutSymbolicLink: Bool\n    ) -> Result<FileInfo?, FileSystemError> {\n        let result: Result<CInterop.Stat, Errno>\n        if infoAboutSymbolicLink {\n            result = Syscall.lstat(path: path)\n        } else {\n            result = Syscall.stat(path: path)\n        }\n\n        return result.map {\n            FileInfo(platformSpecificStatus: $0)\n        }.flatMapError { errno in\n            if errno == .noSuchFileOrDirectory {\n                return .success(nil)\n            } else {\n                let name = infoAboutSymbolicLink ? \"lstat\" : \"stat\"\n                return .failure(.stat(name, errno: errno, path: path, location: .here()))\n            }\n        }\n    }\n\n    /// Represents an item in a directory that needs copying, or an explicit indication of the end\n    /// of items. The provision of the ``endOfDir`` case significantly simplifies the parallel code\n    enum DirCopyItem: Hashable, Sendable {\n        case endOfDir\n        case toCopy(from: DirectoryEntry, to: FilePath)\n    }\n\n    /// Creates the directory ``destinationPath`` based on the directory at ``sourcePath`` including\n    /// any permissions/attributes. It does not copy the contents but indicates the items within\n    /// ``sourcePath`` which should be copied.\n    ///\n    /// This is a little cumbersome, because it is used by ``copyDirectorySequential`` and\n    /// ``copyDirectoryParallel``. It is desirable to use the directories' file descriptor for as\n    /// little time as possible, and certainly not across asynchronous invocations. The downstream\n    /// paths in the parallel and sequential paths are very different\n    /// - Returns: An array of `DirCopyItem` which have passed the ``shouldCopyItem``` filter. The\n    ///     target file paths will all be in ``destinationPath``. The array will always finish with\n    ///     an ``DirCopyItem.endOfDir``.\n    private func prepareDirectoryForRecusiveCopy(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws -> [DirCopyItem] {\n        try await self.withDirectoryHandle(atPath: NIOFilePath(sourcePath)) { dir in\n            // Grab the directory info to copy permissions.\n            let info = try await dir.info()\n            try await self.createDirectory(\n                at: NIOFilePath(destinationPath),\n                withIntermediateDirectories: false,\n                permissions: info.permissions,\n                idempotent: false  // Fail if the destination dir already exists.\n            )\n\n            #if !os(Android)\n            // Copy over extended attributes, if any exist.\n            do {\n                let attributes = try await dir.attributeNames()\n\n                if !attributes.isEmpty {\n                    try await self.withDirectoryHandle(\n                        atPath: NIOFilePath(destinationPath)\n                    ) { destinationDir in\n                        for attribute in attributes {\n                            let value = try await dir.valueForAttribute(attribute)\n                            try await destinationDir.updateValueForAttribute(\n                                value,\n                                attribute: attribute\n                            )\n                        }\n                    }\n                }\n            } catch let error as FileSystemError where error.code == .unsupported {\n                // Not all file systems support extended attributes. Swallow errors indicating this.\n                ()\n            }\n            #endif\n            // Build a list of items the caller needs to deal with, then do any further work after\n            // closing the current directory.\n            var contentsToCopy = [DirCopyItem]()\n\n            for try await batch in dir.listContents().batched() {\n                for entry in batch {\n                    // Any further work is pointless. We are under no obligation to cleanup. Exit as\n                    // fast and cleanly as possible.\n                    try Task.checkCancellation()\n                    let entryDestination = destinationPath.appending(entry.name)\n\n                    if await shouldCopyItem(entry, entryDestination) {\n                        // Assume there's a good chance of everything in the batch being included in\n                        // the common case. Let geometric growth go from this point though.\n                        if contentsToCopy.isEmpty {\n                            // Reserve space for the endOfDir entry too.\n                            contentsToCopy.reserveCapacity(batch.count + 1)\n                        }\n                        switch entry.type {\n                        case .regular, .symlink, .directory:\n                            contentsToCopy.append(.toCopy(from: entry, to: entryDestination))\n\n                        default:\n                            let error = FileSystemError(\n                                code: .unsupported,\n                                message: \"\"\"\n                                    Can't copy '\\(entry.path)' of type '\\(entry.type)'; only regular \\\n                                    files, symbolic links and directories can be copied.\n                                    \"\"\",\n                                cause: nil,\n                                location: .here()\n                            )\n\n                            try await shouldProceedAfterError(entry, error)\n                        }\n                    }\n                }\n            }\n\n            contentsToCopy.append(.endOfDir)\n            return contentsToCopy\n        }\n    }\n\n    /// This could be achieved through quite complicated special casing of the parallel copy. The\n    /// resulting code is far harder to read and debug, so this is kept as a special case.\n    private func copyDirectorySequential(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        // Strategy: find all needed items to copy/recurse into while the directory is open; defer\n        // actual copying and recursion until after the source directory has been closed to avoid\n        // consuming too many file descriptors.\n        let toCopy = try await self.prepareDirectoryForRecusiveCopy(\n            from: sourcePath,\n            to: destinationPath,\n            shouldProceedAfterError: shouldProceedAfterError,\n            shouldCopyItem: shouldCopyItem\n        )\n\n        for entry in toCopy {\n            switch entry {\n            case .endOfDir:\n                // Sequential cases doesn't need to worry about this, it uses simple recursion.\n                continue\n            case let .toCopy(source, destination):\n                // Note: The entry type could have changed between finding it and acting on it. This\n                // is inherent in file systems, just more likely in an asynchronous environment. We\n                // just accept those coming through as regular errors.\n                switch source.type {\n                case .regular:\n                    do {\n                        try await self.copyRegularFile(\n                            from: source.path.underlying,\n                            to: destination,\n                            replaceExisting: false\n                        )\n                    } catch {\n                        try await shouldProceedAfterError(source, error)\n                    }\n\n                case .symlink:\n                    do {\n                        try await self.copySymbolicLink(\n                            from: source.path.underlying,\n                            to: destination\n                        )\n                    } catch {\n                        try await shouldProceedAfterError(source, error)\n                    }\n\n                case .directory:\n                    try await self.copyDirectorySequential(\n                        from: source.path.underlying,\n                        to: destination,\n                        shouldProceedAfterError: shouldProceedAfterError,\n                        shouldCopyItem: shouldCopyItem\n                    )\n\n                default:\n                    let error = FileSystemError(\n                        code: .unsupported,\n                        message: \"\"\"\n                            Can't copy '\\(source.path)' of type '\\(source.type)'; only regular \\\n                            files, symbolic links and directories can be copied.\n                            \"\"\",\n                        cause: nil,\n                        location: .here()\n                    )\n\n                    try await shouldProceedAfterError(source, error)\n                }\n            }\n        }\n    }\n\n    /// Copies the directory from `sourcePath` to `destinationPath`.\n    private func copyDirectory(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        strategy copyStrategy: CopyStrategy,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        switch copyStrategy.wrapped {\n        case .sequential:\n            return try await self.copyDirectorySequential(\n                from: sourcePath,\n                to: destinationPath,\n                shouldProceedAfterError: shouldProceedAfterError,\n                shouldCopyItem: shouldCopyItem\n            )\n        case let .parallel(maxDescriptors):\n            // Note that maxDescriptors was validated on construction of CopyStrategy. See notes on\n            // CopyStrategy about assumptions on descriptor use. For now, we take the worst case\n            // peak for every operation, which is two file descriptors. This keeps the downstream\n            // limiting code simple.\n            //\n            // We do not preclude the use of more granular limiting in the future (e.g. a directory\n            // scan requires only a single file descriptor). For now we just drop any excess\n            // remainder entirely.\n            let limitValue = maxDescriptors / 2\n            return try await self.copyDirectoryParallel(\n                from: sourcePath,\n                to: destinationPath,\n                maxConcurrentOperations: limitValue,\n                shouldProceedAfterError: shouldProceedAfterError,\n                shouldCopyItem: shouldCopyItem\n            )\n        }\n    }\n\n    /// Building block of the parallel directory copy implementation. Each invocation of this is\n    /// allowed to consume two file descriptors. Any further work (if any) should be sent to `yield`\n    /// for future processing.\n    func copySelfAndEnqueueChildren(\n        from: DirectoryEntry,\n        to: FilePath,\n        yield: @Sendable ([DirCopyItem]) -> Void,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        switch from.type {\n        case .regular:\n            do {\n                try await self.copyRegularFile(\n                    from: from.path.underlying,\n                    to: to,\n                    replaceExisting: false\n                )\n            } catch {\n                try await shouldProceedAfterError(from, error)\n            }\n\n        case .symlink:\n            do {\n                try await self.copySymbolicLink(\n                    from: from.path.underlying,\n                    to: to\n                )\n            } catch {\n                try await shouldProceedAfterError(from, error)\n            }\n\n        case .directory:\n            do {\n                let addToQueue = try await self.prepareDirectoryForRecusiveCopy(\n                    from: from.path.underlying,\n                    to: to,\n                    shouldProceedAfterError: shouldProceedAfterError,\n                    shouldCopyItem: shouldCopyItem\n                )\n                yield(addToQueue)\n            } catch {\n                // The caller expects an end-of-dir regardless of whether there was an error or not.\n                yield([.endOfDir])\n                try await shouldProceedAfterError(from, error)\n            }\n\n        default:\n            let error = FileSystemError(\n                code: .unsupported,\n                message: \"\"\"\n                    Can't copy '\\(from.path)' of type '\\(from.type)'; only regular \\\n                    files, symbolic links and directories can be copied.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n\n            try await shouldProceedAfterError(from, error)\n        }\n    }\n\n    private func copyRegularFile(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._copyRegularFile(\n                from: sourcePath,\n                to: destinationPath,\n                replaceExisting: replaceExisting\n            ).get()\n        }\n    }\n\n    private func _copyRegularFile(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool = false\n    ) -> Result<Void, FileSystemError> {\n        #if canImport(Darwin)\n        // COPYFILE_CLONE clones the file if possible and will fallback to doing a copy.\n        // COPYFILE_ALL is shorthand for:\n        //    COPYFILE_STAT | COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA\n        var flags = copyfile_flags_t(COPYFILE_CLONE) | copyfile_flags_t(COPYFILE_ALL)\n        if replaceExisting {\n            flags |= copyfile_flags_t(COPYFILE_UNLINK)\n        }\n\n        return Libc.copyfile(\n            from: sourcePath,\n            to: destinationPath,\n            state: nil,\n            flags: flags\n        ).mapError { errno in\n            FileSystemError.copyfile(\n                errno: errno,\n                from: sourcePath,\n                to: destinationPath,\n                location: .here()\n            )\n        }\n\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        if replaceExisting {\n            return self._copyRegularFileReplacing(\n                from: sourcePath,\n                to: destinationPath\n            )\n        } else {\n            return self._copyFileContents(\n                from: sourcePath,\n                to: destinationPath\n            ) { destinationPath, writeOptions in\n                self._openFile(\n                    forWritingAt: destinationPath,\n                    options: writeOptions\n                ).mapError {\n                    FileSystemError(\n                        message: \"Can't copy '\\(sourcePath)' as '\\(destinationPath)' couldn't be opened.\",\n                        wrapping: $0\n                    )\n                }\n            }\n        }\n        #endif\n    }\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    private func _copyRegularFileReplacing(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath\n    ) -> Result<Void, FileSystemError> {\n        // on Linux platforms we implement replaceExisting by copying the source file into\n        // a temporary destination and then atomically renaming it, using the renameat2(2) system call.\n        let parentDirectory = destinationPath.removingLastComponent()\n        let destinationDirectoryHandle: DirectoryFileHandle\n        switch self._openDirectory(\n            at: parentDirectory.isEmpty ? FilePath(\".\") : parentDirectory,\n            // not following symlinks here to prevent TOCTOU attacks where the parent directory\n            // is replaced with a symlink pointing to an attacker-controlled location\n            options: OpenOptions.Directory(followSymbolicLinks: false)\n        ) {\n        case let .success(handle):\n            destinationDirectoryHandle = handle\n        case let .failure(error):\n            return .failure(\n                FileSystemError(\n                    message: \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory couldn't be opened.\",\n                    wrapping: error\n                )\n            )\n        }\n        defer {\n            _ = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                ._close(materialize: true)\n        }\n\n        guard\n            let destinationDirectoryFD = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                .descriptorIfAvailable()\n        else {\n            let error = FileSystemError(\n                code: .closed,\n                message:\n                    \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory descriptor unavailable.\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        let temporaryFilepath = FilePath(\".tmp-\" + String(randomAlphaNumericOfLength: 6))\n        let copyResult = self._copyFileContents(\n            from: sourcePath,\n            to: temporaryFilepath\n        ) { destinationPath, writeOptions in\n            destinationDirectoryFD.open(\n                atPath: destinationPath,\n                mode: .writeOnly,\n                options: writeOptions.descriptorOptions,\n                permissions: writeOptions.permissionsForRegularFile\n            )\n            .mapError { errno in\n                let openError = FileSystemError.open(\n                    \"openat\",\n                    error: errno,\n                    path: destinationPath,\n                    location: .here()\n                )\n                return FileSystemError(\n                    message: \"Can't copy '\\(sourcePath)' as '\\(destinationPath)' couldn't be opened.\",\n                    wrapping: openError\n                )\n            }\n            .map { fd in\n                let handle = SystemFileHandle(\n                    takingOwnershipOf: fd,\n                    path: destinationPath,\n                    threadPool: self.threadPool\n                )\n                return WriteFileHandle(wrapping: handle)\n            }\n        }\n        guard case .success = copyResult else {\n            _ = Syscall.unlinkat(path: temporaryFilepath, relativeTo: destinationDirectoryFD)\n            return copyResult\n        }\n\n        guard let destinationFilename = destinationPath.lastComponent else {\n            return .failure(\n                FileSystemError(\n                    code: .invalidArgument,\n                    message: \"Can't copy to '\\(destinationPath)', path has no filename component.\",\n                    cause: nil,\n                    location: .here()\n                )\n            )\n        }\n        let destinationFilepath = FilePath(root: nil, components: destinationFilename)\n\n        switch Syscall.rename(\n            from: temporaryFilepath,\n            relativeTo: destinationDirectoryFD,\n            to: destinationFilepath,\n            relativeTo: destinationDirectoryFD,\n            flags: []\n        ) {\n        case .failure(let errno):\n            _ = Syscall.unlinkat(path: temporaryFilepath, relativeTo: destinationDirectoryFD)\n            return .failure(\n                FileSystemError.rename(\n                    \"renameat2\",\n                    errno: errno,\n                    oldName: temporaryFilepath,\n                    newName: destinationFilepath,\n                    location: .here()\n                )\n            )\n        case .success:\n            return .success(())\n        }\n    }\n\n    private func _copyFileContents(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        openDestination: (FilePath, OpenOptions.Write) -> Result<WriteFileHandle, FileSystemError>\n    ) -> Result<Void, FileSystemError> {\n        func makeOnUnavailableError(\n            path: FilePath,\n            location: FileSystemError.SourceLocation\n        ) -> FileSystemError {\n            FileSystemError(\n                code: .closed,\n                message: \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', '\\(path)' is closed.\",\n                cause: nil,\n                location: location\n            )\n        }\n\n        let openSourceResult = self._openFile(\n            forReadingAt: sourcePath,\n            options: OpenOptions.Read(followSymbolicLinks: true)\n        ).mapError {\n            FileSystemError(\n                message: \"Can't copy '\\(sourcePath)', it couldn't be opened.\",\n                wrapping: $0\n            )\n        }\n\n        let source: ReadFileHandle\n        switch openSourceResult {\n        case let .success(handle):\n            source = handle\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        defer {\n            _ = source.fileHandle.systemFileHandle.sendableView._close(materialize: true)\n        }\n\n        let sourceInfo: FileInfo\n        switch source.fileHandle.systemFileHandle.sendableView._info() {\n        case let .success(info):\n            sourceInfo = info\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        let options = OpenOptions.Write(\n            existingFile: .none,\n            newFile: OpenOptions.NewFile(\n                permissions: sourceInfo.permissions,\n                transactionalCreation: false\n            )\n        )\n\n        let destination: WriteFileHandle\n        switch openDestination(destinationPath, options) {\n        case let .success(handle):\n            destination = handle\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        let copyResult: Result<Void, FileSystemError>\n        copyResult = source.fileHandle.systemFileHandle.sendableView._withUnsafeDescriptorResult { sourceFD in\n            destination.fileHandle.systemFileHandle.sendableView._withUnsafeDescriptorResult { destinationFD in\n                var offset = 0\n\n                while offset < sourceInfo.size {\n                    // sendfile(2) limits writes to 0x7ffff000 in size\n                    let size = min(Int(sourceInfo.size) - offset, 0x7fff_f000)\n                    let result = Syscall.sendfile(\n                        to: destinationFD,\n                        from: sourceFD,\n                        offset: offset,\n                        size: size\n                    ).mapError { errno in\n                        FileSystemError.sendfile(\n                            errno: errno,\n                            from: sourcePath,\n                            to: destinationPath,\n                            location: .here()\n                        )\n                    }\n\n                    switch result {\n                    case let .success(bytesCopied):\n                        offset += bytesCopied\n                    case let .failure(error):\n                        return .failure(error)\n                    }\n                }\n                return .success(())\n            } onUnavailable: {\n                makeOnUnavailableError(path: destinationPath, location: .here())\n            }\n        } onUnavailable: {\n            makeOnUnavailableError(path: sourcePath, location: .here())\n        }\n\n        let closeResult = destination.fileHandle.systemFileHandle.sendableView._close(materialize: true)\n        return copyResult.flatMap { closeResult }\n    }\n    #endif\n\n    private func copySymbolicLink(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool = false\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._copySymbolicLink(\n                from: sourcePath,\n                to: destinationPath,\n                replaceExisting: replaceExisting\n            ).get()\n        }\n    }\n\n    private func _copySymbolicLink(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool\n    ) -> Result<Void, FileSystemError> {\n        if replaceExisting {\n            return self._copySymbolicLinkReplacing(from: sourcePath, to: destinationPath)\n        } else {\n            return self._destinationOfSymbolicLink(at: sourcePath).flatMap { linkDestination in\n                self._createSymbolicLink(at: destinationPath, withDestination: linkDestination)\n            }\n        }\n    }\n\n    private func _copySymbolicLinkReplacing(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath\n    ) -> Result<Void, FileSystemError> {\n        // There is no atomic symlink replace copy on either Darwin or Linux platforms\n        // so we copy the source symlink into a temporary symlink using `symlinkat` system call and then\n        // rename it into the destination symlink using the `renameatx_np(2)` on Darwin and\n        // `renameat2(2)` on Linux.\n        let parentDirectory = destinationPath.removingLastComponent()\n        let destinationDirectoryHandle: DirectoryFileHandle\n        switch self._openDirectory(\n            at: parentDirectory.isEmpty ? FilePath(\".\") : parentDirectory,\n            // not following symlinks here to prevent TOCTOU attacks where the parent directory\n            // is replaced with a symlink pointing to an attacker-controlled location\n            options: OpenOptions.Directory(followSymbolicLinks: false)\n        ) {\n        case let .success(handle):\n            destinationDirectoryHandle = handle\n        case let .failure(error):\n            return .failure(\n                FileSystemError(\n                    message: \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory couldn't be opened.\",\n                    wrapping: error\n                )\n            )\n        }\n        defer {\n            _ = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                ._close(materialize: true)\n        }\n\n        guard\n            let destinationDirectoryFD = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                .descriptorIfAvailable()\n        else {\n            let error = FileSystemError(\n                code: .closed,\n                message:\n                    \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory descriptor unavailable.\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        let sourceSymlinkTarget: FilePath\n        switch self._destinationOfSymbolicLink(at: sourcePath) {\n        case let .success(target):\n            sourceSymlinkTarget = target\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        let temporarySymlinkPath = FilePath(\".tmp-link-\" + String(randomAlphaNumericOfLength: 6))\n        if case let .failure(errno) = Syscall.symlinkat(\n            to: sourceSymlinkTarget,\n            in: destinationDirectoryFD,\n            from: temporarySymlinkPath\n        ) {\n            let error = FileSystemError.symlink(\n                \"symlinkat\",\n                errno: errno,\n                link: temporarySymlinkPath,\n                target: sourceSymlinkTarget,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        guard let destinationFilename = destinationPath.lastComponent else {\n            return .failure(\n                FileSystemError(\n                    code: .invalidArgument,\n                    message: \"Can't copy to '\\(destinationPath)', path has no filename component.\",\n                    cause: nil,\n                    location: .here()\n                )\n            )\n        }\n\n        let destinationFilePath = FilePath(root: nil, components: destinationFilename)\n        #if canImport(Darwin)\n        switch Syscall.rename(\n            from: temporarySymlinkPath,\n            relativeTo: destinationDirectoryFD,\n            to: destinationFilePath,\n            relativeTo: destinationDirectoryFD,\n            options: []\n        ) {\n        case .success:\n            return .success(())\n        case .failure(let errno):\n            _ = Syscall.unlinkat(path: temporarySymlinkPath, relativeTo: destinationDirectoryFD)\n            let error = FileSystemError.rename(\n                \"renameatx_np\",\n                errno: errno,\n                oldName: temporarySymlinkPath,\n                newName: destinationFilePath,\n                location: .here()\n            )\n            return .failure(error)\n        }\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        switch Syscall.rename(\n            from: temporarySymlinkPath,\n            relativeTo: destinationDirectoryFD,\n            to: destinationFilePath,\n            relativeTo: destinationDirectoryFD,\n            flags: []\n        ) {\n        case .success:\n            return .success(())\n        case .failure(let errno):\n            _ = Syscall.unlinkat(path: temporarySymlinkPath, relativeTo: destinationDirectoryFD)\n            let error = FileSystemError.rename(\n                \"renameat2\",\n                errno: errno,\n                oldName: temporarySymlinkPath,\n                newName: destinationFilePath,\n                location: .here()\n            )\n            return .failure(error)\n        }\n        #endif\n    }\n\n    @_spi(Testing)\n    public func removeOneItem(\n        at path: FilePath,\n        function: String = #function,\n        file: String = #fileID,\n        line: Int = #line\n    ) async throws -> Int {\n        try await self.threadPool.runIfActive {\n            switch Libc.remove(path) {\n            case .success:\n                return 1\n            case .failure(.noSuchFileOrDirectory):\n                return 0\n            case .failure(let errno):\n                throw FileSystemError.remove(\n                    errno: errno,\n                    path: path,\n                    location: .init(function: function, file: file, line: line)\n                )\n            }\n        }\n    }\n\n    private enum MoveResult {\n        case moved\n        case differentLogicalDevices\n    }\n\n    private func _moveItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath\n    ) -> Result<MoveResult, FileSystemError> {\n        // Check that the destination doesn't exist. 'rename' will remove it otherwise!\n        switch self._info(forFileAt: destinationPath, infoAboutSymbolicLink: true) {\n        case .success(.none):\n            // Doesn't exist: continue\n            ()\n\n        case .success(.some):\n            let fileSystemError = FileSystemError(\n                code: .fileAlreadyExists,\n                message: \"\"\"\n                    Unable to move '\\(sourcePath)' to '\\(destinationPath)', the destination path \\\n                    already exists.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n\n        case let .failure(error):\n            let fileSystemError = FileSystemError(\n                message: \"\"\"\n                    Unable to move '\\(sourcePath)' to '\\(destinationPath)', could not determine \\\n                    whether the destination path exists or not.\n                    \"\"\",\n                wrapping: error\n            )\n            return .failure(fileSystemError)\n        }\n\n        switch Syscall.rename(from: sourcePath, to: destinationPath) {\n        case .success:\n            return .success(.moved)\n\n        case .failure(.improperLink):\n            // The two paths are on different logical devices; copy and then remove the original.\n            return .success(.differentLogicalDevices)\n\n        case let .failure(errno):\n            let error = FileSystemError.rename(\n                \"rename\",\n                errno: errno,\n                oldName: sourcePath,\n                newName: destinationPath,\n                location: .here()\n            )\n            return .failure(error)\n        }\n    }\n\n    private func parseTemporaryDirectoryTemplate(\n        _ template: FilePath\n    ) -> Result<(FilePath, String, Int), FileSystemError> {\n        // Check whether template is valid (i.e. has a `lastComponent`).\n        guard let lastComponentPath = template.lastComponent else {\n            let fileSystemError = FileSystemError(\n                code: .invalidArgument,\n                message: \"\"\"\n                    Can't create temporary directory, the template ('\\(template)') is invalid. \\\n                    The template should be a file path ending in at least three 'X's.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n        }\n\n        let lastComponent = lastComponentPath.string\n\n        // Finding the index of the last non-'X' character in `lastComponent.string` and advancing\n        // it by one.\n        let prefix: String\n        var index = lastComponent.lastIndex(where: { $0 != \"X\" })\n        if index != nil {\n            lastComponent.formIndex(after: &(index!))\n            prefix = String(lastComponent[..<index!])\n        } else if lastComponent.first == \"X\" {\n            // The directory name from the template contains only 'X's.\n            prefix = \"\"\n            index = lastComponent.startIndex\n        } else {\n            let fileSystemError = FileSystemError(\n                code: .invalidArgument,\n                message: \"\"\"\n                    Can't create temporary directory, the template ('\\(template)') is invalid. \\\n                    The template must end in at least three 'X's.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n        }\n\n        // Computing the number of 'X's.\n        let suffixLength = lastComponent.distance(from: index!, to: lastComponent.endIndex)\n        guard suffixLength >= 3 else {\n            let fileSystemError = FileSystemError(\n                code: .invalidArgument,\n                message: \"\"\"\n                    Can't create temporary directory, the template ('\\(template)') is invalid. \\\n                    The template must end in at least three 'X's.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n        }\n\n        return .success((template.removingLastComponent(), prefix, suffixLength))\n    }\n\n    private func _createTemporaryDirectory(\n        template: FilePath\n    ) -> Result<FilePath, FileSystemError> {\n        let prefix: String\n        let root: FilePath\n        let suffixLength: Int\n\n        let parseResult = self.parseTemporaryDirectoryTemplate(template)\n        switch parseResult {\n        case let .success((parseRoot, parsePrefix, parseSuffixLength)):\n            root = parseRoot\n            prefix = parsePrefix\n            suffixLength = parseSuffixLength\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        for _ in 1...16 {\n            let name = prefix + String(randomAlphaNumericOfLength: suffixLength)\n\n            // Trying to create the directory.\n            let finalPath = root.appending(name)\n            let createDirectoriesResult = self._createDirectory(\n                at: finalPath,\n                withIntermediateDirectories: true,\n                permissions: FilePermissions.defaultsForDirectory\n            )\n            switch createDirectoriesResult {\n            case .success:\n                return .success(finalPath)\n            case let .failure(error):\n                if let systemCallError = error.cause as? FileSystemError.SystemCallError {\n                    switch systemCallError.errno {\n                    // If the file at the generated path already exists, we generate a new file\n                    // path.\n                    case .fileExists, .isDirectory:\n                        break\n                    default:\n                        let fileSystemError = FileSystemError(\n                            message: \"Unable to create temporary directory '\\(template)'.\",\n                            wrapping: error\n                        )\n                        return .failure(fileSystemError)\n                    }\n                } else {\n                    let fileSystemError = FileSystemError(\n                        message: \"Unable to create temporary directory '\\(template)'.\",\n                        wrapping: error\n                    )\n                    return .failure(fileSystemError)\n                }\n            }\n        }\n        let fileSystemError = FileSystemError(\n            code: .unknown,\n            message: \"\"\"\n                Could not create a temporary directory from the provided template ('\\(template)'). \\\n                Try adding more 'X's at the end of the template.\n                \"\"\",\n            cause: nil,\n            location: .here()\n        )\n        return .failure(fileSystemError)\n    }\n\n    func _createSymbolicLink(\n        at linkPath: FilePath,\n        withDestination destinationPath: FilePath\n    ) -> Result<Void, FileSystemError> {\n        Syscall.symlink(to: destinationPath, from: linkPath).mapError { errno in\n            FileSystemError.symlink(\n                \"symlink\",\n                errno: errno,\n                link: linkPath,\n                target: destinationPath,\n                location: .here()\n            )\n        }\n    }\n\n    func _destinationOfSymbolicLink(at path: FilePath) -> Result<FilePath, FileSystemError> {\n        Syscall.readlink(at: path).mapError { errno in\n            FileSystemError.readlink(\n                errno: errno,\n                path: path,\n                location: .here()\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileSystemError+Syscall.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#endif\n\nextension FileSystemError {\n    /// Creates a ``FileSystemError`` by constructing a ``SystemCallError`` as the cause.\n    internal init(\n        code: Code,\n        message: String,\n        systemCall: String,\n        errno: Errno,\n        location: SourceLocation\n    ) {\n        self.init(\n            code: code,\n            message: message,\n            cause: SystemCallError(systemCall: systemCall, errno: errno),\n            location: location\n        )\n    }\n}\n\nextension FileSystemError {\n    /// Create a file system error appropriate for the `stat`/`lstat`/`fstat` system calls.\n    @_spi(Testing)\n    public static func stat(\n        _ name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 fstat'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Unable to get information about '\\(path)', the file is closed.\"\n        default:\n            code = .unknown\n            message = \"Unable to get information about '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public static func fchmod(\n        operation: SystemFileHandle.UpdatePermissionsOperation,\n        operand: FilePermissions,\n        permissions: FilePermissions,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let message: String\n        let code: FileSystemError.Code\n\n        // See: 'man 2 fchmod'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not \\(operation) permissions '\\(operand)', '\\(path)' is closed.\"\n\n        case .invalidArgument:\n            // Permissions are invalid so display the raw value in octal.\n            let rawPermissions = String(permissions.rawValue, radix: 0o10)\n            let op: String\n            switch operation {\n            case .set:\n                op = \"set\"\n            case .add:\n                op = \"added\"\n            case .remove:\n                op = \"removed\"\n            }\n            code = .invalidArgument\n            message = \"\"\"\n                Invalid permissions ('\\(rawPermissions)') could not be \\(op) for file '\\(path)'.\n                \"\"\"\n\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"\"\"\n                Not permitted to \\(operation) permissions '\\(operand)' for file '\\(path)', \\\n                the effective user ID does not match the owner of the file and the effective \\\n                user ID is not the super-user.\n                \"\"\"\n\n        default:\n            code = .unknown\n            message = \"Could not \\(operation) permissions '\\(operand)' to '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fchmod\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func flistxattr(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not list extended attributes, '\\(path)' is closed.\"\n\n        case .notSupported:\n            code = .unsupported\n            message = \"Extended attributes are disabled or not supported by the filesystem.\"\n\n        case .notPermitted:\n            code = .unsupported\n            message = \"Extended attributes are not supported by '\\(path)'.\"\n\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"Not permitted to list extended attributes for '\\(path)'.\"\n\n        default:\n            code = .unknown\n            message = \"Could not to list extended attributes for '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"flistxattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fgetxattr(\n        attribute name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"\"\"\n                Could not get value for extended attribute ('\\(name)'), '\\(path)' is closed.\n                \"\"\"\n        case .notSupported:\n            code = .unsupported\n            message = \"Extended attributes are disabled or not supported by the filesystem.\"\n        #if canImport(Darwin)\n        case .fileNameTooLong:\n            code = .invalidArgument\n            message = \"\"\"\n                Length of UTF-8 extended attribute name (\\(name.utf8.count)) is greater \\\n                than the limit (\\(XATTR_MAXNAMELEN)). Use a shorter attribute name.\n                \"\"\"\n        #endif\n        default:\n            code = .unknown\n            message = \"Could not get value for extended attribute ('\\(name)') for '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fgetxattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fsetxattr(\n        attribute name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 fsetxattr'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"\"\"\n                Could not set value for extended attribute ('\\(name)'), '\\(path)' is closed.\n                \"\"\"\n\n        case .notSupported:\n            code = .unsupported\n            message = \"\"\"\n                Extended attributes are disabled or not supported by the filesystem.\n                \"\"\"\n\n        #if canImport(Darwin)\n        case .fileNameTooLong:\n            code = .invalidArgument\n            message = \"\"\"\n                Length of UTF-8 extended attribute name (\\(name.utf8.count)) is greater \\\n                than the limit limit (\\(XATTR_MAXNAMELEN)). Use a shorter attribute \\\n                name.\n                \"\"\"\n        #endif\n\n        case .invalidArgument:\n            code = .invalidArgument\n            message = \"\"\"\n                Extended attribute name ('\\(name)') must be a valid UTF-8 string.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"\"\"\n                Could not set value for extended attribute ('\\(name)') for '\\(path)'.\n                \"\"\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fsetxattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fremovexattr(\n        attribute name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 fremovexattr'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not remove extended attribute ('\\(name)'), '\\(path)' is closed.\"\n\n        case .notSupported:\n            code = .unsupported\n            message = \"Extended attributes are disabled or not supported by the filesystem.\"\n\n        #if canImport(Darwin)\n        case .fileNameTooLong:\n            code = .invalidArgument\n            message = \"\"\"\n                Length of UTF-8 extended attribute name (\\(name.utf8.count)) is greater \\\n                than the limit (\\(XATTR_MAXNAMELEN)). Use a shorter attribute name.\n                \"\"\"\n        #endif\n\n        default:\n            code = .unknown\n            message = \"Could not remove extended attribute ('\\(name)') from '\\(path)'\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fremovexattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fsync(\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not synchronize file, '\\(path)' is closed.\"\n        case .ioError:\n            code = .io\n            message = \"An I/O error occurred while synchronizing '\\(path)'.\"\n        default:\n            code = .unknown\n            message = \"Could not synchronize file '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fsync\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func dup(error: Error, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Unable to duplicate descriptor of closed handle for '\\(path)'.\"\n            default:\n                code = .unknown\n                message = \"Unable to duplicate descriptor of handle for '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: \"dup\", errno: errno)\n        } else {\n            code = .unknown\n            message = \"Unable to duplicate descriptor of handle for '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func ftruncate(error: Error, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Can't resize '\\(path)', it's closed.\"\n            case .fileTooLarge:\n                code = .invalidArgument\n                message = \"The requested size for '\\(path)' is too large.\"\n            case .invalidArgument:\n                code = .invalidArgument\n                message = \"The requested size for '\\(path)' is negative, therefore invalid.\"\n            default:\n                code = .unknown\n                message = \"Unable to resize '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: \"ftruncate\", errno: errno)\n        } else {\n            code = .unknown\n            message = \"Unable to resize '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func close(error: Error, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        // See: 'man 2 close'\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"File already closed or file descriptor was invalid ('\\(path)').\"\n            case .ioError:\n                code = .io\n                message = \"I/O error during close, some writes to '\\(path)' may have failed.\"\n            default:\n                code = .unknown\n                message = \"Error closing file '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: \"close\", errno: errno)\n        } else {\n            code = .unknown\n            message = \"Error closing file '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public enum ReadSyscall: String, Sendable {\n        case read\n        case pread\n    }\n\n    @_spi(Testing)\n    public static func read(\n        usingSyscall syscall: ReadSyscall,\n        error: Error,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        // We expect an Errno as 'swift-system' uses result types under-the-hood,\n        // but don't require that in case something changes.\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Could not read from closed file '\\(path)'.\"\n            case .ioError:\n                code = .io\n                message = \"\"\"\n                    Could not read from file ('\\(path)'); an I/O error occurred while reading \\\n                    from the file system.\n                    \"\"\"\n            case .illegalSeek:\n                code = .unsupported\n                message = \"File is not seekable: '\\(path)'.\"\n            default:\n                code = .unknown\n                message = \"Could not read from file '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: syscall.rawValue, errno: errno)\n        } else {\n            code = .unknown\n            message = \"Could not read from file '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public enum WriteSyscall: String, Sendable {\n        case write\n        case pwrite\n    }\n\n    @_spi(Testing)\n    public static func write(\n        usingSyscall syscall: WriteSyscall,\n        error: Error,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        // We expect an Errno as 'swift-system' uses result types under-the-hood,\n        // but don't require that in case something changes.\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Could not write to closed file '\\(path)'.\"\n            case .ioError:\n                code = .io\n                message = \"\"\"\n                    Could not write to file ('\\(path)'); an I/O error occurred while writing to \\\n                    the file system.\n                    \"\"\"\n            case .illegalSeek:\n                code = .unsupported\n                message = \"File is not seekable: '\\(path)'.\"\n            default:\n                code = .unknown\n                message = \"Could not write to file.\"\n            }\n            cause = SystemCallError(systemCall: syscall.rawValue, errno: errno)\n        } else {\n            code = .unknown\n            message = \"Could not write to file.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fdopendir(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unknown,\n            message: \"Unable to open directory stream for '\\(path)'.\",\n            systemCall: \"fdopendir\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func readdir(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unknown,\n            message: \"Unable to read directory stream for '\\(path)'.\",\n            systemCall: \"readdir\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func ftsRead(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unknown,\n            message: \"Unable to read FTS stream for '\\(path)'.\",\n            systemCall: \"fts_read\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func open(\n        _ name: String,\n        error: Error,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Unable to open file at path '\\(path)', the descriptor is closed.\"\n            case .permissionDenied:\n                code = .permissionDenied\n                message = \"Unable to open file at path '\\(path)', permissions denied.\"\n            case .fileExists:\n                code = .fileAlreadyExists\n                message = \"\"\"\n                    Unable to create file at path '\\(path)', no existing file options were set \\\n                    which implies that no file should exist but a file already exists at the \\\n                    specified path.\n                    \"\"\"\n            case .ioError:\n                code = .io\n                message = \"\"\"\n                    Unable to create file at path '\\(path)', an I/O error occurred while \\\n                    creating the file.\n                    \"\"\"\n            case .tooManyOpenFiles:\n                code = .unavailable\n                message = \"\"\"\n                    Unable to open file at path '\\(path)', too many file descriptors are open.\n                    \"\"\"\n            case .noSuchFileOrDirectory:\n                code = .notFound\n                message = \"\"\"\n                    Unable to open or create file at path '\\(path)', either a component of the \\\n                    path did not exist or the named file to be opened did not exist.\n                    \"\"\"\n            case .notDirectory:\n                code = .notFound\n                message = \"\"\"\n                    Unable to open or create file at path '\\(path)', an intermediate component of \\\n                    the path was not a directory.\n                    \"\"\"\n            case .tooManySymbolicLinkLevels:\n                code = .invalidArgument\n                message = \"\"\"\n                    Can't open file at path '\\(path)', the target is a symbolic link and \\\n                    'followSymbolicLinks' was set to 'false'.\n                    \"\"\"\n            default:\n                code = .unknown\n                message = \"Unable to open file at path '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: name, errno: errno)\n        } else {\n            code = .unknown\n            message = \"Unable to open file at path '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(code: code, message: message, cause: cause, location: location)\n    }\n\n    @_spi(Testing)\n    public static func mkdir(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permissions to create a directory at '\\(path)'. Search permissions \\\n                denied for a component of the path or write permission denied for the parent \\\n                directory.\n                \"\"\"\n        case .isDirectory:\n            code = .invalidArgument\n            message = \"Can't create directory, '\\(path)' is the root directory.\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"Can't create directory, the pathname '\\(path)' already exists.\"\n        case .notDirectory:\n            code = .invalidArgument\n            message = \"Can't create directory, a component of '\\(path)' is not a directory.\"\n        case .noSuchFileOrDirectory:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't create directory, a component of '\\(path)' does not exist. Ensure all \\\n                parent directories exist or set 'withIntermediateDirectories' to 'true' when \\\n                calling 'createDirectory(at:withIntermediateDirectories:permissions)'.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"An I/O error occurred when the directory at '\\(path)'.\"\n        default:\n            code = .unknown\n            message = \"\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"mkdir\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func rename(\n        _ name: String,\n        errno: Errno,\n        oldName: FilePath,\n        newName: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permissions to rename '\\(oldName)' to '\\(newName)'. Search \\\n                permissions were denied on a component of either path, or write permissions were \\\n                denied on the parent directory of either path.\n                \"\"\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"Can't rename '\\(oldName)' to '\\(newName)' as it already exists.\"\n        case .invalidArgument:\n            code = .invalidArgument\n            if oldName == \".\" || oldName == \"..\" {\n                message = \"\"\"\n                    Can't rename '\\(oldName)' to '\\(newName)', '.' and '..' can't be renamed.\n                    \"\"\"\n            } else {\n                message = \"\"\"\n                    Can't rename '\\(oldName)', it may be a parent directory of '\\(newName)'.\n                    \"\"\"\n            }\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"\"\"\n                Can't rename '\\(oldName)' to '\\(newName)', a component of '\\(oldName)' does \\\n                not exist.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't rename '\\(oldName)' to '\\(newName)', an I/O error occurred while making \\\n                or updating a directory entry.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't rename '\\(oldName)' to '\\(newName)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func remove(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permissions to remove '\\(path)'. Search permissions denied \\\n                on a component of the path or write permission denied on the directory \\\n                containing the item to be removed.\n                \"\"\"\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permission to remove '\\(path)', the effective user ID of the \\\n                process is not permitted to remove the file.\n                \"\"\"\n        case .resourceBusy:\n            code = .unavailable\n            message = \"\"\"\n                Can't remove '\\(path)', it may be being used by another process or is the mount \\\n                point for a mounted file system.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't remove '\\(path)', an I/O error occurred while deleting its directory entry.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't remove '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"remove\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func symlink(\n        _ name: String,\n        errno: Errno,\n        link: FilePath,\n        target: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', write access to the \\\n                directory containing the link was denied or one of the directories in its path \\\n                denied search permissions.\n                \"\"\"\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', the file system \\\n                containing '\\(link)' doesn't support the creation of symbolic links.\n                \"\"\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', '\\(link)' already exists.\n                \"\"\"\n        case .noSuchFileOrDirectory:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', a component of '\\(link)' \\\n                does not exist or is a dangling symbolic link.\n                \"\"\"\n        case .notDirectory:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', a component of '\\(link)' \\\n                is not a directory.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', an I/O error occurred.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't create symbolic link '\\(link)' to '\\(target)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func readlink(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't read symbolic link at '\\(path)'; search permission was denied for a \\\n                component in its prefix.\n                \"\"\"\n        case .invalidArgument:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't read '\\(path)'; it is not a symbolic link.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't read symbolic link at '\\(path)'; an I/O error occurred.\n                \"\"\"\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"\"\"\n                Can't read symbolic link, no file exists at '\\(path)'.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't read symbolic link at '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"readlink\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func link(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 link'\n        switch errno {\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"\"\"\n                Can't link '\\(sourcePath)' to '\\(destinationPath)', a file already exists \\\n                at '\\(destinationPath)'.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"I/O error while linking '\\(sourcePath)' to '\\(destinationPath)'.\"\n        default:\n            code = .unknown\n            message = \"Error linking '\\(sourcePath)' to '\\(destinationPath)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: SystemCallError(systemCall: \"linkat\", errno: errno),\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func unlink(\n        _ name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 unlink'\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Search permission denied for a component of the path ('\\(path)') or write \\\n                permission denied on the directory containing the link to be removed.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"I/O error while unlinking '\\(path)'.\"\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"The named file ('\\(path)') doesn't exist.\"\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"Insufficient permissions to unlink '\\(path)'.\"\n        default:\n            code = .unknown\n            message = \"Error unlinking '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: SystemCallError(systemCall: name, errno: errno),\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func getcwd(errno: Errno, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unavailable,\n            message: \"Can't get current working directory.\",\n            systemCall: \"getcwd\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func confstr(name: String, errno: Errno, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unavailable,\n            message: \"Can't get configuration value for '\\(name)'.\",\n            systemCall: \"confstr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func getpwuid_r(errno: Errno, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unavailable,\n            message: \"Can't get home directory for current user.\",\n            systemCall: \"getpwuid_r\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fcopyfile(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        Self._copyfile(\n            \"fcopyfile\",\n            errno: errno,\n            from: sourcePath,\n            to: destinationPath,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func copyfile(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        Self._copyfile(\n            \"copyfile\",\n            errno: errno,\n            from: sourcePath,\n            to: destinationPath,\n            location: location\n        )\n    }\n\n    private static func _copyfile(\n        _ name: String,\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .notSupported:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't copy file from '\\(sourcePath)' to '\\(destinationPath)', the item to copy is \\\n                not a directory, symbolic link or regular file.\n                \"\"\"\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't copy file, search permission was denied for a component of the path \\\n                prefix for the source ('\\(sourcePath)') or destination ('\\(destinationPath)'), \\\n                or write permission was denied for a component of the path prefix for the source.\n                \"\"\"\n        case .invalidArgument:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't copy file from '\\(sourcePath)' to '\\(destinationPath)', the destination \\\n                path already exists.\n                \"\"\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"\"\"\n                Unable to create file at path '\\(destinationPath)', no existing file options were set \\\n                which implies that no file should exist but a file already exists at the \\\n                specified path.\n                \"\"\"\n        case .tooManyOpenFiles:\n            code = .unavailable\n            message = \"\"\"\n                Unable to open the source ('\\(sourcePath)') or destination ('\\(destinationPath)') files, \\\n                too many file descriptors are open.\n                \"\"\"\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"\"\"\n                Unable to open or create file at path '\\(sourcePath)', either a component of the \\\n                path did not exist or the named file to be opened did not exist.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't copy file from '\\(sourcePath)' to '\\(destinationPath)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func sendfile(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> FileSystemError {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                An I/O error occurred while reading from '\\(sourcePath)', can't copy to \\\n                '\\(destinationPath)'.\n                \"\"\"\n        case .noMemory:\n            code = .io\n            message = \"\"\"\n                Insufficient memory to read from '\\(sourcePath)', can't copy to \\\n                '\\(destinationPath)'.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't copy file from '\\(sourcePath)' to '\\(destinationPath)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"sendfile\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func futimens(\n        errno: Errno,\n        path: FilePath,\n        lastAccessTime: FileInfo.Timespec?,\n        lastDataModificationTime: FileInfo.Timespec?,\n        location: SourceLocation\n    ) -> FileSystemError {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied, .notPermitted:\n            code = .permissionDenied\n            message = \"Not permitted to change last access or last data modification times for \\(path).\"\n\n        case .readOnlyFileSystem:\n            code = .unsupported\n            message =\n                \"Not permitted to change last access or last data modification times for \\(path): this is a read-only file system.\"\n\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not change last access or last data modification dates for \\(path): file is closed.\"\n\n        default:\n            code = .unknown\n            message = \"Could not change last access or last data modification dates for \\(path).\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"futimens\",\n            errno: errno,\n            location: location\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileSystemError.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// An error thrown as a result of interaction with the file system.\n///\n/// All errors have a high-level ``FileSystemError/Code-swift.struct`` which identifies the domain\n/// of the error. For example an operation performed on a ``FileHandleProtocol`` which has already been\n/// closed will result in a ``FileSystemError/Code-swift.struct/closed`` error code. Errors also\n/// include a message describing what went wrong and how to remedy it (if applicable). The\n/// ``FileSystemError/message`` is not static and may include dynamic information such as the path\n/// of the file for which the operation failed, for example.\n///\n/// Errors may have a ``FileSystemError/cause``, an underlying error which caused the operation to\n/// fail which may be platform specific.\npublic struct FileSystemError: Error, Sendable {\n    /// A high-level error code to provide broad a classification.\n    public var code: Code\n\n    /// A message describing what went wrong and how it may be remedied.\n    public var message: String\n\n    /// An underlying error which caused the operation to fail. This may include additional details\n    /// about the root cause of the failure.\n    public var cause: Error?\n\n    /// The location from which this error was thrown.\n    public var location: SourceLocation\n\n    public init(\n        code: Code,\n        message: String,\n        cause: Error?,\n        location: SourceLocation\n    ) {\n        self.code = code\n        self.message = message\n        self.cause = cause\n        self.location = location\n    }\n\n    /// Creates a ``FileSystemError`` by wrapping the given `cause` and its location and code.\n    internal init(message: String, wrapping cause: FileSystemError) {\n        self.init(code: cause.code, message: message, cause: cause, location: cause.location)\n    }\n}\n\nextension FileSystemError: CustomStringConvertible {\n    public var description: String {\n        if let cause = self.cause {\n            return \"\\(self.code): \\(self.message) (\\(cause))\"\n        } else {\n            return \"\\(self.code): \\(self.message)\"\n        }\n    }\n}\n\nextension FileSystemError: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        if let cause = self.cause {\n            return \"\"\"\n                \\(String(reflecting: self.code)): \\(String(reflecting: self.message)) \\\n                (\\(String(reflecting: cause)))\n                \"\"\"\n        } else {\n            return \"\\(String(reflecting: self.code)): \\(String(reflecting: self.message))\"\n        }\n    }\n}\n\nextension FileSystemError {\n    private func detailedDescriptionLines() -> [String] {\n        // Build up a tree-like description of the error. This allows nested causes to be formatted\n        // correctly, especially when they are also FileSystemErrors.\n        //\n        // An example is:\n        //\n        //  FileSystemError: Closed\n        //  ├─ Reason: Unable to open file at path 'foo.swift', the descriptor is closed.\n        //  ├─ Cause: 'openat' system call failed with '(9) Bad file descriptor'.\n        //  └─ Source location: openFile(forReadingAt:_:) (FileSystem.swift:314)\n        var lines = [\n            \"FileSystemError: \\(self.code)\",\n            \"├─ Reason: \\(self.message)\",\n        ]\n\n        if let error = self.cause as? FileSystemError {\n            lines.append(\"├─ Cause:\")\n            let causeLines = error.detailedDescriptionLines()\n            // We know this will never be empty.\n            lines.append(\"│  └─ \\(causeLines.first!)\")\n            lines.append(contentsOf: causeLines.dropFirst().map { \"│     \\($0)\" })\n        } else if let error = self.cause {\n            lines.append(\"├─ Cause: \\(String(reflecting: error))\")\n        }\n\n        lines.append(\n            \"└─ Source location: \\(self.location.function) (\\(self.location.file):\\(self.location.line))\"\n        )\n\n        return lines\n    }\n\n    /// A detailed multi-line description of the error.\n    ///\n    /// - Returns: A multi-line description of the error.\n    public func detailedDescription() -> String {\n        self.detailedDescriptionLines().joined(separator: \"\\n\")\n    }\n}\n\nextension FileSystemError {\n    /// A high level indication of the kind of error being thrown.\n    public struct Code: Hashable, Sendable, CustomStringConvertible {\n        private enum Wrapped: Hashable, Sendable, CustomStringConvertible {\n            case closed\n            case invalidArgument\n            case io\n            case permissionDenied\n            case notEmpty\n            case notFound\n            case resourceExhausted\n            case unavailable\n            case unknown\n            case unsupported\n            case fileAlreadyExists\n\n            var description: String {\n                switch self {\n                case .closed:\n                    return \"Closed\"\n                case .invalidArgument:\n                    return \"Invalid argument\"\n                case .io:\n                    return \"I/O error\"\n                case .permissionDenied:\n                    return \"Permission denied\"\n                case .resourceExhausted:\n                    return \"Resource exhausted\"\n                case .notEmpty:\n                    return \"Not empty\"\n                case .notFound:\n                    return \"Not found\"\n                case .unavailable:\n                    return \"Unavailable\"\n                case .unknown:\n                    return \"Unknown\"\n                case .unsupported:\n                    return \"Unsupported\"\n                case .fileAlreadyExists:\n                    return \"File already exists\"\n                }\n            }\n        }\n\n        public var description: String {\n            String(describing: self.code)\n        }\n\n        private var code: Wrapped\n        private init(_ code: Wrapped) {\n            self.code = code\n        }\n\n        /// An operation on the file could not be performed because the file is closed\n        /// (or detached).\n        public static var closed: Self {\n            Self(.closed)\n        }\n\n        /// A provided argument was not valid for the operation.\n        public static var invalidArgument: Self {\n            Self(.invalidArgument)\n        }\n\n        /// An I/O error occurred.\n        public static var io: Self {\n            Self(.io)\n        }\n\n        /// The caller did not have sufficient permission to perform the operation.\n        public static var permissionDenied: Self {\n            Self(.permissionDenied)\n        }\n\n        /// A required resource was exhausted.\n        public static var resourceExhausted: Self {\n            Self(.resourceExhausted)\n        }\n\n        /// The directory wasn't empty.\n        public static var notEmpty: Self {\n            Self(.notEmpty)\n        }\n\n        /// The file could not be found.\n        public static var notFound: Self {\n            Self(.notFound)\n        }\n\n        /// The file system is not currently available, for example if the underlying executor\n        /// is not running.\n        public static var unavailable: Self {\n            Self(.unavailable)\n        }\n\n        /// The error is not known or may not have an appropriate classification. See\n        /// ``FileSystemError/cause`` for more information about the error.\n        public static var unknown: Self {\n            Self(.unknown)\n        }\n\n        /// The operation is not supported or is not enabled.\n        public static var unsupported: Self {\n            Self(.unsupported)\n        }\n\n        /// The file already exists.\n        public static var fileAlreadyExists: Self {\n            Self(.fileAlreadyExists)\n        }\n    }\n\n    /// A location within source code.\n    public struct SourceLocation: Sendable, Hashable {\n        /// The function in which the error was thrown.\n        public var function: String\n\n        /// The file in which the error was thrown.\n        public var file: String\n\n        /// The line on which the error was thrown.\n        public var line: Int\n\n        public init(function: String, file: String, line: Int) {\n            self.function = function\n            self.file = file\n            self.line = line\n        }\n\n        internal static func here(\n            function: String = #function,\n            file: String = #fileID,\n            line: Int = #line\n        ) -> Self {\n            SourceLocation(function: function, file: file, line: line)\n        }\n    }\n}\n\nextension FileSystemError {\n    /// An error resulting from a system call.\n    public struct SystemCallError: Error, Hashable, CustomStringConvertible {\n        /// The name of the system call which produced the error.\n        public var systemCall: String\n        /// The errno set by the system call.\n        public var errno: Errno\n\n        public init(systemCall: String, errno: Errno) {\n            self.systemCall = systemCall\n            self.errno = errno\n        }\n\n        public var description: String {\n            \"'\\(self.systemCall)' system call failed with '(\\(self.errno.rawValue)) \\(self.errno)'.\"\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileSystemProtocol.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// The interface for interacting with a file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol FileSystemProtocol: Sendable {\n    /// The type of ``ReadableFileHandleProtocol`` to return when opening files for reading.\n    associatedtype ReadFileHandle: ReadableFileHandleProtocol\n\n    /// The type of ``WritableFileHandleProtocol`` to return when opening files for writing.\n    associatedtype WriteFileHandle: WritableFileHandleProtocol\n\n    /// The type of ``ReadableAndWritableFileHandleProtocol`` to return when opening files for reading and writing.\n    associatedtype ReadWriteFileHandle: ReadableAndWritableFileHandleProtocol\n\n    /// The type of ``DirectoryFileHandleProtocol`` to return when opening directories.\n    associatedtype DirectoryFileHandle: DirectoryFileHandleProtocol\n    where\n        DirectoryFileHandle.ReadFileHandle == ReadFileHandle,\n        DirectoryFileHandle.ReadWriteFileHandle == ReadWriteFileHandle,\n        DirectoryFileHandle.WriteFileHandle == WriteFileHandle\n\n    // MARK: - File access\n\n    /// Opens the file at `path` for reading and returns a handle to it.\n    ///\n    /// The file being opened must exist otherwise this function will throw a ``FileSystemError``\n    /// with code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A readable handle to the opened file.\n    func openFile(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle\n\n    /// Opens the file at `path` for writing and returns a handle to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    /// - Returns: A writable handle to the opened file.\n    func openFile(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle\n\n    /// Opens the file at `path` for reading and writing and returns a handle to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    func openFile(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle\n\n    /// Opens the directory at `path` and returns a handle to it.\n    ///\n    /// The directory being opened must already exist otherwise this function will throw an error.\n    /// Use ``createDirectory(at:withIntermediateDirectories:permissions:)`` to create directories.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the directory should be opened.\n    /// - Returns: A handle to the opened directory.\n    func openDirectory(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory\n    ) async throws -> DirectoryFileHandle\n\n    /// Create a directory at the given path.\n    ///\n    /// If a directory (or file) already exists at `path` then an error will be thrown. If\n    /// `createIntermediateDirectories` is `false` then the full prefix of `path` must already\n    /// exist. If set to `true` then all intermediate directories will be created.\n    ///\n    /// Related system calls: `mkdir(2)`.\n    ///\n    /// - Parameters:\n    ///   - path: The directory to create.\n    ///   - createIntermediateDirectories: Whether intermediate directories should be created.\n    ///   - permissions: The permissions to set on the new directory; default permissions will be\n    ///       used if not specified.\n    func createDirectory(\n        at path: NIOFilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions?\n    ) async throws\n\n    // MARK: - Common directories\n\n    /// Returns the current working directory.\n    var currentWorkingDirectory: NIOFilePath { get async throws }\n\n    /// Returns the current user's home directory.\n    var homeDirectory: NIOFilePath { get async throws }\n\n    /// Returns the path of the temporary directory.\n    var temporaryDirectory: NIOFilePath { get async throws }\n\n    /// Create a temporary directory at the given path, from a template.\n    ///\n    /// The template for the path of the temporary directory must end in at least\n    /// three 'X's, which will be replaced with a unique alphanumeric combination.\n    /// The template can contain intermediary directories which will be created\n    /// if they do not exist already.\n    ///\n    /// Related system calls: `mkdir(2)`.\n    ///\n    /// - Parameters:\n    ///   - template: The template for the path of the temporary directory.\n    /// - Returns:\n    ///   - The path to the new temporary directory.\n    func createTemporaryDirectory(\n        template: NIOFilePath\n    ) async throws -> NIOFilePath\n\n    // MARK: - File information\n\n    /// Returns information about the file at the given path, if it exists; nil otherwise.\n    ///\n    /// - Parameters:\n    ///    - path: The path to get information about.\n    ///    - infoAboutSymbolicLink: If the file is a symbolic link and this parameter is `true` then\n    ///        information about the link will be returned, otherwise information about the\n    ///        destination of the symbolic link is returned.\n    /// - Returns: Information about the file at the given path or `nil` if no file exists.\n    func info(\n        forFileAt path: NIOFilePath,\n        infoAboutSymbolicLink: Bool\n    ) async throws -> FileInfo?\n\n    // MARK: - Symbolic links\n\n    /// Creates a symbolic link that points to the destination.\n    ///\n    /// If a file or directory exists at `path` then an error is thrown.\n    ///\n    /// - Parameters:\n    ///   - path: The path at which to create the symbolic link.\n    ///   - destinationPath: The path that contains the item that the symbolic link points to.`\n    func createSymbolicLink(\n        at path: NIOFilePath,\n        withDestination destinationPath: NIOFilePath\n    ) async throws\n\n    /// Returns the path of the item pointed to by a symbolic link.\n    ///\n    /// - Parameter path: The path of a file or directory.\n    /// - Returns: The path of the file or directory to which the symbolic link points to.\n    func destinationOfSymbolicLink(\n        at path: NIOFilePath\n    ) async throws -> NIOFilePath\n\n    // MARK: - File copying, removal, and moving\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy (when `replaceExisting` is `false`) or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// If `sourcePath` is a symbolic link then only the link is copied. The copied file will\n    /// preserve permissions and any extended attributes (if supported by the file system).\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - copyStrategy: How to deal with concurrent aspects of the copy, only relevant to directories.\n    ///   - replaceExisting: If `true`, atomically replace any existing file at `destinationPath`.\n    ///   - shouldProceedAfterError: A closure which is executed to determine whether to continue\n    ///       copying files if an error is encountered during the operation. See Errors section for full details.\n    ///   - shouldCopyItem: A closure which is executed before each copy to determine whether each\n    ///       item should be copied. See Filtering section for full details\n    ///\n    /// #### Errors\n    ///\n    /// No errors should be throw by implementors without first calling `shouldProceedAfterError`,\n    /// if that returns without throwing this is taken as permission to continue and the error is swallowed.\n    /// If instead the closure throws then ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    ///  will throw and copying will stop, though the precise semantics of this can depend on the `strategy`.\n    ///\n    /// if using ``CopyStrategy/parallel(maxDescriptors:)``\n    /// Already started work may continue for an indefinite period of time. In particular, after throwing an error\n    /// it is possible that invocations of `shouldCopyItem` may continue to occur!\n    ///\n    /// If using ``CopyStrategy/sequential`` only one invocation of any of the `should*` closures will occur at a time,\n    /// and an error will immediately stop further activity.\n    ///\n    /// The specific error thrown from copyItem is undefined, it does not have to be the same error thrown from\n    /// `shouldProceedAfterError`.\n    /// In the event of any errors (ignored or otherwise) implementations are under no obbligation to\n    /// attempt to 'tidy up' after themselves. The state of the file system within `destinationPath`\n    /// after an aborted copy should is undefined.\n    ///\n    /// When calling `shouldProceedAfterError` implementations of this method\n    /// MUST:\n    ///  - Do so once and only once per item.\n    ///  - Not hold any locks when doing so.\n    /// MAY:\n    ///  - invoke the function multiple times concurrently (except when using ``CopyStrategy/sequential``)\n    ///\n    /// #### Filtering\n    ///\n    /// When invoking `shouldCopyItem` implementations of this method\n    /// MUST:\n    ///  - Do so once and only once per item.\n    ///  - Do so before attempting any operations related to the copy (including determining if they can do so).\n    ///  - Not hold any locks when doing so.\n    ///  - Check parent directories *before* items within them,\n    ///     * if a parent is ignored no items within it should be considered or checked\n    ///  - Skip all contents of a directory which is filtered out.\n    ///  - Invoke it for the `sourcePath` itself.\n    /// MAY:\n    ///  - invoke the function multiple times concurrently (except when using ``CopyStrategy/sequential``)\n    ///  - invoke the function an arbitrary point before actually trying to copy the file\n    func copyItem(\n        at sourcePath: NIOFilePath,\n        to destinationPath: NIOFilePath,\n        strategy copyStrategy: CopyStrategy,\n        replaceExisting: Bool,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: NIOFilePath\n            ) async -> Bool\n    ) async throws\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory and `removeItemRecursively` is `true` then the\n    /// contents of all of its subdirectories will be removed recursively before the directory at\n    /// `path`. Symbolic links are removed (but their targets are not deleted).\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removalStrategy: Whether to delete files sequentially (one-by-one), or perform a\n    ///       concurrent scan of the tree at `path` and delete files when they are found. Ignored if\n    ///       the item being removed isn't a directory.\n    ///   - removeItemRecursively: If the item being removed is a directory, remove it by\n    ///       recursively removing its children. Setting this to `true` is synonymous with calling\n    ///       `rm -r`, setting this false is synonymous to calling `rmdir`. Ignored if the item\n    ///       being removed isn't a directory.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    func removeItem(\n        at path: NIOFilePath,\n        strategy removalStrategy: RemovalStrategy,\n        recursively removeItemRecursively: Bool\n    ) async throws -> Int\n\n    /// Moves the file or directory at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// If the file at `sourcePath` is a symbolic link then only the link is moved to the new path.\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to move.\n    ///   - destinationPath: The path at which to place the item.\n    func moveItem(at sourcePath: NIOFilePath, to destinationPath: NIOFilePath) async throws\n\n    /// Replaces the item at `destinationPath` with the item at `existingPath`.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `existingPath` does\n    ///    not exist,\n    /// - ``FileSystemError/Code-swift.struct/io`` if the file at `existingPath` was successfully\n    ///    copied to `destinationPath` but an error occurred while removing it from `existingPath.`\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// The item at `destinationPath` is not required to exist. Note that it is possible to replace\n    /// a file with a directory and vice versa. After the file or directory at `destinationPath`\n    /// has been replaced, the item at `existingPath` will be removed.\n    ///\n    /// - Parameters:\n    ///   - destinationPath: The path of the file or directory to replace.\n    ///   - existingPath: The path of the existing file or directory.\n    func replaceItem(at destinationPath: NIOFilePath, withItemAt existingPath: NIOFilePath) async throws\n}\n\n// MARK: - Open existing files/directories\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemProtocol {\n    /// Opens the file at the given path and provides scoped read-only access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns. Files may also be opened in read-write or write-only\n    /// mode by calling ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)`` and\n    /// ``FileSystemProtocol/withFileHandle(forWritingAt:options:execute:)``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides read-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read = OpenOptions.Read(),\n        execute: (_ read: ReadFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAt: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped write-only access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns. Files may also be opened in read-write or read-only\n    /// mode by calling ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)`` and\n    /// ``FileSystemProtocol/withFileHandle(forReadingAt:options:execute:)``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides write-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute: (_ write: WriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forWritingAt: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { result in\n            switch result {\n            case .success:\n                try await handle.close()\n            case .failure:\n                try await handle.close(makeChangesVisible: false)\n            }\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped read-write access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the function returns. Files may also be opened in read-only or\n    /// write-only mode by with ``FileSystemProtocol/withFileHandle(forReadingAt:options:execute:)`` and\n    /// ``FileSystemProtocol/withFileHandle(forWritingAt:options:execute:)``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading and writing.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute: (_ readWrite: ReadWriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAndWritingAt: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n\n    /// Opens the directory at the given path and provides scoped access to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides access to the directory.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withDirectoryHandle<Result>(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory = OpenOptions.Directory(),\n        execute: (_ directory: DirectoryFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openDirectory(atPath: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemProtocol {\n    /// Opens the file at `path` for reading and returns a handle to it.\n    ///\n    /// The file being opened must exist otherwise this function will throw a ``FileSystemError``\n    /// with code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    /// - Returns: A readable handle to the opened file.\n    public func openFile(\n        forReadingAt path: NIOFilePath\n    ) async throws -> ReadFileHandle {\n        try await self.openFile(forReadingAt: path, options: OpenOptions.Read())\n    }\n\n    /// Opens the directory at `path` and returns a handle to it.\n    ///\n    /// The directory being opened must already exist otherwise this function will throw an error.\n    /// Use ``createDirectory(at:withIntermediateDirectories:permissions:)`` to create directories.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    /// - Returns: A handle to the opened directory.\n    public func openDirectory(\n        atPath path: NIOFilePath\n    ) async throws -> DirectoryFileHandle {\n        try await self.openDirectory(atPath: path, options: OpenOptions.Directory())\n    }\n\n    /// Returns information about the file at the given path, if it exists; nil otherwise.\n    ///\n    /// Calls ``info(forFileAt:infoAboutSymbolicLink:)`` setting `infoAboutSymbolicLink` to `false`.\n    ///\n    /// - Parameters:\n    ///    - path: The path to get information about.\n    /// - Returns: Information about the file at the given path or `nil` if no file exists.\n    public func info(forFileAt path: NIOFilePath) async throws -> FileInfo? {\n        try await self.info(forFileAt: path, infoAboutSymbolicLink: false)\n    }\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown. If any error is encountered during the copy\n    /// then the copy is aborted. You can modify the behaviour with the `shouldProceedAfterError`\n    /// parameter of ``FileSystemProtocol/copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``.\n    ///\n    /// If the file at `sourcePath` is a symbolic link then only the link is copied to the new path.\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - copyStrategy: This controls the concurrency used if the file at `sourcePath` is a directory.\n    public func copyItem(\n        at sourcePath: NIOFilePath,\n        to destinationPath: NIOFilePath,\n        strategy copyStrategy: CopyStrategy = .platformDefault\n    ) async throws {\n        try await self.copyItem(\n            at: sourcePath,\n            to: destinationPath,\n            strategy: copyStrategy,\n            replaceExisting: false,\n            shouldProceedAfterError: { _, error in\n                throw error\n            },\n            shouldCopyItem: { _, _ in\n                true\n            }\n        )\n    }\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// If `sourcePath` is a symbolic link then only the link is copied. The copied file will\n    /// preserve permissions and any extended attributes (if supported by the file system).\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - shouldProceedAfterError: A closure which is executed to determine whether to continue\n    ///       copying files if an error is encountered during the operation. See Errors section for full details.\n    ///   - shouldCopyItem: A closure which is executed before each copy to determine whether each\n    ///       item should be copied. See Filtering section for full details\n    ///\n    /// #### Parallelism\n    ///\n    /// This overload uses ``CopyStrategy/platformDefault`` which is likely to result in multiple concurrency domains being used\n    /// in the event of copying a directory.\n    /// See the detailed description on ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    /// for the implications of this with respect to the `shouldProceedAfterError` and `shouldCopyItem` callbacks\n    public func copyItem(\n        at sourcePath: NIOFilePath,\n        to destinationPath: NIOFilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: NIOFilePath\n            ) async -> Bool\n    ) async throws {\n        try await self.copyItem(\n            at: sourcePath,\n            to: destinationPath,\n            strategy: .platformDefault,\n            replaceExisting: false,\n            shouldProceedAfterError: shouldProceedAfterError,\n            shouldCopyItem: shouldCopyItem\n        )\n    }\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory then the contents of all of its subdirectories will\n    /// be removed recursively before the directory at `path`. Symbolic links are removed (but their\n    /// targets are not deleted).\n    ///\n    /// The strategy for deletion will be determined automatically depending on the discovered\n    /// platform.\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: NIOFilePath\n    ) async throws -> Int {\n        try await self.removeItem(at: path, strategy: .platformDefault, recursively: true)\n    }\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory then the contents of all of its subdirectories will\n    /// be removed recursively before the directory at `path`. Symbolic links are removed (but their\n    /// targets are not deleted).\n    ///\n    /// The strategy for deletion will be determined automatically depending on the discovered\n    /// platform.\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removeItemRecursively: If the item being removed is a directory, remove it by\n    ///       recursively removing its children. Setting this to `true` is synonymous with calling\n    ///       `rm -r`, setting this false is synonymous to calling `rmdir`. Ignored if the item\n    ///       being removed isn't a directory.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: NIOFilePath,\n        recursively removeItemRecursively: Bool\n    ) async throws -> Int {\n        try await self.removeItem(at: path, strategy: .platformDefault, recursively: removeItemRecursively)\n    }\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory then the contents of all of its subdirectories will\n    /// be removed recursively before the directory at `path`. Symbolic links are removed (but their\n    /// targets are not deleted).\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removalStrategy: Whether to delete files sequentially (one-by-one), or perform a\n    ///       concurrent scan of the tree at `path` and delete files when they are found.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: NIOFilePath,\n        strategy removalStrategy: RemovalStrategy\n    ) async throws -> Int {\n        try await self.removeItem(at: path, strategy: removalStrategy, recursively: true)\n    }\n\n    /// Create a directory at the given path.\n    ///\n    /// If a directory (or file) already exists at `path` then an error will be thrown. If\n    /// `createIntermediateDirectories` is `false` then the full prefix of `path` must already\n    /// exist. If set to `true` then all intermediate directories will be created.\n    ///\n    /// New directories will be given read-write-execute owner permissions and read-execute group\n    /// and other permissions.\n    ///\n    /// Related system calls: `mkdir(2)`.\n    ///\n    /// - Parameters:\n    ///   - path: The directory to create.\n    ///   - createIntermediateDirectories: Whether intermediate directories should be created.\n    public func createDirectory(\n        at path: NIOFilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool\n    ) async throws {\n        try await self.createDirectory(\n            at: path,\n            withIntermediateDirectories: createIntermediateDirectories,\n            permissions: .defaultsForDirectory\n        )\n    }\n\n    /// Create a temporary directory and removes it once the function returns.\n    ///\n    /// You can use `prefix` to specify the directory in which the temporary directory should\n    /// be created. If `prefix` is `nil` then the value of ``temporaryDirectory`` is used as\n    /// the prefix.\n    ///\n    /// The temporary directory, and all of its contents, is removed once `execute` returns.\n    ///\n    /// - Parameters:\n    ///   - prefix: The prefix to use for the path of the temporary directory.\n    ///   - options: Options used to create the directory.\n    ///   - execute: A closure which provides access to the directory and its path.\n    /// - Returns: The result of `execute`.\n    public func withTemporaryDirectory<Result>(\n        prefix: NIOFilePath? = nil,\n        options: OpenOptions.Directory = OpenOptions.Directory(),\n        execute: (_ directory: DirectoryFileHandle, _ path: NIOFilePath) async throws -> Result\n    ) async throws -> Result {\n        let template: FilePath\n\n        if let prefix = prefix {\n            template = prefix.underlying.appending(\"XXXXXXXX\")\n        } else {\n            template = try await self.temporaryDirectory.underlying.appending(\"XXXXXXXX\")\n        }\n\n        let directory = try await self.createTemporaryDirectory(template: NIOFilePath(template))\n        return try await withUncancellableTearDown {\n            try await withDirectoryHandle(atPath: directory, options: options) { handle in\n                try await execute(handle, directory)\n            }\n        } tearDown: { _ in\n            try await self.removeItem(at: directory, strategy: .platformDefault, recursively: true)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/FileType.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\n\n/// The type of a file system object.\npublic struct FileType: Hashable, Sendable {\n    internal enum Wrapped: Hashable, Sendable, CaseIterable {\n        case regular\n        case block\n        case character\n        case fifo\n        case directory\n        case symlink\n        case socket\n        case whiteout\n        case unknown\n    }\n\n    internal let wrapped: Wrapped\n    private init(_ wrapped: Wrapped) {\n        self.wrapped = wrapped\n    }\n}\n\nextension FileType {\n    /// Regular file.\n    public static var regular: Self { Self(.regular) }\n\n    /// Directory.\n    public static var directory: Self { Self(.directory) }\n\n    /// Symbolic link.\n    public static var symlink: Self { Self(.symlink) }\n\n    /// Hardware block device.\n    public static var block: Self { Self(.block) }\n\n    /// Hardware character device.\n    public static var character: Self { Self(.character) }\n\n    /// FIFO (or named pipe).\n    public static var fifo: Self { Self(.fifo) }\n\n    /// Socket.\n    public static var socket: Self { Self(.socket) }\n\n    /// Whiteout file.\n    public static var whiteout: Self { Self(.whiteout) }\n\n    /// A file of unknown type.\n    public static var unknown: Self { Self(.unknown) }\n}\n\nextension FileType: CustomStringConvertible {\n    public var description: String {\n        switch self.wrapped {\n        case .regular:\n            return \"regular\"\n        case .block:\n            return \"block\"\n        case .character:\n            return \"character\"\n        case .fifo:\n            return \"fifo\"\n        case .directory:\n            return \"directory\"\n        case .symlink:\n            return \"symlink\"\n        case .socket:\n            return \"socket\"\n        case .whiteout:\n            return \"whiteout\"\n        case .unknown:\n            return \"unknown\"\n        }\n    }\n}\n\nextension FileType: CaseIterable {\n    public static var allCases: [FileType] {\n        Self.Wrapped.allCases.map { FileType($0) }\n    }\n}\n\nextension FileType {\n    /// Initializes a file type from a `CInterop.Mode`.\n    ///\n    /// Note: an appropriate mask is applied to `mode`.\n    public init(platformSpecificMode: CInterop.Mode) {\n        // See: `man 2 stat`\n        switch platformSpecificMode & S_IFMT {\n        case S_IFIFO:\n            self = .fifo\n        case S_IFCHR:\n            self = .character\n        case S_IFDIR:\n            self = .directory\n        case S_IFBLK:\n            self = .block\n        case S_IFREG:\n            self = .regular\n        case S_IFLNK:\n            self = .symlink\n        case S_IFSOCK:\n            self = .socket\n        #if canImport(Darwin)\n        case S_IFWHT:\n            self = .whiteout\n        #endif\n        default:\n            self = .unknown\n        }\n    }\n\n    /// Initializes a file type from the `d_type` from `dirent`.\n    @_spi(Testing)\n    public init(direntType: UInt8) {\n        #if canImport(Darwin) || canImport(Musl) || os(Android)\n        let value = Int32(direntType)\n        #elseif canImport(Glibc)\n        let value = Int(direntType)\n        #endif\n\n        switch value {\n        case DT_FIFO:\n            self = .fifo\n        case DT_CHR:\n            self = .character\n        case DT_DIR:\n            self = .directory\n        case DT_BLK:\n            self = .block\n        case DT_REG:\n            self = .regular\n        case DT_LNK:\n            self = .symlink\n        case DT_SOCK:\n            self = .socket\n        #if canImport(Darwin)\n        case DT_WHT:\n            self = .whiteout\n        #endif\n        case DT_UNKNOWN:\n            self = .unknown\n        default:\n            self = .unknown\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/IOStrategy.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// How many file descriptors to open when performing I/O operations.\nenum IOStrategy: Hashable, Sendable {\n    // platformDefault is reified into one of the concrete options below:\n    case sequential\n    case parallel(_ maxDescriptors: Int)\n\n    // These selections are relatively arbitrary but the rationale is as follows:\n    //\n    // - Never exceed the default OS limits even if 4 such operations were happening at once.\n    // - Sufficient to enable significant speed up from parallelism\n    // - Not wasting effort by pushing contention to the underlying storage device. Further we\n    //   assume an SSD or similar underlying storage tech. Users on spinning rust need to account\n    //   for that themselves anyway.\n    //\n    // That said, empirical testing for this has not been performed, suggestions welcome.\n    //\n    // Note: The directory scan is modelled after a copy strategy needing two handles: during the\n    // creation of the destination directory we hold the handle while copying attributes. A much\n    // more complex internal state machine could allow doing two of these if desired. This may not\n    // result in a faster copy though so things are left simple.\n    internal static func determinePlatformDefault() -> Self {\n        #if os(macOS) || os(Linux) || os(Windows)\n        // Eight file descriptors allow for four concurrent file copies/directory scans. Avoiding\n        // storage system contention is of utmost importance.\n        //\n        // Testing was performed on an SSD, while copying objects (a dense directory of small files\n        // and subdirectories of similar shape) to the same volume, totalling 12GB. Results showed\n        // improvements in elapsed time for (expected) increases in CPU time up to parallel(8).\n        // Beyond this, the increases in CPU led to only moderate gains.\n        //\n        // Anyone tuning this is encouraged to cover worst case scenarios.\n        return .parallel(8)\n        #elseif (canImport(Darwin) && !os(macOS)) || os(Android)\n        // Reduced maximum descriptors in embedded world. This is chosen based on biasing towards\n        // safety, not empirical testing.\n        return .parallel(4)\n        #else\n        // Safety first. If we do not know what system we run on, we keep it simple.\n        return .sequential\n        #endif\n    }\n}\n\n/// How to perform copies. Currently only relevant to directory level copies when using\n/// ``FileSystemProtocol/copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)`` or other\n/// overloads that use the default behaviour.\npublic struct CopyStrategy: Hashable, Sendable {\n    internal let wrapped: IOStrategy\n    private init(_ strategy: IOStrategy) {\n        switch strategy {\n        case .sequential:\n            self.wrapped = .sequential\n        case let .parallel(maxDescriptors):\n            self.wrapped = .parallel(maxDescriptors)\n        }\n    }\n\n    // A copy fundamentally can't work without two descriptors unless you copy everything into\n    // memory which is infeasible/inefficient for large copies.\n    private static let minDescriptorsAllowed = 2\n\n    /// Operate in whatever manner is deemed a reasonable default for the platform. This will limit\n    /// the maximum file descriptors usage based on reasonable defaults.\n    ///\n    /// Current assumptions (which are subject to change):\n    /// - Only one copy operation would be performed at once\n    /// - The copy operation is not intended to be the primary activity on the device\n    public static let platformDefault: Self = Self(IOStrategy.determinePlatformDefault())\n\n    /// The copy is done asynchronously, but only one operation will occur at a time. This is the\n    /// only way to guarantee only one callback to the `shouldCopyItem` will happen at a time.\n    public static let sequential: Self = Self(.sequential)\n\n    /// Allow multiple I/O operations to run concurrently, including file copies/directory creation\n    /// and scanning.\n    ///\n    /// - Parameter maxDescriptors: a conservative limit on the number of concurrently open file\n    ///     descriptors involved in the copy. This number must be >= 2 though, if you are using a\n    ///     value that low you should use ``sequential``\n    ///\n    /// - Throws: ``FileSystemError/Code-swift.struct/invalidArgument`` if `maxDescriptors` is less\n    ///     than 2.\n    ///\n    public static func parallel(maxDescriptors: Int) throws -> Self {\n        guard maxDescriptors >= Self.minDescriptorsAllowed else {\n            // 2 is not quite the same as sequential, you could have two concurrent directory\n            // listings for example less than 2 and you can't actually do a _copy_ though so it's\n            // non-sensical.\n            throw FileSystemError(\n                code: .invalidArgument,\n                message: \"Can't do a copy operation without at least 2 file descriptors '\\(maxDescriptors)' is illegal\",\n                cause: nil,\n                location: .here()\n            )\n        }\n        return .init(.parallel(maxDescriptors))\n    }\n}\n\nextension CopyStrategy: CustomStringConvertible {\n    public var description: String {\n        switch self.wrapped {\n        case .sequential:\n            return \"sequential\"\n        case let .parallel(maxDescriptors):\n            return \"parallel with max \\(maxDescriptors) descriptors\"\n        }\n    }\n}\n\n/// How to perform file deletions. Currently only relevant to directory level deletions when using\n/// ``FileSystemProtocol/removeItem(at:strategy:recursively:)`` or other overloads that use the\n/// default behaviour.\npublic struct RemovalStrategy: Hashable, Sendable {\n    internal let wrapped: IOStrategy\n    private init(_ strategy: IOStrategy) {\n        switch strategy {\n        case .sequential:\n            self.wrapped = .sequential\n        case let .parallel(maxDescriptors):\n            self.wrapped = .parallel(maxDescriptors)\n        }\n    }\n\n    // A deletion requires no file descriptors. We only consume a file descriptor while scanning the\n    // contents of a directory, so the minimum is 1.\n    private static let minRequiredDescriptors = 1\n\n    /// Operate in whatever manner is deemed a reasonable default for the platform. This will limit\n    /// the maximum file descriptors usage based on reasonable defaults.\n    ///\n    /// Current assumptions (which are subject to change):\n    /// - Only one delete operation would be performed at once\n    /// - The delete operation is not intended to be the primary activity on the device\n    public static let platformDefault: Self = Self(IOStrategy.determinePlatformDefault())\n\n    /// Traversal of directories and removal of files will be done sequentially without any\n    /// parallelization.\n    public static let sequential: Self = Self(.sequential)\n\n    /// Allow for one or more directory scans to run at the same time. Removal of files will happen\n    /// on asynchronous tasks in parallel.\n    ///\n    /// Setting `maxDescriptors` to 1, will limit the speed of directory discovery. Deletion of\n    /// files within that directory will run in parallel, but discovery of subdirectories will be\n    /// limited to one at a time.\n    public static func parallel(maxDescriptors: Int) throws -> Self {\n        guard maxDescriptors >= Self.minRequiredDescriptors else {\n            throw FileSystemError(\n                code: .invalidArgument,\n                message:\n                    \"Can't do a remove operation without at least one file descriptor '\\(maxDescriptors)' is illegal\",\n                cause: nil,\n                location: .here()\n            )\n        }\n        return .init(.parallel(maxDescriptors))\n    }\n}\n\nextension RemovalStrategy: CustomStringConvertible {\n    public var description: String {\n        switch self.wrapped {\n        case .sequential:\n            return \"sequential\"\n        case let .parallel(maxDescriptors):\n            return \"parallel with max \\(maxDescriptors) descriptors\"\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/BufferedOrAnyStream.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Wraps a ``NIOThrowingAsyncSequenceProducer<Element>`` or ``AnyAsyncSequence<Element>``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal enum BufferedOrAnyStream<Element: Sendable, Delegate: NIOAsyncSequenceProducerDelegate>: Sendable {\n    typealias AsyncSequenceProducer = NIOThrowingAsyncSequenceProducer<\n        Element, Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, Delegate\n    >\n\n    case nioThrowingAsyncSequenceProducer(AsyncSequenceProducer)\n    case anyAsyncSequence(AnyAsyncSequence<Element>)\n\n    internal init(wrapping stream: AsyncSequenceProducer) {\n        self = .nioThrowingAsyncSequenceProducer(stream)\n    }\n\n    internal init<S: AsyncSequence & Sendable>(wrapping stream: S)\n    where S.Element == Element, S.AsyncIterator: NIOFileSystemSendableMetatype {\n        self = .anyAsyncSequence(AnyAsyncSequence(wrapping: stream))\n    }\n\n    internal func makeAsyncIterator() -> AsyncIterator {\n        switch self {\n        case let .nioThrowingAsyncSequenceProducer(stream):\n            return AsyncIterator(wrapping: stream.makeAsyncIterator())\n        case let .anyAsyncSequence(stream):\n            return AsyncIterator(wrapping: stream.makeAsyncIterator())\n        }\n    }\n\n    internal enum AsyncIterator: AsyncIteratorProtocol {\n        case bufferedStream(AsyncSequenceProducer.AsyncIterator)\n        case anyAsyncSequence(AnyAsyncSequence<Element>.AsyncIterator)\n\n        internal mutating func next() async throws -> Element? {\n            let element: Element?\n            switch self {\n            case let .bufferedStream(iterator):\n                defer { self = .bufferedStream(iterator) }\n                element = try await iterator.next()\n            case var .anyAsyncSequence(iterator):\n                defer { self = .anyAsyncSequence(iterator) }\n                element = try await iterator.next()\n            }\n            return element\n        }\n\n        internal init(wrapping iterator: AsyncSequenceProducer.AsyncIterator) {\n            self = .bufferedStream(iterator)\n        }\n\n        internal init(wrapping iterator: AnyAsyncSequence<Element>.AsyncIterator) {\n            self = .anyAsyncSequence(iterator)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal struct AnyAsyncSequence<Element>: AsyncSequence, Sendable {\n    private let _makeAsyncIterator: @Sendable () -> AsyncIterator\n\n    internal init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n    where S.Element == Element, S.AsyncIterator: NIOFileSystemSendableMetatype {\n        self._makeAsyncIterator = {\n            AsyncIterator(wrapping: sequence.makeAsyncIterator())\n        }\n    }\n\n    internal func makeAsyncIterator() -> AsyncIterator {\n        self._makeAsyncIterator()\n    }\n\n    internal struct AsyncIterator: AsyncIteratorProtocol, NIOFileSystemSendableMetatype {\n        private var iterator: any AsyncIteratorProtocol\n\n        init<I: AsyncIteratorProtocol>(wrapping iterator: I) where I.Element == Element {\n            self.iterator = iterator\n        }\n\n        internal mutating func next() async throws -> Element? {\n            try await self.iterator.next() as? Element\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/BufferedStream.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\n\n/// An asynchronous sequence generated from an error-throwing closure that\n/// calls a continuation to produce new elements.\n///\n/// `BufferedStream` conforms to `AsyncSequence`, providing a convenient\n/// way to create an asynchronous sequence without manually implementing an\n/// asynchronous iterator. In particular, an asynchronous stream is well-suited\n/// to adapt callback- or delegation-based APIs to participate with\n/// `async`-`await`.\n///\n/// In contrast to `AsyncStream`, this type can throw an error from the awaited\n/// `next()`, which terminates the stream with the thrown error.\n///\n/// You initialize an `BufferedStream` with a closure that receives an\n/// `BufferedStream.Continuation`. Produce elements in this closure, then\n/// provide them to the stream by calling the continuation's `yield(_:)` method.\n/// When there are no further elements to produce, call the continuation's\n/// `finish()` method. This causes the sequence iterator to produce a `nil`,\n/// which terminates the sequence. If an error occurs, call the continuation's\n/// `finish(throwing:)` method, which causes the iterator's `next()` method to\n/// throw the error to the awaiting call point. The continuation is `Sendable`,\n/// which permits calling it from concurrent contexts external to the iteration\n/// of the `BufferedStream`.\n///\n/// An arbitrary source of elements can produce elements faster than they are\n/// consumed by a caller iterating over them. Because of this, `BufferedStream`\n/// defines a buffering behavior, allowing the stream to buffer a specific\n/// number of oldest or newest elements. By default, the buffer limit is\n/// `Int.max`, which means it's unbounded.\n///\n/// ### Adapting Existing Code to Use Streams\n///\n/// To adapt existing callback code to use `async`-`await`, use the callbacks\n/// to provide values to the stream, by using the continuation's `yield(_:)`\n/// method.\n///\n/// Consider a hypothetical `QuakeMonitor` type that provides callers with\n/// `Quake` instances every time it detects an earthquake. To receive callbacks,\n/// callers set a custom closure as the value of the monitor's\n/// `quakeHandler` property, which the monitor calls back as necessary. Callers\n/// can also set an `errorHandler` to receive asynchronous error notifications,\n/// such as the monitor service suddenly becoming unavailable.\n///\n///     class QuakeMonitor {\n///         var quakeHandler: ((Quake) -> Void)?\n///         var errorHandler: ((Error) -> Void)?\n///\n///         func startMonitoring() {…}\n///         func stopMonitoring() {…}\n///     }\n///\n/// To adapt this to use `async`-`await`, extend the `QuakeMonitor` to add a\n/// `quakes` property, of type `BufferedStream<Quake>`. In the getter for\n/// this property, return an `BufferedStream`, whose `build` closure --\n/// called at runtime to create the stream -- uses the continuation to\n/// perform the following steps:\n///\n/// 1. Creates a `QuakeMonitor` instance.\n/// 2. Sets the monitor's `quakeHandler` property to a closure that receives\n/// each `Quake` instance and forwards it to the stream by calling the\n/// continuation's `yield(_:)` method.\n/// 3. Sets the monitor's `errorHandler` property to a closure that receives\n/// any error from the monitor and forwards it to the stream by calling the\n/// continuation's `finish(throwing:)` method. This causes the stream's\n/// iterator to throw the error and terminate the stream.\n/// 4. Sets the continuation's `onTermination` property to a closure that\n/// calls `stopMonitoring()` on the monitor.\n/// 5. Calls `startMonitoring` on the `QuakeMonitor`.\n///\n/// ```\n/// extension QuakeMonitor {\n///\n///     static var throwingQuakes: BufferedStream<Quake, Error> {\n///         BufferedStream { continuation in\n///             let monitor = QuakeMonitor()\n///             monitor.quakeHandler = { quake in\n///                  continuation.yield(quake)\n///             }\n///             monitor.errorHandler = { error in\n///                 continuation.finish(throwing: error)\n///             }\n///             continuation.onTermination = { @Sendable _ in\n///                 monitor.stopMonitoring()\n///             }\n///             monitor.startMonitoring()\n///         }\n///     }\n/// }\n/// ```\n///\n///\n/// Because the stream is an `AsyncSequence`, the call point uses the\n/// `for`-`await`-`in` syntax to process each `Quake` instance as produced by the stream:\n///\n///     do {\n///         for try await quake in quakeStream {\n///             print(\"Quake: \\(quake.date)\")\n///         }\n///         print(\"Stream done.\")\n///     } catch {\n///         print(\"Error: \\(error)\")\n///     }\n///\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal struct BufferedStream<Element: Sendable> {\n    final class _Backing: Sendable {\n        let storage: _BackPressuredStorage\n\n        init(storage: _BackPressuredStorage) {\n            self.storage = storage\n        }\n\n        deinit {\n            self.storage.sequenceDeinitialized()\n        }\n    }\n\n    enum _Implementation: Sendable {\n        /// This is the implementation with backpressure based on the Source\n        case backpressured(_Backing)\n    }\n\n    let implementation: _Implementation\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream: AsyncSequence {\n    /// The asynchronous iterator for iterating an asynchronous stream.\n    ///\n    /// This type is not `Sendable`. Don't use it from multiple\n    /// concurrent contexts. It is a programmer error to invoke `next()` from a\n    /// concurrent context that contends with another such call, which\n    /// results in a call to `fatalError()`.\n    internal struct Iterator: AsyncIteratorProtocol {\n        final class _Backing {\n            let storage: _BackPressuredStorage\n\n            init(storage: _BackPressuredStorage) {\n                self.storage = storage\n                self.storage.iteratorInitialized()\n            }\n\n            deinit {\n                self.storage.iteratorDeinitialized()\n            }\n        }\n        enum _Implementation {\n            /// This is the implementation with backpressure based on the Source\n            case backpressured(_Backing)\n        }\n\n        var implementation: _Implementation\n\n        /// The next value from the asynchronous stream.\n        ///\n        /// When `next()` returns `nil`, this signifies the end of the\n        /// `BufferedStream`.\n        ///\n        /// It is a programmer error to invoke `next()` from a concurrent context\n        /// that contends with another such call, which results in a call to\n        ///  `fatalError()`.\n        ///\n        /// If you cancel the task this iterator is running in while `next()` is\n        /// awaiting a value, the `BufferedStream` terminates. In this case,\n        /// `next()` may return `nil` immediately, or else return `nil` on\n        /// subsequent calls.\n        internal mutating func next() async throws -> Element? {\n            switch self.implementation {\n            case .backpressured(let backing):\n                return try await backing.storage.next()\n            }\n        }\n    }\n\n    /// Creates the asynchronous iterator that produces elements of this\n    /// asynchronous sequence.\n    internal func makeAsyncIterator() -> Iterator {\n        switch self.implementation {\n        case .backpressured(let backing):\n            return Iterator(implementation: .backpressured(.init(storage: backing.storage)))\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream: Sendable {}\n\ninternal struct _ManagedCriticalState<State>: @unchecked Sendable {\n    let lock: NIOLockedValueBox<State>\n\n    internal init(_ initial: State) {\n        self.lock = .init(initial)\n    }\n\n    internal func withCriticalRegion<R>(\n        _ critical: (inout State) throws -> R\n    ) rethrows -> R {\n        try self.lock.withLockedValue(critical)\n    }\n}\n\ninternal struct AlreadyFinishedError: Error {}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    /// A mechanism to interface between producer code and an asynchronous stream.\n    ///\n    /// Use this source to provide elements to the stream by calling one of the `write` methods, then terminate the stream normally\n    /// by calling the `finish()` method. You can also use the source's `finish(throwing:)` method to terminate the stream by\n    /// throwing an error.\n    internal struct Source: Sendable {\n        /// A strategy that handles the backpressure of the asynchronous stream.\n        internal struct BackPressureStrategy: Sendable {\n            /// When the high watermark is reached producers will be suspended. All producers will be resumed again once\n            /// the low watermark is reached.\n            internal static func watermark(low: Int, high: Int) -> BackPressureStrategy {\n                BackPressureStrategy(\n                    internalBackPressureStrategy: .watermark(.init(low: low, high: high))\n                )\n            }\n\n            private init(internalBackPressureStrategy: _InternalBackPressureStrategy) {\n                self._internalBackPressureStrategy = internalBackPressureStrategy\n            }\n\n            fileprivate let _internalBackPressureStrategy: _InternalBackPressureStrategy\n        }\n\n        /// A type that indicates the result of writing elements to the source.\n        internal enum WriteResult: Sendable {\n            /// A token that is returned when the asynchronous stream's backpressure strategy indicated that production should\n            /// be suspended. Use this token to enqueue a callback by  calling the ``enqueueCallback(_:)`` method.\n            internal struct CallbackToken: Sendable {\n                let id: UInt\n            }\n\n            /// Indicates that more elements should be produced and written to the source.\n            case produceMore\n\n            /// Indicates that a callback should be enqueued.\n            ///\n            /// The associated token should be passed to the ``enqueueCallback(_:)`` method.\n            case enqueueCallback(CallbackToken)\n        }\n\n        /// Backing class for the source used to hook a deinit.\n        final class _Backing: Sendable {\n            let storage: _BackPressuredStorage\n\n            init(storage: _BackPressuredStorage) {\n                self.storage = storage\n            }\n\n            deinit {\n                self.storage.sourceDeinitialized()\n            }\n        }\n\n        /// A callback to invoke when the stream finished.\n        ///\n        /// The stream finishes and calls this closure in the following cases:\n        /// - No iterator was created and the sequence was deinited\n        /// - An iterator was created and deinited\n        /// - After ``finish(throwing:)`` was called and all elements have been consumed\n        /// - The consuming task got cancelled\n        internal var onTermination: (@Sendable () -> Void)? {\n            set {\n                self._backing.storage.onTermination = newValue\n            }\n            get {\n                self._backing.storage.onTermination\n            }\n        }\n\n        private var _backing: _Backing\n\n        internal init(storage: _BackPressuredStorage) {\n            self._backing = .init(storage: storage)\n        }\n\n        /// Writes new elements to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// first element of the provided sequence. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// - Parameter sequence: The elements to write to the asynchronous stream.\n        /// - Returns: The result that indicates if more elements should be produced at this time.\n        internal func write<S>(contentsOf sequence: S) throws -> WriteResult\n        where Element == S.Element, S: Sequence, Element: Sendable {\n            try self._backing.storage.write(contentsOf: sequence)\n        }\n\n        /// Write the element to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// provided element. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// - Parameter element: The element to write to the asynchronous stream.\n        /// - Returns: The result that indicates if more elements should be produced at this time.\n        internal func write(_ element: Element) throws -> WriteResult {\n            try self._backing.storage.write(contentsOf: CollectionOfOne(element))\n        }\n\n        /// Enqueues a callback that will be invoked once more elements should be produced.\n        ///\n        /// Call this method after ``write(contentsOf:)`` or ``write(:)`` returned ``WriteResult/enqueueCallback(_:)``.\n        ///\n        /// - Important: Enqueueing the same token multiple times is not allowed.\n        ///\n        /// - Parameters:\n        ///   - callbackToken: The callback token.\n        ///   - onProduceMore: The callback which gets invoked once more elements should be produced.\n        internal func enqueueCallback(\n            callbackToken: WriteResult.CallbackToken,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) {\n            self._backing.storage.enqueueProducer(\n                callbackToken: callbackToken,\n                onProduceMore: onProduceMore\n            )\n        }\n\n        /// Cancel an enqueued callback.\n        ///\n        /// Call this method to cancel a callback enqueued by the ``enqueueCallback(callbackToken:onProduceMore:)`` method.\n        ///\n        /// - Note: This methods supports being called before ``enqueueCallback(callbackToken:onProduceMore:)`` is called and\n        /// will mark the passed `callbackToken` as cancelled.\n        ///\n        /// - Parameter callbackToken: The callback token.\n        internal func cancelCallback(callbackToken: WriteResult.CallbackToken) {\n            self._backing.storage.cancelProducer(callbackToken: callbackToken)\n        }\n\n        /// Write new elements to the asynchronous stream and provide a callback which will be invoked once more elements should be produced.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// first element of the provided sequence. If the asynchronous stream already terminated then `onProduceMore` will be invoked with\n        /// a `Result.failure`.\n        ///\n        /// - Parameters:\n        ///   - sequence: The elements to write to the asynchronous stream.\n        ///   - onProduceMore: The callback which gets invoked once more elements should be produced. This callback might be\n        ///   invoked during the call to ``write(contentsOf:onProduceMore:)``.\n        internal func write<S>(\n            contentsOf sequence: S,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) where Element == S.Element, S: Sequence, Element: Sendable {\n            do {\n                let writeResult = try self.write(contentsOf: sequence)\n\n                switch writeResult {\n                case .produceMore:\n                    onProduceMore(Result<Void, Error>.success(()))\n\n                case .enqueueCallback(let callbackToken):\n                    self.enqueueCallback(callbackToken: callbackToken, onProduceMore: onProduceMore)\n                }\n            } catch {\n                onProduceMore(.failure(error))\n            }\n        }\n\n        /// Writes the element to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// provided element. If the asynchronous stream already terminated then `onProduceMore` will be invoked with\n        /// a `Result.failure`.\n        ///\n        /// - Parameters:\n        ///   - sequence: The element to write to the asynchronous stream.\n        ///   - onProduceMore: The callback which gets invoked once more elements should be produced. This callback might be\n        ///   invoked during the call to ``write(_:onProduceMore:)``.\n        internal func write(\n            _ element: Element,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) {\n            self.write(contentsOf: CollectionOfOne(element), onProduceMore: onProduceMore)\n        }\n\n        /// Write new elements to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// first element of the provided sequence. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// This method returns once more elements should be produced.\n        ///\n        /// - Parameters:\n        ///   - sequence: The elements to write to the asynchronous stream.\n        internal func write<S>(contentsOf sequence: S) async throws\n        where Element == S.Element, S: Sequence, Element: Sendable {\n            let writeResult = try { try self.write(contentsOf: sequence) }()\n\n            switch writeResult {\n            case .produceMore:\n                return\n\n            case .enqueueCallback(let callbackToken):\n                try await withTaskCancellationHandler {\n                    try await withCheckedThrowingContinuation { continuation in\n                        self.enqueueCallback(\n                            callbackToken: callbackToken,\n                            onProduceMore: { result in\n                                switch result {\n                                case .success():\n                                    continuation.resume(returning: ())\n                                case .failure(let error):\n                                    continuation.resume(throwing: error)\n                                }\n                            }\n                        )\n                    }\n                } onCancel: {\n                    self.cancelCallback(callbackToken: callbackToken)\n                }\n            }\n        }\n\n        /// Write new element to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// provided element. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// This method returns once more elements should be produced.\n        ///\n        /// - Parameters:\n        ///   - sequence: The element to write to the asynchronous stream.\n        internal func write(_ element: Element) async throws {\n            try await self.write(contentsOf: CollectionOfOne(element))\n        }\n\n        /// Write the elements of the asynchronous sequence to the asynchronous stream.\n        ///\n        /// This method returns once the provided asynchronous sequence or the  the asynchronous stream finished.\n        ///\n        /// - Important: This method does not finish the source if consuming the upstream sequence terminated.\n        ///\n        /// - Parameters:\n        ///   - sequence: The elements to write to the asynchronous stream.\n        internal func write<S>(contentsOf sequence: S) async throws\n        where Element == S.Element, S: AsyncSequence, Element: Sendable {\n            for try await element in sequence {\n                try await self.write(contentsOf: CollectionOfOne(element))\n            }\n        }\n\n        /// Indicates that the production terminated.\n        ///\n        /// After all buffered elements are consumed the next iteration point will return `nil` or throw an error.\n        ///\n        /// Calling this function more than once has no effect. After calling finish, the stream enters a terminal state and doesn't accept\n        /// new elements.\n        ///\n        /// - Parameters:\n        ///   - error: The error to throw, or `nil`, to finish normally.\n        internal func finish(throwing error: Error?) {\n            self._backing.storage.finish(error)\n        }\n    }\n\n    /// Initializes a new ``BufferedStream`` and an ``BufferedStream/Source``.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the stream.\n    ///   - failureType: The failure type of the stream.\n    ///   - backPressureStrategy: The backpressure strategy that the stream should use.\n    /// - Returns: A tuple containing the stream and its source. The source should be passed to the\n    ///   producer while the stream should be passed to the consumer.\n    internal static func makeStream(\n        of elementType: Element.Type = Element.self,\n        throwing failureType: Error.Type = Error.self,\n        backPressureStrategy: Source.BackPressureStrategy\n    ) -> (`Self`, Source) where Error == Error {\n        let storage = _BackPressuredStorage(\n            backPressureStrategy: backPressureStrategy._internalBackPressureStrategy\n        )\n        let source = Source(storage: storage)\n\n        return (.init(storage: storage), source)\n    }\n\n    init(storage: _BackPressuredStorage) {\n        self.implementation = .backpressured(.init(storage: storage))\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    struct _WatermarkBackPressureStrategy {\n        /// The low watermark where demand should start.\n        private let _low: Int\n        /// The high watermark where demand should be stopped.\n        private let _high: Int\n\n        /// Initializes a new ``_WatermarkBackPressureStrategy``.\n        ///\n        /// - Parameters:\n        ///   - low: The low watermark where demand should start.\n        ///   - high: The high watermark where demand should be stopped.\n        init(low: Int, high: Int) {\n            precondition(low <= high)\n            self._low = low\n            self._high = high\n        }\n\n        func didYield(bufferDepth: Int) -> Bool {\n            // We are demanding more until we reach the high watermark\n            bufferDepth < self._high\n        }\n\n        func didConsume(bufferDepth: Int) -> Bool {\n            // We start demanding again once we are below the low watermark\n            bufferDepth < self._low\n        }\n    }\n\n    enum _InternalBackPressureStrategy {\n        case watermark(_WatermarkBackPressureStrategy)\n\n        mutating func didYield(bufferDepth: Int) -> Bool {\n            switch self {\n            case .watermark(let strategy):\n                return strategy.didYield(bufferDepth: bufferDepth)\n            }\n        }\n\n        mutating func didConsume(bufferDepth: Int) -> Bool {\n            switch self {\n            case .watermark(let strategy):\n                return strategy.didConsume(bufferDepth: bufferDepth)\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    // We are unchecked Sendable since we are protecting our state with a lock.\n    final class _BackPressuredStorage: Sendable {\n        /// The state machine\n        let _stateMachine: _ManagedCriticalState<_StateMachine>\n\n        var onTermination: (@Sendable () -> Void)? {\n            set {\n                self._stateMachine.withCriticalRegion {\n                    $0._onTermination = newValue\n                }\n            }\n            get {\n                self._stateMachine.withCriticalRegion {\n                    $0._onTermination\n                }\n            }\n        }\n\n        init(\n            backPressureStrategy: _InternalBackPressureStrategy\n        ) {\n            self._stateMachine = .init(.init(backPressureStrategy: backPressureStrategy))\n        }\n\n        func sequenceDeinitialized() {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.sequenceDeinitialized()\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .failProducersAndCallOnTermination(let producerContinuations, let onTermination):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n                onTermination?()\n\n            case .none:\n                break\n            }\n        }\n\n        func iteratorInitialized() {\n            self._stateMachine.withCriticalRegion {\n                $0.iteratorInitialized()\n            }\n        }\n\n        func iteratorDeinitialized() {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.iteratorDeinitialized()\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .failProducersAndCallOnTermination(let producerContinuations, let onTermination):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n                onTermination?()\n\n            case .none:\n                break\n            }\n        }\n\n        func sourceDeinitialized() {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.sourceDeinitialized()\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .failProducersAndCallOnTermination(let producerContinuations, let onTermination):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n                onTermination?()\n\n            case .failProducers(let producerContinuations):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n\n            case .none:\n                break\n            }\n        }\n\n        func write(\n            contentsOf sequence: some Sequence<Element>\n        ) throws -> Source.WriteResult {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.write(sequence)\n            }\n\n            switch action {\n            case .returnProduceMore:\n                return .produceMore\n\n            case .returnEnqueue(let callbackToken):\n                return .enqueueCallback(callbackToken)\n\n            case .resumeConsumerAndReturnProduceMore(let continuation, let element):\n                continuation.resume(returning: element)\n                return .produceMore\n\n            case .resumeConsumerAndReturnEnqueue(let continuation, let element, let callbackToken):\n                continuation.resume(returning: element)\n                return .enqueueCallback(callbackToken)\n\n            case .throwFinishedError:\n                throw AlreadyFinishedError()\n            }\n        }\n\n        func enqueueProducer(\n            callbackToken: Source.WriteResult.CallbackToken,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.enqueueProducer(callbackToken: callbackToken, onProduceMore: onProduceMore)\n            }\n\n            switch action {\n            case .resumeProducer(let onProduceMore):\n                onProduceMore(Result<Void, Error>.success(()))\n\n            case .resumeProducerWithError(let onProduceMore, let error):\n                onProduceMore(Result<Void, Error>.failure(error))\n\n            case .none:\n                break\n            }\n        }\n\n        func cancelProducer(callbackToken: Source.WriteResult.CallbackToken) {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.cancelProducer(callbackToken: callbackToken)\n            }\n\n            switch action {\n            case .resumeProducerWithCancellationError(let onProduceMore):\n                onProduceMore(Result<Void, Error>.failure(CancellationError()))\n\n            case .none:\n                break\n            }\n        }\n\n        func finish(_ failure: Error?) {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.finish(failure)\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .resumeConsumerAndCallOnTermination(\n                let consumerContinuation,\n                let failure,\n                let onTermination\n            ):\n                switch failure {\n                case .some(let error):\n                    consumerContinuation.resume(throwing: error)\n                case .none:\n                    consumerContinuation.resume(returning: nil)\n                }\n\n                onTermination?()\n\n            case .resumeProducers(let producerContinuations):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n\n            case .none:\n                break\n            }\n        }\n\n        func next() async throws -> Element? {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.next()\n            }\n\n            switch action {\n            case .returnElement(let element):\n                return element\n\n            case .returnElementAndResumeProducers(let element, let producerContinuations):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(Result<Void, Error>.success(()))\n                }\n\n                return element\n\n            case .returnErrorAndCallOnTermination(let failure, let onTermination):\n                onTermination?()\n                switch failure {\n                case .some(let error):\n                    throw error\n\n                case .none:\n                    return nil\n                }\n\n            case .returnNil:\n                return nil\n\n            case .suspendTask:\n                return try await self.suspendNext()\n            }\n        }\n\n        func suspendNext() async throws -> Element? {\n            try await withTaskCancellationHandler {\n                try await withCheckedThrowingContinuation { continuation in\n                    let action = self._stateMachine.withCriticalRegion {\n                        $0.suspendNext(continuation: continuation)\n                    }\n\n                    switch action {\n                    case .resumeConsumerWithElement(let continuation, let element):\n                        continuation.resume(returning: element)\n\n                    case .resumeConsumerWithElementAndProducers(\n                        let continuation,\n                        let element,\n                        let producerContinuations\n                    ):\n                        continuation.resume(returning: element)\n                        for producerContinuation in producerContinuations {\n                            producerContinuation(Result<Void, Error>.success(()))\n                        }\n\n                    case .resumeConsumerWithErrorAndCallOnTermination(\n                        let continuation,\n                        let failure,\n                        let onTermination\n                    ):\n                        switch failure {\n                        case .some(let error):\n                            continuation.resume(throwing: error)\n\n                        case .none:\n                            continuation.resume(returning: nil)\n                        }\n                        onTermination?()\n\n                    case .resumeConsumerWithNil(let continuation):\n                        continuation.resume(returning: nil)\n\n                    case .none:\n                        break\n                    }\n                }\n            } onCancel: {\n                let action = self._stateMachine.withCriticalRegion {\n                    $0.cancelNext()\n                }\n\n                switch action {\n                case .resumeConsumerWithCancellationErrorAndCallOnTermination(\n                    let continuation,\n                    let onTermination\n                ):\n                    continuation.resume(throwing: CancellationError())\n                    onTermination?()\n\n                case .failProducersAndCallOnTermination(\n                    let producerContinuations,\n                    let onTermination\n                ):\n                    for producerContinuation in producerContinuations {\n                        producerContinuation(.failure(AlreadyFinishedError()))\n                    }\n                    onTermination?()\n\n                case .none:\n                    break\n                }\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    /// The state machine of the backpressured async stream.\n    struct _StateMachine {\n        enum _State {\n            struct Initial {\n                /// The backpressure strategy.\n                var backPressureStrategy: _InternalBackPressureStrategy\n                /// Indicates if the iterator was initialized.\n                var iteratorInitialized: Bool\n                /// The onTermination callback.\n                var onTermination: (@Sendable () -> Void)?\n            }\n\n            struct Streaming {\n                /// The backpressure strategy.\n                var backPressureStrategy: _InternalBackPressureStrategy\n                /// Indicates if the iterator was initialized.\n                var iteratorInitialized: Bool\n                /// The onTermination callback.\n                var onTermination: (@Sendable () -> Void)?\n                /// The buffer of elements.\n                var buffer: Deque<Element>\n                /// The optional consumer continuation.\n                var consumerContinuation: CheckedContinuation<Element?, Error>?\n                /// The producer continuations.\n                var producerContinuations: Deque<(UInt, (Result<Void, Error>) -> Void)>\n                /// The producers that have been cancelled.\n                var cancelledAsyncProducers: Deque<UInt>\n                /// Indicates if we currently have outstanding demand.\n                var hasOutstandingDemand: Bool\n            }\n\n            struct SourceFinished {\n                /// Indicates if the iterator was initialized.\n                var iteratorInitialized: Bool\n                /// The buffer of elements.\n                var buffer: Deque<Element>\n                /// The failure that should be thrown after the last element has been consumed.\n                var failure: Error?\n                /// The onTermination callback.\n                var onTermination: (@Sendable () -> Void)?\n            }\n\n            case initial(Initial)\n            /// The state once either any element was yielded or `next()` was called.\n            case streaming(Streaming)\n            /// The state once the underlying source signalled that it is finished.\n            case sourceFinished(SourceFinished)\n\n            /// The state once there can be no outstanding demand. This can happen if:\n            /// 1. The iterator was deinited\n            /// 2. The underlying source finished and all buffered elements have been consumed\n            case finished(iteratorInitialized: Bool)\n\n            /// An intermediate state to avoid CoWs.\n            case modify\n        }\n\n        /// The state machine's current state.\n        var _state: _State\n\n        // The ID used for the next CallbackToken.\n        var nextCallbackTokenID: UInt = 0\n\n        var _onTermination: (@Sendable () -> Void)? {\n            set {\n                switch self._state {\n                case .initial(var initial):\n                    initial.onTermination = newValue\n                    self._state = .initial(initial)\n\n                case .streaming(var streaming):\n                    streaming.onTermination = newValue\n                    self._state = .streaming(streaming)\n\n                case .sourceFinished(var sourceFinished):\n                    sourceFinished.onTermination = newValue\n                    self._state = .sourceFinished(sourceFinished)\n\n                case .finished:\n                    break\n\n                case .modify:\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n            }\n            get {\n                switch self._state {\n                case .initial(let initial):\n                    return initial.onTermination\n\n                case .streaming(let streaming):\n                    return streaming.onTermination\n\n                case .sourceFinished(let sourceFinished):\n                    return sourceFinished.onTermination\n\n                case .finished:\n                    return nil\n\n                case .modify:\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n            }\n        }\n\n        /// Initializes a new `StateMachine`.\n        ///\n        /// We are passing and holding the back-pressure strategy here because\n        /// it is a customizable extension of the state machine.\n        ///\n        /// - Parameter backPressureStrategy: The back-pressure strategy.\n        init(\n            backPressureStrategy: _InternalBackPressureStrategy\n        ) {\n            self._state = .initial(\n                .init(\n                    backPressureStrategy: backPressureStrategy,\n                    iteratorInitialized: false,\n                    onTermination: nil\n                )\n            )\n        }\n\n        /// Generates the next callback token.\n        mutating func nextCallbackToken() -> Source.WriteResult.CallbackToken {\n            let id = self.nextCallbackTokenID\n            self.nextCallbackTokenID += 1\n            return .init(id: id)\n        }\n\n        /// Actions returned by `sequenceDeinitialized()`.\n        enum SequenceDeinitializedAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((@Sendable () -> Void)?)\n            /// Indicates that  all producers should be failed and `onTermination` should be called.\n            case failProducersAndCallOnTermination(\n                [(Result<Void, Error>) -> Void],\n                (@Sendable () -> Void)?\n            )\n        }\n\n        mutating func sequenceDeinitialized() -> SequenceDeinitializedAction? {\n            switch self._state {\n            case .initial(let initial):\n                if initial.iteratorInitialized {\n                    // An iterator was created and we deinited the sequence.\n                    // This is an expected pattern and we just continue on normal.\n                    return .none\n                } else {\n                    // No iterator was created so we can transition to finished right away.\n                    self._state = .finished(iteratorInitialized: false)\n\n                    return .callOnTermination(initial.onTermination)\n                }\n\n            case .streaming(let streaming):\n                if streaming.iteratorInitialized {\n                    // An iterator was created and we deinited the sequence.\n                    // This is an expected pattern and we just continue on normal.\n                    return .none\n                } else {\n                    // No iterator was created so we can transition to finished right away.\n                    self._state = .finished(iteratorInitialized: false)\n\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                }\n\n            case .sourceFinished(let sourceFinished):\n                if sourceFinished.iteratorInitialized {\n                    // An iterator was created and we deinited the sequence.\n                    // This is an expected pattern and we just continue on normal.\n                    return .none\n                } else {\n                    // No iterator was created so we can transition to finished right away.\n                    self._state = .finished(iteratorInitialized: false)\n\n                    return .callOnTermination(sourceFinished.onTermination)\n                }\n\n            case .finished:\n                // We are already finished so there is nothing left to clean up.\n                // This is just the references dropping afterwards.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        mutating func iteratorInitialized() {\n            switch self._state {\n            case .initial(var initial):\n                if initial.iteratorInitialized {\n                    // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                    fatalError(\"Only a single AsyncIterator can be created\")\n                } else {\n                    // The first and only iterator was initialized.\n                    initial.iteratorInitialized = true\n                    self._state = .initial(initial)\n                }\n\n            case .streaming(var streaming):\n                if streaming.iteratorInitialized {\n                    // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                    fatalError(\"Only a single AsyncIterator can be created\")\n                } else {\n                    // The first and only iterator was initialized.\n                    streaming.iteratorInitialized = true\n                    self._state = .streaming(streaming)\n                }\n\n            case .sourceFinished(var sourceFinished):\n                if sourceFinished.iteratorInitialized {\n                    // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                    fatalError(\"Only a single AsyncIterator can be created\")\n                } else {\n                    // The first and only iterator was initialized.\n                    sourceFinished.iteratorInitialized = true\n                    self._state = .sourceFinished(sourceFinished)\n                }\n\n            case .finished(iteratorInitialized: true):\n                // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                fatalError(\"Only a single AsyncIterator can be created\")\n\n            case .finished(iteratorInitialized: false):\n                // It is strange that an iterator is created after we are finished\n                // but it can definitely happen, e.g.\n                // Sequence.init -> source.finish -> sequence.makeAsyncIterator\n                self._state = .finished(iteratorInitialized: true)\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `iteratorDeinitialized()`.\n        enum IteratorDeinitializedAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((@Sendable () -> Void)?)\n            /// Indicates that  all producers should be failed and `onTermination` should be called.\n            case failProducersAndCallOnTermination(\n                [(Result<Void, Error>) -> Void],\n                (@Sendable () -> Void)?\n            )\n        }\n\n        mutating func iteratorDeinitialized() -> IteratorDeinitializedAction? {\n            switch self._state {\n            case .initial(let initial):\n                if initial.iteratorInitialized {\n                    // An iterator was created and deinited. Since we only support\n                    // a single iterator we can now transition to finish.\n                    self._state = .finished(iteratorInitialized: true)\n                    return .callOnTermination(initial.onTermination)\n                } else {\n                    // An iterator needs to be initialized before it can be deinitialized.\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n            case .streaming(let streaming):\n                if streaming.iteratorInitialized {\n                    // An iterator was created and deinited. Since we only support\n                    // a single iterator we can now transition to finish.\n                    self._state = .finished(iteratorInitialized: true)\n\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                } else {\n                    // An iterator needs to be initialized before it can be deinitialized.\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n            case .sourceFinished(let sourceFinished):\n                if sourceFinished.iteratorInitialized {\n                    // An iterator was created and deinited. Since we only support\n                    // a single iterator we can now transition to finish.\n                    self._state = .finished(iteratorInitialized: true)\n                    return .callOnTermination(sourceFinished.onTermination)\n                } else {\n                    // An iterator needs to be initialized before it can be deinitialized.\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n            case .finished:\n                // We are already finished so there is nothing left to clean up.\n                // This is just the references dropping afterwards.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `sourceDeinitialized()`.\n        enum SourceDeinitializedAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((() -> Void)?)\n            /// Indicates that  all producers should be failed and `onTermination` should be called.\n            case failProducersAndCallOnTermination(\n                [(Result<Void, Error>) -> Void],\n                (@Sendable () -> Void)?\n            )\n            /// Indicates that all producers should be failed.\n            case failProducers([(Result<Void, Error>) -> Void])\n        }\n\n        mutating func sourceDeinitialized() -> SourceDeinitializedAction? {\n            switch self._state {\n            case .initial(let initial):\n                // The source got deinited before anything was written\n                self._state = .finished(iteratorInitialized: initial.iteratorInitialized)\n                return .callOnTermination(initial.onTermination)\n\n            case .streaming(let streaming):\n                if streaming.buffer.isEmpty {\n                    // We can transition to finished right away since the buffer is empty now\n                    self._state = .finished(iteratorInitialized: streaming.iteratorInitialized)\n\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                } else {\n                    // The continuation must be `nil` if the buffer has elements\n                    precondition(streaming.consumerContinuation == nil)\n\n                    self._state = .sourceFinished(\n                        .init(\n                            iteratorInitialized: streaming.iteratorInitialized,\n                            buffer: streaming.buffer,\n                            failure: nil,\n                            onTermination: streaming.onTermination\n                        )\n                    )\n\n                    return .failProducers(\n                        Array(streaming.producerContinuations.map { $0.1 })\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                // This is normal and we just have to tolerate it\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `write()`.\n        enum WriteAction {\n            /// Indicates that the producer should be notified to produce more.\n            case returnProduceMore\n            /// Indicates that the producer should be suspended to stop producing.\n            case returnEnqueue(\n                callbackToken: Source.WriteResult.CallbackToken\n            )\n            /// Indicates that the consumer should be resumed and the producer should be notified to produce more.\n            case resumeConsumerAndReturnProduceMore(\n                continuation: CheckedContinuation<Element?, Error>,\n                element: Element\n            )\n            /// Indicates that the consumer should be resumed and the producer should be suspended.\n            case resumeConsumerAndReturnEnqueue(\n                continuation: CheckedContinuation<Element?, Error>,\n                element: Element,\n                callbackToken: Source.WriteResult.CallbackToken\n            )\n            /// Indicates that the producer has been finished.\n            case throwFinishedError\n\n            init(\n                callbackToken: Source.WriteResult.CallbackToken?,\n                continuationAndElement: (CheckedContinuation<Element?, Error>, Element)? = nil\n            ) {\n                switch (callbackToken, continuationAndElement) {\n                case (.none, .none):\n                    self = .returnProduceMore\n\n                case (.some(let callbackToken), .none):\n                    self = .returnEnqueue(callbackToken: callbackToken)\n\n                case (.none, .some((let continuation, let element))):\n                    self = .resumeConsumerAndReturnProduceMore(\n                        continuation: continuation,\n                        element: element\n                    )\n\n                case (.some(let callbackToken), .some((let continuation, let element))):\n                    self = .resumeConsumerAndReturnEnqueue(\n                        continuation: continuation,\n                        element: element,\n                        callbackToken: callbackToken\n                    )\n                }\n            }\n        }\n\n        mutating func write(_ sequence: some Sequence<Element>) -> WriteAction {\n            switch self._state {\n            case .initial(var initial):\n                var buffer = Deque<Element>()\n                buffer.append(contentsOf: sequence)\n\n                let shouldProduceMore = initial.backPressureStrategy.didYield(\n                    bufferDepth: buffer.count\n                )\n                let callbackToken = shouldProduceMore ? nil : self.nextCallbackToken()\n\n                self._state = .streaming(\n                    .init(\n                        backPressureStrategy: initial.backPressureStrategy,\n                        iteratorInitialized: initial.iteratorInitialized,\n                        onTermination: initial.onTermination,\n                        buffer: buffer,\n                        consumerContinuation: nil,\n                        producerContinuations: .init(),\n                        cancelledAsyncProducers: .init(),\n                        hasOutstandingDemand: shouldProduceMore\n                    )\n                )\n\n                return .init(callbackToken: callbackToken)\n\n            case .streaming(var streaming):\n                self._state = .modify\n\n                streaming.buffer.append(contentsOf: sequence)\n\n                // We have an element and can resume the continuation\n                let shouldProduceMore = streaming.backPressureStrategy.didYield(\n                    bufferDepth: streaming.buffer.count\n                )\n                streaming.hasOutstandingDemand = shouldProduceMore\n                let callbackToken = shouldProduceMore ? nil : self.nextCallbackToken()\n\n                if let consumerContinuation = streaming.consumerContinuation {\n                    guard let element = streaming.buffer.popFirst() else {\n                        // We got a yield of an empty sequence. We just tolerate this.\n                        self._state = .streaming(streaming)\n\n                        return .init(callbackToken: callbackToken)\n                    }\n\n                    // We got a consumer continuation and an element. We can resume the consumer now\n                    streaming.consumerContinuation = nil\n                    self._state = .streaming(streaming)\n                    return .init(\n                        callbackToken: callbackToken,\n                        continuationAndElement: (consumerContinuation, element)\n                    )\n                } else {\n                    // We don't have a suspended consumer so we just buffer the elements\n                    self._state = .streaming(streaming)\n                    return .init(\n                        callbackToken: callbackToken\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                // If the source has finished we are dropping the elements.\n                return .throwFinishedError\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `enqueueProducer()`.\n        enum EnqueueProducerAction {\n            /// Indicates that the producer should be notified to produce more.\n            case resumeProducer((Result<Void, Error>) -> Void)\n            /// Indicates that the producer should be notified about an error.\n            case resumeProducerWithError((Result<Void, Error>) -> Void, Error)\n        }\n\n        mutating func enqueueProducer(\n            callbackToken: Source.WriteResult.CallbackToken,\n            onProduceMore: @Sendable @escaping (Result<Void, Error>) -> Void\n        ) -> EnqueueProducerAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                // This is enforced because the CallbackToken has no internal init so\n                // one must create it by calling `write` first.\n                fatalError(\"AsyncStream internal inconsistency\")\n\n            case .streaming(var streaming):\n                if let index = streaming.cancelledAsyncProducers.firstIndex(of: callbackToken.id) {\n                    // Our producer got marked as cancelled.\n                    self._state = .modify\n                    streaming.cancelledAsyncProducers.remove(at: index)\n                    self._state = .streaming(streaming)\n\n                    return .resumeProducerWithError(onProduceMore, CancellationError())\n                } else if streaming.hasOutstandingDemand {\n                    // We hit an edge case here where we wrote but the consuming thread got interleaved\n                    return .resumeProducer(onProduceMore)\n                } else {\n                    self._state = .modify\n                    streaming.producerContinuations.append((callbackToken.id, onProduceMore))\n\n                    self._state = .streaming(streaming)\n                    return .none\n                }\n\n            case .sourceFinished, .finished:\n                // Since we are unlocking between yielding and suspending the yield\n                // It can happen that the source got finished or the consumption fully finishes.\n                return .resumeProducerWithError(onProduceMore, AlreadyFinishedError())\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `cancelProducer()`.\n        enum CancelProducerAction {\n            /// Indicates that the producer should be notified about cancellation.\n            case resumeProducerWithCancellationError((Result<Void, Error>) -> Void)\n        }\n\n        mutating func cancelProducer(\n            callbackToken: Source.WriteResult.CallbackToken\n        ) -> CancelProducerAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                fatalError(\"AsyncStream internal inconsistency\")\n\n            case .streaming(var streaming):\n                if let index = streaming.producerContinuations.firstIndex(where: {\n                    $0.0 == callbackToken.id\n                }) {\n                    // We have an enqueued producer that we need to resume now\n                    self._state = .modify\n                    let continuation = streaming.producerContinuations.remove(at: index).1\n                    self._state = .streaming(streaming)\n\n                    return .resumeProducerWithCancellationError(continuation)\n                } else {\n                    // The task that yields was cancelled before yielding so the cancellation handler\n                    // got invoked right away\n                    self._state = .modify\n                    streaming.cancelledAsyncProducers.append(callbackToken.id)\n                    self._state = .streaming(streaming)\n\n                    return .none\n                }\n\n            case .sourceFinished, .finished:\n                // Since we are unlocking between yielding and suspending the yield\n                // It can happen that the source got finished or the consumption fully finishes.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `finish()`.\n        enum FinishAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((() -> Void)?)\n            /// Indicates that the consumer  should be resumed with the failure, the producers\n            /// should be resumed with an error and `onTermination` should be called.\n            case resumeConsumerAndCallOnTermination(\n                consumerContinuation: CheckedContinuation<Element?, Error>,\n                failure: Error?,\n                onTermination: (() -> Void)?\n            )\n            /// Indicates that the producers should be resumed with an error.\n            case resumeProducers(\n                producerContinuations: [(Result<Void, Error>) -> Void]\n            )\n        }\n\n        @inlinable\n        mutating func finish(_ failure: Error?) -> FinishAction? {\n            switch self._state {\n            case .initial(let initial):\n                // Nothing was yielded nor did anybody call next\n                // This means we can transition to sourceFinished and store the failure\n                self._state = .sourceFinished(\n                    .init(\n                        iteratorInitialized: initial.iteratorInitialized,\n                        buffer: .init(),\n                        failure: failure,\n                        onTermination: initial.onTermination\n                    )\n                )\n\n                return .callOnTermination(initial.onTermination)\n\n            case .streaming(let streaming):\n                if let consumerContinuation = streaming.consumerContinuation {\n                    // We have a continuation, this means our buffer must be empty\n                    // Furthermore, we can now transition to finished\n                    // and resume the continuation with the failure\n                    precondition(streaming.buffer.isEmpty, \"Expected an empty buffer\")\n                    precondition(\n                        streaming.producerContinuations.isEmpty,\n                        \"Expected no suspended producers\"\n                    )\n\n                    self._state = .finished(iteratorInitialized: streaming.iteratorInitialized)\n\n                    return .resumeConsumerAndCallOnTermination(\n                        consumerContinuation: consumerContinuation,\n                        failure: failure,\n                        onTermination: streaming.onTermination\n                    )\n                } else {\n                    self._state = .sourceFinished(\n                        .init(\n                            iteratorInitialized: streaming.iteratorInitialized,\n                            buffer: streaming.buffer,\n                            failure: failure,\n                            onTermination: streaming.onTermination\n                        )\n                    )\n\n                    return .resumeProducers(\n                        producerContinuations: Array(streaming.producerContinuations.map { $0.1 })\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                // If the source has finished, finishing again has no effect.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `next()`.\n        enum NextAction {\n            /// Indicates that the element should be returned to the caller.\n            case returnElement(Element)\n            /// Indicates that the element should be returned to the caller and that all producers should be called.\n            case returnElementAndResumeProducers(Element, [(Result<Void, Error>) -> Void])\n            /// Indicates that the `Error` should be returned to the caller and that `onTermination` should be called.\n            case returnErrorAndCallOnTermination(Error?, (() -> Void)?)\n            /// Indicates that the `nil` should be returned to the caller.\n            case returnNil\n            /// Indicates that the `Task` of the caller should be suspended.\n            case suspendTask\n        }\n\n        mutating func next() -> NextAction {\n            switch self._state {\n            case .initial(let initial):\n                // We are not interacting with the back-pressure strategy here because\n                // we are doing this inside `next(:)`\n                self._state = .streaming(\n                    .init(\n                        backPressureStrategy: initial.backPressureStrategy,\n                        iteratorInitialized: initial.iteratorInitialized,\n                        onTermination: initial.onTermination,\n                        buffer: Deque<Element>(),\n                        consumerContinuation: nil,\n                        producerContinuations: .init(),\n                        cancelledAsyncProducers: .init(),\n                        hasOutstandingDemand: false\n                    )\n                )\n\n                return .suspendTask\n            case .streaming(var streaming):\n                guard streaming.consumerContinuation == nil else {\n                    // We have multiple AsyncIterators iterating the sequence\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n                self._state = .modify\n\n                if let element = streaming.buffer.popFirst() {\n                    // We have an element to fulfil the demand right away.\n                    let shouldProduceMore = streaming.backPressureStrategy.didConsume(\n                        bufferDepth: streaming.buffer.count\n                    )\n                    streaming.hasOutstandingDemand = shouldProduceMore\n\n                    if shouldProduceMore {\n                        // There is demand and we have to resume our producers\n                        let producers = Array(streaming.producerContinuations.map { $0.1 })\n                        streaming.producerContinuations.removeAll()\n                        self._state = .streaming(streaming)\n                        return .returnElementAndResumeProducers(element, producers)\n                    } else {\n                        // We don't have any new demand, so we can just return the element.\n                        self._state = .streaming(streaming)\n                        return .returnElement(element)\n                    }\n                } else {\n                    // There is nothing in the buffer to fulfil the demand so we need to suspend.\n                    // We are not interacting with the back-pressure strategy here because\n                    // we are doing this inside `suspendNext`\n                    self._state = .streaming(streaming)\n\n                    return .suspendTask\n                }\n\n            case .sourceFinished(var sourceFinished):\n                // Check if we have an element left in the buffer and return it\n                self._state = .modify\n\n                if let element = sourceFinished.buffer.popFirst() {\n                    self._state = .sourceFinished(sourceFinished)\n\n                    return .returnElement(element)\n                } else {\n                    // We are returning the queued failure now and can transition to finished\n                    self._state = .finished(iteratorInitialized: sourceFinished.iteratorInitialized)\n\n                    return .returnErrorAndCallOnTermination(\n                        sourceFinished.failure,\n                        sourceFinished.onTermination\n                    )\n                }\n\n            case .finished:\n                return .returnNil\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `suspendNext()`.\n        enum SuspendNextAction {\n            /// Indicates that the consumer should be resumed.\n            case resumeConsumerWithElement(CheckedContinuation<Element?, Error>, Element)\n            /// Indicates that the consumer and all producers should be resumed.\n            case resumeConsumerWithElementAndProducers(\n                CheckedContinuation<Element?, Error>,\n                Element,\n                [(Result<Void, Error>) -> Void]\n            )\n            /// Indicates that the consumer should be resumed with the failure and that `onTermination` should be called.\n            case resumeConsumerWithErrorAndCallOnTermination(\n                CheckedContinuation<Element?, Error>,\n                Error?,\n                (() -> Void)?\n            )\n            /// Indicates that the consumer should be resumed with `nil`.\n            case resumeConsumerWithNil(CheckedContinuation<Element?, Error>)\n        }\n\n        mutating func suspendNext(\n            continuation: CheckedContinuation<Element?, Error>\n        ) -> SuspendNextAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                preconditionFailure(\"AsyncStream internal inconsistency\")\n\n            case .streaming(var streaming):\n                guard streaming.consumerContinuation == nil else {\n                    // We have multiple AsyncIterators iterating the sequence\n                    fatalError(\n                        \"This should never happen since we only allow a single Iterator to be created\"\n                    )\n                }\n\n                self._state = .modify\n\n                // We have to check here again since we might have a producer interleave next and suspendNext\n                if let element = streaming.buffer.popFirst() {\n                    // We have an element to fulfil the demand right away.\n\n                    let shouldProduceMore = streaming.backPressureStrategy.didConsume(\n                        bufferDepth: streaming.buffer.count\n                    )\n                    streaming.hasOutstandingDemand = shouldProduceMore\n\n                    if shouldProduceMore {\n                        // There is demand and we have to resume our producers\n                        let producers = Array(streaming.producerContinuations.map { $0.1 })\n                        streaming.producerContinuations.removeAll()\n                        self._state = .streaming(streaming)\n                        return .resumeConsumerWithElementAndProducers(\n                            continuation,\n                            element,\n                            producers\n                        )\n                    } else {\n                        // We don't have any new demand, so we can just return the element.\n                        self._state = .streaming(streaming)\n                        return .resumeConsumerWithElement(continuation, element)\n                    }\n                } else {\n                    // There is nothing in the buffer to fulfil the demand so we to store the continuation.\n                    streaming.consumerContinuation = continuation\n                    self._state = .streaming(streaming)\n\n                    return .none\n                }\n\n            case .sourceFinished(var sourceFinished):\n                // Check if we have an element left in the buffer and return it\n                self._state = .modify\n\n                if let element = sourceFinished.buffer.popFirst() {\n                    self._state = .sourceFinished(sourceFinished)\n\n                    return .resumeConsumerWithElement(continuation, element)\n                } else {\n                    // We are returning the queued failure now and can transition to finished\n                    self._state = .finished(iteratorInitialized: sourceFinished.iteratorInitialized)\n\n                    return .resumeConsumerWithErrorAndCallOnTermination(\n                        continuation,\n                        sourceFinished.failure,\n                        sourceFinished.onTermination\n                    )\n                }\n\n            case .finished:\n                return .resumeConsumerWithNil(continuation)\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `cancelNext()`.\n        enum CancelNextAction {\n            /// Indicates that the continuation should be resumed with a cancellation error, the producers should be finished and call onTermination.\n            case resumeConsumerWithCancellationErrorAndCallOnTermination(\n                CheckedContinuation<Element?, Error>,\n                (() -> Void)?\n            )\n            /// Indicates that the producers should be finished and call onTermination.\n            case failProducersAndCallOnTermination([(Result<Void, Error>) -> Void], (() -> Void)?)\n        }\n\n        mutating func cancelNext() -> CancelNextAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                fatalError(\"AsyncStream internal inconsistency\")\n\n            case .streaming(let streaming):\n                self._state = .finished(iteratorInitialized: streaming.iteratorInitialized)\n\n                if let consumerContinuation = streaming.consumerContinuation {\n                    precondition(\n                        streaming.producerContinuations.isEmpty,\n                        \"Internal inconsistency. Unexpected producer continuations.\"\n                    )\n                    return .resumeConsumerWithCancellationErrorAndCallOnTermination(\n                        consumerContinuation,\n                        streaming.onTermination\n                    )\n                } else {\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/Cancellation.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Executes the closure and masks cancellation.\n@_spi(Testing)\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic func withoutCancellation<R: Sendable>(\n    _ execute: @escaping () async throws -> R\n) async throws -> R {\n    // Okay as we immediately wait for the result of the task.\n    let unsafeExecute = UnsafeTransfer(execute)\n    let t = Task {\n        try await unsafeExecute.wrappedValue()\n    }\n    return try await t.value\n}\n\n/// Executes `fn` and then `tearDown`, which cannot be cancelled.\n@_spi(Testing)\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic func withUncancellableTearDown<R>(\n    _ fn: () async throws -> R,\n    tearDown: @escaping (Result<Void, Error>) async throws -> Void\n) async throws -> R {\n    let result: Result<R, Error>\n    do {\n        result = .success(try await fn())\n    } catch {\n        result = .failure(error)\n    }\n\n    let errorOnlyResult: Result<Void, Error> = result.map { _ in () }\n    let tearDownResult: Result<Void, Error> = try await withoutCancellation {\n        do {\n            return .success(try await tearDown(errorOnlyResult))\n        } catch {\n            return .failure(error)\n        }\n    }\n\n    try tearDownResult.get()\n    return try result.get()\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/Concurrency Primitives/TokenBucket.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the Swift open source project\n//\n// Copyright (c) 2023 Apple Inc. and the Swift project authors\n// Licensed under Apache License v2.0 with Runtime Library Exception\n//\n// See http://swift.org/LICENSE.txt for license information\n// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\n\n/// Type modeled after a \"token bucket\" pattern, which is similar to a semaphore, but is built with\n/// Swift Concurrency primitives.\n///\n/// This is an adaptation of the TokenBucket found in Swift Package Manager.\n/// Instead of using an ``actor``, we define a class and limit access through\n/// ``NIOLock``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class TokenBucket: @unchecked Sendable {\n    private struct State {\n        var tokens: Int\n        var waiters: Deque<CheckedContinuation<Void, Never>>\n\n        enum TakeTokenResult {\n            /// A token is available to use.\n            case tookToken\n            /// No token is available, call back with a continuation.\n            case tryAgainWithContinuation\n            /// No token is available, the continuation will be resumed with one later.\n            case storedContinuation\n        }\n\n        mutating func takeToken(continuation: CheckedContinuation<Void, Never>?) -> TakeTokenResult {\n            if self.tokens > 0 {\n                self.tokens &-= 1\n                return .tookToken\n            } else if let continuation = continuation {\n                self.waiters.append(continuation)\n                return .storedContinuation\n            } else {\n                return .tryAgainWithContinuation\n            }\n        }\n\n        mutating func returnToken() -> CheckedContinuation<Void, Never>? {\n            if let next = self.waiters.popFirst() {\n                return next\n            } else {\n                self.tokens &+= 1\n                return nil\n            }\n        }\n    }\n\n    private let lock: NIOLockedValueBox<State>\n\n    init(tokens: Int) {\n        precondition(tokens >= 1, \"Need at least one token!\")\n        self.lock = NIOLockedValueBox(State(tokens: tokens, waiters: []))\n    }\n\n    /// Executes an `async` closure immediately when a token is available.\n    /// Only the same number of closures will be executed concurrently as the number\n    /// of `tokens` passed to ``TokenBucket/init(tokens:)``, all subsequent\n    /// invocations of `withToken` will suspend until a \"free\" token is available.\n    /// - Parameter body: The closure to invoke when a token is available.\n    /// - Returns: Resulting value returned by `body`.\n    func withToken<ReturnType>(\n        _ body: @Sendable () async throws -> ReturnType\n    ) async rethrows -> ReturnType {\n        await self.getToken()\n        defer { self.returnToken() }\n        return try await body()\n    }\n\n    private func getToken() async {\n        switch self.lock.withLockedValue({ $0.takeToken(continuation: nil) }) {\n        case .tookToken:\n            ()\n\n        case .tryAgainWithContinuation:\n            // Holding the lock here *should* be safe but because of a bug in the runtime\n            // it isn't, so drop the lock, create the continuation and try again.\n            //\n            // See also: https://github.com/swiftlang/swift/issues/85668\n            await withCheckedContinuation { continuation in\n                switch self.lock.withLockedValue({ $0.takeToken(continuation: continuation) }) {\n                case .tookToken:\n                    continuation.resume()\n                case .storedContinuation:\n                    ()\n                case .tryAgainWithContinuation:\n                    // Only possible when 'takeToken(continuation:)' is called with no continuation.\n                    fatalError()\n                }\n            }\n\n        case .storedContinuation:\n            // Only possible when 'takeToken(continuation:)' is called with a continuation.\n            fatalError()\n        }\n    }\n\n    private func returnToken() {\n        let continuation = self.lock.withLockedValue { $0.returnToken() }\n        continuation?.resume()\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/ParallelDirCopy.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    /// Iterative implementation of a recursive parallel copy of the directory from `sourcePath` to\n    /// `destinationPath`.\n    ///\n    /// The parallelism is solely at the level of individual items (files, symbolic links and\n    /// directories). A larger file is not 'split' into concurrent reads or writes.\n    ///\n    /// If a symbolic link is encountered, then only the link is copied. If supported by the file\n    /// system, the copied items will preserve permissions and any extended attributes.\n    ///\n    /// Note: `maxConcurrentOperations` is used as a hard (conservative) limit on the number of open\n    /// file descriptors at any point. Operations are assumed to consume 2 descriptors, so the\n    /// maximum open descriptors are `maxConcurrentOperations * 2`\n    @usableFromInline\n    func copyDirectoryParallel(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        maxConcurrentOperations: Int,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        // Implemented with NIOAsyncSequenceProducer rather than AsyncStream. It is approximately\n        // the same speed in the best case, but has significantly less variance.\n        // NIOAsyncSequenceProducer also enforces a multi-producer, single-consumer access pattern.\n        let copyRequiredQueue = NIOAsyncSequenceProducer.makeSequence(\n            elementType: DirCopyItem.self,\n            backPressureStrategy: NoBackPressureStrategy(),\n            finishOnDeinit: false,\n            delegate: DirCopyDelegate()\n        )\n\n        // We ignore the result of yield in all cases, because we are not implementing back\n        // pressure, and cancellation is dealt with separately.\n        @Sendable func yield(_ contentsOf: [DirCopyItem]) {\n            _ = copyRequiredQueue.source.yield(contentsOf: contentsOf)\n        }\n\n        // Kick-start the procees by enqueuing the root entry. The calling function already\n        // validated the root needed copying, so it is safe to force unwrap the value.\n        _ = copyRequiredQueue.source.yield(\n            .toCopy(from: .init(path: NIOFilePath(sourcePath), type: .directory)!, to: destinationPath)\n        )\n\n        // The processing of the very first item (the root) will increment this counter. Processing\n        // will finish when the counter hits zero again.\n        //\n        // This does not need to be a ManagedAtomic or similar because:\n        // - All state maintenance is done within the withThrowingTaskGroup closure\n        // - All actual file system work is done by tasks created on the `taskGroup`\n        var activeDirCount = 0\n\n        // Despite there being no 'result' for each operation, we cannot use a discarding task group,\n        // because we use the 'drain results' queue as a concurrency limiting side effect.\n        try await withThrowingTaskGroup(of: Void.self) { taskGroup in\n            // Process each item in the current task.\n            //\n            // Side Effects:\n            // - Updates activeDirCount and finishes the stream if required.\n            // - Might add a task to `taskGroup`.\n            //\n            // Returns true if it added a task, false otherwise.\n            func onNextItem(_ item: DirCopyItem) -> Bool {\n                switch item {\n                case .endOfDir:\n                    activeDirCount -= 1\n                    if activeDirCount == 0 {\n                        copyRequiredQueue.source.finish()\n                    }\n                    return false\n                case let .toCopy(from: from, to: to):\n                    if from.type == .directory {\n                        activeDirCount += 1\n                    }\n                    taskGroup.addTask {\n                        try await copySelfAndEnqueueChildren(\n                            from: from,\n                            to: to,\n                            yield: yield,\n                            shouldProceedAfterError: shouldProceedAfterError,\n                            shouldCopyItem: shouldCopyItem\n                        )\n                    }\n                    return true\n                }\n            }\n\n            let iter = copyRequiredQueue.sequence.makeAsyncIterator()\n\n            // inProgress counts the number of tasks we have added to the task group.\n            // Get up to the maximum concurrency first.\n            // We haven't started monitoring for task completion, so inProgress is 'worst case'.\n            var inProgress = 0\n            while inProgress <= maxConcurrentOperations {\n                let item = await iter.next()\n                if let item = item {\n                    if onNextItem(item) {\n                        inProgress += 1\n                    }\n                } else {\n                    // Either we completed things before we hit the limit or we were cancelled. In\n                    // the latter case we choose to propagate the cancellation clearly. This makes\n                    // testing for it more reliable.\n                    try Task.checkCancellation()\n\n                    // If any child tasks failed throw up an error.\n                    try await taskGroup.waitForAll()\n\n                    return\n                }\n            }\n\n            // One in (finish) -> one out (start another), but only for items that trigger a task.\n            while let _ = try await taskGroup.next() {\n                var keepConsuming = true\n                while keepConsuming {\n                    let item = await iter.next()\n                    if let item = item {\n                        keepConsuming = !onNextItem(item)\n                    } else {\n                        // We must check here, to accurately propagate the cancellation.\n                        try Task.checkCancellation()\n                        keepConsuming = false\n                    }\n                }\n            }\n        }\n    }\n}\n\n/// An 'always ask for more' no back-pressure strategy for a ``NIOAsyncSequenceProducer``.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate struct NoBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategy {\n    mutating func didYield(bufferDepth: Int) -> Bool { true }\n\n    mutating func didConsume(bufferDepth: Int) -> Bool { true }\n}\n\n/// We ignore back pressure, the inherent handle limiting in copyDirectoryParallel means it is unnecessary.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate struct DirCopyDelegate: NIOAsyncSequenceProducerDelegate, Sendable {\n    @inlinable\n    func produceMore() {}\n\n    @inlinable\n    func didTerminate() {}\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/ParallelRemoval.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    /// Recursively walk all objects found in `path`. Call ourselves recursively\n    /// on each directory that we find, as soon as the file descriptor for\n    /// `path` has been closed; also delete all files that we come across.\n    func discoverAndRemoveItemsInTree(\n        at path: FilePath,\n        _ bucket: TokenBucket\n    ) async throws -> Int {\n        // Discover current directory and find all files/directories. Free up\n        // the handle as fast as possible.\n        let (directoriesToRecurseInto, itemsToDelete) = try await bucket.withToken {\n            try await self.withDirectoryHandle(atPath: NIOFilePath(path)) { directory in\n                var subdirectories: [FilePath] = []\n                var itemsInDirectory: [FilePath] = []\n\n                for try await batch in directory.listContents().batched() {\n                    for entry in batch {\n                        switch entry.type {\n                        case .directory:\n                            subdirectories.append(entry.path.underlying)\n                        default:\n                            itemsInDirectory.append(entry.path.underlying)\n                        }\n                    }\n                }\n\n                return (subdirectories, itemsInDirectory)\n            }\n        }\n\n        return try await withThrowingTaskGroup(of: Int.self) { group in\n            // Delete all items we found in the current directory.\n            for item in itemsToDelete {\n                group.addTask {\n                    try await self.removeOneItem(at: item)\n                }\n            }\n\n            // Recurse into all newly found subdirectories.\n            for directory in directoriesToRecurseInto {\n                group.addTask {\n                    try await self.discoverAndRemoveItemsInTree(at: directory, bucket)\n                }\n            }\n\n            // Await task groups to finish and sum all items deleted so far.\n            var numberOfDeletedItems = try await group.reduce(0, +)\n\n            // Remove top level directory.\n            numberOfDeletedItems += try await self.removeOneItem(at: path)\n\n            return numberOfDeletedItems\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/String+UnsafeUnititializedCapacity.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension String {\n    @inlinable\n    init(\n        backportUnsafeUninitializedCapacity capacity: Int,\n        initializingUTF8With initializer: (_ buffer: UnsafeMutableBufferPointer<UInt8>) throws -> Int\n    ) rethrows {\n        // The buffer will store zero terminated C string\n        let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: capacity + 1)\n        defer {\n            buffer.deallocate()\n        }\n\n        let initializedCount = try initializer(buffer)\n        precondition(initializedCount <= capacity, \"Overran buffer in initializer!\")\n\n        // add zero termination\n        buffer[initializedCount] = 0\n\n        self = String(cString: buffer.baseAddress!)\n    }\n}\n\n// Frustratingly, Swift 5.3 shipped before the macOS 11 SDK did, so we cannot gate the availability of\n// this declaration on having the 5.3 compiler. This has caused a number of build issues. While updating\n// to newer Xcodes does work, we can save ourselves some hassle and just wait until 5.4 to get this\n// enhancement on Apple platforms.\nextension String {\n    @inlinable\n    init(\n        customUnsafeUninitializedCapacity capacity: Int,\n        initializingUTF8With initializer: (\n            _ buffer: UnsafeMutableBufferPointer<UInt8>\n        ) throws -> Int\n    ) rethrows {\n        if #available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) {\n            try self.init(\n                unsafeUninitializedCapacity: capacity,\n                initializingUTF8With: initializer\n            )\n        } else {\n            try self.init(\n                backportUnsafeUninitializedCapacity: capacity,\n                initializingUTF8With: initializer\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/System Calls/CInterop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\nimport CNIODarwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n/// Aliases for platform-dependent types used for system calls.\nextension CInterop {\n    #if canImport(Darwin)\n    public typealias Stat = Darwin.stat\n    #elseif canImport(Glibc)\n    public typealias Stat = Glibc.stat\n    #elseif canImport(Musl)\n    public typealias Stat = Musl.stat\n    #elseif canImport(Android)\n    public typealias Stat = Android.stat\n    #endif\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static let maxPathLength = Darwin.PATH_MAX\n    #elseif canImport(Glibc)\n    @_spi(Testing)\n    public static let maxPathLength = Glibc.PATH_MAX\n    #elseif canImport(Musl)\n    @_spi(Testing)\n    public static let maxPathLength = Musl.PATH_MAX\n    #elseif canImport(Android)\n    @_spi(Testing)\n    public static let maxPathLength = Android.PATH_MAX\n    #endif\n\n    #if canImport(Darwin)\n    typealias DirPointer = UnsafeMutablePointer<Darwin.DIR>\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    typealias DirPointer = OpaquePointer\n    #endif\n\n    #if canImport(Darwin)\n    typealias DirEnt = Darwin.dirent\n    #elseif canImport(Glibc)\n    typealias DirEnt = Glibc.dirent\n    #elseif canImport(Musl)\n    typealias DirEnt = Musl.dirent\n    #elseif canImport(Android)\n    typealias DirEnt = Android.dirent\n    #endif\n\n    #if canImport(Darwin)\n    typealias FTS = CNIODarwin.FTS\n    typealias FTSEnt = CNIODarwin.FTSENT\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    typealias FTS = CNIOLinux.FTS\n    typealias FTSEnt = CNIOLinux.FTSENT\n    #endif\n\n    typealias FTSPointer = UnsafeMutablePointer<FTS>\n    typealias FTSEntPointer = UnsafeMutablePointer<CInterop.FTSEnt>\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/System Calls/Errno.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\n\nextension Errno {\n    @_spi(Testing)\n    public static var _current: Errno {\n        get {\n            #if canImport(Darwin)\n            return Errno(rawValue: Darwin.errno)\n            #elseif canImport(Glibc)\n            return Errno(rawValue: Glibc.errno)\n            #elseif canImport(Musl)\n            return Errno(rawValue: Musl.errno)\n            #elseif canImport(Android)\n            return Errno(rawValue: Android.errno)\n            #endif\n        }\n        set {\n            #if canImport(Darwin)\n            Darwin.errno = newValue.rawValue\n            #elseif canImport(Glibc)\n            Glibc.errno = newValue.rawValue\n            #elseif canImport(Musl)\n            Musl.errno = newValue.rawValue\n            #elseif canImport(Android)\n            Android.errno = newValue.rawValue\n            #endif\n        }\n    }\n\n    fileprivate static func clear() {\n        #if canImport(Darwin)\n        Darwin.errno = 0\n        #elseif canImport(Glibc)\n        Glibc.errno = 0\n        #elseif canImport(Musl)\n        Musl.errno = 0\n        #elseif canImport(Android)\n        Android.errno = 0\n        #endif\n    }\n}\n\n/// Returns a `Result` representing the value returned from the given closure\n/// or an `Errno` if that value was -1.\n///\n/// If desired this function can call the closure in a loop until it does not\n/// result in `Errno` being `.interrupted`.\n@_spi(Testing)\npublic func valueOrErrno<I: FixedWidthInteger>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> I\n) -> Result<I, Errno> {\n    while true {\n        Errno.clear()\n        let result = fn()\n        if result == -1 {\n            let errno = Errno._current\n            if errno == .interrupted, retryOnInterrupt {\n                continue\n            } else {\n                return .failure(errno)\n            }\n        } else {\n            return .success(result)\n        }\n    }\n}\n\n/// As `valueOrErrno` but discards the success value.\n@_spi(Testing)\npublic func nothingOrErrno<I: FixedWidthInteger>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> I\n) -> Result<Void, Errno> {\n    valueOrErrno(retryOnInterrupt: retryOnInterrupt, fn).map { _ in }\n}\n\n/// Returns a `Result` representing the value returned from the given closure\n/// or an `Errno` if that value was `nil`.\n///\n/// If desired this function can call the closure in a loop until it does not\n/// result in `Errno` being `.interrupted`. `Errno` is only checked if the\n/// closure returns `nil`.\n@_spi(Testing)\npublic func optionalValueOrErrno<R>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> R?\n) -> Result<R?, Errno> {\n    while true {\n        Errno.clear()\n        if let result = fn() {\n            return .success(result)\n        } else {\n            let errno = Errno._current\n            if errno == .interrupted, retryOnInterrupt {\n                continue\n            } else if errno.rawValue == 0 {\n                return .success(nil)\n            } else {\n                return .failure(errno)\n            }\n        }\n    }\n}\n\n/// As `valueOrErrno` but unconditionally checks the current `Errno`.\n@_spi(Testing)\npublic func valueOrErrno<R>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> R\n) -> Result<R, Errno> {\n    while true {\n        Errno.clear()\n        let value = fn()\n        let errno = Errno._current\n        if errno.rawValue == 0 {\n            return .success(value)\n        } else if errno == .interrupted, retryOnInterrupt {\n            continue\n        } else {\n            return .failure(errno)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/System Calls/FileDescriptor+Syscalls.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\nimport CNIOLinux\n#endif\n\nextension FileDescriptor {\n    /// Opens or creates a file for reading or writing.\n    ///\n    /// The corresponding C function is `fdopenat`.\n    ///\n    /// - Parameters:\n    ///   - path: The location of the file to open. If the path is relative then the file is opened\n    ///       relative to the descriptor.\n    ///   - mode: The read and write access to use.\n    ///   - options: The behavior for opening the file.\n    ///   - permissions: The file permissions to use for created files.\n    ///   - retryOnInterrupt: Whether to retry the operation if it throws `Errno.interrupted`. The\n    ///       default is true. Pass false to try only once and throw an error upon interruption.\n    /// - Returns: A file descriptor for the open file.\n    @_spi(Testing)\n    public func `open`(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        retryOnInterrupt: Bool = true\n    ) -> Result<FileDescriptor, Errno> {\n        let oFlag = mode.rawValue | options.rawValue\n        let rawValue = valueOrErrno(retryOnInterrupt: retryOnInterrupt) {\n            path.withPlatformString {\n                if let permissions = permissions {\n                    return system_fdopenat(self.rawValue, $0, oFlag, permissions.rawValue)\n                } else {\n                    precondition(!options.contains(.create), \"Create must be given permissions\")\n                    return system_fdopenat(self.rawValue, $0, oFlag)\n                }\n            }\n        }\n\n        return rawValue.map { FileDescriptor(rawValue: $0) }\n    }\n\n    /// Returns information about the status of the open file.\n    ///\n    /// The corresponding C function is `fstat`.\n    ///\n    /// - Returns: Information about the open file.\n    @_spi(Testing)\n    public func status() -> Result<CInterop.Stat, Errno> {\n        var status = CInterop.Stat()\n        return nothingOrErrno(retryOnInterrupt: false) {\n            system_fstat(self.rawValue, &status)\n        }.map { status }\n    }\n\n    /// Sets the permission bits of the open file.\n    ///\n    /// The corresponding C function is `fchmod`.\n    ///\n    /// - Parameters:\n    ///   - mode: The permissions to set on the file.\n    ///   - retryOnInterrupt: Whether to retry the operation if it throws `Errno.interrupted`. The\n    ///       default is true. Pass false to try only once and throw an error upon interruption.\n    @_spi(Testing)\n    public func changeMode(\n        _ mode: FilePermissions,\n        retryOnInterrupt: Bool = true\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: retryOnInterrupt) {\n            system_fchmod(self.rawValue, mode.rawValue)\n        }\n    }\n\n    /// List the names of extended attributes.\n    ///\n    /// The corresponding C function is `flistxattr`.\n    ///\n    /// - Parameter buffer: The buffer into which names are written. Names are written are NULL\n    ///     terminated UTF-8 strings and are returned in an arbitrary order. There is no padding\n    ///     between strings. If `buffer` is `nil` then the return value is the size of the buffer\n    ///     required to list all extended attributes. If there is not enough space in the `buffer`\n    ///     then `Errno.outOfRange` is returned.\n    /// - Returns: The size of the extended attribute list.\n    @_spi(Testing)\n    public func listExtendedAttributes(\n        _ buffer: UnsafeMutableBufferPointer<CChar>?\n    ) -> Result<Int, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            system_flistxattr(self.rawValue, buffer?.baseAddress, buffer?.count ?? 0)\n        }\n    }\n\n    /// Get the value of the named extended attribute.\n    ///\n    /// The corresponding C function is `fgetxattr`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the extended attribute.\n    ///   - buffer: The buffer into which the value is written. If `buffer` is `nil` then the return\n    ///       value is the size of the buffer required to read the value. If there is not enough\n    ///       space in the `buffer` then `Errno.outOfRange` is returned.\n    /// - Returns: The size of the extended attribute value.\n    @_spi(Testing)\n    public func getExtendedAttribute(\n        named name: String,\n        buffer: UnsafeMutableRawBufferPointer?\n    ) -> Result<Int, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            name.withPlatformString {\n                system_fgetxattr(self.rawValue, $0, buffer?.baseAddress, buffer?.count ?? 0)\n            }\n        }\n    }\n\n    /// Set the value of the named extended attribute.\n    ///\n    /// The corresponding C function is `fsetxattr`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the extended attribute.\n    ///   - value: The data to set for the attribute.\n    @_spi(Testing)\n    public func setExtendedAttribute(\n        named name: String,\n        to value: UnsafeRawBufferPointer?\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            name.withPlatformString { namePointer in\n                system_fsetxattr(self.rawValue, namePointer, value?.baseAddress, value?.count ?? 0)\n            }\n        }\n    }\n\n    /// Remove the value for the named extended attribute.\n    ///\n    /// The corresponding C function is `fremovexattr`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the extended attribute.\n    @_spi(Testing)\n    public func removeExtendedAttribute(_ name: String) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            name.withPlatformString {\n                system_fremovexattr(self.rawValue, $0)\n            }\n        }\n    }\n\n    /// Synchronize modified data and metadata to a permanent storage device.\n    ///\n    /// The corresponding C functions is `fsync`.\n    ///\n    /// - Parameter retryOnInterrupt: Whether the call should be retried on `Errno.interrupted`.\n    @_spi(Testing)\n    public func synchronize(retryOnInterrupt: Bool = true) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: retryOnInterrupt) {\n            system_fsync(self.rawValue)\n        }\n    }\n\n    /// Returns a pointer to a directory structure.\n    ///\n    /// The corresponding C function is `fdopendir`\n    ///\n    /// - Important: Calling this function cedes ownership of the file descriptor to the system. The\n    ///     caller should not modify the descriptor or close the descriptor via `close()`. Once\n    ///     directory iteration has been completed then `Libc.closdir(_:)` must be called.\n    internal func opendir() -> Result<CInterop.DirPointer, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            libc_fdopendir(self.rawValue)\n        }\n    }\n}\n\nextension FileDescriptor {\n    func listExtendedAttributes() -> Result<[String], Errno> {\n        // Required capacity is returned if a no buffer is passed to flistxattr.\n        self.listExtendedAttributes(nil).flatMap { capacity in\n            guard capacity > 0 else {\n                // Required capacity is zero: no attributes to read.\n                return .success([])\n            }\n\n            // Read and decode.\n            var buffer = [UInt8](repeating: 0, count: capacity)\n            return buffer.withUnsafeMutableBufferPointer { pointer in\n                pointer.withMemoryRebound(to: CChar.self) { pointer in\n                    self.listExtendedAttributes(pointer)\n                }\n            }.map { size in\n                // The buffer contains null terminated C-strings.\n                var attributes = [String]()\n                var slice = buffer.prefix(size)\n                while let index = slice.firstIndex(of: 0) {\n                    // TODO: can we do this more cheaply?\n                    let prefix = slice[..<index]\n                    attributes.append(String(decoding: Array(prefix), as: Unicode.UTF8.self))\n                    slice = slice.dropFirst(prefix.count + 1)\n                }\n\n                return attributes\n            }\n        }\n    }\n\n    func readExtendedAttribute(named name: String) -> Result<[UInt8], Errno> {\n        // Required capacity is returned if a no buffer is passed to fgetxattr.\n        self.getExtendedAttribute(named: name, buffer: nil).flatMap { capacity in\n            guard capacity > 0 else {\n                // Required capacity is zero: no values to read.\n                return .success([])\n            }\n\n            // Read and decode.\n            var buffer = [UInt8](repeating: 0, count: capacity)\n            return buffer.withUnsafeMutableBytes { bytes in\n                self.getExtendedAttribute(named: name, buffer: bytes)\n            }.map { size in\n                // Remove any trailing zeros.\n                buffer.removeLast(buffer.count - size)\n                return buffer\n            }\n        }\n    }\n}\n\nextension FileDescriptor {\n    func readChunk(fromAbsoluteOffset offset: Int64, length: Int64) -> Result<ByteBuffer, Error> {\n        self._readChunk(fromAbsoluteOffset: offset, length: length)\n    }\n\n    func readChunk(length: Int64) -> Result<ByteBuffer, Error> {\n        self._readChunk(fromAbsoluteOffset: nil, length: length)\n    }\n\n    private func _readChunk(\n        fromAbsoluteOffset offset: Int64?,\n        length: Int64\n    ) -> Result<ByteBuffer, Error> {\n        // This is used by the `FileChunks` and means we allocate for every chunk that we read for\n        // the file. That's fine for now because the syscall cost is likely to be the dominant\n        // factor here. However we should investigate whether it's possible to have a pool of\n        // buffers which we can reuse. This would need to be at least as large as the high watermark\n        // of the chunked file for it to be useful.\n        Result {\n            var buffer = ByteBuffer()\n            try buffer.writeWithUnsafeMutableBytes(minimumWritableBytes: Int(length)) { buffer in\n                let bufferPointer: UnsafeMutableRawBufferPointer\n\n                // Don't vend a buffer which is larger than `length`; we can read less but we must\n                // not read more.\n                if length < buffer.count {\n                    bufferPointer = UnsafeMutableRawBufferPointer(\n                        start: buffer.baseAddress,\n                        count: Int(length)\n                    )\n                } else {\n                    bufferPointer = buffer\n                }\n\n                if let offset {\n                    return try self.read(fromAbsoluteOffset: offset, into: bufferPointer)\n                } else {\n                    return try self.read(into: bufferPointer)\n                }\n            }\n            return buffer\n        }\n    }\n}\n\nextension FileDescriptor {\n    func write(\n        contentsOf bytes: some Sequence<UInt8>,\n        toAbsoluteOffset offset: Int64\n    ) -> Result<Int64, Error> {\n        Result {\n            Int64(try self.writeAll(toAbsoluteOffset: offset, bytes))\n        }\n    }\n\n    func write(\n        contentsOf bytes: some Sequence<UInt8>\n    ) -> Result<Int64, Error> {\n        Result {\n            Int64(try self.writeAll(bytes))\n        }\n    }\n}\n\n#if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\nextension FileDescriptor.OpenOptions {\n    static var temporaryFile: Self {\n        Self(rawValue: CNIOLinux_O_TMPFILE)\n    }\n}\n\nextension FileDescriptor {\n    static var currentWorkingDirectory: Self {\n        Self(rawValue: AT_FDCWD)\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOFS/Internal/System Calls/Mocking.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// This source file is part of the Swift System open source project//\n// Copyright (c) 2020 Apple Inc. and the Swift System project authors\n// Licensed under Apache License v2.0 with Runtime Library Exception//\n// See https://swift.org/LICENSE.txt for license information\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n// Syscall mocking support.\n//\n// NOTE: This is currently the bare minimum needed for System's testing purposes, though we do\n// eventually want to expose some solution to users.\n//\n// Mocking is contextual, accessible through MockingDriver.withMockingEnabled. Mocking\n// state, including whether it is enabled, is stored in thread-local storage. Mocking is only\n// enabled in testing builds of System currently, to minimize runtime overhead of release builds.\n//\n\n#if ENABLE_MOCKING\n@_spi(Testing)\npublic struct Trace {\n    @_spi(Testing)\n    public struct Entry {\n        @_spi(Testing)\n        public var name: String\n        @_spi(Testing)\n        public var arguments: [AnyHashable]\n\n        @_spi(Testing)\n        public init(name: String, _ arguments: [AnyHashable]) {\n            self.name = name\n            self.arguments = arguments\n        }\n    }\n\n    private var entries: [Entry] = []\n    private var firstEntry: Int = 0\n\n    @_spi(Testing)\n    public var isEmpty: Bool { firstEntry >= entries.count }\n\n    @_spi(Testing)\n    public mutating func dequeue() -> Entry? {\n        guard !self.isEmpty else { return nil }\n        defer { firstEntry += 1 }\n        return entries[firstEntry]\n    }\n\n    fileprivate mutating func add(_ e: Entry) {\n        entries.append(e)\n    }\n}\n\n@available(*, unavailable)\nextension Trace: Sendable {}\n\n@available(*, unavailable)\nextension Trace.Entry: Sendable {}\n\n@_spi(Testing)\npublic enum ForceErrno: Equatable, Sendable {\n    case none\n    case always(errno: CInt)\n\n    case counted(errno: CInt, count: Int)\n}\n\n// Provide access to the driver, context, and trace stack of mocking\n@_spi(Testing)\npublic final class MockingDriver {\n    // Record syscalls and their arguments\n    @_spi(Testing)\n    public var trace = Trace()\n\n    // Mock errors inside syscalls\n    @_spi(Testing)\n    public var forceErrno = ForceErrno.none\n\n    // Whether we should pretend to be Windows for syntactic operations\n    // inside FilePath\n    fileprivate var forceWindowsSyntaxForPaths = false\n}\n\n@available(*, unavailable)\nextension MockingDriver: Sendable {}\n\nprivate let driverKey: _PlatformTLSKey = { makeTLSKey() }()\n\ninternal var currentMockingDriver: MockingDriver? {\n    #if !ENABLE_MOCKING\n    fatalError(\"Contextual mocking in non-mocking build\")\n    #endif\n    guard let rawPtr = getTLS(driverKey) else { return nil }\n\n    return Unmanaged<MockingDriver>.fromOpaque(rawPtr).takeUnretainedValue()\n}\n\nextension MockingDriver {\n    /// Enables mocking for the duration of `f` with a clean trace queue\n    /// Restores prior mocking status and trace queue after execution\n    @_spi(Testing)\n    public static func withMockingEnabled(\n        _ f: (MockingDriver) throws -> Void\n    ) rethrows {\n        let priorMocking = currentMockingDriver\n        let driver = MockingDriver()\n\n        defer {\n            if let object = priorMocking {\n                setTLS(driverKey, Unmanaged.passUnretained(object).toOpaque())\n            } else {\n                setTLS(driverKey, nil)\n            }\n            _fixLifetime(driver)\n        }\n\n        setTLS(driverKey, Unmanaged.passUnretained(driver).toOpaque())\n        return try f(driver)\n    }\n}\n\n// Check TLS for mocking\n@inline(never)\nprivate var contextualMockingEnabled: Bool {\n    currentMockingDriver != nil\n}\n\nextension MockingDriver {\n    @_spi(Testing)\n    public static var enabled: Bool { mockingEnabled }\n\n    @_spi(Testing)\n    public static var forceWindowsPaths: Bool {\n        currentMockingDriver?.forceWindowsSyntaxForPaths ?? false\n    }\n}\n\n#endif  // ENABLE_MOCKING\n\n@inline(__always)\ninternal var mockingEnabled: Bool {\n    // Fast constant-foldable check for release builds\n    #if ENABLE_MOCKING\n    return contextualMockingEnabled\n    #else\n    return false\n    #endif\n}\n\n@inline(__always)\ninternal var forceWindowsPaths: Bool {\n    #if !ENABLE_MOCKING\n    return false\n    #else\n    return MockingDriver.forceWindowsPaths\n    #endif\n}\n\n#if ENABLE_MOCKING\n// Strip the mock_system prefix and the arg list suffix\nprivate func originalSyscallName(_ function: String) -> String {\n    // `function` must be of format `system_<name>(<parameters>)`\n    for `prefix` in [\"system_\", \"libc_\"] {\n        if function.starts(with: `prefix`) {\n            return String(function.dropFirst(`prefix`.count).prefix { $0 != \"(\" })\n        }\n    }\n    preconditionFailure(\"\\(function) must start with 'system_' or 'libc_'\")\n}\n\nprivate func mockImpl(syscall name: String, args: [AnyHashable]) -> CInt {\n    precondition(mockingEnabled)\n    let origName = originalSyscallName(name)\n    guard let driver = currentMockingDriver else {\n        fatalError(\"Mocking requested from non-mocking context\")\n    }\n\n    driver.trace.add(Trace.Entry(name: origName, args))\n\n    switch driver.forceErrno {\n    case .none: break\n    case .always(let e):\n        system_errno = e\n        return -1\n    case .counted(let e, let count):\n        assert(count >= 1)\n        system_errno = e\n        driver.forceErrno = count > 1 ? .counted(errno: e, count: count - 1) : .none\n        return -1\n    }\n\n    return 0\n}\n\nprivate func reinterpret(_ args: [AnyHashable?]) -> [AnyHashable] {\n    args.map { arg in\n        switch arg {\n        case let charPointer as UnsafePointer<CInterop.PlatformChar>:\n            return String(_errorCorrectingPlatformString: charPointer)\n        case is UnsafeMutablePointer<CInterop.PlatformChar>:\n            return \"<buffer>\"\n        case is UnsafeMutableRawPointer:\n            return \"<buffer>\"\n        case is UnsafeRawPointer:\n            return \"<buffer>\"\n        case .none:\n            return \"nil\"\n        case let .some(arg):\n            return arg\n        }\n    }\n}\n\nfunc mock(\n    syscall name: String = #function,\n    _ args: AnyHashable?...\n) -> CInt {\n    mockImpl(syscall: name, args: reinterpret(args))\n}\n\nfunc mockInt(\n    syscall name: String = #function,\n    _ args: AnyHashable?...\n) -> Int {\n    Int(mockImpl(syscall: name, args: reinterpret(args)))\n}\n\n#endif  // ENABLE_MOCKING\n\n// Force paths to be treated as Windows syntactically if `enabled` is\n// true.\n@_spi(Testing)\npublic func _withWindowsPaths(enabled: Bool, _ body: () -> Void) {\n    #if ENABLE_MOCKING\n    guard enabled else {\n        body()\n        return\n    }\n    MockingDriver.withMockingEnabled { driver in\n        driver.forceWindowsSyntaxForPaths = true\n        body()\n    }\n    #else\n    body()\n    #endif\n}\n\n// Internal wrappers and typedefs which help reduce #if littering in System's\n// code base.\n\n// TODO: Should CSystem just include all the header files we need?\n\ninternal typealias _COffT = off_t\n\n// MARK: syscalls and variables\n\n#if canImport(Darwin)\ninternal var system_errno: CInt {\n    get { Darwin.errno }\n    set { Darwin.errno = newValue }\n}\n#elseif canImport(Glibc)\ninternal var system_errno: CInt {\n    get { Glibc.errno }\n    set { Glibc.errno = newValue }\n}\n#elseif canImport(Musl)\ninternal var system_errno: CInt {\n    get { Musl.errno }\n    set { Musl.errno = newValue }\n}\n#elseif canImport(Android)\ninternal var system_errno: CInt {\n    get { Android.errno }\n    set { Android.errno = newValue }\n}\n#endif\n\n// MARK: C stdlib decls\n\n// Convention: `system_foo` is system's wrapper for `foo`.\n\ninternal func system_strerror(_ __errnum: Int32) -> UnsafeMutablePointer<Int8>! {\n    strerror(__errnum)\n}\n\ninternal func system_strlen(_ s: UnsafePointer<CChar>) -> Int {\n    strlen(s)\n}\ninternal func system_strlen(_ s: UnsafeMutablePointer<CChar>) -> Int {\n    strlen(s)\n}\n\n// Convention: `system_platform_foo` is a\n// platform-representation-abstracted wrapper around `foo`-like functionality.\n// Type and layout differences such as the `char` vs `wchar` are abstracted.\n//\n\n// strlen for the platform string\ninternal func system_platform_strlen(_ s: UnsafePointer<CInterop.PlatformChar>) -> Int {\n    strlen(s)\n}\n\n// memset for raw buffers\n// FIXME: Do we really not have something like this in the stdlib already?\ninternal func system_memset(\n    _ buffer: UnsafeMutableRawBufferPointer,\n    to byte: UInt8\n) {\n    guard buffer.count > 0 else { return }\n    memset(buffer.baseAddress!, CInt(byte), buffer.count)\n}\n\n// Interop between String and platfrom string\nextension String {\n    internal func _withPlatformString<Result>(\n        _ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result\n    ) rethrows -> Result {\n        // Need to #if because CChar may be signed\n        try withCString(body)\n    }\n\n    internal init(\n        _errorCorrectingPlatformString platformString: UnsafePointer<CInterop.PlatformChar>\n    ) {\n        // Need to #if because CChar may be signed\n        self.init(cString: platformString)\n    }\n}\n\ninternal typealias _PlatformTLSKey = pthread_key_t\n\ninternal func makeTLSKey() -> _PlatformTLSKey {\n    var raw = pthread_key_t()\n    guard 0 == pthread_key_create(&raw, nil) else {\n        fatalError(\"Unable to create key\")\n    }\n    return raw\n}\n\ninternal func setTLS(_ key: _PlatformTLSKey, _ p: UnsafeMutableRawPointer?) {\n    guard 0 == pthread_setspecific(key, p) else {\n        fatalError(\"Unable to set TLS\")\n    }\n}\n\ninternal func getTLS(_ key: _PlatformTLSKey) -> UnsafeMutableRawPointer? {\n    pthread_getspecific(key)\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/System Calls/Syscall.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\nimport CNIODarwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\nimport CNIOLinux\n#endif\n\n@_spi(Testing)\npublic enum Syscall: Sendable {\n    @_spi(Testing)\n    public static func stat(path: FilePath) -> Result<CInterop.Stat, Errno> {\n        path.withPlatformString { platformPath in\n            var status = CInterop.Stat()\n            return valueOrErrno(retryOnInterrupt: false) {\n                system_stat(platformPath, &status)\n            }.map { _ in\n                status\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func lstat(path: FilePath) -> Result<CInterop.Stat, Errno> {\n        path.withPlatformString { platformPath in\n            var status = CInterop.Stat()\n            return valueOrErrno(retryOnInterrupt: false) {\n                system_lstat(platformPath, &status)\n            }.map { _ in\n                status\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func mkdir(at path: FilePath, permissions: FilePermissions) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString { p in\n                system_mkdir(p, permissions.rawValue)\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func rename(from old: FilePath, to new: FilePath) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_rename(oldPath, newPath)\n                }\n            }\n        }\n    }\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static func rename(\n        from old: FilePath,\n        to new: FilePath,\n        options: RenameOptions\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_renamex_np(oldPath, newPath, options.rawValue)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func rename(\n        from old: FilePath,\n        relativeTo oldFD: FileDescriptor,\n        to new: FilePath,\n        relativeTo newFD: FileDescriptor,\n        options: RenameOptions\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_renameatx_np(\n                        oldFD.rawValue,\n                        oldPath,\n                        newFD.rawValue,\n                        newPath,\n                        options.rawValue\n                    )\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public struct RenameOptions: OptionSet, Sendable {\n        public var rawValue: CUnsignedInt\n\n        public init(rawValue: CUnsignedInt) {\n            self.rawValue = rawValue\n        }\n\n        public static var exclusive: Self {\n            Self(rawValue: UInt32(bitPattern: RENAME_EXCL))\n        }\n\n        public static var swap: Self {\n            Self(rawValue: UInt32(bitPattern: RENAME_SWAP))\n        }\n    }\n    #endif\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func rename(\n        from old: FilePath,\n        relativeTo oldFD: FileDescriptor,\n        to new: FilePath,\n        relativeTo newFD: FileDescriptor,\n        flags: RenameAtFlags\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_renameat2(\n                        oldFD.rawValue,\n                        oldPath,\n                        newFD.rawValue,\n                        newPath,\n                        flags.rawValue\n                    )\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public struct RenameAtFlags: OptionSet {\n        public var rawValue: CUnsignedInt\n\n        public init(rawValue: CUnsignedInt) {\n            self.rawValue = rawValue\n        }\n\n        public static var exclusive: Self {\n            Self(rawValue: CNIOLinux_RENAME_NOREPLACE)\n        }\n\n        public static var swap: Self {\n            Self(rawValue: CNIOLinux_RENAME_EXCHANGE)\n        }\n    }\n    #endif\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public struct LinkAtFlags: OptionSet {\n        @_spi(Testing)\n        public var rawValue: CInt\n\n        @_spi(Testing)\n        public init(rawValue: CInt) {\n            self.rawValue = rawValue\n        }\n\n        @_spi(Testing)\n        public static var emptyPath: Self {\n            Self(rawValue: CNIOLinux_AT_EMPTY_PATH)\n        }\n\n        @_spi(Testing)\n        public static var followSymbolicLinks: Self {\n            Self(rawValue: AT_SYMLINK_FOLLOW)\n        }\n    }\n\n    @_spi(Testing)\n    public static func linkAt(\n        from source: FilePath,\n        relativeTo sourceFD: FileDescriptor,\n        to destination: FilePath,\n        relativeTo destinationFD: FileDescriptor,\n        flags: LinkAtFlags\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_linkat(\n                        sourceFD.rawValue,\n                        src,\n                        destinationFD.rawValue,\n                        dst,\n                        flags.rawValue\n                    )\n                }\n            }\n        }\n    }\n    #endif\n\n    @_spi(Testing)\n    public static func link(\n        from source: FilePath,\n        to destination: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_link(src, dst)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func unlink(path: FilePath) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString { ptr in\n                system_unlink(ptr)\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func unlinkat(\n        path: FilePath,\n        relativeTo directoryDescriptor: FileDescriptor,\n        flags: CInt = 0\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString { ptr in\n                system_unlinkat(directoryDescriptor.rawValue, ptr, flags)\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func symlink(\n        to destination: FilePath,\n        from source: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_symlink(dst, src)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func symlinkat(\n        to destination: FilePath,\n        in directoryDescriptor: FileDescriptor,\n        from source: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_symlinkat(dst, directoryDescriptor.rawValue, src)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func readlink(at path: FilePath) -> Result<FilePath, Errno> {\n        do {\n            let resolved = try path.withPlatformString { p in\n                try String(customUnsafeUninitializedCapacity: Int(CInterop.maxPathLength)) { pointer in\n                    let result = pointer.withMemoryRebound(to: CInterop.PlatformChar.self) { ptr in\n                        valueOrErrno(retryOnInterrupt: false) {\n                            system_readlink(p, ptr.baseAddress!, ptr.count)\n                        }\n                    }\n                    return try result.get()\n                }\n            }\n            return .success(FilePath(resolved))\n        } catch let error as Errno {\n            return .failure(error)\n        } catch {\n            // Shouldn't happen: we deal in Result types and only ever with Errno.\n            fatalError(\"Unexpected error '\\(error)' caught\")\n        }\n    }\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func sendfile(\n        to output: FileDescriptor,\n        from input: FileDescriptor,\n        offset: Int,\n        size: Int\n    ) -> Result<Int, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            system_sendfile(output.rawValue, input.rawValue, off_t(offset), size)\n        }\n    }\n    #endif\n\n    @_spi(Testing)\n    public static func futimens(\n        fileDescriptor fd: FileDescriptor,\n        times: UnsafePointer<timespec>?\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            system_futimens(fd.rawValue, times)\n        }\n    }\n\n    #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func getuid() -> uid_t {\n        system_getuid()\n    }\n    #endif\n}\n\n@_spi(Testing)\npublic enum Libc: Sendable {\n    static func readdir(\n        _ dir: CInterop.DirPointer\n    ) -> Result<UnsafeMutablePointer<CInterop.DirEnt>?, Errno> {\n        optionalValueOrErrno(retryOnInterrupt: false) {\n            libc_readdir(dir)\n        }\n    }\n\n    static func closedir(\n        _ dir: CInterop.DirPointer\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            libc_closedir(dir)\n        }\n    }\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static func fcopyfile(\n        from source: FileDescriptor,\n        to destination: FileDescriptor,\n        state: copyfile_state_t?,\n        flags: copyfile_flags_t\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            libc_fcopyfile(source.rawValue, destination.rawValue, state, flags)\n        }\n    }\n    #endif\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static func copyfile(\n        from source: FilePath,\n        to destination: FilePath,\n        state: copyfile_state_t?,\n        flags: copyfile_flags_t\n    ) -> Result<Void, Errno> {\n        source.withPlatformString { sourcePath in\n            destination.withPlatformString { destinationPath in\n                nothingOrErrno(retryOnInterrupt: false) {\n                    libc_copyfile(sourcePath, destinationPath, state, flags)\n                }\n            }\n        }\n    }\n    #endif\n\n    @_spi(Testing)\n    public static func remove(\n        _ path: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString {\n                libc_remove($0)\n            }\n        }\n    }\n\n    static func getcwd() -> Result<FilePath, Errno> {\n        var buffer = [CInterop.PlatformChar](\n            repeating: 0,\n            count: Int(CInterop.maxPathLength)\n        )\n\n        return optionalValueOrErrno(retryOnInterrupt: false) {\n            buffer.withUnsafeMutableBufferPointer { pointer in\n                libc_getcwd(pointer.baseAddress!, pointer.count)\n            }\n        }.map { ptr in\n            // 'ptr' is just the input pointer, we should ignore it and just rely on the bytes\n            // in buffer.\n            //\n            // At this point 'ptr' must be non-nil, because if it were 'nil' we should be on the\n            // error path.\n            precondition(ptr != nil)\n            return FilePath(platformString: buffer)\n        }\n    }\n\n    #if !os(Android)\n    static func constr(_ name: CInt) -> Result<String, Errno> {\n        var buffer = [UInt8](repeating: 0, count: 128)\n\n        repeat {\n            let result = valueOrErrno(retryOnInterrupt: false) {\n                buffer.withUnsafeMutableBufferPointer { pointer in\n                    pointer.withMemoryRebound(to: CInterop.PlatformChar.self) { buffer in\n                        libc_confstr(name, buffer.baseAddress!, buffer.count)\n                    }\n                }\n            }\n\n            switch result {\n            case let .success(length):\n                if length <= buffer.count {\n                    let nullTerminationIndex = buffer.firstIndex(of: 0) ?? buffer.endIndex\n                    return .success(String(decoding: buffer[..<nullTerminationIndex], as: Unicode.UTF8.self))\n                } else {\n                    // The buffer wasn't long enough. Double and try again.\n                    buffer.append(contentsOf: repeatElement(0, count: buffer.capacity))\n                }\n            case let .failure(errno):\n                return .failure(errno)\n            }\n        } while true\n    }\n    #endif\n\n    static func ftsOpen(_ path: FilePath, options: FTSOpenOptions) -> Result<CInterop.FTSPointer, Errno> {\n        // 'fts_open' needs an unsafe mutable pointer to the C-string, `FilePath` doesn't offer this\n        // so copy out its bytes.\n        var pathBytes = path.withPlatformString { pointer in\n            // Length excludes the null terminator, so add it back.\n            let bufferPointer = UnsafeBufferPointer(start: pointer, count: path.length + 1)\n            return Array(bufferPointer)\n        }\n\n        return valueOrErrno {\n            pathBytes.withUnsafeMutableBufferPointer { pointer in\n                // The array must be terminated with a nil.\n                libc_fts_open([pointer.baseAddress, nil], options.rawValue)\n            }\n        }\n    }\n\n    /// Options passed to 'fts_open'.\n    struct FTSOpenOptions: OptionSet {\n        var rawValue: CInt\n\n        /// Don't change directory while walking the filesystem hierarchy.\n        static var noChangeDir: Self { Self(rawValue: FTS_NOCHDIR) }\n\n        /// Return FTS entries for symbolic links rather than their targets.\n        static var physical: Self { Self(rawValue: FTS_PHYSICAL) }\n\n        /// Return FTS entries for the targets of symbolic links.\n        static var logical: Self { Self(rawValue: FTS_LOGICAL) }\n    }\n\n    static func ftsRead(\n        _ pointer: CInterop.FTSPointer\n    ) -> Result<UnsafeMutablePointer<CInterop.FTSEnt>?, Errno> {\n        optionalValueOrErrno {\n            libc_fts_read(pointer)\n        }\n    }\n\n    static func ftsClose(\n        _ pointer: CInterop.FTSPointer\n    ) -> Result<Void, Errno> {\n        nothingOrErrno {\n            libc_fts_close(pointer)\n        }\n    }\n\n    @_spi(Testing)\n    public static func homeDirectoryFromEnvironment() -> FilePath? {\n        if let home = getenv(\"HOME\"), home.pointee != 0 {\n            return FilePath(String(cString: home))\n        }\n        #if os(Windows)\n        if let profile = getenv(\"USERPROFILE\"), profile.pointee != 0 {\n            return FilePath(String(cString: profile))\n        }\n        #endif\n        return nil\n    }\n\n    #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func homeDirectoryFromPasswd() -> Result<FilePath, Errno> {\n        let uid = Syscall.getuid()\n        var pwd = passwd()\n        var result: UnsafeMutablePointer<passwd>? = nil\n\n        return withUnsafeTemporaryAllocation(of: CChar.self, capacity: 1024) { buffer in\n            let callResult = nothingOrErrno(retryOnInterrupt: true) {\n                libc_getpwuid_r(\n                    uid,\n                    &pwd,\n                    buffer.baseAddress!,\n                    buffer.count,\n                    &result\n                )\n            }\n            switch callResult {\n            case .success:\n                guard result != nil, let directoryPointer = pwd.pw_dir else {\n                    return .failure(.noSuchFileOrDirectory)\n                }\n                return .success(FilePath(String(cString: directoryPointer)))\n            case .failure(let errno):\n                return .failure(errno)\n            }\n        }\n    }\n    #endif\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/System Calls/Syscalls.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\nimport CNIODarwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n// MARK: - system\n\n/// openat(2): Open or create a file for reading or writing\nfunc system_fdopenat(\n    _ fd: FileDescriptor.RawValue,\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ oflag: Int32\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, path, oflag)\n    }\n    #endif\n    return openat(fd, path, oflag)\n}\n\n/// openat(2): Open or create a file for reading or writing\nfunc system_fdopenat(\n    _ fd: FileDescriptor.RawValue,\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ oflag: Int32,\n    _ mode: CInterop.Mode\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, path, oflag, mode)\n    }\n    #endif\n    return openat(fd, path, oflag, mode)\n}\n\n/// stat(2): Get file status\nfunc system_stat(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ info: inout CInterop.Stat\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return stat(path, &info)\n}\n\n/// lstat(2): Get file status\ninternal func system_lstat(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ info: inout CInterop.Stat\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return lstat(path, &info)\n}\n\n/// fstat(2): Get file status\ninternal func system_fstat(\n    _ fd: FileDescriptor.RawValue,\n    _ info: inout CInterop.Stat\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd)\n    }\n    #endif\n    return fstat(fd, &info)\n}\n\n/// fchmod(2): Change mode of file\ninternal func system_fchmod(\n    _ fd: FileDescriptor.RawValue,\n    _ mode: CInterop.Mode\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, mode)\n    }\n    #endif\n    return fchmod(fd, mode)\n}\n\n/// fsync(2): Synchronize modifications to a file to permanent storage\ninternal func system_fsync(\n    _ fd: FileDescriptor.RawValue\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd)\n    }\n    #endif\n    return fsync(fd)\n}\n\n/// mkdir(2): Make a directory file\ninternal func system_mkdir(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ mode: CInterop.Mode\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path, mode)\n    }\n    #endif\n    return mkdir(path, mode)\n}\n\n/// symlink(2): Make symolic link to a file\ninternal func system_symlink(\n    _ destination: UnsafePointer<CInterop.PlatformChar>,\n    _ source: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(destination, source)\n    }\n    #endif\n    return symlink(destination, source)\n}\n\n/// symlinkat(2): Make symbolic link to a file relative to directory file descriptor\ninternal func system_symlinkat(\n    _ destination: UnsafePointer<CInterop.PlatformChar>,\n    _ dirfd: FileDescriptor.RawValue,\n    _ source: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(destination, dirfd, source)\n    }\n    #endif\n    return symlinkat(destination, dirfd, source)\n}\n\n/// readlink(2): Read value of a symolic link\ninternal func system_readlink(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ buffer: UnsafeMutablePointer<CInterop.PlatformChar>,\n    _ bufferSize: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(path, buffer, bufferSize)\n    }\n    #endif\n    return readlink(path, buffer, bufferSize)\n}\n\n/// flistxattr(2): List extended attribute names\ninternal func system_flistxattr(\n    _ fd: FileDescriptor.RawValue,\n    _ namebuf: UnsafeMutablePointer<CChar>?,\n    _ size: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(fd, namebuf, size)\n    }\n    #endif\n    #if canImport(Darwin)\n    // The final parameter is 'options'; there is no equivalent on Linux.\n    return flistxattr(fd, namebuf, size, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return flistxattr(fd, namebuf, size)\n    #endif\n}\n\n/// fgetxattr(2): Get an extended attribute value\ninternal func system_fgetxattr(\n    _ fd: FileDescriptor.RawValue,\n    _ name: UnsafePointer<CChar>,\n    _ value: UnsafeMutableRawPointer?,\n    _ size: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(fd, name, value, size)\n    }\n    #endif\n\n    #if canImport(Darwin)\n    // Penultimate parameter is position which is reserved and should be zero.\n    // The final parameter is 'options'; there is no equivalent on Linux.\n    return fgetxattr(fd, name, value, size, 0, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return fgetxattr(fd, name, value, size)\n    #endif\n}\n\n/// fsetxattr(2): Set an extended attribute value\ninternal func system_fsetxattr(\n    _ fd: FileDescriptor.RawValue,\n    _ name: UnsafePointer<CChar>,\n    _ value: UnsafeRawPointer?,\n    _ size: Int\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, name, value, size)\n    }\n    #endif\n\n    // The final parameter is 'options'/'flags' on Darwin/Linux respectively.\n    #if canImport(Darwin)\n    // Penultimate parameter is position which is reserved and should be zero.\n    return fsetxattr(fd, name, value, size, 0, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return fsetxattr(fd, name, value, size, 0)\n    #endif\n}\n\n/// fremovexattr(2): Remove an extended attribute value\ninternal func system_fremovexattr(\n    _ fd: FileDescriptor.RawValue,\n    _ name: UnsafePointer<CChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, name)\n    }\n    #endif\n\n    #if canImport(Darwin)\n    // The final parameter is 'options'; there is no equivalent on Linux.\n    return fremovexattr(fd, name, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return fremovexattr(fd, name)\n    #endif\n}\n\n/// rename(2): Change the name of a file\ninternal func system_rename(\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ new: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(old, new)\n    }\n    #endif\n    return rename(old, new)\n}\n\n#if canImport(Darwin)\ninternal func system_renamex_np(\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CUnsignedInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(old, new, flags)\n    }\n    #endif\n    return renamex_np(old, new, flags)\n}\n\n/// renameatx_np(2): Rename a file relative to directory file descriptors\ninternal func system_renameatx_np(\n    _ oldFD: FileDescriptor.RawValue,\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ newFD: FileDescriptor.RawValue,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CUnsignedInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(oldFD, old, newFD, new, flags)\n    }\n    #endif\n    return renameatx_np(oldFD, old, newFD, new, flags)\n}\n#endif\n\n#if canImport(Glibc) || canImport(Musl) || canImport(Android)\ninternal func system_renameat2(\n    _ oldFD: FileDescriptor.RawValue,\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ newFD: FileDescriptor.RawValue,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CUnsignedInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(oldFD, old, newFD, new, flags)\n    }\n    #endif\n    return CNIOLinux_renameat2(oldFD, old, newFD, new, flags)\n}\n#endif\n\n/// link(2): Creates a new link for a file.\n#if canImport(Glibc) || canImport(Musl) || canImport(Android)\ninternal func system_linkat(\n    _ oldFD: FileDescriptor.RawValue,\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ newFD: FileDescriptor.RawValue,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(oldFD, old, newFD, new, flags)\n    }\n    #endif\n    return linkat(oldFD, old, newFD, new, flags)\n}\n#endif\n\n/// link(2): Creates a new link for a file.\ninternal func system_link(\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ new: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(old, new)\n    }\n    #endif\n    return link(old, new)\n}\n\n/// unlink(2): Remove a directory entry.\ninternal func system_unlink(\n    _ path: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return unlink(path)\n}\n\n/// unlinkat(2): Remove a directory entry relative to a directory file descriptor\ninternal func system_unlinkat(\n    _ fd: FileDescriptor.RawValue,\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, path, flags)\n    }\n    #endif\n    return unlinkat(fd, path, flags)\n}\n\n#if canImport(Glibc) || canImport(Musl) || canImport(Android)\n/// sendfile(2): Transfer data between descriptors\ninternal func system_sendfile(\n    _ outFD: CInt,\n    _ inFD: CInt,\n    _ offset: off_t,\n    _ count: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(outFD, inFD, offset, count)\n    }\n    #endif\n    var offset = offset\n    return sendfile(outFD, inFD, &offset, count)\n}\n#endif\n\ninternal func system_futimens(\n    _ fd: CInt,\n    _ times: UnsafePointer<timespec>?\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, times)\n    }\n    #endif\n    return futimens(fd, times)\n}\n\n// MARK: - libc\n\n/// fdopendir(3): Opens a directory stream for the file descriptor\ninternal func libc_fdopendir(\n    _ fd: FileDescriptor.RawValue\n) -> CInterop.DirPointer {\n    fdopendir(fd)!\n}\n\n/// readdir(3): Returns a pointer to the next directory entry\ninternal func libc_readdir(\n    _ dir: CInterop.DirPointer\n) -> UnsafeMutablePointer<CInterop.DirEnt>? {\n    readdir(dir)\n}\n\n/// readdir(3): Closes the directory stream and frees associated structures\ninternal func libc_closedir(\n    _ dir: CInterop.DirPointer\n) -> CInt {\n    closedir(dir)\n}\n\n/// remove(3): Remove directory entry\ninternal func libc_remove(\n    _ path: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return remove(path)\n}\n\n#if canImport(Darwin)\n/// fcopyfile(3): Copy a file from one file to another.\ninternal func libc_fcopyfile(\n    _ from: CInt,\n    _ to: CInt,\n    _ state: copyfile_state_t?,\n    _ flags: copyfile_flags_t\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(from, to, state, flags)\n    }\n    #endif\n    return fcopyfile(from, to, state, flags)\n}\n#endif\n\n#if canImport(Darwin)\n/// copyfile(3): Copy a file from one file to another.\ninternal func libc_copyfile(\n    _ from: UnsafePointer<CInterop.PlatformChar>,\n    _ to: UnsafePointer<CInterop.PlatformChar>,\n    _ state: copyfile_state_t?,\n    _ flags: copyfile_flags_t\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(from, to, state, flags)\n    }\n    #endif\n    return copyfile(from, to, state, flags)\n}\n#endif\n\n/// getcwd(3): Get working directory pathname\ninternal func libc_getcwd(\n    _ buffer: UnsafeMutablePointer<CInterop.PlatformChar>,\n    _ size: Int\n) -> UnsafeMutablePointer<CInterop.PlatformChar>? {\n    getcwd(buffer, size)\n}\n\n/// confstr(3)\n#if !os(Android)\ninternal func libc_confstr(\n    _ name: CInt,\n    _ buffer: UnsafeMutablePointer<CInterop.PlatformChar>,\n    _ size: Int\n) -> Int {\n    confstr(name, buffer, size)\n}\n#endif\n\n/// fts(3)\ninternal func libc_fts_open(\n    _ path: [UnsafeMutablePointer<CInterop.PlatformChar>?],\n    _ options: CInt\n) -> UnsafeMutablePointer<CInterop.FTS> {\n    #if os(Android)\n    // This branch is a workaround for incorrect nullability annotations in the Android SDK.\n    // They were added in https://android.googlesource.com/platform/bionic/+/dec8efd72a6ad8b807a15a614ae1519487cfa456,\n    // and lasted for more than a year: https://android.googlesource.com/platform/bionic/+/da81ec4d1cbd0279014feb60535bf38defcd9346.\n    CNIOLinux_fts_open(path, options, nil)!\n    #else\n    fts_open(path, options, nil)!\n    #endif\n}\n\n/// fts(3)\ninternal func libc_fts_read(\n    _ fts: UnsafeMutablePointer<CInterop.FTS>\n) -> UnsafeMutablePointer<CInterop.FTSEnt>? {\n    fts_read(fts)\n}\n\n/// fts(3)\ninternal func libc_fts_close(\n    _ fts: UnsafeMutablePointer<CInterop.FTS>\n) -> CInt {\n    fts_close(fts)\n}\n\n#if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Android)\n/// getuid(2): Get user identification\ninternal func system_getuid() -> uid_t {\n    getuid()\n}\n\n/// getpwuid_r(3): Get password file entry\ninternal func libc_getpwuid_r(\n    _ uid: uid_t,\n    _ pwd: UnsafeMutablePointer<passwd>,\n    _ buffer: UnsafeMutablePointer<CChar>,\n    _ bufferSize: Int,\n    _ result: UnsafeMutablePointer<UnsafeMutablePointer<passwd>?>\n) -> CInt {\n    getpwuid_r(uid, pwd, buffer, bufferSize, result)\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOFS/Internal/SystemFileHandle.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#endif\n\n/// An implementation of ``FileHandleProtocol`` which is backed by system calls and a file\n/// descriptor.\n@_spi(Testing)\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic final class SystemFileHandle: Sendable {\n    /// The executor on which to execute system calls.\n    internal var threadPool: NIOThreadPool { self.sendableView.threadPool }\n\n    /// The path used to open this handle.\n    internal var path: FilePath { self.sendableView.path }\n\n    @_spi(Testing)\n    public struct Materialization: Sendable {\n        /// The path of the file which was created.\n        var created: FilePath\n        /// The desired path of the file.\n        var desired: FilePath\n        /// Whether the ``desired`` file must be created exclusively. If `true` then if a file\n        /// already exists at the ``desired`` path then an error is thrown, otherwise any existing\n        /// file will be replaced.`\n        var exclusive: Bool\n        /// The mode used to materialize the file.\n        var mode: Mode\n\n        enum Mode {\n            /// Rename the created file to become the desired file.\n            case rename\n            #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n            /// Link the unnamed file to the desired file using 'linkat(2)'.\n            case link\n            #endif\n        }\n    }\n\n    fileprivate enum Lifecycle {\n        case open(FileDescriptor)\n        case detached\n        case closed\n    }\n\n    @_spi(Testing)\n    public let sendableView: SendableView\n\n    /// The file handle may be for a non-seekable file, so it shouldn't be 'Sendable', however, most\n    /// of the work performed on behalf of the handle is executed in a thread pool which means that\n    /// its state must be 'Sendable'.\n    @_spi(Testing)\n    public struct SendableView: Sendable {\n        /// The lifecycle of the file handle.\n        fileprivate let lifecycle: NIOLockedValueBox<Lifecycle>\n\n        /// The executor on which to execute system calls.\n        internal let threadPool: NIOThreadPool\n\n        /// The path used to open this handle.\n        internal let path: FilePath\n\n        /// An action to take when closing the file handle.\n        fileprivate let materialization: Materialization?\n\n        fileprivate init(\n            lifecycle: Lifecycle,\n            threadPool: NIOThreadPool,\n            path: FilePath,\n            materialization: Materialization?\n        ) {\n            self.lifecycle = NIOLockedValueBox(lifecycle)\n            self.threadPool = threadPool\n            self.path = path\n            self.materialization = materialization\n        }\n    }\n\n    /// Creates a handle which takes ownership of the provided descriptor.\n    ///\n    /// - Precondition: The descriptor must be open.\n    /// - Parameters:\n    ///   - descriptor: The open file descriptor.\n    ///   - path: The path to the file used to open the descriptor.\n    ///   - executor: The executor which system calls will be performed on.\n    @_spi(Testing)\n    public init(\n        takingOwnershipOf descriptor: FileDescriptor,\n        path: FilePath,\n        materialization: Materialization? = nil,\n        threadPool: NIOThreadPool\n    ) {\n        self.sendableView = SendableView(\n            lifecycle: .open(descriptor),\n            threadPool: threadPool,\n            path: path,\n            materialization: materialization\n        )\n    }\n\n    deinit {\n        self.sendableView.lifecycle.withLockedValue { lifecycle -> Void in\n            switch lifecycle {\n            case .open:\n                fatalError(\n                    \"\"\"\n                    Leaking file descriptor: the handle for '\\(self.sendableView.path)' MUST be closed or \\\n                    detached with 'close()' or 'detachUnsafeFileDescriptor()' before the final \\\n                    reference to the handle is dropped.\n                    \"\"\"\n                )\n            case .detached, .closed:\n                ()\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    /// Returns the file descriptor if it's available; `nil` otherwise.\n    internal func descriptorIfAvailable() -> FileDescriptor? {\n        self.lifecycle.withLockedValue {\n            switch $0 {\n            case let .open(descriptor):\n                return descriptor\n            case .detached, .closed:\n                return nil\n            }\n        }\n    }\n\n    /// Executes a closure with the file descriptor if it's available otherwise throws the result\n    /// of `onUnavailable`.\n    internal func _withUnsafeDescriptor<R>(\n        _ execute: (FileDescriptor) throws -> R,\n        onUnavailable: () -> FileSystemError\n    ) throws -> R {\n        if let descriptor = self.descriptorIfAvailable() {\n            return try execute(descriptor)\n        } else {\n            throw onUnavailable()\n        }\n    }\n\n    /// Executes a closure with the file descriptor if it's available otherwise returns the result\n    /// of `onUnavailable` as a `Result` Error.\n    internal func _withUnsafeDescriptorResult<R>(\n        _ execute: (FileDescriptor) -> Result<R, FileSystemError>,\n        onUnavailable: () -> FileSystemError\n    ) -> Result<R, FileSystemError> {\n        if let descriptor = self.descriptorIfAvailable() {\n            return execute(descriptor)\n        } else {\n            return .failure(onUnavailable())\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: FileHandleProtocol {\n    // Notes which apply to the following block of functions:\n    //\n    // 1. Documentation is inherited from ``FileHandleProtocol`` and is not repeated here.\n    // 2. The functions should be annotated with @_spi(Testing); this is not possible with the\n    //    conformance to FileHandleProtocol which requires them to be only marked public. However\n    //    this is not an issue: the implementing type is annotated with @_spi(Testing) so the\n    //    functions are not actually public.\n    // 3. Most of these functions call through to a synchronous version prefixed with an underscore,\n    //    this is to make testing possible with the system call mocking infrastructure we are\n    //    currently using.\n\n    public func info() async throws -> FileInfo {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._info().get()\n        }\n    }\n\n    public func replacePermissions(_ permissions: FilePermissions) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._replacePermissions(permissions)\n        }\n    }\n\n    public func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._addPermissions(permissions)\n        }\n    }\n\n    public func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._removePermissions(permissions)\n        }\n    }\n\n    public func attributeNames() async throws -> [String] {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._attributeNames()\n        }\n    }\n\n    public func valueForAttribute(_ name: String) async throws -> [UInt8] {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._valueForAttribute(name)\n        }\n    }\n\n    public func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._updateValueForAttribute(bytes, attribute: name)\n        }\n    }\n\n    public func removeValueForAttribute(_ name: String) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._removeValueForAttribute(name)\n        }\n    }\n\n    public func synchronize() async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._synchronize()\n        }\n    }\n\n    public func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._withUnsafeDescriptor {\n                try execute($0)\n            } onUnavailable: {\n                FileSystemError(\n                    code: .closed,\n                    message: \"File is closed ('\\(sendableView.path)').\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func detachUnsafeFileDescriptor() throws -> FileDescriptor {\n        try self.sendableView.lifecycle.withLockedValue { lifecycle in\n            switch lifecycle {\n            case let .open(descriptor):\n                lifecycle = .detached\n\n                // We need to be careful handling files which have delayed materialization to avoid\n                // leftover temporary files.\n                //\n                // Where we use the 'link' mode we simply call materialize and return the\n                // descriptor as it will be materialized when closed.\n                //\n                // For the 'rename' mode we create a hard link to the desired file and unlink the\n                // created file.\n                guard let materialization = self.sendableView.materialization else {\n                    // File opened 'normally', just detach and return.\n                    return descriptor\n                }\n\n                switch materialization.mode {\n                #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                case .link:\n                    let result = self.sendableView._materializeLink(\n                        descriptor: descriptor,\n                        from: materialization.created,\n                        to: materialization.desired,\n                        exclusive: materialization.exclusive\n                    )\n                    return try result.map { descriptor }.get()\n                #endif\n\n                case .rename:\n                    let result = Syscall.link(\n                        from: materialization.created,\n                        to: materialization.desired\n                    ).mapError { errno in\n                        FileSystemError.link(\n                            errno: errno,\n                            from: materialization.created,\n                            to: materialization.desired,\n                            location: .here()\n                        )\n                    }.flatMap {\n                        Syscall.unlink(path: materialization.created).mapError { errno in\n                            .unlink(\"unlink\", errno: errno, path: materialization.created, location: .here())\n                        }\n                    }\n\n                    return try result.map { descriptor }.get()\n                }\n\n            case .detached:\n                throw FileSystemError(\n                    code: .closed,\n                    message: \"\"\"\n                        File descriptor has already been detached ('\\(self.path)'). Handles may \\\n                        only be detached once.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n\n            case .closed:\n                throw FileSystemError(\n                    code: .closed,\n                    message: \"\"\"\n                        Cannot detach descriptor for closed file ('\\(self.path)'). Handles may \\\n                        only be detached while they are open.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func close() async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._close(materialize: true).get()\n        }\n    }\n\n    public func close(makeChangesVisible: Bool) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._close(materialize: makeChangesVisible).get()\n        }\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._setTimes(\n                lastAccess: lastAccess,\n                lastDataModification: lastDataModification\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public enum UpdatePermissionsOperation: Sendable { case set, add, remove }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    /// Returns a string in the format: \"{message}, the file '{path}' is closed.\"\n    private func fileIsClosed(_ message: String) -> String {\n        \"\\(message), the file '\\(self.path)' is closed.\"\n    }\n\n    /// Returns a string in the format: \"{message} for '{path}'.\"\n    private func unknown(_ message: String) -> String {\n        \"\\(message) for '\\(self.path)'.\"\n    }\n\n    @_spi(Testing)\n    public func _info() -> Result<FileInfo, FileSystemError> {\n        self._withUnsafeDescriptorResult { descriptor in\n            descriptor.status().map { stat in\n                FileInfo(platformSpecificStatus: stat)\n            }.mapError { errno in\n                .stat(\"fstat\", errno: errno, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to get information\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _replacePermissions(_ permissions: FilePermissions) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            try self.updatePermissions(\n                permissions,\n                operation: .set,\n                operand: permissions,\n                descriptor: descriptor\n            )\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to replace permissions\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _addPermissions(_ permissions: FilePermissions) throws -> FilePermissions {\n        try self._withUnsafeDescriptor { descriptor in\n            switch descriptor.status() {\n            case let .success(status):\n                let info = FileInfo(platformSpecificStatus: status)\n                let merged = info.permissions.union(permissions)\n\n                // Check if we need to make any changes.\n                if merged == info.permissions {\n                    return merged\n                }\n\n                // Apply the new permissions.\n                try self.updatePermissions(\n                    merged,\n                    operation: .add,\n                    operand: permissions,\n                    descriptor: descriptor\n                )\n\n                return merged\n\n            case let .failure(errno):\n                throw FileSystemError(\n                    message: \"Unable to add permissions.\",\n                    wrapping: .stat(\"fstat\", errno: errno, path: self.path, location: .here())\n                )\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to add permissions\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _removePermissions(_ permissions: FilePermissions) throws -> FilePermissions {\n        try self._withUnsafeDescriptor { descriptor in\n            switch descriptor.status() {\n            case let .success(status):\n                let info = FileInfo(platformSpecificStatus: status)\n                let merged = info.permissions.subtracting(permissions)\n\n                // Check if we need to make any changes.\n                if merged == info.permissions {\n                    return merged\n                }\n\n                // Apply the new permissions.\n                try self.updatePermissions(\n                    merged,\n                    operation: .remove,\n                    operand: permissions,\n                    descriptor: descriptor\n                )\n\n                return merged\n\n            case let .failure(errno):\n                throw FileSystemError(\n                    message: \"Unable to remove permissions.\",\n                    wrapping: .stat(\"fstat\", errno: errno, path: self.path, location: .here())\n                )\n\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to remove permissions\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    private func updatePermissions(\n        _ permissions: FilePermissions,\n        operation: SystemFileHandle.UpdatePermissionsOperation,\n        operand: FilePermissions,\n        descriptor: FileDescriptor\n    ) throws {\n        try descriptor.changeMode(permissions).mapError { errno in\n            FileSystemError.fchmod(\n                operation: operation,\n                operand: operand,\n                permissions: permissions,\n                errno: errno,\n                path: self.path,\n                location: .here()\n            )\n        }.get()\n    }\n\n    @_spi(Testing)\n    public func _attributeNames() throws -> [String] {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.listExtendedAttributes().mapError { errno in\n                FileSystemError.flistxattr(errno: errno, path: self.path, location: .here())\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Could not list extended attributes\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _valueForAttribute(_ name: String) throws -> [UInt8] {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.readExtendedAttribute(\n                named: name\n            ).flatMapError { errno -> Result<[UInt8], FileSystemError> in\n                switch errno {\n                #if canImport(Darwin)\n                case .attributeNotFound:\n                    // Okay, return empty value.\n                    return .success([])\n                #endif\n                case .noData:\n                    // Okay, return empty value.\n                    return .success([])\n                default:\n                    let error = FileSystemError.fgetxattr(\n                        attribute: name,\n                        errno: errno,\n                        path: self.path,\n                        location: .here()\n                    )\n                    return .failure(error)\n                }\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\n                    \"Could not get value for extended attribute ('\\(name)')\"\n                ),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _updateValueForAttribute(\n        _ bytes: some RandomAccessCollection<UInt8>,\n        attribute name: String\n    ) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            func withUnsafeBufferPointer(_ body: (UnsafeBufferPointer<UInt8>) throws -> Void) throws {\n                try bytes.withContiguousStorageIfAvailable(body)\n                    ?? Array(bytes).withUnsafeBufferPointer(body)\n            }\n\n            try withUnsafeBufferPointer { pointer in\n                let rawBufferPointer = UnsafeRawBufferPointer(pointer)\n                return try descriptor.setExtendedAttribute(\n                    named: name,\n                    to: rawBufferPointer\n                ).mapError { errno in\n                    FileSystemError.fsetxattr(\n                        attribute: name,\n                        errno: errno,\n                        path: self.path,\n                        location: .here()\n                    )\n                }.get()\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\n                    \"Could not set value for extended attribute ('\\(name)')\"\n                ),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _removeValueForAttribute(_ name: String) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.removeExtendedAttribute(name).mapError { errno in\n                FileSystemError.fremovexattr(\n                    attribute: name,\n                    errno: errno,\n                    path: self.path,\n                    location: .here()\n                )\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Could not remove extended attribute ('\\(name)')\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _synchronize() throws {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.synchronize().mapError { errno in\n                FileSystemError.fsync(errno: errno, path: self.path, location: .here())\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Could not synchronize\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    internal func _duplicate() -> Result<FileDescriptor, FileSystemError> {\n        self._withUnsafeDescriptorResult { descriptor in\n            Result {\n                try descriptor.duplicate()\n            }.mapError { error in\n                FileSystemError.dup(error: error, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"Unable to duplicate descriptor of closed handle for '\\(self.path)'.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _close(materialize: Bool, failRenameat2WithEINVAL: Bool = false) -> Result<Void, FileSystemError> {\n        let descriptor: FileDescriptor? = self.lifecycle.withLockedValue { lifecycle in\n            switch lifecycle {\n            case let .open(descriptor):\n                lifecycle = .closed\n                return descriptor\n            case .detached, .closed:\n                return nil\n            }\n        }\n\n        guard let descriptor = descriptor else {\n            return .success(())\n        }\n\n        // Materialize then close.\n        let materializeResult = self._materialize(\n            materialize,\n            descriptor: descriptor,\n            failRenameat2WithEINVAL: failRenameat2WithEINVAL\n        )\n\n        return Result {\n            try descriptor.close()\n        }.mapError { error in\n            .close(error: error, path: self.path, location: .here())\n        }.flatMap {\n            materializeResult\n        }\n    }\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    fileprivate func _materializeLink(\n        descriptor: FileDescriptor,\n        from createdPath: FilePath,\n        to desiredPath: FilePath,\n        exclusive: Bool\n    ) -> Result<Void, FileSystemError> {\n        func linkAtEmptyPath() -> Result<Void, Errno> {\n            Syscall.linkAt(\n                from: \"\",\n                relativeTo: descriptor,\n                to: desiredPath,\n                relativeTo: .currentWorkingDirectory,\n                flags: [.emptyPath]\n            )\n        }\n\n        func linkAtProcFS() -> Result<Void, Errno> {\n            Syscall.linkAt(\n                from: FilePath(\"/proc/self/fd/\\(descriptor.rawValue)\"),\n                relativeTo: .currentWorkingDirectory,\n                to: desiredPath,\n                relativeTo: .currentWorkingDirectory,\n                flags: [.followSymbolicLinks]\n            )\n        }\n\n        let result: Result<Void, FileSystemError>\n\n        switch linkAtEmptyPath() {\n        case .success:\n            result = .success(())\n\n        case .failure(.fileExists) where !exclusive:\n            // File exists and materialization _isn't_ exclusive. Remove the existing\n            // file and try again.\n            let removeResult = Libc.remove(desiredPath).mapError { errno in\n                FileSystemError.remove(errno: errno, path: desiredPath, location: .here())\n            }\n\n            let linkAtResult = linkAtEmptyPath().flatMapError { errno in\n                // ENOENT means we likely didn't have the 'CAP_DAC_READ_SEARCH' capability\n                // so try again by linking to the descriptor via procfs.\n                if errno == .noSuchFileOrDirectory {\n                    return linkAtProcFS()\n                } else {\n                    return .failure(errno)\n                }\n            }.mapError { errno in\n                FileSystemError.link(\n                    errno: errno,\n                    from: createdPath,\n                    to: desiredPath,\n                    location: .here()\n                )\n            }\n\n            result = removeResult.flatMap { linkAtResult }\n\n        case .failure(.noSuchFileOrDirectory):\n            result = linkAtProcFS().flatMapError { errno in\n                if errno == .fileExists, !exclusive {\n                    return Libc.remove(desiredPath).mapError { errno in\n                        FileSystemError.remove(\n                            errno: errno,\n                            path: desiredPath,\n                            location: .here()\n                        )\n                    }.flatMap {\n                        linkAtProcFS().mapError { errno in\n                            FileSystemError.link(\n                                errno: errno,\n                                from: createdPath,\n                                to: desiredPath,\n                                location: .here()\n                            )\n                        }\n                    }\n                } else {\n                    let error = FileSystemError.link(\n                        errno: errno,\n                        from: createdPath,\n                        to: desiredPath,\n                        location: .here()\n                    )\n                    return .failure(error)\n                }\n            }\n\n        case .failure(let errno):\n            result = .failure(\n                .link(errno: errno, from: createdPath, to: desiredPath, location: .here())\n            )\n        }\n\n        return result\n    }\n    #endif\n\n    func _materialize(\n        _ materialize: Bool,\n        descriptor: FileDescriptor,\n        failRenameat2WithEINVAL: Bool\n    ) -> Result<Void, FileSystemError> {\n        guard let materialization = self.materialization else { return .success(()) }\n\n        let createdPath = materialization.created\n        let desiredPath = materialization.desired\n\n        let result: Result<Void, FileSystemError>\n        switch materialization.mode {\n        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        case .link:\n            if materialize {\n                result = self._materializeLink(\n                    descriptor: descriptor,\n                    from: createdPath,\n                    to: desiredPath,\n                    exclusive: materialization.exclusive\n                )\n            } else {\n                result = .success(())\n            }\n        #endif\n\n        case .rename:\n            if materialize {\n                var renameResult: Result<Void, Errno>\n                let renameFunction: String\n                #if canImport(Darwin)\n                renameFunction = \"renamex_np\"\n                renameResult = Syscall.rename(\n                    from: createdPath,\n                    to: desiredPath,\n                    options: materialization.exclusive ? [.exclusive] : []\n                )\n                #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                // The created and desired paths are absolute, so the relative descriptors are\n                // ignored. However, they must still be provided to 'rename' in order to pass\n                // flags.\n                renameFunction = \"renameat2\"\n                if materialization.exclusive, failRenameat2WithEINVAL {\n                    renameResult = .failure(.invalidArgument)\n                } else {\n                    renameResult = Syscall.rename(\n                        from: createdPath,\n                        relativeTo: .currentWorkingDirectory,\n                        to: desiredPath,\n                        relativeTo: .currentWorkingDirectory,\n                        flags: materialization.exclusive ? [.exclusive] : []\n                    )\n                }\n                #endif\n\n                if materialization.exclusive {\n                    switch renameResult {\n                    case .failure(.fileExists):\n                        // A file exists at the desired path and the user specified exclusive\n                        // creation, clear up by removing the file that we did create.\n                        _ = Libc.remove(createdPath)\n\n                    case .failure(.invalidArgument):\n                        // If 'renameat2' failed on Linux with EINVAL then in all likelihood the\n                        // 'RENAME_NOREPLACE' option isn't supported. As we're doing an exclusive\n                        // create, check the desired path doesn't exist then do a regular rename.\n                        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                        switch Syscall.stat(path: desiredPath) {\n                        case .failure(.noSuchFileOrDirectory):\n                            // File doesn't exist, do a 'regular' rename.\n                            renameResult = Syscall.rename(from: createdPath, to: desiredPath)\n\n                        case .success:\n                            // File exists so exclusive create isn't possible. Remove the file\n                            // we did create then throw.\n                            _ = Libc.remove(createdPath)\n                            let error = FileSystemError(\n                                code: .fileAlreadyExists,\n                                message: \"\"\"\n                                    Couldn't open '\\(desiredPath)', it already exists and the \\\n                                    file was opened with the 'existingFile' option set to 'none'.\n                                    \"\"\",\n                                cause: nil,\n                                location: .here()\n                            )\n                            return .failure(error)\n\n                        case .failure:\n                            // Failed to stat the desired file for reasons unknown. Remove the file\n                            // we did create then throw.\n                            _ = Libc.remove(createdPath)\n                            let error = FileSystemError(\n                                code: .unknown,\n                                message: \"Couldn't open '\\(desiredPath)'.\",\n                                cause: FileSystemError.rename(\n                                    \"renameat2\",\n                                    errno: .invalidArgument,\n                                    oldName: createdPath,\n                                    newName: desiredPath,\n                                    location: .here()\n                                ),\n                                location: .here()\n                            )\n                            return .failure(error)\n                        }\n                        #else\n                        ()  // Not Linux, use the normal error flow.\n                        #endif\n\n                    case .success, .failure:\n                        ()\n                    }\n                }\n\n                result = renameResult.mapError { errno in\n                    .rename(\n                        renameFunction,\n                        errno: errno,\n                        oldName: createdPath,\n                        newName: desiredPath,\n                        location: .here()\n                    )\n                }\n            } else {\n                // Don't materialize the source, remove it\n                result = Libc.remove(createdPath).mapError {\n                    .remove(errno: $0, path: createdPath, location: .here())\n                }\n            }\n        }\n\n        return result\n    }\n\n    func _setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            let syscallResult: Result<Void, Errno>\n            switch (lastAccess, lastDataModification) {\n            case (.none, .none):\n                // If the timespec array is nil, as per the `futimens` docs,\n                // both the last accessed and last modification times\n                // will be set to now.\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: nil\n                )\n\n            case (.some(let lastAccess), .none):\n                // Don't modify the last modification time.\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: [timespec(lastAccess), timespec(.omit)]\n                )\n\n            case (.none, .some(let lastDataModification)):\n                // Don't modify the last access time.\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: [timespec(.omit), timespec(lastDataModification)]\n                )\n\n            case (.some(let lastAccess), .some(let lastDataModification)):\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: [timespec(lastAccess), timespec(lastDataModification)]\n                )\n            }\n\n            try syscallResult.mapError { errno in\n                FileSystemError.futimens(\n                    errno: errno,\n                    path: self.path,\n                    lastAccessTime: lastAccess,\n                    lastDataModificationTime: lastDataModification,\n                    location: .here()\n                )\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"Couldn't modify file dates, the file '\\(self.path)' is closed.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n}\n\nextension timespec {\n    fileprivate init(_ fileinfoTimespec: FileInfo.Timespec) {\n        // Clamp seconds to be positive\n        let seconds = max(0, fileinfoTimespec.seconds)\n\n        // If nanoseconds are not UTIME_NOW or UTIME_OMIT, clamp to be between\n        // 0 and 1,000 million.\n        let nanoseconds: Int\n        switch fileinfoTimespec {\n        case .now, .omit:\n            nanoseconds = fileinfoTimespec.nanoseconds\n        default:\n            nanoseconds = min(1_000_000_000, max(0, fileinfoTimespec.nanoseconds))\n        }\n\n        self.init(\n            tv_sec: seconds,\n            tv_nsec: nanoseconds\n        )\n    }\n}\n\n// MARK: - Readable File Handle\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: ReadableFileHandleProtocol {\n    // Notes which apply to the following block of functions:\n    //\n    // 1. Documentation is inherited from ``FileHandleProtocol`` and is not repeated here.\n    // 2. The functions should be annotated with @_spi(Testing); this is not possible with the\n    //    conformance to FileHandleProtocol which requires them to be only marked public. However\n    //    this is not an issue: the implementing type is annotated with @_spi(Testing) so the\n    //    functions are not actually public.\n\n    public func readChunk(\n        fromAbsoluteOffset offset: Int64,\n        length: ByteCount\n    ) async throws -> ByteBuffer {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._withUnsafeDescriptor { descriptor in\n                try descriptor.readChunk(\n                    fromAbsoluteOffset: offset,\n                    length: length.bytes\n                ).flatMapError { error in\n                    if let errno = error as? Errno, errno == .illegalSeek {\n                        guard offset == 0 else {\n                            return .failure(\n                                FileSystemError(\n                                    code: .unsupported,\n                                    message: \"File is unseekable.\",\n                                    cause: nil,\n                                    location: .here()\n                                )\n                            )\n                        }\n\n                        return descriptor.readChunk(length: length.bytes).mapError { error in\n                            FileSystemError.read(\n                                usingSyscall: .read,\n                                error: error,\n                                path: sendableView.path,\n                                location: .here()\n                            )\n                        }\n                    } else {\n                        return .failure(\n                            FileSystemError.read(\n                                usingSyscall: .pread,\n                                error: error,\n                                path: sendableView.path,\n                                location: .here()\n                            )\n                        )\n                    }\n                }\n                .get()\n            } onUnavailable: {\n                FileSystemError(\n                    code: .closed,\n                    message: \"Couldn't read chunk, the file '\\(sendableView.path)' is closed.\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func readChunks(\n        in range: Range<Int64>,\n        chunkLength size: ByteCount\n    ) -> FileChunks {\n        FileChunks(handle: self, chunkLength: size, range: range)\n    }\n}\n\n// MARK: - Writable File Handle\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: WritableFileHandleProtocol {\n    @discardableResult\n    public func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._withUnsafeDescriptor { descriptor in\n                try descriptor.write(contentsOf: bytes, toAbsoluteOffset: offset)\n                    .flatMapError { error in\n                        if let errno = error as? Errno, errno == .illegalSeek {\n                            guard offset == 0 else {\n                                return .failure(\n                                    FileSystemError(\n                                        code: .unsupported,\n                                        message: \"File is unseekable.\",\n                                        cause: nil,\n                                        location: .here()\n                                    )\n                                )\n                            }\n\n                            return descriptor.write(contentsOf: bytes)\n                                .mapError { error in\n                                    FileSystemError.write(\n                                        usingSyscall: .write,\n                                        error: error,\n                                        path: sendableView.path,\n                                        location: .here()\n                                    )\n                                }\n                        } else {\n                            return .failure(\n                                FileSystemError.write(\n                                    usingSyscall: .pwrite,\n                                    error: error,\n                                    path: sendableView.path,\n                                    location: .here()\n                                )\n                            )\n                        }\n                    }\n                    .get()\n            } onUnavailable: {\n                FileSystemError(\n                    code: .closed,\n                    message: \"Couldn't write bytes, the file '\\(sendableView.path)' is closed.\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func resize(to size: ByteCount) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._resize(to: size).get()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    func _resize(to size: ByteCount) -> Result<(), FileSystemError> {\n        self._withUnsafeDescriptorResult { descriptor in\n            Result {\n                try descriptor.resize(to: size.bytes, retryOnInterrupt: true)\n            }.mapError { error in\n                FileSystemError.ftruncate(error: error, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"Unable to resize file '\\(self.path)'.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n}\n\n// MARK: - Directory File Handle\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: DirectoryFileHandleProtocol {\n    public typealias ReadFileHandle = SystemFileHandle\n    public typealias WriteFileHandle = SystemFileHandle\n    public typealias ReadWriteFileHandle = SystemFileHandle\n\n    public func listContents(recursive: Bool) -> DirectoryEntries {\n        DirectoryEntries(handle: self, recursive: recursive)\n    }\n\n    public func openFile(\n        forReadingAt path: NIOFilePath,\n        options: OpenOptions.Read\n    ) async throws -> SystemFileHandle {\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path.underlying,\n                mode: .readOnly,\n                options: opts,\n                transactionalIfPossible: false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    public func openFile(\n        forReadingAndWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> SystemFileHandle {\n        let perms = options.permissionsForRegularFile\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path.underlying,\n                mode: .readWrite,\n                options: opts,\n                permissions: perms,\n                transactionalIfPossible: options.newFile?.transactionalCreation ?? false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    public func openFile(\n        forWritingAt path: NIOFilePath,\n        options: OpenOptions.Write\n    ) async throws -> SystemFileHandle {\n        let perms = options.permissionsForRegularFile\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path.underlying,\n                mode: .writeOnly,\n                options: opts,\n                permissions: perms,\n                transactionalIfPossible: options.newFile?.transactionalCreation ?? false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    public func openDirectory(\n        atPath path: NIOFilePath,\n        options: OpenOptions.Directory\n    ) async throws -> SystemFileHandle {\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path.underlying,\n                mode: .readOnly,\n                options: opts,\n                transactionalIfPossible: false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    func _open(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions? = nil,\n        transactionalIfPossible transactional: Bool\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        if transactional {\n            if path.isAbsolute {\n                // The provided path is absolute: just open the handle normally.\n                return SystemFileHandle.syncOpen(\n                    atPath: path,\n                    mode: mode,\n                    options: options,\n                    permissions: permissions,\n                    transactionalIfPossible: transactional,\n                    threadPool: self.threadPool\n                )\n            } else if self.path.isAbsolute {\n                // The parent path is absolute and the provided path is relative; combine them.\n                return SystemFileHandle.syncOpen(\n                    atPath: self.path.appending(path.components),\n                    mode: mode,\n                    options: options,\n                    permissions: permissions,\n                    transactionalIfPossible: transactional,\n                    threadPool: self.threadPool\n                )\n            }\n\n            // At this point transactional file creation isn't possible. Fallback to\n            // non-transactional.\n        }\n\n        // Provided and parent paths are relative. There's no way we can safely delay\n        // materialization as we don't know if the parent descriptor will be available when\n        // closing the opened file.\n        return self._withUnsafeDescriptorResult { descriptor in\n            descriptor.open(\n                atPath: path,\n                mode: mode,\n                options: options,\n                permissions: permissions\n            ).map { newDescriptor in\n                SystemFileHandle(\n                    takingOwnershipOf: newDescriptor,\n                    path: self.path.appending(path.components).lexicallyNormalized(),\n                    threadPool: self.threadPool\n                )\n            }.mapError { errno in\n                .open(\"openat\", error: errno, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"\"\"\n                    Unable to open file at path '\\(path)' relative to '\\(self.path)', the file \\\n                    is closed.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle {\n    static func syncOpen(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        transactionalIfPossible transactional: Bool,\n        threadPool: NIOThreadPool\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        let isWritable = (mode == .writeOnly || mode == .readWrite)\n        let exclusiveCreate = options.contains(.exclusiveCreate)\n        let truncate = options.contains(.truncate)\n        let delayMaterialization = transactional && isWritable && (exclusiveCreate || truncate)\n\n        if delayMaterialization {\n            // When opening in this mode we can more \"atomically\" create the file, that is, by not\n            // leaving the user with a half written file should e.g. the system crash or throw an\n            // error while writing. On non-Android Linux we do this by opening the directory for\n            // the path with `O_TMPFILE` and creating a hard link when closing the file. On other\n            // platforms we generate a dot file with a randomised suffix name and rename it to the\n            // destination.\n            #if os(Android)\n            let temporaryHardLink = false\n            #else\n            let temporaryHardLink = true\n            #endif\n            return Self.syncOpenWithMaterialization(\n                atPath: path,\n                mode: mode,\n                options: options,\n                permissions: permissions,\n                threadPool: threadPool,\n                useTemporaryFileIfPossible: temporaryHardLink\n            )\n        } else {\n            return Self.syncOpen(\n                atPath: path,\n                mode: mode,\n                options: options,\n                permissions: permissions,\n                threadPool: threadPool\n            )\n        }\n    }\n\n    static func syncOpen(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        threadPool: NIOThreadPool\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        Result {\n            try FileDescriptor.open(\n                path,\n                mode,\n                options: options,\n                permissions: permissions\n            )\n        }.map { descriptor in\n            SystemFileHandle(\n                takingOwnershipOf: descriptor,\n                path: path,\n                threadPool: threadPool\n            )\n        }.mapError { errno in\n            FileSystemError.open(\"open\", error: errno, path: path, location: .here())\n        }\n    }\n\n    @_spi(Testing)\n    public static func syncOpenWithMaterialization(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options originalOptions: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        threadPool: NIOThreadPool,\n        useTemporaryFileIfPossible: Bool = true\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        let openedPath: FilePath\n        let desiredPath: FilePath\n\n        // There are two different approaches to materializing the file. On Linux, and where\n        // supported, we can open the file with the 'O_TMPFILE' flag which creates a temporary\n        // unnamed file. If we later decide the make the file visible we use 'linkat(2)' with\n        // the appropriate flags to link the unnamed temporary file to the desired file path.\n        //\n        // On other platforms, and when not supported on Linux, we create a regular file as we\n        // normally would and when we decide to materialize it we simply rename it to the desired\n        // name (or remove it if we aren't materializing it).\n        //\n        // There are, however, some wrinkles.\n        //\n        // Normally when a file is opened the system will open files specified with relative paths\n        // relative to the current working directory. However, when we delay making a file visible\n        // the current working directory could change which introduces an awkward race. Consider\n        // the following sequence of events:\n        //\n        // 1. User opens a file with delay materialization using a relative path\n        // 2. A temporary file is opened relative to the current working directory\n        // 3. The current working directory is changed\n        // 4. The file is closed.\n        //\n        // Where is the file created? It *should* be relative to the working directory at the time\n        // the user opened the file. However, if materializing the file relative to the new\n        // working directory would be very surprising behaviour for the user.\n        //\n        // To work around this we will get the current working directory only if the provided path\n        // is relative. That way all operations can be done on a path relative to a fixed point\n        // (i.e. the current working directory at this point in time).\n        if path.isRelative {\n            let currentWorkingDirectory: FilePath\n\n            switch Libc.getcwd() {\n            case .success(let path):\n                currentWorkingDirectory = path\n            case .failure(let errno):\n                let error = FileSystemError(\n                    message: \"\"\"\n                        Can't open relative '\\(path)' as the current working directory couldn't \\\n                        be determined.\n                        \"\"\",\n                    wrapping: .getcwd(errno: errno, location: .here())\n                )\n                return .failure(error)\n            }\n\n            func makePath() -> FilePath {\n                #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                if useTemporaryFileIfPossible {\n                    return currentWorkingDirectory.appending(path.components.dropLast())\n                }\n                #endif\n                return currentWorkingDirectory.appending(path.components.dropLast())\n                    .appending(\".tmp-\" + String(randomAlphaNumericOfLength: 6))\n            }\n\n            openedPath = makePath()\n            desiredPath = currentWorkingDirectory.appending(path.components)\n        } else {\n            func makePath() -> FilePath {\n                #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                if useTemporaryFileIfPossible {\n                    return path.removingLastComponent()\n                }\n                #endif\n                return path.removingLastComponent()\n                    .appending(\".tmp-\" + String(randomAlphaNumericOfLength: 6))\n            }\n\n            openedPath = makePath()\n            desiredPath = path\n        }\n\n        let materializationMode: Materialization.Mode\n        let options: FileDescriptor.OpenOptions\n\n        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        if useTemporaryFileIfPossible {\n            options = [.temporaryFile]\n            materializationMode = .link\n        } else {\n            options = originalOptions\n            materializationMode = .rename\n        }\n        #else\n        options = originalOptions\n        materializationMode = .rename\n        #endif\n\n        let materialization = Materialization(\n            created: openedPath,\n            desired: desiredPath,\n            exclusive: originalOptions.contains(.exclusiveCreate),\n            mode: materializationMode\n        )\n\n        do {\n            let descriptor = try FileDescriptor.open(\n                openedPath,\n                mode,\n                options: options,\n                permissions: permissions\n            )\n\n            let handle = SystemFileHandle(\n                takingOwnershipOf: descriptor,\n                path: openedPath,\n                materialization: materialization,\n                threadPool: threadPool\n            )\n\n            return .success(handle)\n        } catch {\n            #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n            // 'O_TMPFILE' isn't supported for the current file system, try again but using\n            // rename instead.\n            if useTemporaryFileIfPossible, let errno = error as? Errno, errno == .notSupported {\n                return Self.syncOpenWithMaterialization(\n                    atPath: path,\n                    mode: mode,\n                    options: originalOptions,\n                    permissions: permissions,\n                    threadPool: threadPool,\n                    useTemporaryFileIfPossible: false\n                )\n            }\n            #endif\n            return .failure(.open(\"open\", error: error, path: path, location: .here()))\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFS/Internal/Utilities.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n@usableFromInline\ninternal final class Ref<Value> {\n    @usableFromInline\n    var value: Value\n    @inlinable\n    init(_ value: Value) {\n        self.value = value\n    }\n}\n\n@available(*, unavailable)\nextension Ref: Sendable {}\n\nextension String {\n    init(randomAlphaNumericOfLength length: Int) {\n        precondition(length > 0)\n\n        let characters = (0..<length).lazy.map {\n            _ in Array.alphaNumericValues.randomElement()!\n        }\n        self = String(decoding: characters, as: UTF8.self)\n    }\n}\n\nextension Array where Element == UInt8 {\n    fileprivate static let alphaNumericValues: [UInt8] = {\n        var alphaNumericValues = Array(UInt8(ascii: \"a\")...UInt8(ascii: \"z\"))\n        alphaNumericValues.append(contentsOf: UInt8(ascii: \"A\")...UInt8(ascii: \"Z\"))\n        alphaNumericValues.append(contentsOf: UInt8(ascii: \"0\")...UInt8(ascii: \"9\"))\n        return alphaNumericValues\n    }()\n}\n"
  },
  {
    "path": "Sources/NIOFS/NIOFilePath.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(System)\nimport System\n#endif\n\n/// `NIOFilePath` is a type for representing a file path. It is backed by `SystemPackage`'s `FilePath` type.\n///\n/// You can create a `NIOFilePath` from a string literal:\n///\n/// ```swift\n/// let path: NIOFilePath = \"/home/user/report.txt\"\n/// ```\n///\n/// To interact with the underlying filepath using `SystemPackage.FilePath`'s API, you can initialize a `SystemPackage.FilePath` instance from a\n/// `NIOFilePath` instance (and vice-versa).\npublic struct NIOFilePath: Equatable, Hashable, Sendable, ExpressibleByStringLiteral, CustomStringConvertible,\n    CustomDebugStringConvertible\n{\n    /// The underlying `SystemPackage.FilePath` instance that ``NIOFilePath`` uses.\n    var underlying: SystemPackage.FilePath\n\n    /// Creates a ``NIOFilePath`` given an underlying `SystemPackage.FilePath` instance.\n    ///\n    /// - Parameter underlying: The `SystemPackage.FilePath` to use as the underlying backing for ``NIOFilePath``.\n    public init(_ underlying: SystemPackage.FilePath) {\n        self.underlying = underlying\n    }\n\n    #if canImport(System)\n    /// Creates a ``NIOFilePath`` given an underlying `System.FilePath` instance.\n    ///\n    /// - Parameter underlying: The `System.FilePath` instance to use to create this ``NIOFilePath`` instance.\n    @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)\n    public init(_ underlying: System.FilePath) {\n        self.underlying = underlying.withPlatformString {\n            SystemPackage.FilePath(platformString: $0)\n        }\n    }\n    #endif\n\n    /// Creates an instance representing an empty and null-terminated filepath.\n    public init() {\n        self.underlying = .init()\n    }\n\n    /// Creates an instance corresponding to the file path represented by the provided string.\n    ///\n    /// - Parameter string: A string whose Unicode encoded contents to use as the contents of the path\n    public init(_ string: String) {\n        self.underlying = .init(string)\n    }\n\n    /// Creates an instance from a string literal.\n    ///\n    /// - Parameter stringLiteral: A string literal whose Unicode encoded contents to use as the contents of the path.\n    public init(stringLiteral: String) {\n        self.init(stringLiteral)\n    }\n\n    /// A textual representation of the file path.\n    ///\n    /// If the content of the path isn't a well-formed Unicode string, this replaces invalid bytes with U+FFFD. See `String.init(decoding:)`\n    public var description: String {\n        self.underlying.description\n    }\n\n    /// A textual representation of the file path, suitable for debugging.\n    ///\n    /// If the content of the path isn't a well-formed Unicode string, this replaces invalid bytes with U+FFFD. See `String.init(decoding:)`\n    public var debugDescription: String {\n        self.underlying.debugDescription\n    }\n}\n\nextension SystemPackage.FilePath {\n    /// Creates a `SystemPackage.FilePath` from a ``NIOFilePath`` instance.\n    public init(_ filePath: NIOFilePath) {\n        self = filePath.underlying\n    }\n}\n\n#if canImport(System)\n@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)\nextension System.FilePath {\n    /// Creates a `System.FilePath` from a ``NIOFilePath`` instance.\n    public init(_ filePath: NIOFilePath) {\n        self = filePath.underlying.withPlatformString {\n            System.FilePath(platformString: $0)\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOFS/NIOFileSystemSendableMetatype.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if compiler(>=6.2)\npublic typealias NIOFileSystemSendableMetatype = SendableMetatype\n#else\npublic typealias NIOFileSystemSendableMetatype = Any\n#endif\n"
  },
  {
    "path": "Sources/NIOFS/OpenOptions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// Options for opening file handles.\npublic enum OpenOptions: Sendable {\n    /// Options for opening a file for reading.\n    public struct Read: Hashable, Sendable {\n        /// If the last path component is a symbolic link then this flag determines whether the\n        /// link is followed. If `false` and the last path component is a symbolic link then an\n        /// error is thrown.\n        public var followSymbolicLinks: Bool\n\n        /// Marks the descriptor of the opened file as 'close-on-exec'.\n        public var closeOnExec: Bool\n\n        /// Creates a new set of options for opening a file for reading.\n        ///\n        /// - Parameters:\n        ///   - followSymbolicLinks: Whether symbolic links should be followed, defaults to `true`.\n        ///   - closeOnExec: Whether the descriptor should be marked as closed-on-exec, defaults\n        ///     to `false`.\n        public init(\n            followSymbolicLinks: Bool = true,\n            closeOnExec: Bool = false\n        ) {\n            self.followSymbolicLinks = followSymbolicLinks\n            self.closeOnExec = closeOnExec\n        }\n    }\n\n    /// Options for opening a directory.\n    public struct Directory: Hashable, Sendable {\n        /// If the last path component is a symbolic link then this flag determines whether the\n        /// link is followed. If `false` and the last path component is a symbolic link then an\n        /// error is thrown.\n        public var followSymbolicLinks: Bool\n\n        /// Marks the descriptor of the opened file as 'close-on-exec'.\n        public var closeOnExec: Bool\n\n        /// Creates a new set of options for opening a directory.\n        ///\n        /// - Parameters:\n        ///   - followSymbolicLinks: Whether symbolic links should be followed, defaults to `true`.\n        ///   - closeOnExec: Whether the descriptor should be marked as closed-on-exec, defaults\n        ///     to `false`.\n        public init(\n            followSymbolicLinks: Bool = true,\n            closeOnExec: Bool = false\n        ) {\n            self.followSymbolicLinks = followSymbolicLinks\n            self.closeOnExec = closeOnExec\n        }\n    }\n\n    /// Options for opening a file for writing (or reading and writing).\n    ///\n    /// You can use the following methods to create commonly used sets of options:\n    /// - ``newFile(replaceExisting:permissions:)`` to create a new file, optionally replacing\n    ///   one which already exists.\n    /// - ``modifyFile(createIfNecessary:permissions:)`` to modify an existing file, optionally\n    ///   creating it if it doesn't exist.\n    public struct Write: Hashable, Sendable {\n        /// The behavior for opening an existing file.\n        public var existingFile: OpenOptions.ExistingFile\n\n        /// The creation options for a new file, if one should be created. `nil` means that no\n        /// file should be created.\n        public var newFile: OpenOptions.NewFile?\n\n        /// If the last path component is a symbolic link then this flag determines whether the\n        /// link is followed. If `false` and the last path component is a symbolic link then an\n        /// error is thrown.\n        public var followSymbolicLinks: Bool\n\n        /// Marks the descriptor of the opened file as 'close-on-exec'.\n        public var closeOnExec: Bool\n\n        /// Creates a new set of options for opening a directory.\n        ///\n        /// - Parameters:\n        ///   - existingFile: Options for handling an existing file.\n        ///   - newFile: Options for creating a new file.\n        ///   - followSymbolicLinks: Whether symbolic links should be followed, defaults to `true`.\n        ///   - closeOnExec: Whether the descriptor should be marked as closed-on-exec, defaults\n        ///     to `false`.\n        public init(\n            existingFile: OpenOptions.ExistingFile,\n            newFile: OpenOptions.NewFile?,\n            followSymbolicLinks: Bool = true,\n            closeOnExec: Bool = false\n        ) {\n            self.existingFile = existingFile\n            self.newFile = newFile\n            self.followSymbolicLinks = followSymbolicLinks\n            self.closeOnExec = closeOnExec\n        }\n\n        /// Create a new file for writing to.\n        ///\n        /// - Parameters:\n        ///   - replaceExisting: Whether any existing file of the same name is replaced. If\n        ///       this is `true` then any existing file of the same name will be replaced with the\n        ///       new file. If this is `false` and a file already exists an error is thrown.\n        ///   - permissions: The permissions to apply to the newly created file. Default permissions\n        ///       (read-write owner permissions and read permissions for everyone else) are applied\n        ///       if `nil`.\n        /// - Returns: Options for creating a new file for writing.\n        public static func newFile(\n            replaceExisting: Bool,\n            permissions: FilePermissions? = nil\n        ) -> Self {\n            Write(\n                existingFile: replaceExisting ? .truncate : .none,\n                newFile: NewFile(permissions: permissions)\n            )\n        }\n\n        /// Opens a file for modifying.\n        ///\n        /// - Parameters:\n        ///   - createIfNecessary: Whether a file should be created if one doesn't exist. If\n        ///     `false` and a file doesn't exist then an error is thrown.\n        ///   - permissions: The permissions to apply to the newly created file. Default permissions\n        ///       (read-write owner permissions and read permissions for everyone else) are applied\n        ///       if `nil`. Ignored if `createIfNonExistent` is `false`.\n        /// - Returns: Options for modifying an existing file for writing.\n        public static func modifyFile(\n            createIfNecessary: Bool,\n            permissions: FilePermissions? = nil\n        ) -> Self {\n            Write(\n                existingFile: .open,\n                newFile: createIfNecessary ? NewFile(permissions: permissions) : nil\n            )\n        }\n    }\n}\n\nextension OpenOptions {\n    /// Options for opening an existing file.\n    public enum ExistingFile: Sendable, Hashable {\n        /// Indicates that no file exists. If a file does exist then an error is thrown when\n        /// opening the file.\n        case none\n\n        /// Any existing file should be opened without modification.\n        case open\n\n        /// Truncate the existing file.\n        ///\n        /// Setting this is equivalent to opening a file with `O_TRUNC`.\n        case truncate\n    }\n\n    /// Options for creating a new file.\n    public struct NewFile: Sendable, Hashable {\n        /// The permissions to apply to the new file. `nil` implies default permissions\n        /// should be applied.\n        public var permissions: FilePermissions?\n\n        /// Whether the file should be created and updated as a single transaction, if\n        /// applicable.\n        ///\n        /// When this option is set and applied the newly created file will only materialize\n        /// on the file system when the file is closed. When used in conjunction with\n        /// ``FileSystemProtocol/withFileHandle(forWritingAt:options:execute:)`` and\n        /// ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)`` the\n        /// file will only materialize when the file is closed and no errors have been thrown.\n        ///\n        /// - Important: This flag is only applied if ``OpenOptions/Write/existingFile`` is\n        ///   ``OpenOptions/ExistingFile/none``.\n        public var transactionalCreation: Bool\n\n        public init(\n            permissions: FilePermissions? = nil,\n            transactionalCreation: Bool = true\n        ) {\n            self.permissions = permissions\n            self.transactionalCreation = transactionalCreation\n        }\n    }\n}\n\nextension OpenOptions.Write {\n    @_spi(Testing)\n    public var permissionsForRegularFile: FilePermissions? {\n        if let newFile = self.newFile {\n            return newFile.permissions ?? .defaultsForRegularFile\n        } else {\n            return nil\n        }\n    }\n\n    var descriptorOptions: FileDescriptor.OpenOptions {\n        var options = FileDescriptor.OpenOptions()\n\n        if !self.followSymbolicLinks {\n            options.insert(.noFollow)\n        }\n\n        if self.closeOnExec {\n            options.insert(.closeOnExec)\n        }\n\n        if self.newFile != nil {\n            options.insert(.create)\n        }\n\n        switch self.existingFile {\n        case .none:\n            options.insert(.exclusiveCreate)\n        case .open:\n            ()\n        case .truncate:\n            options.insert(.truncate)\n        }\n\n        return options\n    }\n}\n\nextension OpenOptions.Read {\n    var descriptorOptions: FileDescriptor.OpenOptions {\n        var options = FileDescriptor.OpenOptions()\n\n        if !self.followSymbolicLinks {\n            options.insert(.noFollow)\n        }\n\n        if self.closeOnExec {\n            options.insert(.closeOnExec)\n        }\n\n        return options\n    }\n}\n\nextension OpenOptions.Directory {\n    var descriptorOptions: FileDescriptor.OpenOptions {\n        var options = FileDescriptor.OpenOptions([.directory])\n\n        if !self.followSymbolicLinks {\n            options.insert(.noFollow)\n        }\n\n        if self.closeOnExec {\n            options.insert(.closeOnExec)\n        }\n\n        return options\n    }\n}\n\nextension FileDescriptor.OpenOptions {\n    public init(_ options: OpenOptions.Read) {\n        self = options.descriptorOptions\n    }\n\n    public init(_ options: OpenOptions.Write) {\n        self = options.descriptorOptions\n    }\n\n    public init(_ options: OpenOptions.Directory) {\n        self = options.descriptorOptions\n    }\n}\n\nextension FilePermissions {\n    /// Default permissions for regular files; owner read-write, group read, other read.\n    internal static let defaultsForRegularFile: FilePermissions = [\n        .ownerReadWrite,\n        .groupRead,\n        .otherRead,\n    ]\n\n    /// Default permissions for directories; owner read-write-execute, group read-execute, other\n    /// read-execute.\n    internal static let defaultsForDirectory: FilePermissions = [\n        .ownerReadWriteExecute,\n        .groupReadExecute,\n        .otherReadExecute,\n    ]\n}\n"
  },
  {
    "path": "Sources/NIOFS/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyTracking</key>\n\t<false/>\n\t<key>NSPrivacyAccessedAPITypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>0A2A.1</string>\n\t\t\t</array>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>\n\t\t</dict>\n\t</array>\n\t<key>NSPrivacyCollectedDataTypes</key>\n\t<array/>\n\t<key>NSPrivacyTrackingDomains</key>\n\t<array/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Sources/NIOFS/String+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension String {\n    /// Reads the contents of the file at the path into a String.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``. If the file is larger than this, an error is thrown.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    ///\n    /// - Throws: If the file is larger than `maximumSizeAllowed`, an ``FileSystemError/Code-swift.struct/resourceExhausted`` error will be thrown.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let byteBuffer = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(maximumSizeAllowed: maximumSizeAllowed)\n        }\n\n        self = Self(buffer: byteBuffer)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``. If the file is larger than this, an error is thrown.\n    ///\n    /// - Throws: If the file is larger than `maximumSizeAllowed`, an ``FileSystemError/Code-swift.struct/resourceExhausted`` error will be thrown.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFSFoundationCompat/Data+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nimport NIOFS\nimport NIOCore\nimport NIOFoundationCompat\nimport struct Foundation.Data\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension Data {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let byteBuffer = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(maximumSizeAllowed: maximumSizeAllowed)\n        }\n\n        self = Data(buffer: byteBuffer)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: NIOFilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NIOFSFoundationCompat/Date+FileInfo.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOFS\n\nimport struct Foundation.Date\n\nextension Date {\n    public init(timespec: FileInfo.Timespec) {\n        let timeInterval = Double(timespec.seconds) + Double(timespec.nanoseconds) / 1_000_000_000\n        self = Date(timeIntervalSince1970: timeInterval)\n    }\n}\n\nextension FileInfo.Timespec {\n    /// The UTC time of the timestamp.\n    public var date: Date {\n        Date(timespec: self)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFileSystem/Docs.docc/index.md",
    "content": "# ``NIOFileSystem``\n\n> Warning: Do not use this module. Instead use [`_NIOFileSystem`][_fs-docs].\n>\n> `NIOFileSystem` currently exposes the same API as `_NIOFileSystem`, which is not API stable. `NIOFileSystem`\n> was created in error, and its lack of underscore incorrectly implies API stability. Users who are currently importing\n> `NIOFileSystem` should move to `_NIOFileSystem`.\n>\n> Refer to [`_NIOFilesystem`][_fs-docs] for documentation on the API of this module.\n>\n> There is ongoing work in NIO to provide a filesystem library with a stable API.\n\n[_fs-docs]: ./_NIOFileSystem\n"
  },
  {
    "path": "Sources/NIOFileSystem/Exports.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_exported import _NIOFileSystem\n"
  },
  {
    "path": "Sources/NIOFoundationCompat/ByteBuffer-foundation.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\n\n/// Errors that may be thrown by ByteBuffer methods that call into Foundation.\npublic enum ByteBufferFoundationError: Error {\n    /// Attempting to encode the given string failed.\n    case failedToEncodeString\n}\n\n// This is NIO's `NIOFoundationCompat` module which at the moment only adds `ByteBuffer` utility methods\n// for Foundation's `Data` type.\n//\n// The reason that it's not in the `NIO` module is that we don't want to have any direct Foundation dependencies\n// in `NIO` as Foundation is problematic for a few reasons:\n//\n// - its implementation is different on Linux and on macOS which means our macOS tests might be inaccurate\n// - on macOS Foundation is mostly written in ObjC which means the autorelease pool might get populated\n// - `swift-corelibs-foundation` (the OSS Foundation used on Linux) links the world which will prevent anyone from\n//   having static binaries. It can also cause problems in the choice of an SSL library as Foundation already brings\n//   the platforms OpenSSL in which might cause problems.\n\nextension ByteBuffer {\n    /// Controls how bytes are transferred between `ByteBuffer` and other storage types.\n    public enum ByteTransferStrategy: Sendable {\n        /// Force a copy of the bytes.\n        case copy\n\n        /// Do not copy the bytes if at all possible.\n        case noCopy\n\n        /// Use a heuristic to decide whether to copy the bytes or not.\n        case automatic\n    }\n\n    // MARK: - Data APIs\n\n    /// Read `length` bytes off this `ByteBuffer`, move the reader index forward by `length` bytes and return the result\n    /// as `Data`.\n    ///\n    /// `ByteBuffer` will use a heuristic to decide whether to copy the bytes or whether to reference `ByteBuffer`'s\n    /// underlying storage from the returned `Data` value. If you want manual control over the byte transferring\n    /// behaviour, please use `readData(length:byteTransferStrategy:)`.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes to be read from this `ByteBuffer`.\n    /// - Returns: A `Data` value containing `length` bytes or `nil` if there aren't at least `length` bytes readable.\n    public mutating func readData(length: Int) -> Data? {\n        self.readData(length: length, byteTransferStrategy: .automatic)\n    }\n\n    /// Read `length` bytes off this `ByteBuffer`, move the reader index forward by `length` bytes and return the result\n    /// as `Data`.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes to be read from this `ByteBuffer`.\n    ///   - byteTransferStrategy: Controls how to transfer the bytes. See `ByteTransferStrategy` for an explanation\n    ///                             of the options.\n    /// - Returns: A `Data` value containing `length` bytes or `nil` if there aren't at least `length` bytes readable.\n    public mutating func readData(length: Int, byteTransferStrategy: ByteTransferStrategy) -> Data? {\n        guard\n            let result = self.getData(at: self.readerIndex, length: length, byteTransferStrategy: byteTransferStrategy)\n        else {\n            return nil\n        }\n        self.moveReaderIndex(forwardBy: length)\n        return result\n    }\n\n    /// Return `length` bytes starting at `index` and return the result as `Data`. This will not change the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// `ByteBuffer` will use a heuristic to decide whether to copy the bytes or whether to reference `ByteBuffer`'s\n    /// underlying storage from the returned `Data` value. If you want manual control over the byte transferring\n    /// behaviour, please use `getData(at:byteTransferStrategy:)`.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes of interest into the `ByteBuffer`\n    ///   - length: The number of bytes of interest\n    /// - Returns: A `Data` value containing the bytes of interest or `nil` if the selected bytes are not readable.\n    public func getData(at index: Int, length: Int) -> Data? {\n        self.getData(at: index, length: length, byteTransferStrategy: .automatic)\n    }\n\n    /// Return `length` bytes starting at `index` and return the result as `Data`. This will not change the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes of interest into the `ByteBuffer`\n    ///   - length: The number of bytes of interest\n    ///   - byteTransferStrategy: Controls how to transfer the bytes. See `ByteTransferStrategy` for an explanation\n    ///                             of the options.\n    /// - Returns: A `Data` value containing the bytes of interest or `nil` if the selected bytes are not readable.\n    public func getData(at index: Int, length: Int, byteTransferStrategy: ByteTransferStrategy) -> Data? {\n        let index = index - self.readerIndex\n        guard index >= 0 && length >= 0 && index <= self.readableBytes - length else {\n            return nil\n        }\n        let doCopy: Bool\n        switch byteTransferStrategy {\n        case .copy:\n            doCopy = true\n        case .noCopy:\n            doCopy = false\n        case .automatic:\n            doCopy = length <= 256 * 1024\n        }\n\n        return self.withUnsafeReadableBytesWithStorageManagement { ptr, storageRef in\n            if doCopy {\n                return Data(\n                    bytes: UnsafeMutableRawPointer(mutating: ptr.baseAddress!.advanced(by: index)),\n                    count: Int(length)\n                )\n            } else {\n                let storage = storageRef.takeUnretainedValue()\n                return Data(\n                    bytesNoCopy: UnsafeMutableRawPointer(mutating: ptr.baseAddress!.advanced(by: index)),\n                    count: Int(length),\n                    deallocator: .custom { _, _ in withExtendedLifetime(storage) {} }\n                )\n            }\n        }\n    }\n\n    /// Return `length` bytes starting at the current `readerIndex` as `Data`. This will not change the reader index.\n    ///\n    /// This method is equivalent to calling `getData(at: readerIndex, length: length, byteTransferStrategy: ...)`.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes of interest.\n    ///   - byteTransferStrategy: Controls how to transfer the bytes (see `ByteTransferStrategy`).\n    /// - Returns: A `Data` value containing the bytes of interest or `nil` if the selected bytes are not readable.\n    @inlinable\n    public func peekData(length: Int, byteTransferStrategy: ByteTransferStrategy) -> Data? {\n        self.getData(\n            at: self.readerIndex,\n            length: length,\n            byteTransferStrategy: byteTransferStrategy\n        )\n    }\n\n    // MARK: - Foundation String APIs\n\n    /// Get a `String` decoding `length` bytes starting at `index` with `encoding`. This will not change the reader index.\n    /// The selected bytes must be readable or else `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes of interest into the `ByteBuffer`.\n    ///   - length: The number of bytes of interest.\n    ///   - encoding: The `String` encoding to be used.\n    /// - Returns: A `String` value containing the bytes of interest or `nil` if the selected bytes are not readable or\n    ///            cannot be decoded with the given encoding.\n    public func getString(at index: Int, length: Int, encoding: String.Encoding) -> String? {\n        guard let data = self.getData(at: index, length: length) else {\n            return nil\n        }\n        return String(data: data, encoding: encoding)\n    }\n\n    /// Read a `String` decoding `length` bytes with `encoding` from the `readerIndex`, moving the `readerIndex` appropriately.\n    ///\n    /// - Parameters:\n    ///   - length: The number of bytes to read.\n    ///   - encoding: The `String` encoding to be used.\n    /// - Returns: A `String` value containing the bytes of interest or `nil` if the `ByteBuffer` doesn't contain enough bytes, or\n    ///     if those bytes cannot be decoded with the given encoding.\n    public mutating func readString(length: Int, encoding: String.Encoding) -> String? {\n        guard length <= self.readableBytes else {\n            return nil\n        }\n\n        guard let string = self.getString(at: self.readerIndex, length: length, encoding: encoding) else {\n            return nil\n        }\n        self.moveReaderIndex(forwardBy: length)\n        return string\n    }\n\n    /// Write `string` into this `ByteBuffer` using the encoding `encoding`, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    ///   - encoding: The encoding to use to encode the string.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    public mutating func writeString(_ string: String, encoding: String.Encoding) throws -> Int {\n        let written = try self.setString(string, encoding: encoding, at: self.writerIndex)\n        self.moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `string` into this `ByteBuffer` at `index` using the encoding `encoding`. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - string: The string to write.\n    ///   - encoding: The encoding to use to encode the string.\n    ///   - index: The index for the first serialized byte.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    public mutating func setString(_ string: String, encoding: String.Encoding, at index: Int) throws -> Int {\n        guard let data = string.data(using: encoding) else {\n            throw ByteBufferFoundationError.failedToEncodeString\n        }\n        return self.setBytes(data, at: index)\n    }\n\n    public init(data: Data) {\n        self = ByteBufferAllocator().buffer(data: data)\n    }\n\n    // MARK: ContiguousBytes and DataProtocol\n    /// Write `bytes` into this `ByteBuffer` at the writer index, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to write.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    @discardableResult\n    public mutating func writeContiguousBytes<Bytes: ContiguousBytes>(_ bytes: Bytes) -> Int {\n        let written = self.setContiguousBytes(bytes, at: self.writerIndex)\n        self.moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write `bytes` into this `ByteBuffer` at `index`. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to write.\n    ///   - index: The index for the first byte.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    @discardableResult\n    public mutating func setContiguousBytes<Bytes: ContiguousBytes>(_ bytes: Bytes, at index: Int) -> Int {\n        bytes.withUnsafeBytes { bufferPointer in\n            self.setBytes(bufferPointer, at: index)\n        }\n    }\n\n    /// Write the bytes of `data` into this `ByteBuffer` at the writer index, moving the writer index forward appropriately.\n    ///\n    /// - Parameters:\n    ///   - data: The data to write.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    @discardableResult\n    public mutating func writeData<D: DataProtocol>(_ data: D) -> Int {\n        let written = self.setData(data, at: self.writerIndex)\n        self.moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Write the bytes of `data` into this `ByteBuffer` at `index`. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - data: The data to write.\n    ///   - index: The index for the first byte.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    @discardableResult\n    public mutating func setData<D: DataProtocol>(_ data: D, at index: Int) -> Int {\n        // DataProtocol refines RandomAccessCollection, so getting `count` must be O(1). This avoids\n        // intermediate allocations in the awkward case by ensuring we definitely have sufficient\n        // space for these writes.\n        self.reserveCapacity(minimumWritableBytes: data.count)\n\n        var written = 0\n        for region in data.regions {\n            written += self.setContiguousBytes(region, at: index + written)\n        }\n        return written\n    }\n\n    // MARK: - UUID\n\n    /// Get a `UUID` from the 16 bytes starting at `index`. This will not change the reader index.\n    /// If there are less than 16 bytes starting at `index` then `nil` will be returned.\n    ///\n    /// - Parameters:\n    ///   - index: The starting index of the bytes of interest into the `ByteBuffer`.\n    /// - Returns: A `UUID` value containing the bytes of interest or `nil` if the selected bytes\n    ///            are not readable or there were not enough bytes.\n    public func getUUIDBytes(at index: Int) -> UUID? {\n        guard let chunk1 = self.getInteger(at: index, as: UInt64.self),\n            let chunk2 = self.getInteger(at: index + 8, as: UInt64.self)\n        else {\n            return nil\n        }\n\n        let uuidBytes = (\n            UInt8(truncatingIfNeeded: chunk1 >> 56),\n            UInt8(truncatingIfNeeded: chunk1 >> 48),\n            UInt8(truncatingIfNeeded: chunk1 >> 40),\n            UInt8(truncatingIfNeeded: chunk1 >> 32),\n            UInt8(truncatingIfNeeded: chunk1 >> 24),\n            UInt8(truncatingIfNeeded: chunk1 >> 16),\n            UInt8(truncatingIfNeeded: chunk1 >> 8),\n            UInt8(truncatingIfNeeded: chunk1),\n            UInt8(truncatingIfNeeded: chunk2 >> 56),\n            UInt8(truncatingIfNeeded: chunk2 >> 48),\n            UInt8(truncatingIfNeeded: chunk2 >> 40),\n            UInt8(truncatingIfNeeded: chunk2 >> 32),\n            UInt8(truncatingIfNeeded: chunk2 >> 24),\n            UInt8(truncatingIfNeeded: chunk2 >> 16),\n            UInt8(truncatingIfNeeded: chunk2 >> 8),\n            UInt8(truncatingIfNeeded: chunk2)\n        )\n\n        return UUID(uuid: uuidBytes)\n    }\n\n    /// Set the bytes of the `UUID` into this `ByteBuffer` at `index`, allocating more storage if\n    /// necessary. Does not move the writer index.\n    ///\n    /// - Parameters:\n    ///   - uuid: The UUID to set.\n    ///   - index: The index into the buffer where `uuid` should be written.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    public mutating func setUUIDBytes(_ uuid: UUID, at index: Int) -> Int {\n        let bytes = uuid.uuid\n\n        // Pack the bytes into two 'UInt64's and set them.\n        var chunk1 = UInt64(bytes.0) << 56\n        chunk1 |= UInt64(bytes.1) << 48\n        chunk1 |= UInt64(bytes.2) << 40\n        chunk1 |= UInt64(bytes.3) << 32\n        chunk1 |= UInt64(bytes.4) << 24\n        chunk1 |= UInt64(bytes.5) << 16\n        chunk1 |= UInt64(bytes.6) << 8\n        chunk1 |= UInt64(bytes.7)\n\n        var chunk2 = UInt64(bytes.8) << 56\n        chunk2 |= UInt64(bytes.9) << 48\n        chunk2 |= UInt64(bytes.10) << 40\n        chunk2 |= UInt64(bytes.11) << 32\n        chunk2 |= UInt64(bytes.12) << 24\n        chunk2 |= UInt64(bytes.13) << 16\n        chunk2 |= UInt64(bytes.14) << 8\n        chunk2 |= UInt64(bytes.15)\n\n        var written = self.setInteger(chunk1, at: index)\n        written &+= self.setInteger(chunk2, at: index &+ written)\n        assert(written == 16)\n        return written\n    }\n\n    /// Read a `UUID` from the first 16 bytes in the buffer. Advances the reader index.\n    ///\n    /// - Returns: The `UUID` or `nil` if the buffer did not contain enough bytes.\n    public mutating func readUUIDBytes() -> UUID? {\n        guard let uuid = self.getUUIDBytes(at: self.readerIndex) else {\n            return nil\n        }\n        self.moveReaderIndex(forwardBy: MemoryLayout<uuid_t>.size)\n        return uuid\n    }\n\n    /// Write a `UUID` info the buffer and advances the writer index.\n    ///\n    /// - Parameter uuid: The `UUID` to write into the buffer.\n    /// - Returns: The number of bytes written.\n    @discardableResult\n    public mutating func writeUUIDBytes(_ uuid: UUID) -> Int {\n        let written = self.setUUIDBytes(uuid, at: self.writerIndex)\n        self.moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    /// Get a `UUID` from the 16 bytes starting at the current `readerIndex`. Does not move the reader index.\n    ///\n    /// If there are fewer than 16 bytes starting at `readerIndex` then `nil` will be returned.\n    ///\n    /// This method is equivalent to calling `getUUIDBytes(at: readerIndex)`.\n    ///\n    /// - Returns: A `UUID` value containing the bytes of interest or `nil` if the selected bytes are not readable.\n    @inlinable\n    public func peekUUIDBytes() -> UUID? {\n        self.getUUIDBytes(at: self.readerIndex)\n    }\n}\n\nextension ByteBufferAllocator {\n    /// Create a fresh `ByteBuffer` containing the bytes contained in the given `Data`.\n    ///\n    /// This will allocate a new `ByteBuffer` with enough space to fit the bytes of the `Data` and potentially\n    /// some extra space using Swift's default allocator.\n    public func buffer(data: Data) -> ByteBuffer {\n        var buffer = self.buffer(capacity: data.count)\n        buffer.writeBytes(data)\n        return buffer\n    }\n}\n\n// MARK: - Conformances\nextension ByteBufferView: ContiguousBytes {}\nextension ByteBufferView: DataProtocol {}\nextension ByteBufferView: MutableDataProtocol {}\n\nextension ByteBufferView {\n    public typealias Regions = CollectionOfOne<ByteBufferView>\n\n    public var regions: CollectionOfOne<ByteBufferView> {\n        .init(self)\n    }\n}\n\n// MARK: - Data\nextension Data {\n\n    /// Creates a `Data` from a given `ByteBuffer`. The entire readable portion of the buffer will be read.\n    /// - Parameters:\n    ///   - buffer: The buffer to read.\n    ///   - byteTransferStrategy: Controls how to transfer the bytes. See `ByteTransferStrategy` for an explanation\n    ///                             of the options.\n    public init(buffer: ByteBuffer, byteTransferStrategy: ByteBuffer.ByteTransferStrategy = .automatic) {\n        var buffer = buffer\n        self = buffer.readData(length: buffer.readableBytes, byteTransferStrategy: byteTransferStrategy)!\n    }\n\n}\n"
  },
  {
    "path": "Sources/NIOFoundationCompat/Codable+ByteBuffer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\n\nextension ByteBuffer {\n    /// Attempts to decode the `length` bytes from `index` using the `JSONDecoder` `decoder` as `T`.\n    ///\n    /// - Parameters:\n    ///    - type: The type type that is attempted to be decoded.\n    ///    - decoder: The `JSONDecoder` that is used for the decoding.\n    ///    - index: The index of the first byte to decode.\n    ///    - length: The number of bytes to decode.\n    /// - Returns: The decoded value if successful or `nil` if there are not enough readable bytes available.\n    @inlinable\n    public func getJSONDecodable<T: Decodable>(\n        _ type: T.Type,\n        decoder: JSONDecoder = JSONDecoder(),\n        at index: Int,\n        length: Int\n    ) throws -> T? {\n        guard let data = self.getData(at: index, length: length, byteTransferStrategy: .noCopy) else {\n            return nil\n        }\n        return try decoder.decode(T.self, from: data)\n    }\n\n    /// Reads `length` bytes from this `ByteBuffer` and then attempts to decode them using the `JSONDecoder` `decoder`.\n    ///\n    /// - Parameters:\n    ///    - type: The type type that is attempted to be decoded.\n    ///    - decoder: The `JSONDecoder` that is used for the decoding.\n    ///    - length: The number of bytes to decode.\n    /// - Returns: The decoded value is successful or `nil` if there are not enough readable bytes available.\n    @inlinable\n    public mutating func readJSONDecodable<T: Decodable>(\n        _ type: T.Type,\n        decoder: JSONDecoder = JSONDecoder(),\n        length: Int\n    ) throws -> T? {\n        guard\n            let decoded = try self.getJSONDecodable(\n                T.self,\n                decoder: decoder,\n                at: self.readerIndex,\n                length: length\n            )\n        else {\n            return nil\n        }\n        self.moveReaderIndex(forwardBy: length)\n        return decoded\n    }\n\n    /// Encodes `value` using the `JSONEncoder` `encoder` and set the resulting bytes into this `ByteBuffer` at the\n    /// given `index`.\n    ///\n    /// - Note: The `writerIndex` remains unchanged.\n    ///\n    /// - Parameters:\n    ///   - value: An `Encodable` value to encode.\n    ///   - encoder: The `JSONEncoder` to encode `value` with.\n    ///   - index: The starting index of the bytes for the value into the `ByteBuffer`.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    @discardableResult\n    public mutating func setJSONEncodable<T: Encodable>(\n        _ value: T,\n        encoder: JSONEncoder = JSONEncoder(),\n        at index: Int\n    ) throws -> Int {\n        let data = try encoder.encode(value)\n        return self.setBytes(data, at: index)\n    }\n\n    /// Encodes `value` using the `JSONEncoder` `encoder` and writes the resulting bytes into this `ByteBuffer`.\n    ///\n    /// If successful, this will move the writer index forward by the number of bytes written.\n    ///\n    /// - Parameters:\n    ///   - value: An `Encodable` value to encode.\n    ///   - encoder: The `JSONEncoder` to encode `value` with.\n    /// - Returns: The number of bytes written.\n    @inlinable\n    @discardableResult\n    public mutating func writeJSONEncodable<T: Encodable>(\n        _ value: T,\n        encoder: JSONEncoder = JSONEncoder()\n    ) throws -> Int {\n        let result = try self.setJSONEncodable(value, encoder: encoder, at: self.writerIndex)\n        self.moveWriterIndex(forwardBy: result)\n        return result\n    }\n}\n\nextension JSONDecoder {\n    /// Returns a value of the type you specify, decoded from a JSON object inside the readable bytes of a `ByteBuffer`.\n    ///\n    /// If the `ByteBuffer` does not contain valid JSON, this method throws the\n    /// `DecodingError.dataCorrupted(_:)` error. If a value within the JSON\n    /// fails to decode, this method throws the corresponding error.\n    ///\n    /// - Note: The provided `ByteBuffer` remains unchanged, neither the `readerIndex` nor the `writerIndex` will move.\n    ///         If you would like the `readerIndex` to move, consider using `ByteBuffer.readJSONDecodable(_:length:)`.\n    ///\n    /// - Parameters:\n    ///   - type: The type of the value to decode from the supplied JSON object.\n    ///   - buffer: The `ByteBuffer` that contains JSON object to decode.\n    /// - Returns: The decoded object.\n    public func decode<T: Decodable>(_ type: T.Type, from buffer: ByteBuffer) throws -> T {\n        try buffer.getJSONDecodable(\n            T.self,\n            decoder: self,\n            at: buffer.readerIndex,\n            length: buffer.readableBytes\n        )!  // must work, enough readable bytes// must work, enough readable bytes\n    }\n}\n\nextension JSONEncoder {\n    /// Writes a JSON-encoded representation of the value you supply into the supplied `ByteBuffer`.\n    ///\n    /// - Parameters:\n    ///   - value: The value to encode as JSON.\n    ///   - buffer: The `ByteBuffer` to encode into.\n    public func encode<T: Encodable>(\n        _ value: T,\n        into buffer: inout ByteBuffer\n    ) throws {\n        try buffer.writeJSONEncodable(value, encoder: self)\n    }\n\n    /// Writes a JSON-encoded representation of the value you supply into a `ByteBuffer` that is freshly allocated.\n    ///\n    /// - Parameters:\n    ///   - value: The value to encode as JSON.\n    ///   - allocator: The `ByteBufferAllocator` which is used to allocate the `ByteBuffer` to be returned.\n    /// - Returns: The `ByteBuffer` containing the encoded JSON.\n    public func encodeAsByteBuffer<T: Encodable>(_ value: T, allocator: ByteBufferAllocator) throws -> ByteBuffer {\n        let data = try self.encode(value)\n        var buffer = allocator.buffer(capacity: data.count)\n        buffer.writeBytes(data)\n        return buffer\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFoundationCompat/JSONSerialization+ByteBuffer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\n\nextension JSONSerialization {\n\n    /// Attempts to derive a Foundation object from a ByteBuffer and return it as `T`.\n    ///\n    /// - Parameters:\n    ///    - buffer: The ByteBuffer being used to derive the Foundation type.\n    ///    - options: The reading option used when the parser derives the Foundation type from the ByteBuffer.\n    /// - Returns: The Foundation value if successful or `nil` if there was an issue creating the Foundation type.\n    @inlinable\n    public static func jsonObject(\n        with buffer: ByteBuffer,\n        options: JSONSerialization.ReadingOptions = []\n    ) throws -> Any {\n        try JSONSerialization.jsonObject(with: Data(buffer: buffer), options: options)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOFoundationCompat/WaitSpinningRunLoop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport Foundation\nimport NIOConcurrencyHelpers\nimport NIOCore\n\nextension EventLoopFuture {\n    /// Wait for the resolution of this `EventLoopFuture` by spinning `RunLoop.current` in `mode` until the future\n    /// resolves. The calling thread will be blocked albeit running `RunLoop.current`.\n    ///\n    /// If the `EventLoopFuture` resolves with a value, that value is returned from `waitSpinningRunLoop()`. If\n    /// the `EventLoopFuture` resolves with an error, that error will be thrown instead.\n    /// `waitSpinningRunLoop()` will block whatever thread it is called on, so it must not be called on event loop\n    /// threads: it is primarily useful for testing, or for building interfaces between blocking\n    /// and non-blocking code.\n    ///\n    /// This is also forbidden in async contexts: prefer `EventLoopFuture/get()`.\n    ///\n    /// - Note: The `Value` must be `Sendable` since it is shared outside of the isolation domain of the event loop.\n    ///\n    /// - Returns: The value of the `EventLoopFuture` when it completes.\n    /// - Throws: The error value of the `EventLoopFuture` if it errors.\n    @available(*, noasync, message: \"waitSpinningRunLoop() can block indefinitely, prefer get()\", renamed: \"get()\")\n    @inlinable\n    public func waitSpinningRunLoop(\n        inMode mode: RunLoop.Mode = .default,\n        file: StaticString = #file,\n        line: UInt = #line\n    ) throws -> Value where Value: Sendable {\n        try self._blockingWaitForFutureCompletion(mode: mode, file: file, line: line)\n    }\n\n    @inlinable\n    @inline(never)\n    func _blockingWaitForFutureCompletion(\n        mode: RunLoop.Mode,\n        file: StaticString,\n        line: UInt\n    ) throws -> Value where Value: Sendable {\n        self.eventLoop._preconditionSafeToWait(file: file, line: line)\n\n        let runLoop = RunLoop.current\n\n        let value: NIOLockedValueBox<Result<Value, any Error>?> = NIOLockedValueBox(nil)\n        self.whenComplete { result in\n            value.withLockedValue { value in\n                value = result\n            }\n        }\n\n        while value.withLockedValue({ $0 }) == nil {\n            _ = runLoop.run(mode: mode, before: Date().addingTimeInterval(0.01))\n        }\n\n        return try value.withLockedValue { value in\n            try value!.get()\n        }\n    }\n}\n\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOHTTP1/ByteCollectionUtils.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nprivate let defaultWhitespaces = [\" \", \"\\t\"].map({ $0.utf8.first! })\n\nextension ByteBufferView {\n    internal func trim(limitingElements: [UInt8]) -> ByteBufferView {\n        guard let lastNonWhitespaceIndex = self.lastIndex(where: { !limitingElements.contains($0) }),\n            let firstNonWhitespaceIndex = self.firstIndex(where: { !limitingElements.contains($0) })\n        else {\n            // This buffer is entirely trimmed elements, so trim it to nothing.\n            return self[self.startIndex..<self.startIndex]\n        }\n        return self[firstNonWhitespaceIndex..<index(after: lastNonWhitespaceIndex)]\n    }\n\n    internal func trimSpaces() -> ByteBufferView {\n        trim(limitingElements: defaultWhitespaces)\n    }\n}\n\nextension Sequence where Self.Element == UInt8 {\n    /// Compares the collection of `UInt8`s to a case insensitive collection.\n    ///\n    /// This collection could be get from applying the `UTF8View`\n    ///   property on the string protocol.\n    ///\n    /// - Parameter bytes: The string constant in the form of a collection of `UInt8`\n    /// - Returns: Whether the collection contains **EXACTLY** this array or no, but by ignoring case.\n    internal func compareCaseInsensitiveASCIIBytes<T: Sequence>(to: T) -> Bool\n    where T.Element == UInt8 {\n        // fast path: we can get the underlying bytes of both\n        let maybeMaybeResult = self.withContiguousStorageIfAvailable { lhsBuffer -> Bool? in\n            to.withContiguousStorageIfAvailable { rhsBuffer in\n                if lhsBuffer.count != rhsBuffer.count {\n                    return false\n                }\n\n                for idx in 0..<lhsBuffer.count {\n                    // let's hope this gets vectorised ;)\n                    if lhsBuffer[idx] & 0xdf != rhsBuffer[idx] & 0xdf {\n                        return false\n                    }\n                }\n                return true\n            }\n        }\n\n        if let maybeResult = maybeMaybeResult, let result = maybeResult {\n            return result\n        } else {\n            return self.elementsEqual(to, by: { ($0 & 0xdf) == ($1 & 0xdf) })\n        }\n    }\n}\n\nextension String {\n    internal func isEqualCaseInsensitiveASCIIBytes(to: String) -> Bool {\n        self.utf8.compareCaseInsensitiveASCIIBytes(to: to.utf8)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPDecoder.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n#if compiler(>=6.1)\nprivate import CNIOLLHTTP\n#else\n@_implementationOnly import CNIOLLHTTP\n#endif\n\nextension UnsafeMutablePointer where Pointee == llhttp_t {\n    /// Returns the `KeepAliveState` for the current message that is parsed.\n    fileprivate var keepAliveState: KeepAliveState {\n        c_nio_llhttp_should_keep_alive(self) == 0 ? .close : .keepAlive\n    }\n}\n\nprivate enum HTTPDecodingState {\n    case beforeMessageBegin\n    case afterMessageBegin\n    case url\n    case headerName\n    case headerValue\n    case trailerName\n    case trailerValue\n    case headersComplete\n}\n\nprivate class BetterHTTPParser {\n    /// Maximum size of a HTTP header field name or value.\n    /// This number is derived largely from the historical behaviour of NIO.\n    private static let maximumHeaderFieldSize = 80 * 1024\n\n    var delegate: HTTPDecoderDelegate! = nil\n    private var parser: llhttp_t? = llhttp_t()  // nil if unaccessible because reference passed away exclusively\n    private var settings: UnsafeMutablePointer<llhttp_settings_t>\n    private var decodingState: HTTPDecodingState = .beforeMessageBegin\n    private var firstNonDiscardableOffset: Int? = nil\n    private var currentFieldByteLength = 0\n    private var httpParserOffset = 0\n    private var rawBytesView: UnsafeRawBufferPointer = .init(start: UnsafeRawPointer(bitPattern: 0xcafbabe), count: 0)\n    private var httpErrno: llhttp_errno_t? = nil\n    private var richerError: Error? = nil\n    private let kind: HTTPDecoderKind\n    var requestHeads = CircularBuffer<HTTPRequestHead>(initialCapacity: 1)\n\n    enum MessageContinuation {\n        case normal\n        case skipBody\n        case error(llhttp_errno_t)\n    }\n\n    private static func fromOpaque(_ opaque: UnsafePointer<llhttp_t>?) -> BetterHTTPParser {\n        Unmanaged<BetterHTTPParser>.fromOpaque(UnsafeRawPointer(opaque!.pointee.data)).takeUnretainedValue()\n    }\n\n    init(kind: HTTPDecoderKind) {\n        self.kind = kind\n        self.settings = UnsafeMutablePointer.allocate(capacity: 1)\n        c_nio_llhttp_settings_init(self.settings)\n        self.settings.pointee.on_body = { opaque, bytes, len in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveBodyData(UnsafeRawBufferPointer(start: bytes, count: len))\n            return 0\n        }\n        self.settings.pointee.on_header_field = { opaque, bytes, len in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveHeaderFieldData(\n                UnsafeRawBufferPointer(start: bytes, count: len)\n            )\n        }\n        self.settings.pointee.on_header_value = { opaque, bytes, len in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveHeaderValueData(\n                UnsafeRawBufferPointer(start: bytes, count: len)\n            )\n        }\n        self.settings.pointee.on_status = { opaque, bytes, len in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveStatusData(UnsafeRawBufferPointer(start: bytes, count: len))\n            return 0\n        }\n        self.settings.pointee.on_url = { opaque, bytes, len in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveURLData(UnsafeRawBufferPointer(start: bytes, count: len))\n        }\n        self.settings.pointee.on_chunk_complete = { opaque in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveChunkCompleteNotification()\n            return 0\n        }\n        self.settings.pointee.on_chunk_header = { opaque in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveChunkHeaderNotification()\n            return 0\n        }\n        self.settings.pointee.on_message_begin = { opaque in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveMessageBeginNotification()\n            return 0\n        }\n        self.settings.pointee.on_headers_complete = { opaque in\n            let parser = BetterHTTPParser.fromOpaque(opaque)\n            switch parser.didReceiveHeadersCompleteNotification(\n                versionMajor: Int(opaque!.pointee.http_major),\n                versionMinor: Int(opaque!.pointee.http_minor),\n                statusCode: Int(opaque!.pointee.status_code),\n                isUpgrade: opaque!.pointee.upgrade != 0,\n                method: llhttp_method(rawValue: numericCast(opaque!.pointee.method)),\n                keepAliveState: opaque!.keepAliveState\n            ) {\n            case .normal:\n                return 0\n            case .skipBody:\n                return 1\n            case .error(let err):\n                parser.httpErrno = err\n                return -1  // error\n            }\n        }\n        self.settings.pointee.on_message_complete = { opaque in\n            BetterHTTPParser.fromOpaque(opaque).didReceiveMessageCompleteNotification()\n            // Temporary workaround for https://github.com/nodejs/llhttp/issues/202, should be removed\n            // when that issue is fixed. We're tracking the work in https://github.com/apple/swift-nio/issues/2274.\n            opaque?.pointee.content_length = 0\n            return 0\n        }\n        self.withExclusiveHTTPParser { parserPtr in\n            switch kind {\n            case .request:\n                c_nio_llhttp_init(parserPtr, HTTP_REQUEST, self.settings)\n            case .response:\n                c_nio_llhttp_init(parserPtr, HTTP_RESPONSE, self.settings)\n            }\n        }\n    }\n\n    deinit {\n        self.settings.deallocate()\n    }\n\n    private func start(bytes: UnsafeRawBufferPointer, newState: HTTPDecodingState) {\n        assert(self.firstNonDiscardableOffset == nil)\n        self.firstNonDiscardableOffset = bytes.baseAddress! - self.rawBytesView.baseAddress!\n        self.decodingState = newState\n    }\n\n    private func finish(_ callout: (inout HTTPDecoderDelegate, UnsafeRawBufferPointer) throws -> Void) rethrows {\n        var currentFieldByteLength = 0\n        swap(&currentFieldByteLength, &self.currentFieldByteLength)\n        let start = self.rawBytesView.startIndex + self.firstNonDiscardableOffset!\n        let end = start + currentFieldByteLength\n        self.firstNonDiscardableOffset = nil\n        precondition(start >= self.rawBytesView.startIndex && end <= self.rawBytesView.endIndex)\n        try callout(&self.delegate, .init(rebasing: self.rawBytesView[start..<end]))\n    }\n\n    private func didReceiveBodyData(_ bytes: UnsafeRawBufferPointer) {\n        self.delegate.didReceiveBody(bytes)\n    }\n\n    private func didReceiveHeaderFieldData(_ bytes: UnsafeRawBufferPointer) -> CInt {\n        switch self.decodingState {\n        case .headerName, .trailerName:\n            ()\n        case .headerValue:\n            self.finish { delegate, bytes in\n                delegate.didReceiveHeaderValue(bytes)\n            }\n            self.start(bytes: bytes, newState: .headerName)\n        case .trailerValue:\n            self.finish { delegate, bytes in\n                delegate.didReceiveTrailerValue(bytes)\n            }\n            self.start(bytes: bytes, newState: .trailerName)\n        case .url:\n            self.finish { delegate, bytes in\n                delegate.didReceiveURL(bytes)\n            }\n            self.start(bytes: bytes, newState: .headerName)\n        case .headersComplete:\n            // these are trailers\n            self.start(bytes: bytes, newState: .trailerName)\n        case .afterMessageBegin:\n            // in case we're parsing responses\n            self.start(bytes: bytes, newState: .headerName)\n        case .beforeMessageBegin:\n            preconditionFailure()\n        }\n        return self.validateHeaderLength(bytes.count)\n    }\n\n    private func didReceiveHeaderValueData(_ bytes: UnsafeRawBufferPointer) -> CInt {\n        do {\n            switch self.decodingState {\n            case .headerValue, .trailerValue:\n                ()\n            case .headerName:\n                try self.finish { delegate, bytes in\n                    try delegate.didReceiveHeaderName(bytes)\n                }\n                self.start(bytes: bytes, newState: .headerValue)\n            case .trailerName:\n                try self.finish { delegate, bytes in\n                    try delegate.didReceiveTrailerName(bytes)\n                }\n                self.start(bytes: bytes, newState: .trailerValue)\n            case .beforeMessageBegin, .afterMessageBegin, .headersComplete, .url:\n                preconditionFailure()\n            }\n            return self.validateHeaderLength(bytes.count)\n        } catch {\n            self.richerError = error\n            return -1\n        }\n    }\n\n    private func didReceiveStatusData(_ bytes: UnsafeRawBufferPointer) {\n        // we don't do anything special here because we'll need the whole 'head' anyway\n    }\n\n    private func didReceiveURLData(_ bytes: UnsafeRawBufferPointer) -> CInt {\n        switch self.decodingState {\n        case .url:\n            ()\n        case .afterMessageBegin:\n            self.start(bytes: bytes, newState: .url)\n        case .beforeMessageBegin, .headersComplete, .headerName, .headerValue, .trailerName, .trailerValue:\n            preconditionFailure()\n        }\n        return self.validateHeaderLength(bytes.count)\n    }\n\n    private func didReceiveChunkCompleteNotification() {\n        // nothing special to do, we handle chunks just like any other body part\n    }\n\n    private func didReceiveChunkHeaderNotification() {\n        // nothing special to do, we handle chunks just like any other body part\n    }\n\n    private func didReceiveMessageBeginNotification() {\n        switch self.decodingState {\n        case .beforeMessageBegin:\n            self.decodingState = .afterMessageBegin\n        case .headersComplete, .headerName, .headerValue, .trailerName, .trailerValue, .afterMessageBegin, .url:\n            preconditionFailure()\n        }\n    }\n\n    private func didReceiveMessageCompleteNotification() {\n        switch self.decodingState {\n        case .headersComplete:\n            ()\n        case .trailerValue:\n            self.finish { delegate, bytes in\n                delegate.didReceiveTrailerValue(bytes)\n            }\n        case .beforeMessageBegin, .headerName, .headerValue, .trailerName, .afterMessageBegin, .url:\n            preconditionFailure()\n        }\n        self.decodingState = .beforeMessageBegin\n        self.delegate.didFinishMessage()\n    }\n\n    private func didReceiveHeadersCompleteNotification(\n        versionMajor: Int,\n        versionMinor: Int,\n        statusCode: Int,\n        isUpgrade: Bool,\n        method: llhttp_method,\n        keepAliveState: KeepAliveState\n    ) -> MessageContinuation {\n        switch self.decodingState {\n        case .headerValue:\n            self.finish { delegate, bytes in\n                delegate.didReceiveHeaderValue(bytes)\n            }\n        case .url:\n            self.finish { delegate, bytes in\n                delegate.didReceiveURL(bytes)\n            }\n        case .afterMessageBegin:\n            // we're okay here for responses (as they don't have URLs) but for requests we must have seen a URL/headers\n            precondition(self.kind == .response)\n        case .beforeMessageBegin, .headersComplete, .headerName, .trailerName, .trailerValue:\n            preconditionFailure()\n        }\n        assert(self.firstNonDiscardableOffset == nil)\n        self.decodingState = .headersComplete\n\n        var skipBody = false\n\n        if self.kind == .response {\n            // http_parser doesn't correctly handle responses to HEAD requests. We have to do something\n            // annoyingly opaque here, and in those cases return 1 instead of 0. This forces http_parser\n            // to not expect a request body.\n            //\n            // The same logic applies to CONNECT: RFC 7230 says that regardless of what the headers say,\n            // responses to CONNECT never have HTTP-level bodies.\n            //\n            // Finally, we need to work around a bug in http_parser for 1XX, 204, and 304 responses.\n            // RFC 7230 says:\n            //\n            // > ... any response with a 1xx (Informational),\n            // > 204 (No Content), or 304 (Not Modified) status\n            // > code is always terminated by the first empty line after the\n            // > header fields, regardless of the header fields present in the\n            // > message, and thus cannot contain a message body.\n            //\n            // However, http_parser only does this for responses that do not contain length fields. That\n            // does not meet the requirement of RFC 7230. This is an outstanding http_parser issue:\n            // https://github.com/nodejs/http-parser/issues/251. As a result, we check for these status\n            // codes and override http_parser's handling as well.\n            guard !self.requestHeads.isEmpty else {\n                self.richerError = NIOHTTPDecoderError.unsolicitedResponse\n                return .error(HPE_INTERNAL)\n            }\n\n            if 100 <= statusCode && statusCode < 200 && statusCode != 101 {\n                // if the response status is in the range of 100..<200 but not 101 we don't want to\n                // pop the request method. The actual request head is expected with the next HTTP\n                // head.\n                skipBody = true\n            } else {\n                let method = self.requestHeads.removeFirst().method\n                if method == .HEAD || method == .CONNECT {\n                    skipBody = true\n                } else if statusCode / 100 == 1  // 1XX codes\n                    || statusCode == 204 || statusCode == 304\n                {\n                    skipBody = true\n                }\n            }\n        }\n\n        let success = self.delegate.didFinishHead(\n            versionMajor: versionMajor,\n            versionMinor: versionMinor,\n            isUpgrade: isUpgrade,\n            method: method,\n            statusCode: statusCode,\n            keepAliveState: keepAliveState\n        )\n        guard success else {\n            return .error(HPE_INVALID_VERSION)\n        }\n\n        return skipBody ? .skipBody : .normal\n    }\n\n    func start() {\n        self.withExclusiveHTTPParser { parserPtr in\n            parserPtr.pointee.data = Unmanaged.passRetained(self).toOpaque()\n        }\n    }\n\n    func stop() {\n        self.withExclusiveHTTPParser { parserPtr in\n            let selfRef = parserPtr.pointee.data\n            Unmanaged<BetterHTTPParser>.fromOpaque(selfRef!).release()\n            parserPtr.pointee.data = UnsafeMutableRawPointer(bitPattern: 0xdedbeef)\n        }\n    }\n\n    private func validateHeaderLength(_ newLength: Int) -> CInt {\n        self.currentFieldByteLength += newLength\n        if self.currentFieldByteLength > Self.maximumHeaderFieldSize {\n            self.richerError = HTTPParserError.headerOverflow\n            return -1\n        }\n\n        return 0\n    }\n\n    @inline(__always)  // this need to be optimised away\n    func withExclusiveHTTPParser<T>(_ body: (UnsafeMutablePointer<llhttp_t>) -> T) -> T {\n        var parser: llhttp_t? = nil\n        assert(self.parser != nil, \"parser must not be nil here, must be a re-entrancy issue\")\n        swap(&parser, &self.parser)\n        defer {\n            assert(self.parser == nil, \"parser must not nil here\")\n            swap(&parser, &self.parser)\n        }\n        return body(&parser!)\n    }\n\n    func feedInput(_ bytes: UnsafeRawBufferPointer?) throws -> Int {\n        var bytesRead = 0\n        let parserErrno: llhttp_errno_t = self.withExclusiveHTTPParser { parserPtr -> llhttp_errno_t in\n            var rc: llhttp_errno_t\n\n            if let bytes = bytes {\n                self.rawBytesView = bytes\n                defer {\n                    self.rawBytesView = .init(start: UnsafeRawPointer(bitPattern: 0xdafbabe), count: 0)\n                }\n\n                let startPointer = bytes.baseAddress! + self.httpParserOffset\n                let bytesToRead = bytes.count - self.httpParserOffset\n\n                rc = c_nio_llhttp_execute_swift(\n                    parserPtr,\n                    startPointer,\n                    bytesToRead\n                )\n\n                if rc == HPE_PAUSED_UPGRADE {\n                    // This is a special pause. We don't need to stop here (our other code will prevent us\n                    // parsing past this point, but we do need a special hook to work out how many bytes were read.\n                    // The force-unwrap is safe: we know we hit an \"error\".\n                    bytesRead = UnsafeRawPointer(c_nio_llhttp_get_error_pos(parserPtr)!) - startPointer\n                    c_nio_llhttp_resume_after_upgrade(parserPtr)\n                    rc = HPE_OK\n                } else {\n                    bytesRead = bytesToRead\n                }\n            } else {\n                rc = c_nio_llhttp_finish(parserPtr)\n                bytesRead = 0\n            }\n\n            return rc\n        }\n\n        // self.parser must be non-nil here because we can't be re-entered here (ByteToMessageDecoder guarantee)\n        guard parserErrno == HPE_OK else {\n            // if we chose to abort (eg. wrong HTTP version) the error will be in self.httpErrno, otherwise http_parser\n            // will tell us...\n            // self.parser must be non-nil here because we can't be re-entered here (ByteToMessageDecoder guarantee)\n            // If we have a richer error than the errno code, and the errno is internal, we'll use it. Otherwise, we use the\n            // error from http_parser.\n            let err = self.httpErrno ?? parserErrno\n            if err == HPE_INTERNAL || err == HPE_USER, let richerError = self.richerError {\n                throw richerError\n            } else {\n                throw HTTPParserError.httpError(fromCHTTPParserErrno: err)!\n            }\n        }\n\n        if let firstNonDiscardableOffset = self.firstNonDiscardableOffset {\n            self.httpParserOffset += bytesRead - firstNonDiscardableOffset\n            self.firstNonDiscardableOffset = 0\n            return firstNonDiscardableOffset\n        } else {\n            // By definition we've consumed all of the http parser offset at this stage. There may still be bytes\n            // left in the buffer though: we didn't consume them because they aren't ours to consume, as they may belong\n            // to an upgraded protocol.\n            //\n            // Set the HTTP parser offset back to zero, and tell the parent that we consumed\n            // the whole buffer.\n            let consumedBytes = self.httpParserOffset + bytesRead\n            self.httpParserOffset = 0\n            return consumedBytes\n        }\n    }\n}\n\nprivate protocol HTTPDecoderDelegate {\n    mutating func didReceiveBody(_ bytes: UnsafeRawBufferPointer)\n    mutating func didReceiveHeaderName(_ bytes: UnsafeRawBufferPointer) throws\n    mutating func didReceiveHeaderValue(_ bytes: UnsafeRawBufferPointer)\n    mutating func didReceiveTrailerName(_ bytes: UnsafeRawBufferPointer) throws\n    mutating func didReceiveTrailerValue(_ bytes: UnsafeRawBufferPointer)\n    mutating func didReceiveURL(_ bytes: UnsafeRawBufferPointer)\n    mutating func didFinishHead(\n        versionMajor: Int,\n        versionMinor: Int,\n        isUpgrade: Bool,\n        method: llhttp_method,\n        statusCode: Int,\n        keepAliveState: KeepAliveState\n    ) -> Bool\n    mutating func didFinishMessage()\n}\n\n/// A `ByteToMessageDecoder` used to decode HTTP/1.x responses. See the documentation\n/// on `HTTPDecoder` for more.\n///\n/// The `HTTPResponseDecoder` must be placed later in the channel pipeline than the `HTTPRequestEncoder`,\n/// as it needs to see the outbound messages in order to keep track of what the HTTP request methods\n/// were for accurate decoding.\n///\n/// Rather than set this up manually, consider using `ChannelPipeline.addHTTPClientHandlers`.\npublic typealias HTTPResponseDecoder = HTTPDecoder<HTTPClientResponsePart, HTTPClientRequestPart>\n\n/// A `ByteToMessageDecoder` used to decode HTTP requests. See the documentation\n/// on `HTTPDecoder` for more.\n///\n/// While the `HTTPRequestDecoder` does not currently have a specific ordering requirement in the\n/// `ChannelPipeline` (unlike `HTTPResponseDecoder`), it is possible that it will develop one. For\n/// that reason, applications should try to ensure that the `HTTPRequestDecoder` *later* in the\n/// `ChannelPipeline` than the `HTTPResponseEncoder`.\n///\n/// Rather than set this up manually, consider using `ChannelPipeline.configureHTTPServerPipeline`.\npublic typealias HTTPRequestDecoder = HTTPDecoder<HTTPServerRequestPart, HTTPServerResponsePart>\n\npublic enum HTTPDecoderKind: Sendable {\n    case request\n    case response\n}\n\nextension HTTPDecoder: WriteObservingByteToMessageDecoder\nwhere In == HTTPClientResponsePart, Out == HTTPClientRequestPart {\n    public typealias OutboundIn = Out\n\n    public func write(data: HTTPClientRequestPart) {\n        if case .head(let head) = data {\n            self.parser.requestHeads.append(head)\n        }\n    }\n}\n\n/// A `ChannelInboundHandler` that parses HTTP/1-style messages, converting them from\n/// unstructured bytes to a sequence of HTTP messages.\n///\n/// The `HTTPDecoder` is a generic channel handler which can produce messages in\n/// either the form of `HTTPClientResponsePart` or `HTTPServerRequestPart`: that is,\n/// it produces messages that correspond to the semantic units of HTTP produced by\n/// the remote peer.\npublic final class HTTPDecoder<In, Out>: ByteToMessageDecoder, HTTPDecoderDelegate {\n    public typealias InboundOut = In\n\n    // things we build incrementally\n    private var headers: [(String, String)] = []\n    private var trailers: [(String, String)]? = nil\n    private var currentHeaderName: String? = nil\n    private var url: String? = nil\n    private var isUpgrade: Bool? = nil\n\n    // temporary, set and unset by `feedInput`\n    private var buffer: ByteBuffer? = nil\n    private var context: ChannelHandlerContext? = nil\n\n    // the actual state\n    private let parser: BetterHTTPParser\n    private let leftOverBytesStrategy: RemoveAfterUpgradeStrategy\n    private let informationalResponseStrategy: NIOInformationalResponseStrategy\n    private let kind: HTTPDecoderKind\n    private var stopParsing = false  // set on upgrade or HTTP version error\n    private var lastResponseHeaderWasInformational = false\n\n    /// Creates a new instance of `HTTPDecoder`.\n    ///\n    /// - Parameters:\n    ///   - leftOverBytesStrategy: The strategy to use when removing the decoder from the pipeline and an upgrade was,\n    ///                              detected. Note that this does not affect what happens on EOF.\n    public convenience init(leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes) {\n        self.init(leftOverBytesStrategy: leftOverBytesStrategy, informationalResponseStrategy: .drop)\n    }\n\n    /// Creates a new instance of `HTTPDecoder`.\n    ///\n    /// - Parameters:\n    ///   - leftOverBytesStrategy: The strategy to use when removing the decoder from the pipeline and an upgrade was,\n    ///                              detected. Note that this does not affect what happens on EOF.\n    ///   - informationalResponseStrategy: Should informational responses (like http status 100) be forwarded or dropped.\n    ///                              Default is `.drop`. This property is only respected when decoding responses.\n    public init(\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        informationalResponseStrategy: NIOInformationalResponseStrategy = .drop\n    ) {\n        self.headers.reserveCapacity(16)\n        if In.self == HTTPServerRequestPart.self {\n            self.kind = .request\n        } else if In.self == HTTPClientResponsePart.self {\n            self.kind = .response\n        } else {\n            preconditionFailure(\"unknown HTTP message type \\(In.self)\")\n        }\n        self.parser = BetterHTTPParser(kind: kind)\n        self.leftOverBytesStrategy = leftOverBytesStrategy\n        self.informationalResponseStrategy = informationalResponseStrategy\n    }\n\n    func didReceiveBody(_ bytes: UnsafeRawBufferPointer) {\n        let offset = self.buffer!.withUnsafeReadableBytes { allBytes -> Int in\n            let offset = bytes.baseAddress! - allBytes.baseAddress!\n            assert(offset >= 0)\n            assert(offset + bytes.count <= allBytes.count)\n            return offset\n        }\n        self.buffer!.moveReaderIndex(forwardBy: offset)\n        switch self.kind {\n        case .request:\n            self.context!.fireChannelRead(\n                NIOAny(HTTPServerRequestPart.body(self.buffer!.readSlice(length: bytes.count)!))\n            )\n        case .response:\n            self.context!.fireChannelRead(\n                NIOAny(HTTPClientResponsePart.body(self.buffer!.readSlice(length: bytes.count)!))\n            )\n        }\n\n    }\n\n    func didReceiveHeaderName(_ bytes: UnsafeRawBufferPointer) throws {\n        assert(self.currentHeaderName == nil)\n\n        // Defensive check: llhttp tolerates a zero-length header field name, but we don't.\n        guard bytes.count > 0 else {\n            throw HTTPParserError.invalidHeaderToken\n        }\n        self.currentHeaderName = String(decoding: bytes, as: Unicode.UTF8.self)\n    }\n\n    func didReceiveHeaderValue(_ bytes: UnsafeRawBufferPointer) {\n        self.headers.append((self.currentHeaderName!, String(decoding: bytes, as: Unicode.UTF8.self)))\n        self.currentHeaderName = nil\n    }\n\n    func didReceiveTrailerName(_ bytes: UnsafeRawBufferPointer) throws {\n        assert(self.currentHeaderName == nil)\n\n        // Defensive check: llhttp tolerates a zero-length header field name, but we don't.\n        guard bytes.count > 0 else {\n            throw HTTPParserError.invalidHeaderToken\n        }\n        self.currentHeaderName = String(decoding: bytes, as: Unicode.UTF8.self)\n    }\n\n    func didReceiveTrailerValue(_ bytes: UnsafeRawBufferPointer) {\n        if self.trailers == nil {\n            self.trailers = []\n        }\n        self.trailers?.append((self.currentHeaderName!, String(decoding: bytes, as: Unicode.UTF8.self)))\n        self.currentHeaderName = nil\n    }\n\n    func didReceiveURL(_ bytes: UnsafeRawBufferPointer) {\n        assert(self.url == nil)\n        self.url = String(decoding: bytes, as: Unicode.UTF8.self)\n    }\n\n    fileprivate func didFinishHead(\n        versionMajor: Int,\n        versionMinor: Int,\n        isUpgrade: Bool,\n        method: llhttp_method,\n        statusCode: Int,\n        keepAliveState: KeepAliveState\n    ) -> Bool {\n        let message: NIOAny?\n\n        guard versionMajor == 1 else {\n            self.stopParsing = true\n            self.context!.fireErrorCaught(HTTPParserError.invalidVersion)\n            return false\n        }\n\n        switch self.kind {\n        case .request:\n            let reqHead = HTTPRequestHead(\n                version: .init(major: versionMajor, minor: versionMinor),\n                method: HTTPMethod.from(httpParserMethod: method),\n                uri: self.url!,\n                headers: HTTPHeaders(\n                    self.headers,\n                    keepAliveState: keepAliveState\n                )\n            )\n            message = NIOAny(HTTPServerRequestPart.head(reqHead))\n\n        case .response where (100..<200).contains(statusCode) && statusCode != 101:\n            self.lastResponseHeaderWasInformational = true\n            switch self.informationalResponseStrategy.base {\n            case .forward:\n                let resHeadPart = HTTPClientResponsePart.head(\n                    versionMajor: versionMajor,\n                    versionMinor: versionMinor,\n                    statusCode: statusCode,\n                    keepAliveState: keepAliveState,\n                    headers: self.headers\n                )\n                message = NIOAny(resHeadPart)\n            case .drop:\n                message = nil\n            }\n\n        case .response:\n            self.lastResponseHeaderWasInformational = false\n            let resHeadPart = HTTPClientResponsePart.head(\n                versionMajor: versionMajor,\n                versionMinor: versionMinor,\n                statusCode: statusCode,\n                keepAliveState: keepAliveState,\n                headers: self.headers\n            )\n            message = NIOAny(resHeadPart)\n        }\n        self.url = nil\n        self.headers.removeAll(keepingCapacity: true)\n        if let message = message {\n            self.context!.fireChannelRead(message)\n        }\n        self.isUpgrade = isUpgrade\n        return true\n    }\n\n    func didFinishMessage() {\n        var trailers: [(String, String)]? = nil\n        swap(&trailers, &self.trailers)\n        switch self.kind {\n        case .request:\n            self.context!.fireChannelRead(NIOAny(HTTPServerRequestPart.end(trailers.map(HTTPHeaders.init))))\n        case .response:\n            if !self.lastResponseHeaderWasInformational {\n                self.context!.fireChannelRead(NIOAny(HTTPClientResponsePart.end(trailers.map(HTTPHeaders.init))))\n            }\n        }\n        self.stopParsing = self.isUpgrade!\n        self.isUpgrade = nil\n    }\n\n    public func decoderAdded(context: ChannelHandlerContext) {\n        self.parser.delegate = self\n        self.parser.start()\n    }\n\n    public func decoderRemoved(context: ChannelHandlerContext) {\n        self.parser.stop()\n        self.parser.delegate = nil\n    }\n\n    private func feedEOF(context: ChannelHandlerContext) throws {\n        self.context = context\n        defer {\n            self.context = nil\n        }\n        // we don't care how much http_parser consumed here because we just fed an EOF so there won't be any more data.\n        _ = try self.parser.feedInput(nil)\n    }\n\n    private func feedInput(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws {\n        self.buffer = buffer\n        self.context = context\n        defer {\n            self.buffer = nil\n            self.context = nil\n        }\n        let consumed = try buffer.withUnsafeReadableBytes { bytes -> Int in\n            try self.parser.feedInput(bytes)\n        }\n        buffer.moveReaderIndex(forwardBy: consumed)\n    }\n\n    public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        if !self.stopParsing {\n            try self.feedInput(context: context, buffer: &buffer)\n        }\n        return .needMoreData\n    }\n\n    public func decodeLast(\n        context: ChannelHandlerContext,\n        buffer: inout ByteBuffer,\n        seenEOF: Bool\n    ) throws -> DecodingState {\n        if !self.stopParsing {\n            while buffer.readableBytes > 0, case .continue = try self.decode(context: context, buffer: &buffer) {}\n            if seenEOF {\n                try self.feedEOF(context: context)\n            }\n        }\n        if buffer.readableBytes > 0 && !seenEOF {\n            // We only do this if we haven't seen EOF because the left-overs strategy must only be invoked when we're\n            // sure that this is the completion of an upgrade.\n            switch self.leftOverBytesStrategy {\n            case .dropBytes:\n                ()\n            case .fireError:\n                context.fireErrorCaught(ByteToMessageDecoderError.leftoverDataWhenDone(buffer))\n            case .forwardBytes:\n                context.fireChannelRead(NIOAny(buffer))\n            }\n        }\n        return .needMoreData\n    }\n}\n\n@available(*, unavailable)\nextension HTTPDecoder: Sendable {}\n\n/// Strategy to use when a HTTPDecoder is removed from a pipeline after a HTTP upgrade was detected.\npublic enum RemoveAfterUpgradeStrategy: Sendable {\n    /// Forward all the remaining bytes that are currently buffered in the deccoder to the next handler in the pipeline.\n    case forwardBytes\n    /// Fires a `ByteToMessageDecoder.leftoverDataWhenDone` error through the pipeline\n    case fireError\n    /// Discard all the remaining bytes that are currently buffered in the decoder.\n    case dropBytes\n}\n\n/// Strategy to use when a HTTPDecoder receives an informational HTTP response (1xx except 101)\npublic struct NIOInformationalResponseStrategy: Hashable, Sendable {\n    @usableFromInline\n    enum Base: Sendable {\n        case drop\n        case forward\n    }\n\n    @usableFromInline\n    var base: Base\n\n    @inlinable\n    init(_ base: Base) {\n        self.base = base\n    }\n\n    /// Drop the informational response and only forward the \"real\" response\n    @inlinable\n    public static var drop: NIOInformationalResponseStrategy {\n        Self(.drop)\n    }\n    /// Forward the informational response and then forward the \"real\" response. This will result in\n    /// multiple `head` before an `end` is emitted.\n    @inlinable\n    public static var forward: NIOInformationalResponseStrategy {\n        Self(.forward)\n    }\n}\n\nextension HTTPParserError {\n    /// Create a `HTTPParserError` from an error returned by `http_parser`.\n    ///\n    /// - Parameter fromCHTTPParserErrno: The error from the underlying library.\n    /// - Returns: The corresponding `HTTPParserError`, or `nil` if there is no\n    ///     corresponding error.\n    fileprivate static func httpError(fromCHTTPParserErrno: llhttp_errno_t) -> HTTPParserError? {\n        switch fromCHTTPParserErrno {\n        case HPE_INTERNAL:\n            return .invalidInternalState\n        case HPE_STRICT:\n            return .strictModeAssertion\n        case HPE_LF_EXPECTED:\n            return .lfExpected\n        case HPE_UNEXPECTED_CONTENT_LENGTH:\n            return .unexpectedContentLength\n        case HPE_CLOSED_CONNECTION:\n            return .closedConnection\n        case HPE_INVALID_METHOD:\n            return .invalidMethod\n        case HPE_INVALID_URL:\n            return .invalidURL\n        case HPE_INVALID_CONSTANT:\n            return .invalidConstant\n        case HPE_INVALID_VERSION:\n            return .invalidVersion\n        case HPE_INVALID_HEADER_TOKEN,\n            HPE_UNEXPECTED_SPACE:\n            return .invalidHeaderToken\n        case HPE_INVALID_CONTENT_LENGTH:\n            return .invalidContentLength\n        case HPE_INVALID_CHUNK_SIZE:\n            return .invalidChunkSize\n        case HPE_INVALID_STATUS:\n            return .invalidStatus\n        case HPE_INVALID_EOF_STATE:\n            return .invalidEOFState\n        case HPE_PAUSED, HPE_PAUSED_UPGRADE, HPE_PAUSED_H2_UPGRADE:\n            return .paused\n        case HPE_INVALID_TRANSFER_ENCODING,\n            HPE_CR_EXPECTED,\n            HPE_CB_MESSAGE_BEGIN,\n            HPE_CB_HEADERS_COMPLETE,\n            HPE_CB_MESSAGE_COMPLETE,\n            HPE_CB_CHUNK_HEADER,\n            HPE_CB_CHUNK_COMPLETE,\n            HPE_USER,\n            HPE_CB_URL_COMPLETE,\n            HPE_CB_STATUS_COMPLETE,\n            HPE_CB_HEADER_FIELD_COMPLETE,\n            HPE_CB_HEADER_VALUE_COMPLETE:\n            // The downside of enums here, we don't have a case for these. Map them to .unknown for now.\n            return .unknown\n        default:\n            return nil\n        }\n    }\n}\n\nextension HTTPMethod {\n    /// Create a `HTTPMethod` from a given `http_method` produced by\n    /// `http_parser`.\n    ///\n    /// - Parameter httpParserMethod: The method returned by `http_parser`.\n    /// - Returns: The corresponding `HTTPMethod`.\n    fileprivate static func from(httpParserMethod: llhttp_method) -> HTTPMethod {\n        switch httpParserMethod {\n        case HTTP_DELETE:\n            return .DELETE\n        case HTTP_GET:\n            return .GET\n        case HTTP_HEAD:\n            return .HEAD\n        case HTTP_POST:\n            return .POST\n        case HTTP_PUT:\n            return .PUT\n        case HTTP_CONNECT:\n            return .CONNECT\n        case HTTP_OPTIONS:\n            return .OPTIONS\n        case HTTP_TRACE:\n            return .TRACE\n        case HTTP_COPY:\n            return .COPY\n        case HTTP_LOCK:\n            return .LOCK\n        case HTTP_MKCOL:\n            return .MKCOL\n        case HTTP_MOVE:\n            return .MOVE\n        case HTTP_PROPFIND:\n            return .PROPFIND\n        case HTTP_PROPPATCH:\n            return .PROPPATCH\n        case HTTP_SEARCH:\n            return .SEARCH\n        case HTTP_UNLOCK:\n            return .UNLOCK\n        case HTTP_BIND:\n            return .BIND\n        case HTTP_REBIND:\n            return .REBIND\n        case HTTP_UNBIND:\n            return .UNBIND\n        case HTTP_ACL:\n            return .ACL\n        case HTTP_REPORT:\n            return .REPORT\n        case HTTP_MKACTIVITY:\n            return .MKACTIVITY\n        case HTTP_CHECKOUT:\n            return .CHECKOUT\n        case HTTP_MERGE:\n            return .MERGE\n        case HTTP_MSEARCH:\n            return .MSEARCH\n        case HTTP_NOTIFY:\n            return .NOTIFY\n        case HTTP_SUBSCRIBE:\n            return .SUBSCRIBE\n        case HTTP_UNSUBSCRIBE:\n            return .UNSUBSCRIBE\n        case HTTP_PATCH:\n            return .PATCH\n        case HTTP_PURGE:\n            return .PURGE\n        case HTTP_MKCALENDAR:\n            return .MKCALENDAR\n        case HTTP_LINK:\n            return .LINK\n        case HTTP_UNLINK:\n            return .UNLINK\n        case HTTP_SOURCE:\n            // This isn't ideal really.\n            return .RAW(value: \"SOURCE\")\n        case HTTP_PRI:\n            return .RAW(value: \"PRI\")\n        case HTTP_DESCRIBE:\n            return .RAW(value: \"DESCRIBE\")\n        case HTTP_ANNOUNCE:\n            return .RAW(value: \"ANNOUNCE\")\n        case HTTP_SETUP:\n            return .RAW(value: \"SETUP\")\n        case HTTP_PLAY:\n            return .RAW(value: \"PLAY\")\n        case HTTP_PAUSE:\n            return .RAW(value: \"PAUSE\")\n        case HTTP_TEARDOWN:\n            return .RAW(value: \"TEARDOWN\")\n        case HTTP_GET_PARAMETER:\n            return .RAW(value: \"GET_PARAMETER\")\n        case HTTP_SET_PARAMETER:\n            return .RAW(value: \"SET_PARAMETER\")\n        case HTTP_REDIRECT:\n            return .RAW(value: \"REDIRECT\")\n        case HTTP_RECORD:\n            return .RAW(value: \"RECORD\")\n        case HTTP_FLUSH:\n            return .RAW(value: \"FLUSH\")\n        default:\n            return .RAW(value: String(cString: c_nio_llhttp_method_name(httpParserMethod)))\n        }\n    }\n}\n\n/// Errors thrown by `HTTPRequestDecoder` and `HTTPResponseDecoder` in addition to\n/// `HTTPParserError`.\npublic struct NIOHTTPDecoderError: Error {\n    private enum BaseError: Hashable {\n        case unsolicitedResponse\n    }\n\n    private let baseError: BaseError\n}\n\nextension NIOHTTPDecoderError {\n    /// A response was received from a server without an associated request having been sent.\n    public static let unsolicitedResponse: NIOHTTPDecoderError = .init(baseError: .unsolicitedResponse)\n}\n\nextension NIOHTTPDecoderError: Hashable {}\n\nextension NIOHTTPDecoderError: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        String(describing: self.baseError)\n    }\n}\n\nextension HTTPClientResponsePart {\n    fileprivate static func head(\n        versionMajor: Int,\n        versionMinor: Int,\n        statusCode: Int,\n        keepAliveState: KeepAliveState,\n        headers: [(String, String)]\n    ) -> HTTPClientResponsePart {\n        HTTPClientResponsePart.head(\n            HTTPResponseHead(\n                version: .init(major: versionMajor, minor: versionMinor),\n                status: .init(statusCode: statusCode),\n                headers: HTTPHeaders(headers, keepAliveState: keepAliveState)\n            )\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPEncoder.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nprivate func writeChunk(\n    wrapOutboundOut: (IOData) -> NIOAny,\n    context: ChannelHandlerContext,\n    isChunked: Bool,\n    chunk: IOData,\n    promise: EventLoopPromise<Void>?\n) {\n    let readableBytes = chunk.readableBytes\n\n    // we don't want to copy the chunk unnecessarily and therefore call write an annoyingly large number of times\n    // we also don't frame empty chunks as they would otherwise end the response stream\n    // we still need to write the empty IODate to complete the promise in the right order but is otherwise a no-op.\n    if isChunked && readableBytes > 0 {\n        let (mW1, mW2, mW3): (EventLoopPromise<Void>?, EventLoopPromise<Void>?, EventLoopPromise<Void>?)\n\n        if let p = promise {\n            // chunked encoding and the user's interested: we need three promises and need to cascade into the users promise\n            let (w1, w2, w3) = (\n                context.eventLoop.makePromise() as EventLoopPromise<Void>,\n                context.eventLoop.makePromise() as EventLoopPromise<Void>,\n                context.eventLoop.makePromise() as EventLoopPromise<Void>\n            )\n            w1.futureResult.and(w2.futureResult).and(w3.futureResult).map { (_: ((((), ()), ()))) in }.cascade(to: p)\n            (mW1, mW2, mW3) = (w1, w2, w3)\n        } else {\n            // user isn't interested, let's not bother even allocating promises\n            (mW1, mW2, mW3) = (nil, nil, nil)\n        }\n\n        var buffer = context.channel.allocator.buffer(capacity: 32)\n        let len = String(readableBytes, radix: 16)\n        buffer.writeString(len)\n        buffer.writeStaticString(\"\\r\\n\")\n        context.write(wrapOutboundOut(.byteBuffer(buffer)), promise: mW1)\n\n        context.write(wrapOutboundOut(chunk), promise: mW2)\n\n        // Just move the buffers readerIndex to only make the \\r\\n readable and depend on COW semantics.\n        buffer.moveReaderIndex(forwardBy: buffer.readableBytes - 2)\n        context.write(wrapOutboundOut(.byteBuffer(buffer)), promise: mW3)\n    } else {\n        context.write(wrapOutboundOut(chunk), promise: promise)\n    }\n}\n\nprivate func writeTrailers(\n    wrapOutboundOut: (IOData) -> NIOAny,\n    context: ChannelHandlerContext,\n    isChunked: Bool,\n    trailers: HTTPHeaders?,\n    promise: EventLoopPromise<Void>?\n) {\n    switch (isChunked, promise) {\n    case (true, let p):\n        var buffer: ByteBuffer\n        if let trailers = trailers {\n            buffer = context.channel.allocator.buffer(capacity: 256)\n            buffer.writeStaticString(\"0\\r\\n\")\n            buffer.write(headers: trailers)  // Includes trailing CRLF.\n        } else {\n            buffer = context.channel.allocator.buffer(capacity: 8)\n            buffer.writeStaticString(\"0\\r\\n\\r\\n\")\n        }\n        context.write(wrapOutboundOut(.byteBuffer(buffer)), promise: p)\n    case (false, .some(let p)):\n        // Not chunked so we have nothing to write. However, we don't want to satisfy this promise out-of-order\n        // so we issue a zero-length write down the chain.\n        let buf = context.channel.allocator.buffer(capacity: 0)\n        context.write(wrapOutboundOut(.byteBuffer(buf)), promise: p)\n    case (false, .none):\n        break\n    }\n}\n\n// starting about swift-5.0-DEVELOPMENT-SNAPSHOT-2019-01-20-a, this doesn't get automatically inlined, which costs\n// 2 extra allocations so we need to help the optimiser out.\n@inline(__always)\nprivate func writeHead(\n    wrapOutboundOut: (IOData) -> NIOAny,\n    writeStartLine: (inout ByteBuffer) -> Void,\n    context: ChannelHandlerContext,\n    headers: HTTPHeaders,\n    promise: EventLoopPromise<Void>?\n) {\n\n    var buffer = context.channel.allocator.buffer(capacity: 256)\n    writeStartLine(&buffer)\n    buffer.write(headers: headers)\n    context.write(wrapOutboundOut(.byteBuffer(buffer)), promise: promise)\n}\n\n/// The type of framing that is used to mark the end of the body.\nprivate enum BodyFraming {\n    case chunked\n    case contentLength\n    case neither\n}\n\n/// Adjusts the response/request headers to ensure that the response/request will be well-framed.\n///\n/// This method strips Content-Length and Transfer-Encoding headers from responses/requests that must\n/// not have a body. It also adds Transfer-Encoding headers to responses/requests that do have bodies\n/// but do not have any other transport headers when using HTTP/1.1. This ensures that we can\n/// always safely reuse a connection.\n///\n/// Note that for HTTP/1.0 if there is no Content-Length then the response should be followed\n/// by connection close. We require that the user send that connection close: we don't do it.\nprivate func correctlyFrameTransportHeaders(\n    hasBody: HTTPMethod.HasBody,\n    headers: inout HTTPHeaders,\n    version: HTTPVersion\n) -> BodyFraming {\n    switch hasBody {\n    case .no:\n        headers.remove(name: \"content-length\")\n        headers.remove(name: \"transfer-encoding\")\n        return .neither\n    case .yes:\n        if headers.contains(name: \"content-length\") {\n            return .contentLength\n        }\n        if version.major == 1 && version.minor >= 1 {\n            headers.replaceOrAdd(name: \"transfer-encoding\", value: \"chunked\")\n            return .chunked\n        } else {\n            return .neither\n        }\n    case .unlikely:\n        if headers.contains(name: \"content-length\") {\n            return .contentLength\n        }\n        if version.major == 1 && version.minor >= 1 {\n            return headers[\"transfer-encoding\"].first == \"chunked\" ? .chunked : .neither\n        }\n        return .neither\n    }\n}\n\n/// Validates the response/request headers to ensure that we correctly send the body with chunked transfer\n/// encoding, when needed.\nprivate func messageIsChunked(headers: HTTPHeaders, version: HTTPVersion) -> Bool {\n    if version.major == 1 && version.minor >= 1 {\n        return headers.first(name: \"transfer-encoding\") == \"chunked\" ? true : false\n    } else {\n        return false\n    }\n}\n\n/// A `ChannelOutboundHandler` that can serialize HTTP requests.\n///\n/// This channel handler is used to translate messages from a series of\n/// `HTTPClientRequestPart` into the HTTP/1.1 wire format.\npublic final class HTTPRequestEncoder: ChannelOutboundHandler, RemovableChannelHandler {\n    public typealias OutboundIn = HTTPClientRequestPart\n    public typealias OutboundOut = IOData\n\n    /// Configuration for the ``HTTPRequestEncoder``.\n    ///\n    /// This object controls the behaviour of the ``HTTPRequestEncoder``. It enables users to\n    /// change the default behaviour of the type to better handle a wide range of use-cases.\n    public struct Configuration: Sendable, Hashable {\n        /// Whether the ``HTTPRequestEncoder`` should automatically add `Content-Length` or\n        /// `Transfer-Encoding` headers when appropriate.\n        ///\n        /// Defaults to `true`.\n        ///\n        /// Set to `false` if you are confident you are appropriately setting these framing\n        /// headers yourself, to skip NIO's transformation.\n        public var automaticallySetFramingHeaders: Bool\n\n        public init() {\n            self.automaticallySetFramingHeaders = true\n        }\n    }\n\n    private var isChunked = false\n\n    private var configuration: Configuration\n\n    public convenience init() {\n        self.init(configuration: Configuration())\n    }\n\n    public init(configuration: Configuration) {\n        self.configuration = configuration\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        switch HTTPRequestEncoder.unwrapOutboundIn(data) {\n        case .head(var request):\n            assert(\n                !(request.headers.contains(name: \"content-length\")\n                    && request.headers[canonicalForm: \"transfer-encoding\"].contains(\"chunked\"[...])),\n                \"illegal HTTP sent: \\(request) contains both a content-length and transfer-encoding:chunked\"\n            )\n            if self.configuration.automaticallySetFramingHeaders {\n                self.isChunked =\n                    correctlyFrameTransportHeaders(\n                        hasBody: request.method.hasRequestBody,\n                        headers: &request.headers,\n                        version: request.version\n                    ) == .chunked\n            } else {\n                self.isChunked = messageIsChunked(headers: request.headers, version: request.version)\n            }\n\n            writeHead(\n                wrapOutboundOut: HTTPRequestEncoder.wrapOutboundOut,\n                writeStartLine: { buffer in\n                    buffer.write(request: request)\n                },\n                context: context,\n                headers: request.headers,\n                promise: promise\n            )\n        case .body(let bodyPart):\n            writeChunk(\n                wrapOutboundOut: HTTPRequestEncoder.wrapOutboundOut,\n                context: context,\n                isChunked: self.isChunked,\n                chunk: bodyPart,\n                promise: promise\n            )\n        case .end(let trailers):\n            writeTrailers(\n                wrapOutboundOut: HTTPRequestEncoder.wrapOutboundOut,\n                context: context,\n                isChunked: self.isChunked,\n                trailers: trailers,\n                promise: promise\n            )\n        }\n    }\n}\n\n@available(*, unavailable)\nextension HTTPRequestEncoder: Sendable {}\n\n/// A `ChannelOutboundHandler` that can serialize HTTP responses.\n///\n/// This channel handler is used to translate messages from a series of\n/// `HTTPServerResponsePart` into the HTTP/1.1 wire format.\npublic final class HTTPResponseEncoder: ChannelOutboundHandler, RemovableChannelHandler {\n    public typealias OutboundIn = HTTPServerResponsePart\n    public typealias OutboundOut = IOData\n\n    /// Configuration for the ``HTTPResponseEncoder``.\n    ///\n    /// This object controls the behaviour of the ``HTTPResponseEncoder``. It enables users to\n    /// change the default behaviour of the type to better handle a wide range of use-cases.\n    public struct Configuration: Sendable, Hashable {\n        /// Whether the ``HTTPResponseEncoder`` should automatically add `Content-Length` or\n        /// `Transfer-Encoding` headers when appropriate.\n        ///\n        /// Defaults to `true`.\n        ///\n        /// Set to `false` if you are confident you are appropriately setting these framing\n        /// headers yourself, to skip NIO's transformation.\n        public var automaticallySetFramingHeaders: Bool\n\n        public init() {\n            self.automaticallySetFramingHeaders = true\n        }\n    }\n\n    private var isChunked = false\n\n    private var configuration: Configuration\n\n    public convenience init() {\n        self.init(configuration: Configuration())\n    }\n\n    public init(configuration: Configuration) {\n        self.configuration = configuration\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        switch HTTPResponseEncoder.unwrapOutboundIn(data) {\n        case .head(var response):\n            assert(\n                !(response.headers.contains(name: \"content-length\")\n                    && response.headers[canonicalForm: \"transfer-encoding\"].contains(\"chunked\"[...])),\n                \"illegal HTTP sent: \\(response) contains both a content-length and transfer-encoding:chunked\"\n            )\n\n            if self.configuration.automaticallySetFramingHeaders {\n                self.isChunked =\n                    correctlyFrameTransportHeaders(\n                        hasBody: response.status.mayHaveResponseBody ? .yes : .no,\n                        headers: &response.headers,\n                        version: response.version\n                    ) == .chunked\n            } else {\n                self.isChunked = messageIsChunked(headers: response.headers, version: response.version)\n            }\n\n            writeHead(\n                wrapOutboundOut: HTTPResponseEncoder.wrapOutboundOut,\n                writeStartLine: { buffer in\n                    buffer.write(response: response)\n                },\n                context: context,\n                headers: response.headers,\n                promise: promise\n            )\n        case .body(let bodyPart):\n            writeChunk(\n                wrapOutboundOut: HTTPResponseEncoder.wrapOutboundOut,\n                context: context,\n                isChunked: self.isChunked,\n                chunk: bodyPart,\n                promise: promise\n            )\n        case .end(let trailers):\n            writeTrailers(\n                wrapOutboundOut: HTTPResponseEncoder.wrapOutboundOut,\n                context: context,\n                isChunked: self.isChunked,\n                trailers: trailers,\n                promise: promise\n            )\n        }\n    }\n}\n\n@available(*, unavailable)\nextension HTTPResponseEncoder: Sendable {}\n\nextension ByteBuffer {\n    private mutating func write(status: HTTPResponseStatus) {\n        self.writeString(String(status.code))\n        self.writeWhitespace()\n        self.writeString(status.reasonPhrase)\n    }\n\n    fileprivate mutating func write(response: HTTPResponseHead) {\n        switch (response.version.major, response.version.minor, response.status) {\n        // Optimization for HTTP/1.0\n        case (1, 0, .custom(_, _)):\n            self.writeStaticString(\"HTTP/1.0 \")\n            self.write(status: response.status)\n            self.writeStaticString(\"\\r\\n\")\n        case (1, 0, .continue):\n            self.writeStaticString(\"HTTP/1.0 100 Continue\\r\\n\")\n        case (1, 0, .switchingProtocols):\n            self.writeStaticString(\"HTTP/1.0 101 Switching Protocols\\r\\n\")\n        case (1, 0, .processing):\n            self.writeStaticString(\"HTTP/1.0 102 Processing\\r\\n\")\n        case (1, 0, .ok):\n            self.writeStaticString(\"HTTP/1.0 200 OK\\r\\n\")\n        case (1, 0, .created):\n            self.writeStaticString(\"HTTP/1.0 201 Created\\r\\n\")\n        case (1, 0, .accepted):\n            self.writeStaticString(\"HTTP/1.0 202 Accepted\\r\\n\")\n        case (1, 0, .nonAuthoritativeInformation):\n            self.writeStaticString(\"HTTP/1.0 203 Non-Authoritative Information\\r\\n\")\n        case (1, 0, .noContent):\n            self.writeStaticString(\"HTTP/1.0 204 No Content\\r\\n\")\n        case (1, 0, .resetContent):\n            self.writeStaticString(\"HTTP/1.0 205 Reset Content\\r\\n\")\n        case (1, 0, .partialContent):\n            self.writeStaticString(\"HTTP/1.0 206 Partial Content\\r\\n\")\n        case (1, 0, .multiStatus):\n            self.writeStaticString(\"HTTP/1.0 207 Multi-Status\\r\\n\")\n        case (1, 0, .alreadyReported):\n            self.writeStaticString(\"HTTP/1.0 208 Already Reported\\r\\n\")\n        case (1, 0, .imUsed):\n            self.writeStaticString(\"HTTP/1.0 226 IM Used\\r\\n\")\n        case (1, 0, .multipleChoices):\n            self.writeStaticString(\"HTTP/1.0 300 Multiple Choices\\r\\n\")\n        case (1, 0, .movedPermanently):\n            self.writeStaticString(\"HTTP/1.0 301 Moved Permanently\\r\\n\")\n        case (1, 0, .found):\n            self.writeStaticString(\"HTTP/1.0 302 Found\\r\\n\")\n        case (1, 0, .seeOther):\n            self.writeStaticString(\"HTTP/1.0 303 See Other\\r\\n\")\n        case (1, 0, .notModified):\n            self.writeStaticString(\"HTTP/1.0 304 Not Modified\\r\\n\")\n        case (1, 0, .useProxy):\n            self.writeStaticString(\"HTTP/1.0 305 Use Proxy\\r\\n\")\n        case (1, 0, .temporaryRedirect):\n            self.writeStaticString(\"HTTP/1.0 307 Tempory Redirect\\r\\n\")\n        case (1, 0, .permanentRedirect):\n            self.writeStaticString(\"HTTP/1.0 308 Permanent Redirect\\r\\n\")\n        case (1, 0, .badRequest):\n            self.writeStaticString(\"HTTP/1.0 400 Bad Request\\r\\n\")\n        case (1, 0, .unauthorized):\n            self.writeStaticString(\"HTTP/1.0 401 Unauthorized\\r\\n\")\n        case (1, 0, .paymentRequired):\n            self.writeStaticString(\"HTTP/1.0 402 Payment Required\\r\\n\")\n        case (1, 0, .forbidden):\n            self.writeStaticString(\"HTTP/1.0 403 Forbidden\\r\\n\")\n        case (1, 0, .notFound):\n            self.writeStaticString(\"HTTP/1.0 404 Not Found\\r\\n\")\n        case (1, 0, .methodNotAllowed):\n            self.writeStaticString(\"HTTP/1.0 405 Method Not Allowed\\r\\n\")\n        case (1, 0, .notAcceptable):\n            self.writeStaticString(\"HTTP/1.0 406 Not Acceptable\\r\\n\")\n        case (1, 0, .proxyAuthenticationRequired):\n            self.writeStaticString(\"HTTP/1.0 407 Proxy Authentication Required\\r\\n\")\n        case (1, 0, .requestTimeout):\n            self.writeStaticString(\"HTTP/1.0 408 Request Timeout\\r\\n\")\n        case (1, 0, .conflict):\n            self.writeStaticString(\"HTTP/1.0 409 Conflict\\r\\n\")\n        case (1, 0, .gone):\n            self.writeStaticString(\"HTTP/1.0 410 Gone\\r\\n\")\n        case (1, 0, .lengthRequired):\n            self.writeStaticString(\"HTTP/1.0 411 Length Required\\r\\n\")\n        case (1, 0, .preconditionFailed):\n            self.writeStaticString(\"HTTP/1.0 412 Precondition Failed\\r\\n\")\n        case (1, 0, .payloadTooLarge):\n            self.writeStaticString(\"HTTP/1.0 413 Payload Too Large\\r\\n\")\n        case (1, 0, .uriTooLong):\n            self.writeStaticString(\"HTTP/1.0 414 URI Too Long\\r\\n\")\n        case (1, 0, .unsupportedMediaType):\n            self.writeStaticString(\"HTTP/1.0 415 Unsupported Media Type\\r\\n\")\n        case (1, 0, .rangeNotSatisfiable):\n            self.writeStaticString(\"HTTP/1.0 416 Range Not Satisfiable\\r\\n\")\n        case (1, 0, .expectationFailed):\n            self.writeStaticString(\"HTTP/1.0 417 Expectation Failed\\r\\n\")\n        case (1, 0, .misdirectedRequest):\n            self.writeStaticString(\"HTTP/1.0 421 Misdirected Request\\r\\n\")\n        case (1, 0, .unprocessableEntity):\n            self.writeStaticString(\"HTTP/1.0 422 Unprocessable Entity\\r\\n\")\n        case (1, 0, .locked):\n            self.writeStaticString(\"HTTP/1.0 423 Locked\\r\\n\")\n        case (1, 0, .failedDependency):\n            self.writeStaticString(\"HTTP/1.0 424 Failed Dependency\\r\\n\")\n        case (1, 0, .upgradeRequired):\n            self.writeStaticString(\"HTTP/1.0 426 Upgrade Required\\r\\n\")\n        case (1, 0, .preconditionRequired):\n            self.writeStaticString(\"HTTP/1.0 428 Precondition Required\\r\\n\")\n        case (1, 0, .tooManyRequests):\n            self.writeStaticString(\"HTTP/1.0 429 Too Many Requests\\r\\n\")\n        case (1, 0, .requestHeaderFieldsTooLarge):\n            self.writeStaticString(\"HTTP/1.0 431 Request Header Fields Too Large\\r\\n\")\n        case (1, 0, .unavailableForLegalReasons):\n            self.writeStaticString(\"HTTP/1.0 451 Unavailable For Legal Reasons\\r\\n\")\n        case (1, 0, .internalServerError):\n            self.writeStaticString(\"HTTP/1.0 500 Internal Server Error\\r\\n\")\n        case (1, 0, .notImplemented):\n            self.writeStaticString(\"HTTP/1.0 501 Not Implemented\\r\\n\")\n        case (1, 0, .badGateway):\n            self.writeStaticString(\"HTTP/1.0 502 Bad Gateway\\r\\n\")\n        case (1, 0, .serviceUnavailable):\n            self.writeStaticString(\"HTTP/1.0 503 Service Unavailable\\r\\n\")\n        case (1, 0, .gatewayTimeout):\n            self.writeStaticString(\"HTTP/1.0 504 Gateway Timeout\\r\\n\")\n        case (1, 0, .httpVersionNotSupported):\n            self.writeStaticString(\"HTTP/1.0 505 HTTP Version Not Supported\\r\\n\")\n        case (1, 0, .variantAlsoNegotiates):\n            self.writeStaticString(\"HTTP/1.0 506 Variant Also Negotiates\\r\\n\")\n        case (1, 0, .insufficientStorage):\n            self.writeStaticString(\"HTTP/1.0 507 Insufficient Storage\\r\\n\")\n        case (1, 0, .loopDetected):\n            self.writeStaticString(\"HTTP/1.0 508 Loop Detected\\r\\n\")\n        case (1, 0, .notExtended):\n            self.writeStaticString(\"HTTP/1.0 510 Not Extended\\r\\n\")\n        case (1, 0, .networkAuthenticationRequired):\n            self.writeStaticString(\"HTTP/1.1 511 Network Authentication Required\\r\\n\")\n\n        // Optimization for HTTP/1.1\n        case (1, 1, .custom(_, _)):\n            self.writeStaticString(\"HTTP/1.1 \")\n            self.write(status: response.status)\n            self.writeStaticString(\"\\r\\n\")\n        case (1, 1, .continue):\n            self.writeStaticString(\"HTTP/1.1 100 Continue\\r\\n\")\n        case (1, 1, .switchingProtocols):\n            self.writeStaticString(\"HTTP/1.1 101 Switching Protocols\\r\\n\")\n        case (1, 1, .processing):\n            self.writeStaticString(\"HTTP/1.1 102 Processing\\r\\n\")\n        case (1, 1, .ok):\n            self.writeStaticString(\"HTTP/1.1 200 OK\\r\\n\")\n        case (1, 1, .created):\n            self.writeStaticString(\"HTTP/1.1 201 Created\\r\\n\")\n        case (1, 1, .accepted):\n            self.writeStaticString(\"HTTP/1.1 202 Accepted\\r\\n\")\n        case (1, 1, .nonAuthoritativeInformation):\n            self.writeStaticString(\"HTTP/1.1 203 Non-Authoritative Information\\r\\n\")\n        case (1, 1, .noContent):\n            self.writeStaticString(\"HTTP/1.1 204 No Content\\r\\n\")\n        case (1, 1, .resetContent):\n            self.writeStaticString(\"HTTP/1.1 205 Reset Content\\r\\n\")\n        case (1, 1, .partialContent):\n            self.writeStaticString(\"HTTP/1.1 206 Partial Content\\r\\n\")\n        case (1, 1, .multiStatus):\n            self.writeStaticString(\"HTTP/1.1 207 Multi-Status\\r\\n\")\n        case (1, 1, .alreadyReported):\n            self.writeStaticString(\"HTTP/1.1 208 Already Reported\\r\\n\")\n        case (1, 1, .imUsed):\n            self.writeStaticString(\"HTTP/1.1 226 IM Used\\r\\n\")\n        case (1, 1, .multipleChoices):\n            self.writeStaticString(\"HTTP/1.1 300 Multiple Choices\\r\\n\")\n        case (1, 1, .movedPermanently):\n            self.writeStaticString(\"HTTP/1.1 301 Moved Permanently\\r\\n\")\n        case (1, 1, .found):\n            self.writeStaticString(\"HTTP/1.1 302 Found\\r\\n\")\n        case (1, 1, .seeOther):\n            self.writeStaticString(\"HTTP/1.1 303 See Other\\r\\n\")\n        case (1, 1, .notModified):\n            self.writeStaticString(\"HTTP/1.1 304 Not Modified\\r\\n\")\n        case (1, 1, .useProxy):\n            self.writeStaticString(\"HTTP/1.1 305 Use Proxy\\r\\n\")\n        case (1, 1, .temporaryRedirect):\n            self.writeStaticString(\"HTTP/1.1 307 Tempory Redirect\\r\\n\")\n        case (1, 1, .permanentRedirect):\n            self.writeStaticString(\"HTTP/1.1 308 Permanent Redirect\\r\\n\")\n        case (1, 1, .badRequest):\n            self.writeStaticString(\"HTTP/1.1 400 Bad Request\\r\\n\")\n        case (1, 1, .unauthorized):\n            self.writeStaticString(\"HTTP/1.1 401 Unauthorized\\r\\n\")\n        case (1, 1, .paymentRequired):\n            self.writeStaticString(\"HTTP/1.1 402 Payment Required\\r\\n\")\n        case (1, 1, .forbidden):\n            self.writeStaticString(\"HTTP/1.1 403 Forbidden\\r\\n\")\n        case (1, 1, .notFound):\n            self.writeStaticString(\"HTTP/1.1 404 Not Found\\r\\n\")\n        case (1, 1, .methodNotAllowed):\n            self.writeStaticString(\"HTTP/1.1 405 Method Not Allowed\\r\\n\")\n        case (1, 1, .notAcceptable):\n            self.writeStaticString(\"HTTP/1.1 406 Not Acceptable\\r\\n\")\n        case (1, 1, .proxyAuthenticationRequired):\n            self.writeStaticString(\"HTTP/1.1 407 Proxy Authentication Required\\r\\n\")\n        case (1, 1, .requestTimeout):\n            self.writeStaticString(\"HTTP/1.1 408 Request Timeout\\r\\n\")\n        case (1, 1, .conflict):\n            self.writeStaticString(\"HTTP/1.1 409 Conflict\\r\\n\")\n        case (1, 1, .gone):\n            self.writeStaticString(\"HTTP/1.1 410 Gone\\r\\n\")\n        case (1, 1, .lengthRequired):\n            self.writeStaticString(\"HTTP/1.1 411 Length Required\\r\\n\")\n        case (1, 1, .preconditionFailed):\n            self.writeStaticString(\"HTTP/1.1 412 Precondition Failed\\r\\n\")\n        case (1, 1, .payloadTooLarge):\n            self.writeStaticString(\"HTTP/1.1 413 Payload Too Large\\r\\n\")\n        case (1, 1, .uriTooLong):\n            self.writeStaticString(\"HTTP/1.1 414 URI Too Long\\r\\n\")\n        case (1, 1, .unsupportedMediaType):\n            self.writeStaticString(\"HTTP/1.1 415 Unsupported Media Type\\r\\n\")\n        case (1, 1, .rangeNotSatisfiable):\n            self.writeStaticString(\"HTTP/1.1 416 Request Range Not Satisified\\r\\n\")\n        case (1, 1, .expectationFailed):\n            self.writeStaticString(\"HTTP/1.1 417 Expectation Failed\\r\\n\")\n        case (1, 1, .misdirectedRequest):\n            self.writeStaticString(\"HTTP/1.1 421 Misdirected Request\\r\\n\")\n        case (1, 1, .unprocessableEntity):\n            self.writeStaticString(\"HTTP/1.1 422 Unprocessable Entity\\r\\n\")\n        case (1, 1, .locked):\n            self.writeStaticString(\"HTTP/1.1 423 Locked\\r\\n\")\n        case (1, 1, .failedDependency):\n            self.writeStaticString(\"HTTP/1.1 424 Failed Dependency\\r\\n\")\n        case (1, 1, .upgradeRequired):\n            self.writeStaticString(\"HTTP/1.1 426 Upgrade Required\\r\\n\")\n        case (1, 1, .preconditionRequired):\n            self.writeStaticString(\"HTTP/1.1 428 Precondition Required\\r\\n\")\n        case (1, 1, .tooManyRequests):\n            self.writeStaticString(\"HTTP/1.1 429 Too Many Requests\\r\\n\")\n        case (1, 1, .requestHeaderFieldsTooLarge):\n            self.writeStaticString(\"HTTP/1.1 431 Range Not Satisfiable\\r\\n\")\n        case (1, 1, .unavailableForLegalReasons):\n            self.writeStaticString(\"HTTP/1.1 451 Unavailable For Legal Reasons\\r\\n\")\n        case (1, 1, .internalServerError):\n            self.writeStaticString(\"HTTP/1.1 500 Internal Server Error\\r\\n\")\n        case (1, 1, .notImplemented):\n            self.writeStaticString(\"HTTP/1.1 501 Not Implemented\\r\\n\")\n        case (1, 1, .badGateway):\n            self.writeStaticString(\"HTTP/1.1 502 Bad Gateway\\r\\n\")\n        case (1, 1, .serviceUnavailable):\n            self.writeStaticString(\"HTTP/1.1 503 Service Unavailable\\r\\n\")\n        case (1, 1, .gatewayTimeout):\n            self.writeStaticString(\"HTTP/1.1 504 Gateway Timeout\\r\\n\")\n        case (1, 1, .httpVersionNotSupported):\n            self.writeStaticString(\"HTTP/1.1 505 HTTP Version Not Supported\\r\\n\")\n        case (1, 1, .variantAlsoNegotiates):\n            self.writeStaticString(\"HTTP/1.1 506 Variant Also Negotiates\\r\\n\")\n        case (1, 1, .insufficientStorage):\n            self.writeStaticString(\"HTTP/1.1 507 Insufficient Storage\\r\\n\")\n        case (1, 1, .loopDetected):\n            self.writeStaticString(\"HTTP/1.1 508 Loop Detected\\r\\n\")\n        case (1, 1, .notExtended):\n            self.writeStaticString(\"HTTP/1.1 510 Not Extended\\r\\n\")\n        case (1, 1, .networkAuthenticationRequired):\n            self.writeStaticString(\"HTTP/1.1 511 Network Authentication Required\\r\\n\")\n\n        // Fallback for non-known HTTP version\n        default:\n            self.write(version: response.version)\n            self.writeWhitespace()\n            self.write(status: response.status)\n            self.writeStaticString(\"\\r\\n\")\n        }\n    }\n\n    private mutating func write(version: HTTPVersion) {\n        switch (version.minor, version.major) {\n        case (1, 0):\n            self.writeStaticString(\"HTTP/1.0\")\n        case (1, 1):\n            self.writeStaticString(\"HTTP/1.1\")\n        default:\n            self.writeStaticString(\"HTTP/\")\n            self.writeString(String(version.major))\n            self.writeStaticString(\".\")\n            self.writeString(String(version.minor))\n        }\n    }\n\n    fileprivate mutating func write(request: HTTPRequestHead) {\n        self.write(method: request.method)\n        self.writeWhitespace()\n        self.writeString(request.uri)\n        self.writeWhitespace()\n        self.write(version: request.version)\n        self.writeStaticString(\"\\r\\n\")\n    }\n\n    fileprivate mutating func writeWhitespace() {\n        self.writeInteger(32, as: UInt8.self)\n    }\n\n    private mutating func write(method: HTTPMethod) {\n        switch method {\n        case .GET:\n            self.writeStaticString(\"GET\")\n        case .PUT:\n            self.writeStaticString(\"PUT\")\n        case .ACL:\n            self.writeStaticString(\"ACL\")\n        case .HEAD:\n            self.writeStaticString(\"HEAD\")\n        case .POST:\n            self.writeStaticString(\"POST\")\n        case .COPY:\n            self.writeStaticString(\"COPY\")\n        case .LOCK:\n            self.writeStaticString(\"LOCK\")\n        case .MOVE:\n            self.writeStaticString(\"MOVE\")\n        case .BIND:\n            self.writeStaticString(\"BIND\")\n        case .LINK:\n            self.writeStaticString(\"LINK\")\n        case .PATCH:\n            self.writeStaticString(\"PATCH\")\n        case .TRACE:\n            self.writeStaticString(\"TRACE\")\n        case .MKCOL:\n            self.writeStaticString(\"MKCOL\")\n        case .MERGE:\n            self.writeStaticString(\"MERGE\")\n        case .PURGE:\n            self.writeStaticString(\"PURGE\")\n        case .NOTIFY:\n            self.writeStaticString(\"NOTIFY\")\n        case .SEARCH:\n            self.writeStaticString(\"SEARCH\")\n        case .UNLOCK:\n            self.writeStaticString(\"UNLOCK\")\n        case .REBIND:\n            self.writeStaticString(\"REBIND\")\n        case .UNBIND:\n            self.writeStaticString(\"UNBIND\")\n        case .REPORT:\n            self.writeStaticString(\"REPORT\")\n        case .DELETE:\n            self.writeStaticString(\"DELETE\")\n        case .UNLINK:\n            self.writeStaticString(\"UNLINK\")\n        case .CONNECT:\n            self.writeStaticString(\"CONNECT\")\n        case .MSEARCH:\n            self.writeStaticString(\"MSEARCH\")\n        case .OPTIONS:\n            self.writeStaticString(\"OPTIONS\")\n        case .PROPFIND:\n            self.writeStaticString(\"PROPFIND\")\n        case .CHECKOUT:\n            self.writeStaticString(\"CHECKOUT\")\n        case .PROPPATCH:\n            self.writeStaticString(\"PROPPATCH\")\n        case .SUBSCRIBE:\n            self.writeStaticString(\"SUBSCRIBE\")\n        case .MKCALENDAR:\n            self.writeStaticString(\"MKCALENDAR\")\n        case .MKACTIVITY:\n            self.writeStaticString(\"MKACTIVITY\")\n        case .UNSUBSCRIBE:\n            self.writeStaticString(\"UNSUBSCRIBE\")\n        case .SOURCE:\n            self.writeStaticString(\"SOURCE\")\n        case .RAW(let value):\n            self.writeString(value)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPHeaderValidator.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// A ChannelHandler to validate that outbound request headers are spec-compliant.\n///\n/// The HTTP RFCs constrain the bytes that are validly present within a HTTP/1.1 header block.\n/// ``NIOHTTPRequestHeadersValidator`` polices this constraint and ensures that only valid header blocks\n/// are emitted on the network. If a header block is invalid, then ``NIOHTTPRequestHeadersValidator``\n/// will send a ``HTTPParserError/invalidHeaderToken``.\n///\n/// ``NIOHTTPRequestHeadersValidator`` will also valid that the HTTP trailers are within specification,\n/// if they are present.\npublic final class NIOHTTPRequestHeadersValidator: ChannelOutboundHandler, RemovableChannelHandler {\n    public typealias OutboundIn = HTTPClientRequestPart\n    public typealias OutboundOut = HTTPClientRequestPart\n\n    public init() {}\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        switch NIOHTTPRequestHeadersValidator.unwrapOutboundIn(data) {\n        case .head(let head):\n            guard head.headers.areValidToSend else {\n                promise?.fail(HTTPParserError.invalidHeaderToken)\n                context.fireErrorCaught(HTTPParserError.invalidHeaderToken)\n                return\n            }\n        case .body, .end(.none):\n            ()\n        case .end(.some(let trailers)):\n            guard trailers.areValidToSend else {\n                promise?.fail(HTTPParserError.invalidHeaderToken)\n                context.fireErrorCaught(HTTPParserError.invalidHeaderToken)\n                return\n            }\n        }\n\n        context.write(data, promise: promise)\n    }\n}\n\n/// A ChannelHandler to validate that outbound response headers are spec-compliant.\n///\n/// The HTTP RFCs constrain the bytes that are validly present within a HTTP/1.1 header block.\n/// ``NIOHTTPResponseHeadersValidator`` polices this constraint and ensures that only valid header blocks\n/// are emitted on the network. If a header block is invalid, then ``NIOHTTPResponseHeadersValidator``\n/// will send a ``HTTPParserError/invalidHeaderToken``.\n///\n/// ``NIOHTTPResponseHeadersValidator`` will also valid that the HTTP trailers are within specification,\n/// if they are present.\npublic final class NIOHTTPResponseHeadersValidator: ChannelOutboundHandler, RemovableChannelHandler {\n    public typealias OutboundIn = HTTPServerResponsePart\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    private enum State {\n        /// Validating response parts.\n        case validating\n        /// Dropping all response parts. This is a terminal state.\n        case dropping\n    }\n\n    private var state: State\n\n    public init() {\n        self.state = .validating\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        switch (NIOHTTPResponseHeadersValidator.unwrapOutboundIn(data), self.state) {\n        case (.head(let head), .validating):\n            if head.headers.areValidToSend {\n                context.write(data, promise: promise)\n            } else {\n                self.state = .dropping\n                promise?.fail(HTTPParserError.invalidHeaderToken)\n                context.fireErrorCaught(HTTPParserError.invalidHeaderToken)\n            }\n\n        case (.body, .validating):\n            context.write(data, promise: promise)\n\n        case (.end(let trailers), .validating):\n            // No trailers are always valid trailers.\n            if trailers?.areValidToSend ?? true {\n                context.write(data, promise: promise)\n            } else {\n                self.state = .dropping\n                promise?.fail(HTTPParserError.invalidHeaderToken)\n                context.fireErrorCaught(HTTPParserError.invalidHeaderToken)\n            }\n\n        case (.head, .dropping), (.body, .dropping), (.end, .dropping):\n            promise?.fail(HTTPParserError.invalidHeaderToken)\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIOHTTPRequestHeadersValidator: Sendable {}\n\n@available(*, unavailable)\nextension NIOHTTPResponseHeadersValidator: Sendable {}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPHeaders+Validation.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension String {\n    /// Validates a given header field value against the definition in RFC 9110.\n    ///\n    /// The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n    /// characters as the following:\n    ///\n    /// ```\n    /// field-value    = *field-content\n    /// field-content  = field-vchar\n    ///                  [ 1*( SP / HTAB / field-vchar ) field-vchar ]\n    /// field-vchar    = VCHAR / obs-text\n    /// obs-text       = %x80-FF\n    /// ```\n    ///\n    /// Additionally, it makes the following note:\n    ///\n    /// \"Field values containing CR, LF, or NUL characters are invalid and dangerous, due to the\n    /// varying ways that implementations might parse and interpret those characters; a recipient\n    /// of CR, LF, or NUL within a field value MUST either reject the message or replace each of\n    /// those characters with SP before further processing or forwarding of that message. Field\n    /// values containing other CTL characters are also invalid; however, recipients MAY retain\n    /// such characters for the sake of robustness when they appear within a safe context (e.g.,\n    /// an application-specific quoted string that will not be processed by any downstream HTTP\n    /// parser).\"\n    ///\n    /// As we cannot guarantee the context is safe, this code will reject all ASCII control characters\n    /// directly _except_ for HTAB, which is explicitly allowed.\n    fileprivate var isValidHeaderFieldValue: Bool {\n        let fastResult = self.utf8.withContiguousStorageIfAvailable { ptr in\n            ptr.allSatisfy { $0.isValidHeaderFieldValueByte }\n        }\n        if let fastResult = fastResult {\n            return fastResult\n        } else {\n            return self.utf8._isValidHeaderFieldValue_slowPath\n        }\n    }\n\n    /// Validates a given header field name against the definition in RFC 9110.\n    ///\n    /// The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n    /// characters as the following:\n    ///\n    /// ```\n    /// field-name     = token\n    ///\n    /// token          = 1*tchar\n    ///\n    /// tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n    ///                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n    ///                / DIGIT / ALPHA\n    ///                ; any VCHAR, except delimiters\n    /// ```\n    ///\n    /// We implement this check directly.\n    fileprivate var isValidHeaderFieldName: Bool {\n        let fastResult = self.utf8.withContiguousStorageIfAvailable { ptr in\n            ptr.allSatisfy { $0.isValidHeaderFieldNameByte }\n        }\n        if let fastResult = fastResult {\n            return fastResult\n        } else {\n            return self.utf8._isValidHeaderFieldName_slowPath\n        }\n    }\n}\n\nextension String.UTF8View {\n    /// The equivalent of `String.isValidHeaderFieldName`, but a slow-path when a\n    /// contiguous UTF8 storage is not available.\n    ///\n    /// This is deliberately `@inline(never)`, as slow paths should be forcibly outlined\n    /// to encourage inlining the fast-path.\n    @inline(never)\n    fileprivate var _isValidHeaderFieldName_slowPath: Bool {\n        self.allSatisfy { $0.isValidHeaderFieldNameByte }\n    }\n\n    /// The equivalent of `String.isValidHeaderFieldValue`, but a slow-path when a\n    /// contiguous UTF8 storage is not available.\n    ///\n    /// This is deliberately `@inline(never)`, as slow paths should be forcibly outlined\n    /// to encourage inlining the fast-path.\n    @inline(never)\n    fileprivate var _isValidHeaderFieldValue_slowPath: Bool {\n        self.allSatisfy { $0.isValidHeaderFieldValueByte }\n    }\n}\n\nextension UInt8 {\n    /// Validates a byte of a given header field name against the definition in RFC 9110.\n    ///\n    /// The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n    /// characters as the following:\n    ///\n    /// ```\n    /// field-name     = token\n    ///\n    /// token          = 1*tchar\n    ///\n    /// tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n    ///                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n    ///                / DIGIT / ALPHA\n    ///                ; any VCHAR, except delimiters\n    /// ```\n    ///\n    /// We implement this check directly.\n    ///\n    /// We use inline always here to force the check to be inlined, which it isn't always, leading to less optimal code.\n    @inline(__always)\n    fileprivate var isValidHeaderFieldNameByte: Bool {\n        switch self {\n        case UInt8(ascii: \"0\")...UInt8(ascii: \"9\"),  // DIGIT\n            UInt8(ascii: \"a\")...UInt8(ascii: \"z\"),\n            UInt8(ascii: \"A\")...UInt8(ascii: \"Z\"),  // ALPHA\n            UInt8(ascii: \"!\"), UInt8(ascii: \"#\"),\n            UInt8(ascii: \"$\"), UInt8(ascii: \"%\"),\n            UInt8(ascii: \"&\"), UInt8(ascii: \"'\"),\n            UInt8(ascii: \"*\"), UInt8(ascii: \"+\"),\n            UInt8(ascii: \"-\"), UInt8(ascii: \".\"),\n            UInt8(ascii: \"^\"), UInt8(ascii: \"_\"),\n            UInt8(ascii: \"`\"), UInt8(ascii: \"|\"),\n            UInt8(ascii: \"~\"):\n\n            return true\n\n        default:\n            return false\n        }\n    }\n\n    /// Validates a byte of a given header field value against the definition in RFC 9110.\n    ///\n    /// The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n    /// characters as the following:\n    ///\n    /// ```\n    /// field-value    = *field-content\n    /// field-content  = field-vchar\n    ///                  [ 1*( SP / HTAB / field-vchar ) field-vchar ]\n    /// field-vchar    = VCHAR / obs-text\n    /// obs-text       = %x80-FF\n    /// ```\n    ///\n    /// Additionally, it makes the following note:\n    ///\n    /// \"Field values containing CR, LF, or NUL characters are invalid and dangerous, due to the\n    /// varying ways that implementations might parse and interpret those characters; a recipient\n    /// of CR, LF, or NUL within a field value MUST either reject the message or replace each of\n    /// those characters with SP before further processing or forwarding of that message. Field\n    /// values containing other CTL characters are also invalid; however, recipients MAY retain\n    /// such characters for the sake of robustness when they appear within a safe context (e.g.,\n    /// an application-specific quoted string that will not be processed by any downstream HTTP\n    /// parser).\"\n    ///\n    /// As we cannot guarantee the context is safe, this code will reject all ASCII control characters\n    /// directly _except_ for HTAB, which is explicitly allowed.\n    ///\n    /// We use inline always here to force the check to be inlined, which it isn't always, leading to less optimal code.\n    @inline(__always)\n    fileprivate var isValidHeaderFieldValueByte: Bool {\n        switch self {\n        case UInt8(ascii: \"\\t\"):\n            // HTAB, explicitly allowed.\n            return true\n        case 0...0x1f, 0x7F:\n            // ASCII control character, forbidden.\n            return false\n        default:\n            // Printable or non-ASCII, allowed.\n            return true\n        }\n    }\n}\n\nextension HTTPHeaders {\n    /// Whether these HTTPHeaders are valid to send on the wire.\n    var areValidToSend: Bool {\n        for (name, value) in self.headers {\n            if !name.isValidHeaderFieldName {\n                return false\n            }\n\n            if !value.isValidHeaderFieldValue {\n                return false\n            }\n        }\n\n        return true\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPPipelineSetup.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Configuration required to configure a HTTP client pipeline for upgrade.\n///\n/// See the documentation for `HTTPClientUpgradeHandler` for details on these\n/// properties.\npublic typealias NIOHTTPClientUpgradeConfiguration = (\n    upgraders: [NIOHTTPClientProtocolUpgrader], completionHandler: @Sendable (ChannelHandlerContext) -> Void\n)\n\npublic typealias NIOHTTPClientUpgradeSendableConfiguration = (\n    upgraders: [NIOHTTPClientProtocolUpgrader & Sendable], completionHandler: @Sendable (ChannelHandlerContext) -> Void\n)\n\n/// Configuration required to configure a HTTP server pipeline for upgrade.\n///\n/// See the documentation for `HTTPServerUpgradeHandler` for details on these\n/// properties.\n@available(*, deprecated, renamed: \"NIOHTTPServerUpgradeConfiguration\")\npublic typealias HTTPUpgradeConfiguration = NIOHTTPServerUpgradeConfiguration\n\npublic typealias NIOHTTPServerUpgradeConfiguration = (\n    upgraders: [HTTPServerProtocolUpgrader], completionHandler: @Sendable (ChannelHandlerContext) -> Void\n)\n\npublic typealias NIOHTTPServerUpgradeSendableConfiguration = (\n    upgraders: [HTTPServerProtocolUpgrader & Sendable], completionHandler: @Sendable (ChannelHandlerContext) -> Void\n)\n\nextension ChannelPipeline {\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    public func addHTTPClientHandlers(\n        position: Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes\n    ) -> EventLoopFuture<Void> {\n        self.addHTTPClientHandlers(\n            position: position,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            withClientUpgrade: nil\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.\n    ///\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - upgrade: Add a `HTTPClientUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of `HTTPClientProtocolUpgrader` and\n    ///         the upgrade completion handler. See the documentation on `HTTPClientUpgradeHandler`\n    ///         for more details.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    @preconcurrency\n    public func addHTTPClientHandlers(\n        position: Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeSendableConfiguration?\n    ) -> EventLoopFuture<Void> {\n        self._addHTTPClientHandlers(\n            position: position,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    private func _addHTTPClientHandlers(\n        position: Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeSendableConfiguration?\n    ) -> EventLoopFuture<Void> {\n        let future: EventLoopFuture<Void>\n\n        if self.eventLoop.inEventLoop {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            let result = Result<Void, Error> {\n                try self.syncOperations.addHTTPClientHandlers(\n                    position: syncPosition,\n                    leftOverBytesStrategy: leftOverBytesStrategy,\n                    withClientUpgrade: upgrade\n                )\n            }\n            future = self.eventLoop.makeCompletedFuture(result)\n        } else {\n            future = self.eventLoop.submit {\n                let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n                try self.syncOperations.addHTTPClientHandlers(\n                    position: syncPosition,\n                    leftOverBytesStrategy: leftOverBytesStrategy,\n                    withClientUpgrade: upgrade\n                )\n            }\n        }\n\n        return future\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - enableOutboundHeaderValidation: Whether the pipeline should confirm that outbound headers are well-formed.\n    ///         Defaults to `true`.\n    ///   - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientUpgradeHandler`` and\n    ///         the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``\n    ///         for more details.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    @preconcurrency\n    public func addHTTPClientHandlers(\n        position: Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeSendableConfiguration? = nil\n    ) -> EventLoopFuture<Void> {\n        let future: EventLoopFuture<Void>\n\n        if self.eventLoop.inEventLoop {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            let result = Result<Void, Error> {\n                try self.syncOperations.addHTTPClientHandlers(\n                    position: syncPosition,\n                    leftOverBytesStrategy: leftOverBytesStrategy,\n                    enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n                    withClientUpgrade: upgrade\n                )\n            }\n            future = self.eventLoop.makeCompletedFuture(result)\n        } else {\n            future = self.eventLoop.submit {\n                let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n                try self.syncOperations.addHTTPClientHandlers(\n                    position: syncPosition,\n                    leftOverBytesStrategy: leftOverBytesStrategy,\n                    enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n                    withClientUpgrade: upgrade\n                )\n            }\n        }\n\n        return future\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - enableOutboundHeaderValidation: Whether the pipeline should confirm that outbound headers are well-formed.\n    ///         Defaults to `true`.\n    ///   - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.\n    ///   - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientUpgradeHandler`` and\n    ///         the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``\n    ///         for more details.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    @preconcurrency\n    public func addHTTPClientHandlers(\n        position: Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        encoderConfiguration: HTTPRequestEncoder.Configuration = .init(),\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeSendableConfiguration? = nil\n    ) -> EventLoopFuture<Void> {\n        let future: EventLoopFuture<Void>\n\n        if self.eventLoop.inEventLoop {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            let result = Result<Void, Error> {\n                try self.syncOperations.addHTTPClientHandlers(\n                    position: syncPosition,\n                    leftOverBytesStrategy: leftOverBytesStrategy,\n                    enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n                    encoderConfiguration: encoderConfiguration,\n                    withClientUpgrade: upgrade\n                )\n            }\n            future = self.eventLoop.makeCompletedFuture(result)\n        } else {\n            future = self.eventLoop.submit {\n                let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n                try self.syncOperations.addHTTPClientHandlers(\n                    position: syncPosition,\n                    leftOverBytesStrategy: leftOverBytesStrategy,\n                    enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n                    encoderConfiguration: encoderConfiguration,\n                    withClientUpgrade: upgrade\n                )\n            }\n        }\n\n        return future\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    @preconcurrency\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeSendableConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true\n    ) -> EventLoopFuture<Void> {\n        self._configureHTTPServerPipeline(\n            position: position,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     ``HTTPServerPipelineHandler``.\n    /// 2. Supporting HTTP upgrade, using the ``HTTPServerUpgradeHandler``.\n    /// 3. Providing assistance handling protocol errors.\n    /// 4. Validating outbound header fields to protect against response splitting attacks.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    ///   - headerValidation: Whether to validate outbound request headers to confirm that they meet\n    ///         spec compliance. Defaults to `true`.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    @preconcurrency\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeSendableConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true\n    ) -> EventLoopFuture<Void> {\n        self._configureHTTPServerPipeline(\n            position: position,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling,\n            withOutboundHeaderValidation: headerValidation\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     ``HTTPServerPipelineHandler``.\n    /// 2. Supporting HTTP upgrade, using the ``HTTPServerUpgradeHandler``.\n    /// 3. Providing assistance handling protocol errors.\n    /// 4. Validating outbound header fields to protect against response splitting attacks.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    ///   - headerValidation: Whether to validate outbound request headers to confirm that they meet\n    ///         spec compliance. Defaults to `true`.\n    ///   - encoderConfiguration: The configuration for the ``HTTPResponseEncoder``.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured.\n    @preconcurrency\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeSendableConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true,\n        withEncoderConfiguration encoderConfiguration: HTTPResponseEncoder.Configuration = .init()\n    ) -> EventLoopFuture<Void> {\n        self._configureHTTPServerPipeline(\n            position: position,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling,\n            withOutboundHeaderValidation: headerValidation,\n            withEncoderConfiguration: encoderConfiguration\n        )\n    }\n\n    private func _configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeSendableConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true,\n        withEncoderConfiguration encoderConfiguration: HTTPResponseEncoder.Configuration = .init()\n    ) -> EventLoopFuture<Void> {\n        let future: EventLoopFuture<Void>\n\n        if self.eventLoop.inEventLoop {\n            let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n            let result = Result<Void, Error> {\n                try self.syncOperations.configureHTTPServerPipeline(\n                    position: syncPosition,\n                    withPipeliningAssistance: pipelining,\n                    withServerUpgrade: upgrade,\n                    withErrorHandling: errorHandling,\n                    withOutboundHeaderValidation: headerValidation,\n                    withEncoderConfiguration: encoderConfiguration\n                )\n            }\n            future = self.eventLoop.makeCompletedFuture(result)\n        } else {\n            future = self.eventLoop.submit {\n                let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n                try self.syncOperations.configureHTTPServerPipeline(\n                    position: syncPosition,\n                    withPipeliningAssistance: pipelining,\n                    withServerUpgrade: upgrade,\n                    withErrorHandling: errorHandling,\n                    withOutboundHeaderValidation: headerValidation,\n                    withEncoderConfiguration: encoderConfiguration\n                )\n            }\n        }\n\n        return future\n    }\n}\n\nextension ChannelPipeline.SynchronousOperations {\n    /// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - upgrade: Add a `HTTPClientUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of `HTTPClientProtocolUpgrader` and\n    ///         the upgrade completion handler. See the documentation on `HTTPClientUpgradeHandler`\n    ///         for more details.\n    /// - Throws: If the pipeline could not be configured.\n    public func addHTTPClientHandlers(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        try self._addHTTPClientHandlers(\n            position: position,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - upgrade: Add a `HTTPClientUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of `HTTPClientProtocolUpgrader` and\n    ///         the upgrade completion handler. See the documentation on `HTTPClientUpgradeHandler`\n    ///         for more details.\n    /// - Throws: If the pipeline could not be configured.\n    @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n    @_disfavoredOverload\n    @preconcurrency\n    public func addHTTPClientHandlers(\n        position: ChannelPipeline.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        try self._addHTTPClientHandlers(\n            position: syncPosition,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - enableOutboundHeaderValidation: Whether or not request header validation is enforced.\n    ///   - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientProtocolUpgrader`` and\n    ///         the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``\n    ///         for more details.\n    /// - Throws: If the pipeline could not be configured.\n    public func addHTTPClientHandlers(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        try self._addHTTPClientHandlers(\n            position: position,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - enableOutboundHeaderValidation: Whether or not request header validation is enforced.\n    ///   - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientProtocolUpgrader`` and\n    ///         the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``\n    ///         for more details.\n    /// - Throws: If the pipeline could not be configured.\n    @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n    @_disfavoredOverload\n    public func addHTTPClientHandlers(\n        position: ChannelPipeline.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        try self._addHTTPClientHandlers(\n            position: syncPosition,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - enableOutboundHeaderValidation: Whether or not request header validation is enforced.\n    ///   - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.\n    ///   - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientProtocolUpgrader`` and\n    ///         the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``\n    ///         for more details.\n    /// - Throws: If the pipeline could not be configured.\n    public func addHTTPClientHandlers(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        encoderConfiguration: HTTPRequestEncoder.Configuration = .init(),\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        try self._addHTTPClientHandlers(\n            position: position,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n            encoderConfiguration: encoderConfiguration,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP client.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.\n    ///   - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`\n    ///         from the pipeline.\n    ///   - enableOutboundHeaderValidation: Whether or not request header validation is enforced.\n    ///   - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.\n    ///   - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for\n    ///         HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientProtocolUpgrader`` and\n    ///         the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``\n    ///         for more details.\n    /// - Throws: If the pipeline could not be configured.\n    @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n    @_disfavoredOverload\n    public func addHTTPClientHandlers(\n        position: ChannelPipeline.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        encoderConfiguration: HTTPRequestEncoder.Configuration = .init(),\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        try self._addHTTPClientHandlers(\n            position: syncPosition,\n            leftOverBytesStrategy: leftOverBytesStrategy,\n            enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n            encoderConfiguration: encoderConfiguration,\n            withClientUpgrade: upgrade\n        )\n    }\n\n    private func _addHTTPClientHandlers(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,\n        enableOutboundHeaderValidation: Bool = true,\n        encoderConfiguration: HTTPRequestEncoder.Configuration = .init(),\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil\n    ) throws {\n        // Why two separate functions? With the fast-path (no upgrader, yes header validator) we can promote the Array of handlers\n        // to the stack and skip an allocation.\n        if upgrade != nil || enableOutboundHeaderValidation != true {\n            try self._addHTTPClientHandlersFallback(\n                position: position,\n                leftOverBytesStrategy: leftOverBytesStrategy,\n                enableOutboundHeaderValidation: enableOutboundHeaderValidation,\n                encoderConfiguration: encoderConfiguration,\n                withClientUpgrade: upgrade\n            )\n        } else {\n            try self._addHTTPClientHandlers(\n                position: position,\n                leftOverBytesStrategy: leftOverBytesStrategy,\n                encoderConfiguration: encoderConfiguration\n            )\n        }\n    }\n\n    private func _addHTTPClientHandlers(\n        position: ChannelPipeline.SynchronousOperations.Position,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy,\n        encoderConfiguration: HTTPRequestEncoder.Configuration\n    ) throws {\n        self.eventLoop.assertInEventLoop()\n        let requestEncoder = HTTPRequestEncoder(configuration: encoderConfiguration)\n        let responseDecoder = HTTPResponseDecoder(leftOverBytesStrategy: leftOverBytesStrategy)\n        let requestHeaderValidator = NIOHTTPRequestHeadersValidator()\n        let handlers: [ChannelHandler] = [\n            requestEncoder, ByteToMessageHandler(responseDecoder), requestHeaderValidator,\n        ]\n        try self.addHandlers(handlers, position: position)\n    }\n\n    private func _addHTTPClientHandlersFallback(\n        position: ChannelPipeline.SynchronousOperations.Position,\n        leftOverBytesStrategy: RemoveAfterUpgradeStrategy,\n        enableOutboundHeaderValidation: Bool,\n        encoderConfiguration: HTTPRequestEncoder.Configuration,\n        withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration?\n    ) throws {\n        self.eventLoop.assertInEventLoop()\n        let requestEncoder = HTTPRequestEncoder(configuration: encoderConfiguration)\n        let responseDecoder = HTTPResponseDecoder(leftOverBytesStrategy: leftOverBytesStrategy)\n        var handlers: [RemovableChannelHandler] = [requestEncoder, ByteToMessageHandler(responseDecoder)]\n\n        if enableOutboundHeaderValidation {\n            handlers.append(NIOHTTPRequestHeadersValidator())\n        }\n\n        if let upgrade = upgrade {\n            let upgrader = NIOHTTPClientUpgradeHandler(\n                upgraders: upgrade.upgraders,\n                httpHandlers: handlers,\n                upgradeCompletionHandler: upgrade.completionHandler\n            )\n            handlers.append(upgrader)\n        }\n\n        try self.addHandlers(handlers, position: position)\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    /// - Throws: If the pipeline could not be configured.\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true\n    ) throws {\n        try self._configureHTTPServerPipeline(\n            position: position,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    /// - Throws: If the pipeline could not be configured.\n    @preconcurrency\n    @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n    @_disfavoredOverload\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true\n    ) throws {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        try self._configureHTTPServerPipeline(\n            position: syncPosition,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    /// 3. Providing assistance handling protocol errors.\n    /// 4. Validating outbound header fields to protect against response splitting attacks.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    ///   - headerValidation: Whether to validate outbound request headers to confirm that they meet\n    ///         spec compliance. Defaults to `true`.\n    /// - Throws: If the pipeline could not be configured.\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true\n    ) throws {\n        try self._configureHTTPServerPipeline(\n            position: position,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling,\n            withOutboundHeaderValidation: headerValidation\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    /// 3. Providing assistance handling protocol errors.\n    /// 4. Validating outbound header fields to protect against response splitting attacks.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    ///   - headerValidation: Whether to validate outbound request headers to confirm that they meet\n    ///         spec compliance. Defaults to `true`.\n    /// - Throws: If the pipeline could not be configured.\n    @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n    @_disfavoredOverload\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true\n    ) throws {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        try self._configureHTTPServerPipeline(\n            position: syncPosition,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling,\n            withOutboundHeaderValidation: headerValidation\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    /// 3. Providing assistance handling protocol errors.\n    /// 4. Validating outbound header fields to protect against response splitting attacks.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    ///   - headerValidation: Whether to validate outbound request headers to confirm that they meet\n    ///         spec compliance. Defaults to `true`.\n    ///   - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.\n    /// - Throws: If the pipeline could not be configured.\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true,\n        withEncoderConfiguration encoderConfiguration: HTTPResponseEncoder.Configuration\n    ) throws {\n        try self._configureHTTPServerPipeline(\n            position: position,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling,\n            withOutboundHeaderValidation: headerValidation,\n            withEncoderConfiguration: encoderConfiguration\n        )\n    }\n\n    /// Configure a `ChannelPipeline` for use as a HTTP server.\n    ///\n    /// This function knows how to set up all first-party HTTP channel handlers appropriately\n    /// for server use. It supports the following features:\n    ///\n    /// 1. Providing assistance handling clients that pipeline HTTP requests, using the\n    ///     `HTTPServerPipelineHandler`.\n    /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.\n    /// 3. Providing assistance handling protocol errors.\n    /// 4. Validating outbound header fields to protect against response splitting attacks.\n    ///\n    /// This method will likely be extended in future with more support for other first-party\n    /// features.\n    ///\n    /// - important: This **must** be called on the Channel's event loop.\n    /// - Parameters:\n    ///   - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.\n    ///   - pipelining: Whether to provide assistance handling HTTP clients that pipeline\n    ///         their requests. Defaults to `true`. If `false`, users will need to handle\n    ///         clients that pipeline themselves.\n    ///   - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for\n    ///         HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If\n    ///         provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade\n    ///         completion handler. See the documentation on `HTTPServerUpgradeHandler` for more\n    ///         details.\n    ///   - errorHandling: Whether to provide assistance handling protocol errors (e.g.\n    ///         failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.\n    ///   - headerValidation: Whether to validate outbound request headers to confirm that they meet\n    ///         spec compliance. Defaults to `true`.\n    ///   - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.\n    /// - Throws: If the pipeline could not be configured.\n    @available(*, deprecated, message: \"Use ChannelPipeline.SynchronousOperations.Position instead\")\n    @_disfavoredOverload\n    public func configureHTTPServerPipeline(\n        position: ChannelPipeline.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true,\n        withEncoderConfiguration encoderConfiguration: HTTPResponseEncoder.Configuration\n    ) throws {\n        let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)\n        try self._configureHTTPServerPipeline(\n            position: syncPosition,\n            withPipeliningAssistance: pipelining,\n            withServerUpgrade: upgrade,\n            withErrorHandling: errorHandling,\n            withOutboundHeaderValidation: headerValidation,\n            withEncoderConfiguration: encoderConfiguration\n        )\n    }\n\n    private func _configureHTTPServerPipeline(\n        position: ChannelPipeline.SynchronousOperations.Position = .last,\n        withPipeliningAssistance pipelining: Bool = true,\n        withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,\n        withErrorHandling errorHandling: Bool = true,\n        withOutboundHeaderValidation headerValidation: Bool = true,\n        withEncoderConfiguration encoderConfiguration: HTTPResponseEncoder.Configuration = .init()\n    ) throws {\n        self.eventLoop.assertInEventLoop()\n\n        let responseEncoder = HTTPResponseEncoder(configuration: encoderConfiguration)\n        let requestDecoder = HTTPRequestDecoder(leftOverBytesStrategy: upgrade == nil ? .dropBytes : .forwardBytes)\n\n        var handlers: [RemovableChannelHandler] = [responseEncoder, ByteToMessageHandler(requestDecoder)]\n\n        if pipelining {\n            handlers.append(HTTPServerPipelineHandler())\n        }\n\n        if headerValidation {\n            handlers.append(NIOHTTPResponseHeadersValidator())\n        }\n\n        if errorHandling {\n            handlers.append(HTTPServerProtocolErrorHandler())\n        }\n\n        if let (upgraders, completionHandler) = upgrade {\n            let upgrader = HTTPServerUpgradeHandler(\n                upgraders: upgraders,\n                httpEncoder: responseEncoder,\n                extraHTTPHandlers: Array(handlers.dropFirst()),\n                upgradeCompletionHandler: completionHandler\n            )\n            handlers.append(upgrader)\n        }\n\n        try self.addHandlers(handlers, position: position)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPServerPipelineHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// A `ChannelHandler` that handles HTTP pipelining by buffering inbound data until a\n/// response has been sent.\n///\n/// This handler ensures that HTTP server pipelines only process one request at a time.\n/// This is the safest way for pipelining-unaware code to operate, as it ensures that\n/// mutation of any shared server state is not parallelised, and that responses are always\n/// sent for each request in turn. In almost all cases this is the behaviour that a\n/// pipeline will want. This is achieved without doing too much buffering by preventing\n/// the `Channel` from reading from the socket until a complete response is processed,\n/// ensuring that a malicious client is not capable of overwhelming a server by shoving\n/// an enormous amount of data down the `Channel` while a server is processing a\n/// slow response.\n///\n/// See [RFC 7320 Section 6.3.2](https://tools.ietf.org/html/rfc7230#section-6.3.2) for\n/// more details on safely handling HTTP pipelining.\n///\n/// In addition to handling the request buffering, this `ChannelHandler` is aware of\n/// TCP half-close. While there are very few HTTP clients that are capable of TCP\n/// half-close, clients that are not HTTP specific (e.g. `netcat`) may trigger a TCP\n/// half-close. Having this `ChannelHandler` be aware of TCP half-close makes it easier\n/// to build HTTP servers that are resilient to this kind of behaviour.\n///\n/// The TCP half-close handling is done by buffering the half-close notification along\n/// with the HTTP request parts. The half-close notification will be delivered in order\n/// with the rest of the reads. If the half-close occurs either before a request is received\n/// or during a request body upload, it will be delivered immediately. If a half-close is\n/// received immediately after `HTTPServerRequestPart.end`, it will also be passed along\n/// immediately, allowing this signal to be seen by the HTTP server as early as possible.\npublic final class HTTPServerPipelineHandler: ChannelDuplexHandler, RemovableChannelHandler {\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias InboundOut = HTTPServerRequestPart\n    public typealias OutboundIn = HTTPServerResponsePart\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    // If this is true AND we're in a debug build, crash the program when an invariant in violated\n    // Otherwise, we will try to handle the situation as cleanly as possible\n    internal var failOnPreconditions: Bool = true\n\n    public init() {\n        self.nextExpectedInboundMessage = nil\n        self.nextExpectedOutboundMessage = nil\n\n        debugOnly {\n            self.nextExpectedInboundMessage = .head\n            self.nextExpectedOutboundMessage = .head\n        }\n    }\n\n    private enum ConnectionStateAction {\n        /// A precondition has been violated. Should send an error down the pipeline\n        case warnPreconditionViolated(message: String)\n\n        /// A further state change was attempted when a precondition has already been violated.\n        /// Should force close this connection\n        case forceCloseConnection\n\n        /// Nothing to do\n        case none\n    }\n\n    public struct ConnectionStateError: Error, CustomStringConvertible, Hashable {\n        enum Base: Hashable, CustomStringConvertible {\n            /// A precondition was violated\n            case preconditionViolated(message: String)\n\n            var description: String {\n                switch self {\n                case .preconditionViolated(let message):\n                    return \"Precondition violated \\(message)\"\n                }\n            }\n        }\n\n        private var base: Base\n        private var file: String\n        private var line: Int\n\n        private init(base: Base, file: String, line: Int) {\n            self.base = base\n            self.file = file\n            self.line = line\n        }\n\n        public static func == (lhs: ConnectionStateError, rhs: ConnectionStateError) -> Bool {\n            lhs.base == rhs.base\n        }\n\n        public func hash(into hasher: inout Hasher) {\n            hasher.combine(self.base)\n        }\n\n        /// A precondition was violated\n        public static func preconditionViolated(message: String, file: String = #fileID, line: Int = #line) -> Self {\n            .init(base: .preconditionViolated(message: message), file: file, line: line)\n        }\n\n        public var description: String {\n            \"\\(self.base) file \\(self.file) line \\(self.line)\"\n        }\n    }\n\n    /// The state of the HTTP connection.\n    private enum ConnectionState {\n        /// We are waiting for a HTTP response to complete before we\n        /// let the next request in.\n        case responseEndPending\n\n        /// We are in the middle of both a request and a response and waiting for both `.end`s.\n        case requestAndResponseEndPending\n\n        /// Nothing is active on this connection, the next message we expect would be a request `.head`.\n        case idle\n\n        /// The server has responded early, before the request has completed. We need\n        /// to wait for the request to complete, but won't block anything.\n        case requestEndPending\n\n        /// The server has closed the output partway through a request. The server will never\n        /// act again, but this may not be in error, so we'll forward the rest of this request to the server.\n        case sentCloseOutputRequestEndPending\n\n        /// The server has closed the output, and a complete request has been delivered.\n        /// It's never going to act again. Generally we expect this to be closely followed\n        /// by read EOF, but we need to keep reading to make that possible, so we\n        /// never suppress reads again.\n        case sentCloseOutput\n\n        /// The user has violated an invariant. We should refuse further IO now\n        case preconditionFailed\n\n        mutating func requestHeadReceived() -> ConnectionStateAction {\n            switch self {\n            case .preconditionFailed:\n                return .forceCloseConnection\n            case .idle:\n                self = .requestAndResponseEndPending\n                return .none\n            case .requestAndResponseEndPending, .responseEndPending, .requestEndPending,\n                .sentCloseOutputRequestEndPending, .sentCloseOutput:\n                let message = \"received request head in state \\(self)\"\n                self = .preconditionFailed\n                return .warnPreconditionViolated(message: message)\n            }\n        }\n\n        mutating func responseEndReceived() -> ConnectionStateAction {\n            switch self {\n            case .preconditionFailed:\n                return .forceCloseConnection\n            case .responseEndPending:\n                // Got the response we were waiting for.\n                self = .idle\n                return .none\n            case .requestAndResponseEndPending:\n                // We got a response while still receiving a request, which we have to\n                // wait for.\n                self = .requestEndPending\n                return .none\n            case .sentCloseOutput, .sentCloseOutputRequestEndPending:\n                // This is a user error: they have sent close(mode: .output), but are continuing to write.\n                // The write will fail, so we can allow it to pass.\n                return .none\n            case .requestEndPending, .idle:\n                let message = \"Unexpectedly received a response in state \\(self)\"\n                self = .preconditionFailed\n                return .warnPreconditionViolated(message: message)\n            }\n        }\n\n        mutating func requestEndReceived() -> ConnectionStateAction {\n            switch self {\n            case .preconditionFailed:\n                return .forceCloseConnection\n            case .requestEndPending:\n                // Got the request end we were waiting for.\n                self = .idle\n                return .none\n            case .requestAndResponseEndPending:\n                // We got a request and the response isn't done, wait for the\n                // response.\n                self = .responseEndPending\n                return .none\n            case .sentCloseOutputRequestEndPending:\n                // Got the request end we were waiting for.\n                self = .sentCloseOutput\n                return .none\n            case .responseEndPending, .idle, .sentCloseOutput:\n                let message = \"Received second request\"\n                self = .preconditionFailed\n                return .warnPreconditionViolated(message: message)\n            }\n        }\n\n        mutating func closeOutputSent() {\n            switch self {\n            case .preconditionFailed:\n                break\n            case .idle, .responseEndPending:\n                self = .sentCloseOutput\n            case .requestEndPending, .requestAndResponseEndPending:\n                self = .sentCloseOutputRequestEndPending\n            case .sentCloseOutput, .sentCloseOutputRequestEndPending:\n                // Weird to duplicate fail, but we tolerate it in both cases.\n                ()\n            }\n        }\n    }\n\n    /// The events that this handler buffers while waiting for the server to\n    /// generate a response.\n    private enum BufferedEvent {\n        /// A channelRead event.\n        case channelRead(NIOAny)\n\n        case error(HTTPParserError)\n\n        /// A TCP half-close. This is buffered to ensure that subsequent channel\n        /// handlers that are aware of TCP half-close are informed about it in\n        /// the appropriate order.\n        case halfClose\n    }\n\n    /// The connection state\n    private var state = ConnectionState.idle\n\n    /// While we're waiting to send the response we don't read from the socket.\n    /// This keeps track of whether we need to call read() when we've send our response.\n    private var readPending = false\n\n    /// The buffered HTTP requests that are not going to be addressed yet. In general clients\n    /// don't pipeline, so this initially allocates no space for data at all. Clients that\n    /// do pipeline will cause dynamic resizing of the buffer, which is generally acceptable.\n    private var eventBuffer = CircularBuffer<BufferedEvent>(initialCapacity: 0)\n\n    enum NextExpectedMessageType {\n        case head\n        case bodyOrEnd\n    }\n\n    enum LifecycleState {\n        /// Operating normally, accepting all events.\n        case acceptingEvents\n\n        /// Quiescing but we're still waiting for the request's `.end` which means we still need to process input.\n        case quiescingWaitingForRequestEnd\n\n        /// Quiescing and the last request's `.end` has been seen which means we no longer accept any input.\n        case quiescingLastRequestEndReceived\n\n        /// Quiescing and we have issued a channel close. Further I/O here is not expected, and won't be managed.\n        case quiescingCompleted\n    }\n\n    private var lifecycleState: LifecycleState = .acceptingEvents\n\n    // always `nil` in release builds, never `nil` in debug builds\n    private var nextExpectedInboundMessage: Optional<NextExpectedMessageType>\n    // always `nil` in release builds, never `nil` in debug builds\n    private var nextExpectedOutboundMessage: Optional<NextExpectedMessageType>\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch self.lifecycleState {\n        case .quiescingLastRequestEndReceived, .quiescingCompleted:\n            // We're done, no more data for you.\n            return\n        case .acceptingEvents, .quiescingWaitingForRequestEnd:\n            // Still accepting I/O\n            ()\n        }\n\n        if self.state == .sentCloseOutput {\n            // Drop all events in this state.\n            return\n        }\n\n        if self.eventBuffer.count != 0 || self.state == .responseEndPending {\n            self.eventBuffer.append(.channelRead(data))\n            return\n        } else {\n            let connectionStateAction = self.deliverOneMessage(context: context, data: data)\n            _ = self.handleConnectionStateAction(context: context, action: connectionStateAction, promise: nil)\n        }\n    }\n\n    private func deliverOneMessage(context: ChannelHandlerContext, data: NIOAny) -> ConnectionStateAction {\n        self.checkAssertion(\n            self.lifecycleState != .quiescingLastRequestEndReceived && self.lifecycleState != .quiescingCompleted,\n            \"deliverOneMessage called in lifecycle illegal state \\(self.lifecycleState)\"\n        )\n        let msg = self.unwrapInboundIn(data)\n\n        debugOnly {\n            switch msg {\n            case .head:\n                self.checkAssertion(self.nextExpectedInboundMessage == .head)\n                self.nextExpectedInboundMessage = .bodyOrEnd\n            case .body:\n                self.checkAssertion(self.nextExpectedInboundMessage == .bodyOrEnd)\n            case .end:\n                self.checkAssertion(self.nextExpectedInboundMessage == .bodyOrEnd)\n                self.nextExpectedInboundMessage = .head\n            }\n        }\n\n        let action: ConnectionStateAction\n        switch msg {\n        case .head:\n            action = self.state.requestHeadReceived()\n        case .end:\n            // New request is complete. We don't want any more data from now on.\n            action = self.state.requestEndReceived()\n\n            if self.lifecycleState == .quiescingWaitingForRequestEnd {\n                self.lifecycleState = .quiescingLastRequestEndReceived\n                self.eventBuffer.removeAll()\n            }\n            if self.lifecycleState == .quiescingLastRequestEndReceived && self.state == .idle {\n                self.lifecycleState = .quiescingCompleted\n                context.close(promise: nil)\n            }\n        case .body:\n            action = .none\n        }\n\n        context.fireChannelRead(data)\n        return action\n    }\n\n    private func deliverOneError(context: ChannelHandlerContext, error: Error) {\n        // there is one interesting case in this error sending logic: If we receive a `HTTPParserError` and we haven't\n        // received a full request nor the beginning of a response we should treat this as a full request. The reason\n        // is that what the user will probably do is send a `.badRequest` response and we should be in a state which\n        // allows that.\n        if (self.state == .idle || self.state == .requestEndPending) && error is HTTPParserError {\n            self.state = .responseEndPending\n        }\n        context.fireErrorCaught(error)\n    }\n\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch event {\n        case is ChannelShouldQuiesceEvent:\n            self.checkAssertion(\n                self.lifecycleState == .acceptingEvents,\n                \"unexpected lifecycle state when receiving ChannelShouldQuiesceEvent: \\(self.lifecycleState)\"\n            )\n            switch self.state {\n            case .responseEndPending:\n                // we're not in the middle of a request, let's just shut the door\n                self.lifecycleState = .quiescingLastRequestEndReceived\n                self.eventBuffer.removeAll()\n            case .preconditionFailed,\n                // An invariant has been violated already, this time we close the connection\n                .idle, .sentCloseOutput:\n                // we're completely idle, let's just close\n                self.lifecycleState = .quiescingCompleted\n                self.eventBuffer.removeAll()\n                context.close(promise: nil)\n            case .requestEndPending, .requestAndResponseEndPending, .sentCloseOutputRequestEndPending:\n                // we're in the middle of a request, we'll need to keep accepting events until we see the .end.\n                // It's ok for us to forget we saw close output here, the lifecycle event will close for us.\n                self.lifecycleState = .quiescingWaitingForRequestEnd\n            }\n        case ChannelEvent.inputClosed:\n            // We only buffer half-close if there are request parts we're waiting to send.\n            // Otherwise we deliver the half-close immediately. Note that we deliver this\n            // even if the server has sent close output, as it's useful information.\n            if case .responseEndPending = self.state, self.eventBuffer.count > 0 {\n                self.eventBuffer.append(.halfClose)\n            } else {\n                context.fireUserInboundEventTriggered(event)\n            }\n        default:\n            context.fireUserInboundEventTriggered(event)\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        guard let httpError = error as? HTTPParserError else {\n            self.deliverOneError(context: context, error: error)\n            return\n        }\n        if case .responseEndPending = self.state {\n            self.eventBuffer.append(.error(httpError))\n            return\n        }\n        self.deliverOneError(context: context, error: error)\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.checkAssertion(\n            self.state != .requestEndPending,\n            \"Received second response while waiting for first one to complete\"\n        )\n        debugOnly {\n            let res = HTTPServerPipelineHandler.unwrapOutboundIn(data)\n            switch res {\n            case .head(let head) where head.isInformational:\n                self.checkAssertion(self.nextExpectedOutboundMessage == .head)\n            case .head:\n                self.checkAssertion(self.nextExpectedOutboundMessage == .head)\n                self.nextExpectedOutboundMessage = .bodyOrEnd\n            case .body:\n                self.checkAssertion(self.nextExpectedOutboundMessage == .bodyOrEnd)\n            case .end:\n                self.checkAssertion(self.nextExpectedOutboundMessage == .bodyOrEnd)\n                self.nextExpectedOutboundMessage = .head\n            }\n        }\n\n        var startReadingAgain = false\n\n        switch HTTPServerPipelineHandler.unwrapOutboundIn(data) {\n        case .head(var head) where self.lifecycleState != .acceptingEvents:\n            if head.isKeepAlive {\n                head.headers.replaceOrAdd(name: \"connection\", value: \"close\")\n            }\n            context.write(HTTPServerPipelineHandler.wrapOutboundOut(.head(head)), promise: promise)\n        case .end:\n            startReadingAgain = true\n\n            switch self.lifecycleState {\n            case .quiescingWaitingForRequestEnd where self.state == .responseEndPending:\n                // we just received the .end that we're missing so we can fall through to closing the connection\n                fallthrough\n            case .quiescingLastRequestEndReceived:\n                let loopBoundContext = context.loopBound\n                self.lifecycleState = .quiescingCompleted\n                context.write(data).flatMap {\n                    let context = loopBoundContext.value\n                    return context.close()\n                }.cascade(to: promise)\n            case .acceptingEvents, .quiescingWaitingForRequestEnd:\n                context.write(data, promise: promise)\n            case .quiescingCompleted:\n                // Uh, why are we writing more data here? We'll write it, but it should be guaranteed\n                // to fail.\n                self.assertionFailed(\"Wrote in quiescing completed state\")\n                context.write(data, promise: promise)\n            }\n        case .body, .head:\n            context.write(data, promise: promise)\n        }\n\n        if startReadingAgain {\n            let connectionStateAction = self.state.responseEndReceived()\n            if self.handleConnectionStateAction(context: context, action: connectionStateAction, promise: promise) {\n                return\n            }\n            self.deliverPendingRequests(context: context)\n            self.startReading(context: context)\n        }\n    }\n\n    public func read(context: ChannelHandlerContext) {\n        switch self.lifecycleState {\n        case .quiescingLastRequestEndReceived, .quiescingCompleted:\n            // We swallow all reads now, as we're going to close the connection.\n            ()\n        case .acceptingEvents, .quiescingWaitingForRequestEnd:\n            if case .responseEndPending = self.state {\n                self.readPending = true\n            } else {\n                context.read()\n            }\n        }\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        // We're being removed from the pipeline. We need to do a few things:\n        //\n        // 1. If we have buffered events, deliver them. While we shouldn't be\n        //     re-entrantly called, we want to ensure that so we take a local copy.\n        // 2. If we are quiescing, we swallowed a quiescing event from the user: replay it,\n        //     as the user has hopefully added a handler that will do something with this.\n        // 3. Finally, if we have a read pending, we need to release it.\n        //\n        // The basic theory here is that if there is anything we were going to do when we received\n        // either a request .end or a response .end, we do it now because there is no future for us.\n        // We also need to ensure we do not drop any data on the floor.\n        //\n        // At this stage we are no longer in the pipeline, so all further content should be\n        // blocked from reaching us. Thus we can avoid mutating our own internal state any\n        // longer.\n        let bufferedEvents = self.eventBuffer\n        for event in bufferedEvents {\n            switch event {\n            case .channelRead(let read):\n                context.fireChannelRead(read)\n            case .halfClose:\n                context.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n            case .error(let error):\n                context.fireErrorCaught(error)\n            }\n        }\n\n        switch self.lifecycleState {\n        case .quiescingLastRequestEndReceived, .quiescingWaitingForRequestEnd:\n            context.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        case .acceptingEvents, .quiescingCompleted:\n            // Either we haven't quiesced, or we succeeded in doing it.\n            ()\n        }\n\n        if self.readPending {\n            context.read()\n        }\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        // Welp, this channel isn't going to work anymore. We may as well drop our pending events here, as we\n        // cannot be expected to act on them any longer.\n        //\n        // Side note: it's important that we drop these. If we don't, handlerRemoved will deliver them all.\n        // While it's fair to immediately pipeline a channel where the user chose to remove the HTTPPipelineHandler,\n        // it's deeply unfair to do so to a user that didn't choose to do that, where it happened to them only because\n        // the channel closed.\n        //\n        // We set keepingCapacity to avoid this reallocating a buffer, as we'll just free it shortly anyway.\n        self.eventBuffer.removeAll(keepingCapacity: true)\n        context.fireChannelInactive()\n    }\n\n    public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        var shouldRead = false\n\n        if mode == .output {\n            // We need to do special handling here. If the server is closing output they don't intend to write anymore.\n            // That means we want to drop anything up to the end of the in-flight request.\n            self.dropAllButInFlightRequest()\n            self.state.closeOutputSent()\n\n            // If there's a read pending, we should deliver it after we forward the close on.\n            shouldRead = self.readPending\n        }\n\n        context.close(mode: mode, promise: promise)\n\n        // Double-check readPending here in case something weird happened.\n        //\n        // Note that because of the state transition in closeOutputSent() above we likely won't actually\n        // forward any further reads to the user, unless they belong to a request currently streaming in.\n        // Any reads past that point will be dropped in channelRead().\n        if shouldRead && self.readPending {\n            self.readPending = false\n            context.read()\n        }\n    }\n\n    /// - Returns: True if an error was sent, ie the caller should not continue\n    private func handleConnectionStateAction(\n        context: ChannelHandlerContext,\n        action: ConnectionStateAction,\n        promise: EventLoopPromise<Void>?\n    ) -> Bool {\n        switch action {\n        case .warnPreconditionViolated(let message):\n            self.assertionFailed(message)\n            let error = ConnectionStateError.preconditionViolated(message: message)\n            self.deliverOneError(context: context, error: error)\n            promise?.fail(error)\n            return true\n        case .forceCloseConnection:\n            let message =\n                \"The connection has been forcefully closed because further IO was attempted after a precondition was violated\"\n            let error = ConnectionStateError.preconditionViolated(message: message)\n            promise?.fail(error)\n            self.close(context: context, mode: .all, promise: nil)\n            return true\n        case .none:\n            return false\n        }\n    }\n\n    /// A response has been sent: we can now start passing reads through\n    /// again if there are no further pending requests, and send any read()\n    /// call we may have swallowed.\n    private func startReading(context: ChannelHandlerContext) {\n        if self.readPending && self.state != .responseEndPending {\n            switch self.lifecycleState {\n            case .quiescingLastRequestEndReceived, .quiescingCompleted:\n                // No more reads in these states.\n                ()\n            case .acceptingEvents, .quiescingWaitingForRequestEnd:\n                self.readPending = false\n                context.read()\n            }\n        }\n    }\n\n    /// A response has been sent: deliver all pending requests and\n    /// mark the channel ready to handle more requests.\n    private func deliverPendingRequests(context: ChannelHandlerContext) {\n        var deliveredRead = false\n\n        while self.state != .responseEndPending, let event = self.eventBuffer.first {\n            self.eventBuffer.removeFirst()\n\n            switch event {\n            case .channelRead(let read):\n                let connectionStateAction = self.deliverOneMessage(context: context, data: read)\n                if !self.handleConnectionStateAction(context: context, action: connectionStateAction, promise: nil) {\n                    deliveredRead = true\n                }\n            case .error(let error):\n                self.deliverOneError(context: context, error: error)\n            case .halfClose:\n                // When we fire the half-close, we want to forget all prior reads.\n                // They will just trigger further half-close notifications we don't\n                // need.\n                self.readPending = false\n                context.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n            }\n        }\n\n        if deliveredRead {\n            context.fireChannelReadComplete()\n        }\n\n        // We need to quickly check whether there is an EOF waiting here, because\n        // if there is we should also unbuffer it and pass it along. There is no\n        // advantage in sitting on it, and it may help the later channel handlers\n        // be more sensible about keep-alive logic if they can see this early.\n        // This is done after `fireChannelReadComplete` to keep the same observable\n        // behaviour as `SocketChannel`, which fires these events in this order.\n        if case .some(.halfClose) = self.eventBuffer.first {\n            self.eventBuffer.removeFirst()\n            self.readPending = false\n            context.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        }\n    }\n\n    private func dropAllButInFlightRequest() {\n        // We're going to walk the request buffer up to the next `.head` and drop from there.\n        let maybeFirstHead = self.eventBuffer.firstIndex(where: { element in\n            switch element {\n            case .channelRead(let read):\n                switch HTTPServerPipelineHandler.unwrapInboundIn(read) {\n                case .head:\n                    return true\n                case .body, .end:\n                    return false\n                }\n            case .error, .halfClose:\n                // Leave these where they are, if they're before the next .head we still want to deliver them.\n                // If they're after the next .head, we don't care.\n                return false\n            }\n        })\n\n        guard let firstHead = maybeFirstHead else {\n            return\n        }\n\n        self.eventBuffer.removeSubrange(firstHead...)\n    }\n\n    /// A utility function that runs the body code only in debug builds, without\n    /// emitting compiler warnings.\n    ///\n    /// This is currently the only way to do this in Swift: see\n    /// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.\n    private func debugOnly(_ body: () -> Void) {\n        self.checkAssertion(\n            {\n                body()\n                return true\n            }()\n        )\n    }\n\n    /// Calls assertionFailure if and only if `self.failOnPreconditions` is true. This allows us to avoid terminating the program in tests\n    private func assertionFailed(_ message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) {\n        if self.failOnPreconditions {\n            assertionFailure(message(), file: file, line: line)\n        }\n    }\n\n    /// Calls assert if and only if `self.failOnPreconditions` is true. This allows us to avoid terminating the program in tests\n    private func checkAssertion(\n        _ closure: @autoclosure () -> Bool,\n        _ message: @autoclosure () -> String = String(),\n        file: StaticString = #file,\n        line: UInt = #line\n    ) {\n        if self.failOnPreconditions {\n            assert(closure(), message(), file: file, line: line)\n        }\n    }\n}\n\n@available(*, unavailable)\nextension HTTPServerPipelineHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPServerProtocolErrorHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// A simple channel handler that catches errors emitted by parsing HTTP requests\n/// and sends 400 Bad Request responses.\n///\n/// This channel handler provides the basic behaviour that the majority of simple HTTP\n/// servers want. This handler does not suppress the parser errors: it allows them to\n/// continue to pass through the pipeline so that other handlers (e.g. logging ones) can\n/// deal with the error.\npublic final class HTTPServerProtocolErrorHandler: ChannelDuplexHandler, RemovableChannelHandler {\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias InboundOut = HTTPServerRequestPart\n    public typealias OutboundIn = HTTPServerResponsePart\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    private var hasUnterminatedResponse: Bool = false\n\n    public init() {}\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        guard error is HTTPParserError else {\n            context.fireErrorCaught(error)\n            return\n        }\n\n        // Any HTTPParserError is automatically fatal, and we don't actually need (or want) to\n        // provide that error to the client: we just want to tell it that it screwed up and then\n        // let the rest of the pipeline shut the door in its face. However, we can only send an\n        // HTTP error response if another response hasn't started yet.\n        //\n        // A side note here: we cannot block or do any delayed work. ByteToMessageDecoder is going\n        // to come along and close the channel right after we return from this function.\n        if !self.hasUnterminatedResponse {\n            let headers = HTTPHeaders([(\"Connection\", \"close\"), (\"Content-Length\", \"0\")])\n            let head = HTTPResponseHead(version: .http1_1, status: .badRequest, headers: headers)\n            context.write(HTTPServerProtocolErrorHandler.wrapOutboundOut(.head(head)), promise: nil)\n            context.writeAndFlush(HTTPServerProtocolErrorHandler.wrapOutboundOut(.end(nil)), promise: nil)\n        }\n\n        // Now pass the error on in case someone else wants to see it.\n        context.fireErrorCaught(error)\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let res = HTTPServerProtocolErrorHandler.unwrapOutboundIn(data)\n        switch res {\n        case .head(let head) where head.isInformational:\n            precondition(!self.hasUnterminatedResponse)\n        case .head:\n            precondition(!self.hasUnterminatedResponse)\n            self.hasUnterminatedResponse = true\n        case .body:\n            precondition(self.hasUnterminatedResponse)\n        case .end:\n            precondition(self.hasUnterminatedResponse)\n            self.hasUnterminatedResponse = false\n        }\n        context.write(data, promise: promise)\n    }\n}\n\n@available(*, unavailable)\nextension HTTPServerProtocolErrorHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPServerUpgradeHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// Errors that may be raised by the `HTTPServerProtocolUpgrader`.\npublic enum HTTPServerUpgradeErrors: Error {\n    case invalidHTTPOrdering\n}\n\n/// User events that may be fired by the `HTTPServerProtocolUpgrader`.\npublic enum HTTPServerUpgradeEvents: Sendable {\n    /// Fired when HTTP upgrade has completed and the\n    /// `HTTPServerProtocolUpgrader` is about to remove itself from the\n    /// `ChannelPipeline`.\n    case upgradeComplete(toProtocol: String, upgradeRequest: HTTPRequestHead)\n}\n\n/// An object that implements `HTTPServerProtocolUpgrader` knows how to handle HTTP upgrade to\n/// a protocol on a server-side channel.\npublic protocol HTTPServerProtocolUpgrader {\n    /// The protocol this upgrader knows how to support.\n    var supportedProtocol: String { get }\n\n    /// All the header fields the protocol needs in the request to successfully upgrade. These header fields\n    /// will be provided to the handler when it is asked to handle the upgrade. They will also be validated\n    ///  against the inbound request's Connection header field.\n    var requiredUpgradeHeaders: [String] { get }\n\n    /// Builds the upgrade response headers. Should return any headers that need to be supplied to the client\n    /// in the 101 Switching Protocols response. If upgrade cannot proceed for any reason, this function should\n    /// fail the future.\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders>\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel pipeline\n    /// to add whatever channel handlers are required. Until the returned `EventLoopFuture` succeeds, all received\n    /// data will be buffered.\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void>\n}\n\n/// A server-side channel handler that receives HTTP requests and optionally performs a HTTP-upgrade.\n/// Removes itself from the channel pipeline after the first inbound request on the connection, regardless of\n/// whether the upgrade succeeded or not.\n///\n/// This handler behaves a bit differently from its Netty counterpart because it does not allow upgrade\n/// on any request but the first on a connection. This is primarily to handle clients that pipeline: it's\n/// sufficiently difficult to ensure that the upgrade happens at a safe time while dealing with pipelined\n/// requests that we choose to punt on it entirely and not allow it. As it happens this is mostly fine:\n/// the odds of someone needing to upgrade midway through the lifetime of a connection are very low.\npublic final class HTTPServerUpgradeHandler: ChannelInboundHandler, RemovableChannelHandler {\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias InboundOut = HTTPServerRequestPart\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    private let upgraders: [String: HTTPServerProtocolUpgrader]\n    private let upgradeCompletionHandler: (ChannelHandlerContext) -> Void\n\n    private let httpEncoder: HTTPResponseEncoder\n    private let extraHTTPHandlers: [RemovableChannelHandler]\n\n    /// Whether we've already seen the first request.\n    private var seenFirstRequest = false\n\n    /// The closure that should be invoked when the end of the upgrade request is received if any.\n    private var upgradeState: UpgradeState = .idle\n    private var receivedMessages: CircularBuffer<NIOAny> = CircularBuffer()\n\n    /// Create a `HTTPServerUpgradeHandler`.\n    ///\n    /// - Parameter upgraders: All `HTTPServerProtocolUpgrader` objects that this pipeline will be able\n    ///     to use to handle HTTP upgrade.\n    /// - Parameter httpEncoder: The `HTTPResponseEncoder` encoding responses from this handler and which will\n    ///     be removed from the pipeline once the upgrade response is sent. This is used to ensure\n    ///     that the pipeline will be in a clean state after upgrade.\n    /// - Parameter extraHTTPHandlers: Any other handlers that are directly related to handling HTTP. At the very least\n    ///     this should include the `HTTPDecoder`, but should also include any other handler that cannot tolerate\n    ///     receiving non-HTTP data.\n    /// - Parameter upgradeCompletionHandler: A block that will be fired when HTTP upgrade is complete.\n    public init(\n        upgraders: [HTTPServerProtocolUpgrader],\n        httpEncoder: HTTPResponseEncoder,\n        extraHTTPHandlers: [RemovableChannelHandler],\n        upgradeCompletionHandler: @escaping (ChannelHandlerContext) -> Void\n    ) {\n        var upgraderMap = [String: HTTPServerProtocolUpgrader]()\n        for upgrader in upgraders {\n            upgraderMap[upgrader.supportedProtocol.lowercased()] = upgrader\n        }\n        self.upgraders = upgraderMap\n        self.upgradeCompletionHandler = upgradeCompletionHandler\n        self.httpEncoder = httpEncoder\n        self.extraHTTPHandlers = extraHTTPHandlers\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        guard !self.seenFirstRequest else {\n            // We're waiting for upgrade to complete: buffer this data.\n            self.receivedMessages.append(data)\n            return\n        }\n\n        let requestPart = HTTPServerUpgradeHandler.unwrapInboundIn(data)\n\n        switch self.upgradeState {\n        case .idle:\n            self.firstRequestHeadReceived(context: context, requestPart: requestPart)\n        case .awaitingUpgrader:\n            if case .end = requestPart {\n                // This is the end of the first request. Swallow it, we're buffering the rest.\n                self.seenFirstRequest = true\n            }\n        case .upgraderReady(let upgrade):\n            if case .end = requestPart {\n                // This is the end of the first request, and we can upgrade. Time to kick it off.\n                self.seenFirstRequest = true\n                upgrade()\n            }\n        case .upgradeFailed:\n            // We were re-entrantly called while delivering the request head. We can just pass this through.\n            context.fireChannelRead(data)\n        case .upgradeComplete:\n            preconditionFailure(\n                \"Upgrade has completed but we have not seen a whole request and still got re-entrantly called.\"\n            )\n        case .upgrading:\n            preconditionFailure(\n                \"We think we saw .end before and began upgrading, but somehow we have not set seenFirstRequest\"\n            )\n        }\n    }\n\n    public func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n        // We have been formally removed from the pipeline. We should send any buffered data we have.\n        // Note that we loop twice. This is because we want to guard against being reentrantly called from fireChannelReadComplete.\n        while self.receivedMessages.count > 0 {\n            while self.receivedMessages.count > 0 {\n                let bufferedPart = self.receivedMessages.removeFirst()\n                context.fireChannelRead(bufferedPart)\n            }\n\n            context.fireChannelReadComplete()\n        }\n\n        context.leavePipeline(removalToken: removalToken)\n    }\n\n    private func firstRequestHeadReceived(context: ChannelHandlerContext, requestPart: HTTPServerRequestPart) {\n        // We should decide if we're going to upgrade based on the first request header: if we aren't upgrading,\n        // by the time the body comes in we should be out of the pipeline. That means that if we don't think we're\n        // upgrading, the only thing we should see is a request head. Anything else in an error.\n        guard case .head(let request) = requestPart else {\n            context.fireErrorCaught(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n            self.notUpgrading(context: context, data: requestPart)\n            return\n        }\n\n        // Ok, we have a HTTP request. Check if it's an upgrade. If it's not, we want to pass it on and remove ourselves\n        // from the channel pipeline.\n        let requestedProtocols = request.headers[canonicalForm: \"upgrade\"].map(String.init)\n        guard requestedProtocols.count > 0 else {\n            self.notUpgrading(context: context, data: requestPart)\n            return\n        }\n\n        // Cool, this is an upgrade request.\n        // We'll attempt to upgrade. This may take a while, so while we're waiting more data can come in.\n        self.upgradeState = .awaitingUpgrader\n\n        self.handleUpgrade(context: context, request: request, requestedProtocols: requestedProtocols)\n            .whenSuccess { callback in\n                if let callback = callback {\n                    self.gotUpgrader(upgrader: callback)\n                } else {\n                    self.notUpgrading(context: context, data: requestPart)\n                }\n            }\n    }\n\n    /// The core of the upgrade handling logic.\n    ///\n    /// - Returns: An isolated `EventLoopFuture` that will contain a callback to invoke if upgrade is requested,\n    /// or nil if upgrade has failed. Never returns a failed future.\n    private func handleUpgrade(\n        context: ChannelHandlerContext,\n        request: HTTPRequestHead,\n        requestedProtocols: [String]\n    ) -> EventLoopFuture<(() -> Void)?>.Isolated {\n\n        let connectionHeader = Set(request.headers[canonicalForm: \"connection\"].map { $0.lowercased() })\n        let allHeaderNames = Set(request.headers.map { $0.name.lowercased() })\n\n        // We now set off a chain of Futures to try to find a protocol upgrade. While this is blocking, we need to buffer inbound data.\n        let protocolIterator = requestedProtocols.makeIterator()\n        return self.handleUpgradeForProtocol(\n            context: context,\n            protocolIterator: protocolIterator,\n            request: request,\n            allHeaderNames: allHeaderNames,\n            connectionHeader: connectionHeader\n        )\n    }\n\n    /// Attempt to upgrade a single protocol.\n    ///\n    /// Will recurse through `protocolIterator` if upgrade fails.\n    ///\n    /// - Returns: An isolated `EventLoopFuture` that will contain a callback to invoke if upgrade is requested,\n    /// or nil if upgrade has failed. Never returns a failed future.\n    private func handleUpgradeForProtocol(\n        context: ChannelHandlerContext,\n        protocolIterator: Array<String>.Iterator,\n        request: HTTPRequestHead,\n        allHeaderNames: Set<String>,\n        connectionHeader: Set<String>\n    ) -> EventLoopFuture<(() -> Void)?>.Isolated {\n        // We want a local copy of the protocol iterator. We'll pass it to the next invocation of the function.\n        var protocolIterator = protocolIterator\n        guard let proto = protocolIterator.next() else {\n            // We're done! No suitable protocol for upgrade.\n            return context.eventLoop.makeSucceededIsolatedFuture(nil)\n        }\n\n        guard let upgrader = self.upgraders[proto.lowercased()] else {\n            return self.handleUpgradeForProtocol(\n                context: context,\n                protocolIterator: protocolIterator,\n                request: request,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            )\n        }\n\n        let requiredHeaders = Set(upgrader.requiredUpgradeHeaders.map { $0.lowercased() })\n        guard requiredHeaders.isSubset(of: allHeaderNames) && requiredHeaders.isSubset(of: connectionHeader) else {\n            return self.handleUpgradeForProtocol(\n                context: context,\n                protocolIterator: protocolIterator,\n                request: request,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            )\n        }\n\n        let responseHeaders = self.buildUpgradeHeaders(protocol: proto)\n        let pipeline = context.pipeline\n\n        return upgrader.buildUpgradeResponse(\n            channel: context.channel,\n            upgradeRequest: request,\n            initialResponseHeaders: responseHeaders\n        ).hop(to: context.eventLoop)\n            .assumeIsolated()\n            .map { finalResponseHeaders in\n                {\n                    // Ok, we're upgrading.\n                    self.upgradeState = .upgrading\n\n                    // Before we finish the upgrade we have to remove the HTTPDecoder and any other non-Encoder HTTP\n                    // handlers from the pipeline, to prevent them parsing any more data. We'll buffer the data until\n                    // that completes.\n                    // While there are a lot of Futures involved here it's quite possible that all of this code will\n                    // actually complete synchronously: we just want to program for the possibility that it won't.\n                    // Once that's done, we send the upgrade response, then remove the HTTP encoder, then call the\n                    // internal handler, then call the user code, and then finally when the user code is done we do\n                    // our final cleanup steps, namely we replay the received data we buffered in the meantime and\n                    // then remove ourselves from the pipeline.\n                    self.removeExtraHandlers(pipeline: pipeline)\n                        .assumeIsolated()\n                        .flatMap {\n                            self.sendUpgradeResponse(\n                                context: context,\n                                upgradeRequest: request,\n                                responseHeaders: finalResponseHeaders\n                            )\n                        }.flatMap {\n                            pipeline.syncOperations.removeHandler(self.httpEncoder)\n                        }.flatMap { () -> EventLoopFuture<Void> in\n                            self.upgradeCompletionHandler(context)\n                            return upgrader.upgrade(context: context, upgradeRequest: request)\n                        }.whenComplete { result in\n                            switch result {\n                            case .success:\n                                context.fireUserInboundEventTriggered(\n                                    HTTPServerUpgradeEvents.upgradeComplete(toProtocol: proto, upgradeRequest: request)\n                                )\n                                self.upgradeState = .upgradeComplete\n                                // When we remove ourselves we'll be delivering any buffered data.\n                                context.pipeline.syncOperations.removeHandler(context: context, promise: nil)\n\n                            case .failure(let error):\n                                // Remain in the '.upgrading' state.\n                                context.fireErrorCaught(error)\n                            }\n                        }\n                }\n            }.flatMapError { error in\n                // No upgrade here. We want to fire the error down the pipeline, and then try another loop iteration.\n                context.fireErrorCaught(error)\n                return self.handleUpgradeForProtocol(\n                    context: context,\n                    protocolIterator: protocolIterator,\n                    request: request,\n                    allHeaderNames: allHeaderNames,\n                    connectionHeader: connectionHeader\n                )\n            }\n    }\n\n    private func gotUpgrader(upgrader: @escaping (() -> Void)) {\n        switch self.upgradeState {\n        case .awaitingUpgrader:\n            self.upgradeState = .upgraderReady(upgrader)\n            if self.seenFirstRequest {\n                // Ok, we're good to go, we can upgrade. Otherwise we're waiting for .end, which\n                // will trigger the upgrade.\n                upgrader()\n            }\n        case .idle, .upgradeComplete, .upgraderReady, .upgradeFailed, .upgrading:\n            preconditionFailure(\"Unexpected upgrader state: \\(self.upgradeState)\")\n        }\n    }\n\n    /// Sends the 101 Switching Protocols response for the pipeline.\n    private func sendUpgradeResponse(\n        context: ChannelHandlerContext,\n        upgradeRequest: HTTPRequestHead,\n        responseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<Void> {\n        var response = HTTPResponseHead(version: .http1_1, status: .switchingProtocols)\n        response.headers = responseHeaders\n        return context.writeAndFlush(wrapOutboundOut(HTTPServerResponsePart.head(response)))\n    }\n\n    /// Called when we know we're not upgrading. Passes the data on and then removes this object from the pipeline.\n    private func notUpgrading(context: ChannelHandlerContext, data: HTTPServerRequestPart) {\n        self.upgradeState = .upgradeFailed\n\n        if !self.seenFirstRequest {\n            // We haven't seen the first request .end. That means we're not buffering anything, and we can\n            // just deliver data.\n            assert(self.receivedMessages.isEmpty)\n            context.fireChannelRead(HTTPServerUpgradeHandler.wrapInboundOut(data))\n        } else {\n            // This is trickier. We've seen the first request .end, so we now need to deliver the .head we\n            // got passed, as well as the .end we swallowed, and any buffered parts. While we're doing this\n            // we may be re-entrantly called, which will cause us to buffer new parts. To make that safe, we\n            // must ensure we aren't holding the buffer mutably, so no for loop for us.\n            context.fireChannelRead(HTTPServerUpgradeHandler.wrapInboundOut(data))\n            context.fireChannelRead(HTTPServerUpgradeHandler.wrapInboundOut(.end(nil)))\n        }\n\n        context.fireChannelReadComplete()\n\n        // Ok, we've delivered all the parts. We can now remove ourselves, which should happen synchronously.\n        context.pipeline.syncOperations.removeHandler(context: context, promise: nil)\n    }\n\n    /// Builds the initial mandatory HTTP headers for HTTP upgrade responses.\n    private func buildUpgradeHeaders(`protocol`: String) -> HTTPHeaders {\n        HTTPHeaders([(\"connection\", \"upgrade\"), (\"upgrade\", `protocol`)])\n    }\n\n    /// Removes any extra HTTP-related handlers from the channel pipeline.\n    private func removeExtraHandlers(pipeline: ChannelPipeline) -> EventLoopFuture<Void> {\n        guard self.extraHTTPHandlers.count > 0 else {\n            return pipeline.eventLoop.makeSucceededFuture(())\n        }\n\n        return .andAllSucceed(\n            self.extraHTTPHandlers.map { pipeline.syncOperations.removeHandler($0) },\n            on: pipeline.eventLoop\n        )\n    }\n}\n\nextension HTTPServerUpgradeHandler: @unchecked Sendable {}\n\nextension HTTPServerUpgradeHandler {\n    /// The state of the upgrade handler.\n    private enum UpgradeState {\n        /// Awaiting some activity.\n        case idle\n\n        /// The request head has been received. We're currently running the future chain awaiting an upgrader.\n        case awaitingUpgrader\n\n        /// We have an upgrader, which means we can begin upgrade.\n        case upgraderReady(() -> Void)\n\n        /// The upgrade is in process.\n        case upgrading\n\n        /// The upgrade has failed, and we are being removed from the pipeline.\n        case upgradeFailed\n\n        /// The upgrade has succeeded, and we are being removed from the pipeline.\n        case upgradeComplete\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPTypedPipelineSetup.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n// MARK: - Server pipeline configuration\n\n/// Configuration for an upgradable HTTP pipeline.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult: Sendable>: Sendable {\n    /// Whether to provide assistance handling HTTP clients that pipeline\n    /// their requests. Defaults to `true`. If `false`, users will need to handle clients that pipeline themselves.\n    public var enablePipelining = true\n\n    /// Whether to provide assistance handling protocol errors (e.g. failure to parse the HTTP\n    /// request) by sending 400 errors. Defaults to `true`.\n    public var enableErrorHandling = true\n\n    /// Whether to validate outbound response headers to confirm that they are\n    /// spec compliant. Defaults to `true`.\n    public var enableResponseHeaderValidation = true\n\n    /// The configuration for the ``HTTPResponseEncoder``.\n    public var encoderConfiguration = HTTPResponseEncoder.Configuration()\n\n    /// The configuration for the ``NIOTypedHTTPServerUpgradeHandler``.\n    public var upgradeConfiguration: NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult>\n\n    /// Initializes a new ``NIOUpgradableHTTPServerPipelineConfiguration`` with default values.\n    ///\n    /// The current defaults provide the following features:\n    /// 1. Assistance handling clients that pipeline HTTP requests.\n    /// 2. Assistance handling protocol errors.\n    /// 3. Outbound header fields validation to protect against response splitting attacks.\n    public init(\n        upgradeConfiguration: NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult>\n    ) {\n        self.upgradeConfiguration = upgradeConfiguration\n    }\n}\n\nextension ChannelPipeline {\n    /// Configure a `ChannelPipeline` for use as an HTTP server.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured. The future contains an `EventLoopFuture`\n    /// that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPServerPipeline<UpgradeResult: Sendable>(\n        configuration: NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult>\n    ) -> EventLoopFuture<EventLoopFuture<UpgradeResult>> {\n        self._configureUpgradableHTTPServerPipeline(\n            configuration: configuration\n        )\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    private func _configureUpgradableHTTPServerPipeline<UpgradeResult: Sendable>(\n        configuration: NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult>\n    ) -> EventLoopFuture<EventLoopFuture<UpgradeResult>> {\n        let future: EventLoopFuture<EventLoopFuture<UpgradeResult>>\n\n        if self.eventLoop.inEventLoop {\n            let result = Result<EventLoopFuture<UpgradeResult>, Error> {\n                try self.syncOperations.configureUpgradableHTTPServerPipeline(\n                    configuration: configuration\n                )\n            }\n            future = self.eventLoop.makeCompletedFuture(result)\n        } else {\n            future = self.eventLoop.submit {\n                try self.syncOperations.configureUpgradableHTTPServerPipeline(\n                    configuration: configuration\n                )\n            }\n        }\n\n        return future\n    }\n}\n\nextension ChannelPipeline.SynchronousOperations {\n    /// Configure a `ChannelPipeline` for use as an HTTP server.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPServerPipeline<UpgradeResult: Sendable>(\n        configuration: NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult>\n    ) throws -> EventLoopFuture<UpgradeResult> {\n        self.eventLoop.assertInEventLoop()\n\n        let responseEncoder = HTTPResponseEncoder(configuration: configuration.encoderConfiguration)\n        let requestDecoder = ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .forwardBytes))\n\n        var extraHTTPHandlers = [RemovableChannelHandler]()\n        extraHTTPHandlers.reserveCapacity(4)\n        extraHTTPHandlers.append(requestDecoder)\n\n        try self.addHandler(responseEncoder)\n        try self.addHandler(requestDecoder)\n\n        if configuration.enablePipelining {\n            let pipeliningHandler = HTTPServerPipelineHandler()\n            try self.addHandler(pipeliningHandler)\n            extraHTTPHandlers.append(pipeliningHandler)\n        }\n\n        if configuration.enableResponseHeaderValidation {\n            let headerValidationHandler = NIOHTTPResponseHeadersValidator()\n            try self.addHandler(headerValidationHandler)\n            extraHTTPHandlers.append(headerValidationHandler)\n        }\n\n        if configuration.enableErrorHandling {\n            let errorHandler = HTTPServerProtocolErrorHandler()\n            try self.addHandler(errorHandler)\n            extraHTTPHandlers.append(errorHandler)\n        }\n\n        let upgrader = NIOTypedHTTPServerUpgradeHandler(\n            httpEncoder: responseEncoder,\n            extraHTTPHandlers: extraHTTPHandlers,\n            upgradeConfiguration: configuration.upgradeConfiguration\n        )\n        try self.addHandler(upgrader)\n\n        return upgrader.upgradeResultFuture\n    }\n}\n\n// MARK: - Client pipeline configuration\n\n/// Configuration for an upgradable HTTP pipeline.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult: Sendable>: Sendable {\n    /// The strategy to use when dealing with leftover bytes after removing the ``HTTPDecoder`` from the pipeline.\n    public var leftOverBytesStrategy = RemoveAfterUpgradeStrategy.dropBytes\n\n    /// Whether to validate outbound response headers to confirm that they are\n    /// spec compliant. Defaults to `true`.\n    public var enableOutboundHeaderValidation = true\n\n    /// The configuration for the ``HTTPRequestEncoder``.\n    public var encoderConfiguration = HTTPRequestEncoder.Configuration()\n\n    /// The configuration for the ``NIOTypedHTTPClientUpgradeHandler``.\n    public var upgradeConfiguration: NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult>\n\n    /// Initializes a new ``NIOUpgradableHTTPClientPipelineConfiguration`` with default values.\n    ///\n    /// The current defaults provide the following features:\n    /// 1. Outbound header fields validation to protect against response splitting attacks.\n    public init(\n        upgradeConfiguration: NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult>\n    ) {\n        self.upgradeConfiguration = upgradeConfiguration\n    }\n}\n\nextension ChannelPipeline {\n    /// Configure a `ChannelPipeline` for use as an HTTP client.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured. The future contains an `EventLoopFuture`\n    /// that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPClientPipeline<UpgradeResult: Sendable>(\n        configuration: NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult>\n    ) -> EventLoopFuture<EventLoopFuture<UpgradeResult>> {\n        self._configureUpgradableHTTPClientPipeline(configuration: configuration)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    private func _configureUpgradableHTTPClientPipeline<UpgradeResult: Sendable>(\n        configuration: NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult>\n    ) -> EventLoopFuture<EventLoopFuture<UpgradeResult>> {\n        let future: EventLoopFuture<EventLoopFuture<UpgradeResult>>\n\n        if self.eventLoop.inEventLoop {\n            let result = Result<EventLoopFuture<UpgradeResult>, Error> {\n                try self.syncOperations.configureUpgradableHTTPClientPipeline(\n                    configuration: configuration\n                )\n            }\n            future = self.eventLoop.makeCompletedFuture(result)\n        } else {\n            future = self.eventLoop.submit {\n                try self.syncOperations.configureUpgradableHTTPClientPipeline(\n                    configuration: configuration\n                )\n            }\n        }\n\n        return future\n    }\n}\n\nextension ChannelPipeline.SynchronousOperations {\n    /// Configure a `ChannelPipeline` for use as an HTTP client.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPClientPipeline<UpgradeResult: Sendable>(\n        configuration: NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult>\n    ) throws -> EventLoopFuture<UpgradeResult> {\n        self.eventLoop.assertInEventLoop()\n\n        let requestEncoder = HTTPRequestEncoder(configuration: configuration.encoderConfiguration)\n        let responseDecoder = ByteToMessageHandler(\n            HTTPResponseDecoder(leftOverBytesStrategy: configuration.leftOverBytesStrategy)\n        )\n        var httpHandlers = [RemovableChannelHandler]()\n        httpHandlers.reserveCapacity(3)\n        httpHandlers.append(requestEncoder)\n        httpHandlers.append(responseDecoder)\n\n        try self.addHandler(requestEncoder)\n        try self.addHandler(responseDecoder)\n\n        if configuration.enableOutboundHeaderValidation {\n            let headerValidationHandler = NIOHTTPRequestHeadersValidator()\n            try self.addHandler(headerValidationHandler)\n            httpHandlers.append(headerValidationHandler)\n        }\n\n        let upgrader = NIOTypedHTTPClientUpgradeHandler(\n            httpHandlers: httpHandlers,\n            upgradeConfiguration: configuration.upgradeConfiguration\n        )\n        try self.addHandler(upgrader)\n\n        return upgrader.upgradeResultFuture\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/HTTPTypes.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\nlet crlf: StaticString = \"\\r\\n\"\nlet headerSeparator: StaticString = \": \"\n\nextension HTTPHeaders {\n    internal enum ConnectionHeaderValue {\n        case keepAlive\n        case close\n        case unspecified\n    }\n}\n\n// Keep track of keep alive state.\ninternal enum KeepAliveState {\n    // We know keep alive should be used.\n    case keepAlive\n    // We know we should close the connection.\n    case close\n    // We need to scan the headers to find out if keep alive is used or not\n    case unknown\n}\n\n/// A representation of the request line and header fields of a HTTP request.\npublic struct HTTPRequestHead: Equatable {\n    private final class _Storage {\n        var method: HTTPMethod\n        var uri: String\n        var version: HTTPVersion\n\n        init(method: HTTPMethod, uri: String, version: HTTPVersion) {\n            self.method = method\n            self.uri = uri\n            self.version = version\n        }\n\n        func copy() -> _Storage {\n            .init(method: self.method, uri: self.uri, version: self.version)\n        }\n    }\n\n    private var _storage: _Storage\n\n    /// The header fields for this HTTP request.\n    // warning: do not put this in `_Storage` as it'd trigger a CoW on every mutation\n    public var headers: HTTPHeaders\n\n    /// The HTTP method for this request.\n    public var method: HTTPMethod {\n        get {\n            self._storage.method\n        }\n        set {\n            self.copyStorageIfNotUniquelyReferenced()\n            self._storage.method = newValue\n        }\n    }\n\n    // This request's URI.\n    public var uri: String {\n        get {\n            self._storage.uri\n        }\n        set {\n            self.copyStorageIfNotUniquelyReferenced()\n            self._storage.uri = newValue\n        }\n    }\n\n    /// The version for this HTTP request.\n    public var version: HTTPVersion {\n        get {\n            self._storage.version\n        }\n        set {\n            self.copyStorageIfNotUniquelyReferenced()\n            self._storage.version = newValue\n        }\n    }\n\n    /// Create a `HTTPRequestHead`\n    ///\n    /// - Parameters:\n    ///   - version: The version for this HTTP request.\n    ///   - method: The HTTP method for this request.\n    ///   - uri: The URI used on this request.\n    ///   - headers: This request's HTTP headers.\n    public init(version: HTTPVersion, method: HTTPMethod, uri: String, headers: HTTPHeaders) {\n        self._storage = .init(method: method, uri: uri, version: version)\n        self.headers = headers\n    }\n\n    /// Create a `HTTPRequestHead`\n    ///\n    /// - Parameter version: The version for this HTTP request.\n    /// - Parameter method: The HTTP method for this request.\n    /// - Parameter uri: The URI used on this request.\n    public init(version: HTTPVersion, method: HTTPMethod, uri: String) {\n        self.init(version: version, method: method, uri: uri, headers: HTTPHeaders())\n    }\n\n    public static func == (lhs: HTTPRequestHead, rhs: HTTPRequestHead) -> Bool {\n        lhs.method == rhs.method && lhs.uri == rhs.uri && lhs.version == rhs.version && lhs.headers == rhs.headers\n    }\n\n    private mutating func copyStorageIfNotUniquelyReferenced() {\n        if !isKnownUniquelyReferenced(&self._storage) {\n            self._storage = self._storage.copy()\n        }\n    }\n}\n\nextension HTTPRequestHead: @unchecked Sendable {}\n\n/// The parts of a complete HTTP message, representing either a request or a response.\n///\n/// An HTTP message is made up of:\n/// - a request or status line with several headers, encoded by a single ``HTTPPart/head(_:)`` part,\n/// - zero or more ``HTTPPart/body(_:)`` parts,\n/// - and some optional trailers (represented as headers) in a single ``HTTPPart/end(_:)`` part.\n///\n/// To indicate that a complete HTTP message has been sent or received,\n/// an ``HTTPPart/end(_:)`` part must be used, even when no trailers are included.\npublic enum HTTPPart<HeadT: Equatable, BodyT: Equatable> {\n    /// The headers of an HTTP request or response.\n    ///\n    /// A single part is always used to encode all headers.\n    case head(HeadT)\n\n    /// A part of an HTTP request or response's body.\n    ///\n    /// Zero or more body parts can be sent or received. The stream is finished when\n    /// an ``HTTPPart/end(_:)`` part is received.\n    case body(BodyT)\n\n    /// The end of an HTTP request or response, optionally containing trailers.\n    ///\n    /// A single part is always used to encode all trailers.\n    case end(HTTPHeaders?)\n}\n\nextension HTTPPart: Sendable where HeadT: Sendable, BodyT: Sendable {}\n\nextension HTTPPart: Equatable {}\n\n/// The components of a HTTP request from the view of a HTTP client.\npublic typealias HTTPClientRequestPart = HTTPPart<HTTPRequestHead, IOData>\n\n/// The components of a HTTP request from the view of a HTTP server.\npublic typealias HTTPServerRequestPart = HTTPPart<HTTPRequestHead, ByteBuffer>\n\n/// The components of a HTTP response from the view of a HTTP client.\npublic typealias HTTPClientResponsePart = HTTPPart<HTTPResponseHead, ByteBuffer>\n\n/// The components of a HTTP response from the view of a HTTP server.\npublic typealias HTTPServerResponsePart = HTTPPart<HTTPResponseHead, IOData>\n\nextension HTTPRequestHead {\n    /// Whether this HTTP request is a keep-alive request: that is, whether the\n    /// connection should remain open after the request is complete.\n    public var isKeepAlive: Bool {\n        headers.isKeepAlive(version: version)\n    }\n}\n\nextension HTTPResponseHead {\n    /// Whether this HTTP response is a keep-alive request: that is, whether the\n    /// connection should remain open after the request is complete.\n    public var isKeepAlive: Bool {\n        self.headers.isKeepAlive(version: self.version)\n    }\n}\n\n/// A representation of the status line and header fields of a HTTP response.\npublic struct HTTPResponseHead: Equatable {\n    private final class _Storage {\n        var status: HTTPResponseStatus\n        var version: HTTPVersion\n        init(status: HTTPResponseStatus, version: HTTPVersion) {\n            self.status = status\n            self.version = version\n        }\n        func copy() -> _Storage {\n            .init(status: self.status, version: self.version)\n        }\n    }\n\n    private var _storage: _Storage\n\n    /// The HTTP headers on this response.\n    // warning: do not put this in `_Storage` as it'd trigger a CoW on every mutation\n    public var headers: HTTPHeaders\n\n    /// The HTTP response status.\n    public var status: HTTPResponseStatus {\n        get {\n            self._storage.status\n        }\n        set {\n            self.copyStorageIfNotUniquelyReferenced()\n            self._storage.status = newValue\n        }\n    }\n\n    /// The HTTP version that corresponds to this response.\n    public var version: HTTPVersion {\n        get {\n            self._storage.version\n        }\n        set {\n            self.copyStorageIfNotUniquelyReferenced()\n            self._storage.version = newValue\n        }\n    }\n\n    /// Create a `HTTPResponseHead`\n    ///\n    /// - Parameter version: The version for this HTTP response.\n    /// - Parameter status: The status for this HTTP response.\n    /// - Parameter headers: The headers for this HTTP response.\n    public init(version: HTTPVersion, status: HTTPResponseStatus, headers: HTTPHeaders = HTTPHeaders()) {\n        self.headers = headers\n        self._storage = _Storage(status: status, version: version)\n    }\n\n    public static func == (lhs: HTTPResponseHead, rhs: HTTPResponseHead) -> Bool {\n        lhs.status == rhs.status && lhs.version == rhs.version && lhs.headers == rhs.headers\n    }\n\n    private mutating func copyStorageIfNotUniquelyReferenced() {\n        if !isKnownUniquelyReferenced(&self._storage) {\n            self._storage = self._storage.copy()\n        }\n    }\n}\n\nextension HTTPResponseHead: @unchecked Sendable {}\n\nextension HTTPResponseHead {\n    /// Determines if the head is purely informational. If a head is informational another head will follow this\n    /// head eventually.\n    var isInformational: Bool {\n        100 <= self.status.code && self.status.code < 200 && self.status.code != 101\n    }\n}\n\nextension UInt8 {\n    fileprivate var isASCII: Bool {\n        self <= 127\n    }\n}\n\nextension HTTPHeaders {\n    func isKeepAlive(version: HTTPVersion) -> Bool {\n        switch self.keepAliveState {\n        case .close:\n            return false\n        case .keepAlive:\n            return true\n        case .unknown:\n            var state = KeepAliveState.unknown\n            for word in self[canonicalForm: \"connection\"] {\n                if word.utf8.compareCaseInsensitiveASCIIBytes(to: \"close\".utf8) {\n                    // if we see multiple values, that's clearly bad and we default to 'close'\n                    state = state != .unknown ? .close : .close\n                } else if word.utf8.compareCaseInsensitiveASCIIBytes(to: \"keep-alive\".utf8) {\n                    // if we see multiple values, that's clearly bad and we default to 'close'\n                    state = state != .unknown ? .close : .keepAlive\n                }\n            }\n\n            switch state {\n            case .close:\n                return false\n            case .keepAlive:\n                return true\n            case .unknown:\n                // HTTP 1.1 use keep-alive by default if not otherwise told.\n                return version.major == 1 && version.minor >= 1\n            }\n        }\n    }\n}\n\n/// A representation of a block of HTTP header fields.\n///\n/// HTTP header fields are a complex data structure. The most natural representation\n/// for these is a sequence of two-tuples of field name and field value, both as\n/// strings. This structure preserves that representation, but provides a number of\n/// convenience features in addition to it.\n///\n/// For example, this structure enables access to header fields based on the\n/// case-insensitive form of the field name, but preserves the original case of the\n/// field when needed. It also supports recomposing headers to a maximally joined\n/// or split representation, such that header fields that are able to be repeated\n/// can be represented appropriately.\npublic struct HTTPHeaders: CustomStringConvertible, ExpressibleByDictionaryLiteral {\n    @usableFromInline\n    internal var headers: [(String, String)]\n    internal var keepAliveState: KeepAliveState = .unknown\n\n    public var description: String {\n        self.headers.lazy.map {\n            \"\\($0.0): \\($0.1)\"\n        }\n        .joined(separator: \"; \")\n    }\n\n    internal var names: [String] {\n        self.headers.map { $0.0 }\n    }\n\n    internal init(_ headers: [(String, String)], keepAliveState: KeepAliveState) {\n        self.headers = headers\n        self.keepAliveState = keepAliveState\n    }\n\n    internal func isConnectionHeader(_ name: String) -> Bool {\n        name.utf8.compareCaseInsensitiveASCIIBytes(to: \"connection\".utf8)\n    }\n\n    /// Construct a `HTTPHeaders` structure.\n    ///\n    /// - Parameters\n    ///   - headers: An initial set of headers to use to populate the header block.\n    ///   - allocator: The allocator to use to allocate the underlying storage.\n    public init(_ headers: [(String, String)] = []) {\n        // Note: this initializer exists because of https://bugs.swift.org/browse/SR-7415.\n        // Otherwise we'd only have the one below with a default argument for `allocator`.\n        self.init(headers, keepAliveState: .unknown)\n    }\n\n    /// Construct a `HTTPHeaders` structure.\n    ///\n    /// - Parameters\n    ///   - elements: name, value pairs provided by a dictionary literal.\n    public init(dictionaryLiteral elements: (String, String)...) {\n        self.init(elements)\n    }\n\n    /// Add a header name/value pair to the block.\n    ///\n    /// This method is strictly additive: if there are other values for the given header name\n    /// already in the block, this will add a new entry.\n    ///\n    /// - Parameter name: The header field name. For maximum compatibility this should be an\n    ///     ASCII string. For future-proofing with HTTP/2 lowercase header names are strongly\n    ///     recommended.\n    /// - Parameter value: The header field value to add for the given name.\n    public mutating func add(name: String, value: String) {\n        precondition(!name.utf8.contains(where: { !$0.isASCII }), \"name must be ASCII\")\n        self.headers.append((name, value))\n        if self.isConnectionHeader(name) {\n            self.keepAliveState = .unknown\n        }\n    }\n\n    /// Add a sequence of header name/value pairs to the block.\n    ///\n    /// This method is strictly additive: if there are other entries with the same header\n    /// name already in the block, this will add new entries.\n    ///\n    /// - Parameter other: The sequence of header name/value pairs. For maximum compatibility\n    ///     the header should be an ASCII string. For future-proofing with HTTP/2 lowercase header\n    ///     names are strongly recommended.\n    @inlinable\n    public mutating func add<S: Sequence>(contentsOf other: S) where S.Element == (String, String) {\n        self.headers.reserveCapacity(self.headers.count + other.underestimatedCount)\n        for (name, value) in other {\n            self.add(name: name, value: value)\n        }\n    }\n\n    /// Add another block of headers to the block.\n    ///\n    /// - Parameter other: The block of headers to add to these headers.\n    public mutating func add(contentsOf other: HTTPHeaders) {\n        self.headers.append(contentsOf: other.headers)\n        if other.keepAliveState == .unknown {\n            self.keepAliveState = .unknown\n        }\n    }\n\n    /// Add a header name/value pair to the block, replacing any previous values for the\n    /// same header name that are already in the block.\n    ///\n    /// This is a supplemental method to `add` that essentially combines `remove` and `add`\n    /// in a single function. It can be used to ensure that a header block is in a\n    /// well-defined form without having to check whether the value was previously there.\n    /// Like `add`, this method performs case-insensitive comparisons of the header field\n    /// names.\n    ///\n    /// - Parameter name: The header field name. For maximum compatibility this should be an\n    ///     ASCII string. For future-proofing with HTTP/2 lowercase header names are strongly\n    //      recommended.\n    /// - Parameter value: The header field value to add for the given name.\n    public mutating func replaceOrAdd(name: String, value: String) {\n        if self.isConnectionHeader(name) {\n            self.keepAliveState = .unknown\n        }\n        self.remove(name: name)\n        self.add(name: name, value: value)\n    }\n\n    /// Remove all values for a given header name from the block.\n    ///\n    /// This method uses case-insensitive comparisons for the header field name.\n    ///\n    /// - Parameter name: The name of the header field to remove from the block.\n    public mutating func remove(name: String) {\n        if self.isConnectionHeader(name) {\n            self.keepAliveState = .unknown\n        }\n        self.headers.removeAll { (headerName, _) in\n            if name.utf8.count != headerName.utf8.count {\n                return false\n            }\n\n            return name.utf8.compareCaseInsensitiveASCIIBytes(to: headerName.utf8)\n        }\n    }\n\n    /// Retrieve all of the values for a give header field name from the block.\n    ///\n    /// This method uses case-insensitive comparisons for the header field name. It\n    /// does not return a maximally-decomposed list of the header fields, but instead\n    /// returns them in their original representation: that means that a comma-separated\n    /// header field list may contain more than one entry, some of which contain commas\n    /// and some do not. If you want a representation of the header fields suitable for\n    /// performing computation on, consider `subscript(canonicalForm:)`.\n    ///\n    /// - Parameter name: The header field name whose values are to be retrieved.\n    /// - Returns: A list of the values for that header field name.\n    public subscript(name: String) -> [String] {\n        self.headers.reduce(into: []) { target, lr in\n            let (key, value) = lr\n            if key.utf8.compareCaseInsensitiveASCIIBytes(to: name.utf8) {\n                target.append(value)\n            }\n        }\n    }\n\n    /// Retrieves the first value for a given header field name from the block.\n    ///\n    /// This method uses case-insensitive comparisons for the header field name. It\n    /// does not return the first value from a maximally-decomposed list of the header fields,\n    /// but instead returns the first value from the original representation: that means\n    /// that a comma-separated header field list may contain more than one entry, some of\n    /// which contain commas and some do not. If you want a representation of the header fields\n    /// suitable for performing computation on, consider `subscript(canonicalForm:)`.\n    ///\n    /// - Parameter name: The header field name whose first value should be retrieved.\n    /// - Returns: The first value for the header field name.\n    public func first(name: String) -> String? {\n        guard !self.headers.isEmpty else {\n            return nil\n        }\n\n        return self.headers.first { header in header.0.isEqualCaseInsensitiveASCIIBytes(to: name) }?.1\n    }\n\n    /// Checks if a header is present\n    ///\n    /// - Parameters:\n    ///   - name: The name of the header\n    //  - returns: `true` if a header with the name (and value) exists, `false` otherwise.\n    public func contains(name: String) -> Bool {\n        for kv in self.headers {\n            if kv.0.utf8.compareCaseInsensitiveASCIIBytes(to: name.utf8) {\n                return true\n            }\n        }\n        return false\n    }\n\n    /// Retrieves the header values for the given header field in \"canonical form\": that is,\n    /// splitting them on commas as extensively as possible such that multiple values received on the\n    /// one line are returned as separate entries. Also respects the fact that Set-Cookie should not\n    /// be split in this way.\n    ///\n    /// - Parameter name: The header field name whose values are to be retrieved.\n    /// - Returns: A list of the values for that header field name.\n    public subscript(canonicalForm name: String) -> [Substring] {\n        let result = self[name]\n\n        guard result.count > 0 else {\n            return []\n        }\n\n        // It's not safe to split Set-Cookie on comma.\n        guard name.lowercased() != \"set-cookie\" else {\n            return result.map { $0[...] }\n        }\n\n        return result.flatMap { $0.split(separator: \",\").map { $0.trimWhitespace() } }\n    }\n}\n\nextension HTTPHeaders: Sendable {}\n\nextension HTTPHeaders {\n\n    /// The total number of headers that can be contained without allocating new storage.\n    public var capacity: Int {\n        self.headers.capacity\n    }\n\n    /// Reserves enough space to store the specified number of headers.\n    ///\n    /// - Parameter minimumCapacity: The requested number of headers to store.\n    public mutating func reserveCapacity(_ minimumCapacity: Int) {\n        self.headers.reserveCapacity(minimumCapacity)\n    }\n}\n\nextension ByteBuffer {\n\n    /// Serializes this HTTP header block to bytes suitable for writing to the wire.\n    ///\n    /// - Parameter buffer: A buffer to write the serialized bytes into. Will increment\n    ///     the writer index of this buffer.\n    mutating func write(headers: HTTPHeaders) {\n        for header in headers.headers {\n            self.writeString(header.0)\n            self.writeStaticString(headerSeparator)\n            self.writeString(header.1)\n            self.writeStaticString(crlf)\n        }\n        self.writeStaticString(crlf)\n    }\n}\n\nextension HTTPHeaders: RandomAccessCollection {\n    public typealias Element = (name: String, value: String)\n\n    public struct Index: Comparable, Sendable {\n        fileprivate let base: Array<(String, String)>.Index\n        public static func < (lhs: Index, rhs: Index) -> Bool {\n            lhs.base < rhs.base\n        }\n    }\n\n    public var startIndex: HTTPHeaders.Index {\n        .init(base: self.headers.startIndex)\n    }\n\n    public var endIndex: HTTPHeaders.Index {\n        .init(base: self.headers.endIndex)\n    }\n\n    public func index(before i: HTTPHeaders.Index) -> HTTPHeaders.Index {\n        .init(base: self.headers.index(before: i.base))\n    }\n\n    public func index(after i: HTTPHeaders.Index) -> HTTPHeaders.Index {\n        .init(base: self.headers.index(after: i.base))\n    }\n\n    public subscript(position: HTTPHeaders.Index) -> Element {\n        self.headers[position.base]\n    }\n}\n\nextension UTF8.CodeUnit {\n    var isASCIIWhitespace: Bool {\n        switch self {\n        case UInt8(ascii: \" \"),\n            UInt8(ascii: \"\\t\"):\n            return true\n\n        default:\n            return false\n        }\n    }\n}\n\nextension String {\n    func trimASCIIWhitespace() -> Substring {\n        Substring(self).trimWhitespace()\n    }\n}\n\nextension Substring {\n    fileprivate func trimWhitespace() -> Substring {\n        guard let firstNonWhitespace = self.utf8.firstIndex(where: { !$0.isASCIIWhitespace }) else {\n            // The whole substring is ASCII whitespace.\n            return Substring()\n        }\n\n        // There must be at least one non-ascii whitespace character, so banging here is safe.\n        let lastNonWhitespace = self.utf8.lastIndex(where: { !$0.isASCIIWhitespace })!\n        return Substring(self.utf8[firstNonWhitespace...lastNonWhitespace])\n    }\n}\n\nextension HTTPHeaders: Equatable {\n    public static func == (lhs: HTTPHeaders, rhs: HTTPHeaders) -> Bool {\n        guard lhs.headers.count == rhs.headers.count else {\n            return false\n        }\n        let lhsNames = Set(lhs.names.map { $0.lowercased() })\n        let rhsNames = Set(rhs.names.map { $0.lowercased() })\n        guard lhsNames == rhsNames else {\n            return false\n        }\n\n        for name in lhsNames {\n            guard lhs[name].sorted() == rhs[name].sorted() else {\n                return false\n            }\n        }\n\n        return true\n    }\n}\n\npublic enum HTTPMethod: Equatable, Sendable {\n    internal enum HasBody {\n        case yes\n        case no\n        case unlikely\n    }\n\n    case GET\n    case PUT\n    case ACL\n    case HEAD\n    case POST\n    case COPY\n    case LOCK\n    case MOVE\n    case BIND\n    case LINK\n    case PATCH\n    case TRACE\n    case MKCOL\n    case MERGE\n    case PURGE\n    case NOTIFY\n    case SEARCH\n    case UNLOCK\n    case REBIND\n    case UNBIND\n    case REPORT\n    case DELETE\n    case UNLINK\n    case CONNECT\n    case MSEARCH\n    case OPTIONS\n    case PROPFIND\n    case CHECKOUT\n    case PROPPATCH\n    case SUBSCRIBE\n    case MKCALENDAR\n    case MKACTIVITY\n    case UNSUBSCRIBE\n    case SOURCE\n    case RAW(value: String)\n\n    /// Whether requests with this verb may have a request body.\n    internal var hasRequestBody: HasBody {\n        switch self {\n        case .TRACE:\n            return .no\n        case .POST, .PUT, .PATCH:\n            return .yes\n        case .GET, .CONNECT, .OPTIONS, .HEAD, .DELETE:\n            fallthrough\n        default:\n            return .unlikely\n        }\n    }\n}\n\n/// A structure representing a HTTP version.\npublic struct HTTPVersion: Equatable, Sendable {\n    /// Create a HTTP version.\n    ///\n    /// - Parameter major: The major version number.\n    /// - Parameter minor: The minor version number.\n    @inlinable\n    public init(major: Int, minor: Int) {\n        self._major = UInt16(major)\n        self._minor = UInt16(minor)\n    }\n\n    @usableFromInline var _minor: UInt16\n    @usableFromInline var _major: UInt16\n\n    /// The major version number.\n    @inlinable\n    public var major: Int {\n        get {\n            Int(self._major)\n        }\n        set {\n            self._major = UInt16(newValue)\n        }\n    }\n\n    /// The minor version number.\n    @inlinable\n    public var minor: Int {\n        get {\n            Int(self._minor)\n        }\n        set {\n            self._minor = UInt16(newValue)\n        }\n    }\n\n    /// HTTP/3\n    @inlinable\n    public static var http3: HTTPVersion {\n        HTTPVersion(major: 3, minor: 0)\n    }\n\n    /// HTTP/2\n    @inlinable\n    public static var http2: HTTPVersion {\n        HTTPVersion(major: 2, minor: 0)\n    }\n\n    /// HTTP/1.1\n    @inlinable\n    public static var http1_1: HTTPVersion {\n        HTTPVersion(major: 1, minor: 1)\n    }\n\n    /// HTTP/1.0\n    @inlinable\n    public static var http1_0: HTTPVersion {\n        HTTPVersion(major: 1, minor: 0)\n    }\n\n    /// HTTP/0.9 (not supported by SwiftNIO)\n    @inlinable\n    public static var http0_9: HTTPVersion {\n        HTTPVersion(major: 0, minor: 9)\n    }\n}\n\nextension HTTPParserError: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        switch self {\n        case .invalidCharactersUsed:\n            return \"illegal characters used in URL/headers\"\n        case .trailingGarbage:\n            return \"trailing garbage bytes\"\n        case .invalidEOFState:\n            return \"stream ended at an unexpected time\"\n        case .headerOverflow:\n            return \"too many header bytes seen; overflow detected\"\n        case .closedConnection:\n            return \"data received after completed connection: close message\"\n        case .invalidVersion:\n            return \"invalid HTTP version\"\n        case .invalidStatus:\n            return \"invalid HTTP status code\"\n        case .invalidMethod:\n            return \"invalid HTTP method\"\n        case .invalidURL:\n            return \"invalid URL\"\n        case .invalidHost:\n            return \"invalid host\"\n        case .invalidPort:\n            return \"invalid port\"\n        case .invalidPath:\n            return \"invalid path\"\n        case .invalidQueryString:\n            return \"invalid query string\"\n        case .invalidFragment:\n            return \"invalid fragment\"\n        case .lfExpected:\n            return \"LF character expected\"\n        case .invalidHeaderToken:\n            return \"invalid character in header\"\n        case .invalidContentLength:\n            return \"invalid character in content-length header\"\n        case .unexpectedContentLength:\n            return \"unexpected content-length header\"\n        case .invalidChunkSize:\n            return \"invalid character in chunk size header\"\n        case .invalidConstant:\n            return \"invalid constant string\"\n        case .invalidInternalState:\n            return \"invalid internal state (swift-http-parser error)\"\n        case .strictModeAssertion:\n            return \"strict mode assertion\"\n        case .paused:\n            return \"paused (swift-http-parser error)\"\n        case .unknown:\n            return \"unknown (http_parser error)\"\n        }\n    }\n}\n\n/// Errors that can be raised while parsing HTTP/1.1.\npublic enum HTTPParserError: Error {\n    case invalidCharactersUsed\n    case trailingGarbage\n    // from CHTTPParser\n    case invalidEOFState\n    case headerOverflow\n    case closedConnection\n    case invalidVersion\n    case invalidStatus\n    case invalidMethod\n    case invalidURL\n\n    @available(*, deprecated, message: \"Cannot be thrown\")\n    case invalidHost\n\n    @available(*, deprecated, message: \"Cannot be thrown\")\n    case invalidPort\n\n    @available(*, deprecated, message: \"Cannot be thrown\")\n    case invalidPath\n\n    @available(*, deprecated, message: \"Cannot be thrown\")\n    case invalidQueryString\n\n    @available(*, deprecated, message: \"Cannot be thrown\")\n    case invalidFragment\n    case lfExpected\n    case invalidHeaderToken\n    case invalidContentLength\n    case unexpectedContentLength\n    case invalidChunkSize\n    case invalidConstant\n    case invalidInternalState\n    case strictModeAssertion\n    case paused\n    case unknown\n}\n\nextension HTTPResponseStatus {\n    /// The numerical status code for a given HTTP response status.\n    public var code: UInt {\n        get {\n            switch self {\n            case .continue:\n                return 100\n            case .switchingProtocols:\n                return 101\n            case .processing:\n                return 102\n            case .ok:\n                return 200\n            case .created:\n                return 201\n            case .accepted:\n                return 202\n            case .nonAuthoritativeInformation:\n                return 203\n            case .noContent:\n                return 204\n            case .resetContent:\n                return 205\n            case .partialContent:\n                return 206\n            case .multiStatus:\n                return 207\n            case .alreadyReported:\n                return 208\n            case .imUsed:\n                return 226\n            case .multipleChoices:\n                return 300\n            case .movedPermanently:\n                return 301\n            case .found:\n                return 302\n            case .seeOther:\n                return 303\n            case .notModified:\n                return 304\n            case .useProxy:\n                return 305\n            case .temporaryRedirect:\n                return 307\n            case .permanentRedirect:\n                return 308\n            case .badRequest:\n                return 400\n            case .unauthorized:\n                return 401\n            case .paymentRequired:\n                return 402\n            case .forbidden:\n                return 403\n            case .notFound:\n                return 404\n            case .methodNotAllowed:\n                return 405\n            case .notAcceptable:\n                return 406\n            case .proxyAuthenticationRequired:\n                return 407\n            case .requestTimeout:\n                return 408\n            case .conflict:\n                return 409\n            case .gone:\n                return 410\n            case .lengthRequired:\n                return 411\n            case .preconditionFailed:\n                return 412\n            case .payloadTooLarge:\n                return 413\n            case .uriTooLong:\n                return 414\n            case .unsupportedMediaType:\n                return 415\n            case .rangeNotSatisfiable:\n                return 416\n            case .expectationFailed:\n                return 417\n            case .imATeapot:\n                return 418\n            case .misdirectedRequest:\n                return 421\n            case .unprocessableEntity:\n                return 422\n            case .locked:\n                return 423\n            case .failedDependency:\n                return 424\n            case .upgradeRequired:\n                return 426\n            case .preconditionRequired:\n                return 428\n            case .tooManyRequests:\n                return 429\n            case .requestHeaderFieldsTooLarge:\n                return 431\n            case .unavailableForLegalReasons:\n                return 451\n            case .internalServerError:\n                return 500\n            case .notImplemented:\n                return 501\n            case .badGateway:\n                return 502\n            case .serviceUnavailable:\n                return 503\n            case .gatewayTimeout:\n                return 504\n            case .httpVersionNotSupported:\n                return 505\n            case .variantAlsoNegotiates:\n                return 506\n            case .insufficientStorage:\n                return 507\n            case .loopDetected:\n                return 508\n            case .notExtended:\n                return 510\n            case .networkAuthenticationRequired:\n                return 511\n            case .custom(let code, reasonPhrase: _):\n                return code\n            }\n        }\n    }\n\n    /// The string reason phrase for a given HTTP response status.\n    public var reasonPhrase: String {\n        get {\n            switch self {\n            case .continue:\n                return \"Continue\"\n            case .switchingProtocols:\n                return \"Switching Protocols\"\n            case .processing:\n                return \"Processing\"\n            case .ok:\n                return \"OK\"\n            case .created:\n                return \"Created\"\n            case .accepted:\n                return \"Accepted\"\n            case .nonAuthoritativeInformation:\n                return \"Non-Authoritative Information\"\n            case .noContent:\n                return \"No Content\"\n            case .resetContent:\n                return \"Reset Content\"\n            case .partialContent:\n                return \"Partial Content\"\n            case .multiStatus:\n                return \"Multi-Status\"\n            case .alreadyReported:\n                return \"Already Reported\"\n            case .imUsed:\n                return \"IM Used\"\n            case .multipleChoices:\n                return \"Multiple Choices\"\n            case .movedPermanently:\n                return \"Moved Permanently\"\n            case .found:\n                return \"Found\"\n            case .seeOther:\n                return \"See Other\"\n            case .notModified:\n                return \"Not Modified\"\n            case .useProxy:\n                return \"Use Proxy\"\n            case .temporaryRedirect:\n                return \"Temporary Redirect\"\n            case .permanentRedirect:\n                return \"Permanent Redirect\"\n            case .badRequest:\n                return \"Bad Request\"\n            case .unauthorized:\n                return \"Unauthorized\"\n            case .paymentRequired:\n                return \"Payment Required\"\n            case .forbidden:\n                return \"Forbidden\"\n            case .notFound:\n                return \"Not Found\"\n            case .methodNotAllowed:\n                return \"Method Not Allowed\"\n            case .notAcceptable:\n                return \"Not Acceptable\"\n            case .proxyAuthenticationRequired:\n                return \"Proxy Authentication Required\"\n            case .requestTimeout:\n                return \"Request Timeout\"\n            case .conflict:\n                return \"Conflict\"\n            case .gone:\n                return \"Gone\"\n            case .lengthRequired:\n                return \"Length Required\"\n            case .preconditionFailed:\n                return \"Precondition Failed\"\n            case .payloadTooLarge:\n                return \"Payload Too Large\"\n            case .uriTooLong:\n                return \"URI Too Long\"\n            case .unsupportedMediaType:\n                return \"Unsupported Media Type\"\n            case .rangeNotSatisfiable:\n                return \"Range Not Satisfiable\"\n            case .expectationFailed:\n                return \"Expectation Failed\"\n            case .imATeapot:\n                return \"I'm a teapot\"\n            case .misdirectedRequest:\n                return \"Misdirected Request\"\n            case .unprocessableEntity:\n                return \"Unprocessable Entity\"\n            case .locked:\n                return \"Locked\"\n            case .failedDependency:\n                return \"Failed Dependency\"\n            case .upgradeRequired:\n                return \"Upgrade Required\"\n            case .preconditionRequired:\n                return \"Precondition Required\"\n            case .tooManyRequests:\n                return \"Too Many Requests\"\n            case .requestHeaderFieldsTooLarge:\n                return \"Request Header Fields Too Large\"\n            case .unavailableForLegalReasons:\n                return \"Unavailable For Legal Reasons\"\n            case .internalServerError:\n                return \"Internal Server Error\"\n            case .notImplemented:\n                return \"Not Implemented\"\n            case .badGateway:\n                return \"Bad Gateway\"\n            case .serviceUnavailable:\n                return \"Service Unavailable\"\n            case .gatewayTimeout:\n                return \"Gateway Timeout\"\n            case .httpVersionNotSupported:\n                return \"HTTP Version Not Supported\"\n            case .variantAlsoNegotiates:\n                return \"Variant Also Negotiates\"\n            case .insufficientStorage:\n                return \"Insufficient Storage\"\n            case .loopDetected:\n                return \"Loop Detected\"\n            case .notExtended:\n                return \"Not Extended\"\n            case .networkAuthenticationRequired:\n                return \"Network Authentication Required\"\n            case .custom(code: _, reasonPhrase: let phrase):\n                return phrase\n            }\n        }\n    }\n}\n\n/// A HTTP response status code.\npublic enum HTTPResponseStatus: Sendable {\n    // use custom if you want to use a non-standard response code or\n    // have it available in a (UInt, String) pair from a higher-level web framework.\n    case custom(code: UInt, reasonPhrase: String)\n\n    // all the codes from http://www.iana.org/assignments/http-status-codes\n\n    // 1xx\n    case `continue`\n    case switchingProtocols\n    case processing\n    // TODO: add '103: Early Hints' (requires bumping SemVer major).\n\n    // 2xx\n    case ok\n    case created\n    case accepted\n    case nonAuthoritativeInformation\n    case noContent\n    case resetContent\n    case partialContent\n    case multiStatus\n    case alreadyReported\n    case imUsed\n\n    // 3xx\n    case multipleChoices\n    case movedPermanently\n    case found\n    case seeOther\n    case notModified\n    case useProxy\n    case temporaryRedirect\n    case permanentRedirect\n\n    // 4xx\n    case badRequest\n    case unauthorized\n    case paymentRequired\n    case forbidden\n    case notFound\n    case methodNotAllowed\n    case notAcceptable\n    case proxyAuthenticationRequired\n    case requestTimeout\n    case conflict\n    case gone\n    case lengthRequired\n    case preconditionFailed\n    case payloadTooLarge\n    case uriTooLong\n    case unsupportedMediaType\n    case rangeNotSatisfiable\n    case expectationFailed\n    case imATeapot\n    case misdirectedRequest\n    case unprocessableEntity\n    case locked\n    case failedDependency\n    case upgradeRequired\n    case preconditionRequired\n    case tooManyRequests\n    case requestHeaderFieldsTooLarge\n    case unavailableForLegalReasons\n\n    // 5xx\n    case internalServerError\n    case notImplemented\n    case badGateway\n    case serviceUnavailable\n    case gatewayTimeout\n    case httpVersionNotSupported\n    case variantAlsoNegotiates\n    case insufficientStorage\n    case loopDetected\n    case notExtended\n    case networkAuthenticationRequired\n\n    /// Whether responses with this status code may have a response body.\n    public var mayHaveResponseBody: Bool {\n        switch self {\n        case .`continue`,\n            .switchingProtocols,\n            .processing,\n            .noContent,\n            .notModified,\n            .custom where (code < 200) && (code >= 100):\n            return false\n        default:\n            return true\n        }\n    }\n\n    /// Initialize a `HTTPResponseStatus` from a given status and reason.\n    ///\n    /// - Parameter statusCode: The integer value of the HTTP response status code\n    /// - Parameter reasonPhrase: The textual reason phrase from the response. This will be\n    ///     discarded in favor of the default if the `statusCode` matches one that we know.\n    public init(statusCode: Int, reasonPhrase: String = \"\") {\n        switch statusCode {\n        case 100:\n            self = .`continue`\n        case 101:\n            self = .switchingProtocols\n        case 102:\n            self = .processing\n        case 200:\n            self = .ok\n        case 201:\n            self = .created\n        case 202:\n            self = .accepted\n        case 203:\n            self = .nonAuthoritativeInformation\n        case 204:\n            self = .noContent\n        case 205:\n            self = .resetContent\n        case 206:\n            self = .partialContent\n        case 207:\n            self = .multiStatus\n        case 208:\n            self = .alreadyReported\n        case 226:\n            self = .imUsed\n        case 300:\n            self = .multipleChoices\n        case 301:\n            self = .movedPermanently\n        case 302:\n            self = .found\n        case 303:\n            self = .seeOther\n        case 304:\n            self = .notModified\n        case 305:\n            self = .useProxy\n        case 307:\n            self = .temporaryRedirect\n        case 308:\n            self = .permanentRedirect\n        case 400:\n            self = .badRequest\n        case 401:\n            self = .unauthorized\n        case 402:\n            self = .paymentRequired\n        case 403:\n            self = .forbidden\n        case 404:\n            self = .notFound\n        case 405:\n            self = .methodNotAllowed\n        case 406:\n            self = .notAcceptable\n        case 407:\n            self = .proxyAuthenticationRequired\n        case 408:\n            self = .requestTimeout\n        case 409:\n            self = .conflict\n        case 410:\n            self = .gone\n        case 411:\n            self = .lengthRequired\n        case 412:\n            self = .preconditionFailed\n        case 413:\n            self = .payloadTooLarge\n        case 414:\n            self = .uriTooLong\n        case 415:\n            self = .unsupportedMediaType\n        case 416:\n            self = .rangeNotSatisfiable\n        case 417:\n            self = .expectationFailed\n        case 418:\n            self = .imATeapot\n        case 421:\n            self = .misdirectedRequest\n        case 422:\n            self = .unprocessableEntity\n        case 423:\n            self = .locked\n        case 424:\n            self = .failedDependency\n        case 426:\n            self = .upgradeRequired\n        case 428:\n            self = .preconditionRequired\n        case 429:\n            self = .tooManyRequests\n        case 431:\n            self = .requestHeaderFieldsTooLarge\n        case 451:\n            self = .unavailableForLegalReasons\n        case 500:\n            self = .internalServerError\n        case 501:\n            self = .notImplemented\n        case 502:\n            self = .badGateway\n        case 503:\n            self = .serviceUnavailable\n        case 504:\n            self = .gatewayTimeout\n        case 505:\n            self = .httpVersionNotSupported\n        case 506:\n            self = .variantAlsoNegotiates\n        case 507:\n            self = .insufficientStorage\n        case 508:\n            self = .loopDetected\n        case 510:\n            self = .notExtended\n        case 511:\n            self = .networkAuthenticationRequired\n        default:\n            self = .custom(code: UInt(statusCode), reasonPhrase: reasonPhrase)\n        }\n    }\n}\n\nextension HTTPResponseStatus: Equatable {}\n\nextension HTTPResponseStatus: Hashable {}\n\nextension HTTPRequestHead: CustomStringConvertible {\n    public var description: String {\n        \"HTTPRequestHead { method: \\(self.method), uri: \\\"\\(self.uri)\\\", version: \\(self.version), headers: \\(self.headers) }\"\n    }\n}\n\nextension HTTPResponseStatus: CustomStringConvertible {\n    public var description: String {\n        \"\\(self.code) \\(self.reasonPhrase)\"\n    }\n}\n\nextension HTTPResponseHead: CustomStringConvertible {\n    public var description: String {\n        \"HTTPResponseHead { version: \\(self.version), status: \\(self.status), headers: \\(self.headers) }\"\n    }\n}\n\nextension HTTPVersion: CustomStringConvertible {\n    public var description: String {\n        \"HTTP/\\(self.major).\\(self.minor)\"\n    }\n}\n\nextension HTTPMethod: RawRepresentable {\n    public var rawValue: String {\n        switch self {\n        case .GET:\n            return \"GET\"\n        case .PUT:\n            return \"PUT\"\n        case .ACL:\n            return \"ACL\"\n        case .HEAD:\n            return \"HEAD\"\n        case .POST:\n            return \"POST\"\n        case .COPY:\n            return \"COPY\"\n        case .LOCK:\n            return \"LOCK\"\n        case .MOVE:\n            return \"MOVE\"\n        case .BIND:\n            return \"BIND\"\n        case .LINK:\n            return \"LINK\"\n        case .PATCH:\n            return \"PATCH\"\n        case .TRACE:\n            return \"TRACE\"\n        case .MKCOL:\n            return \"MKCOL\"\n        case .MERGE:\n            return \"MERGE\"\n        case .PURGE:\n            return \"PURGE\"\n        case .NOTIFY:\n            return \"NOTIFY\"\n        case .SEARCH:\n            return \"SEARCH\"\n        case .UNLOCK:\n            return \"UNLOCK\"\n        case .REBIND:\n            return \"REBIND\"\n        case .UNBIND:\n            return \"UNBIND\"\n        case .REPORT:\n            return \"REPORT\"\n        case .DELETE:\n            return \"DELETE\"\n        case .UNLINK:\n            return \"UNLINK\"\n        case .CONNECT:\n            return \"CONNECT\"\n        case .MSEARCH:\n            return \"MSEARCH\"\n        case .OPTIONS:\n            return \"OPTIONS\"\n        case .PROPFIND:\n            return \"PROPFIND\"\n        case .CHECKOUT:\n            return \"CHECKOUT\"\n        case .PROPPATCH:\n            return \"PROPPATCH\"\n        case .SUBSCRIBE:\n            return \"SUBSCRIBE\"\n        case .MKCALENDAR:\n            return \"MKCALENDAR\"\n        case .MKACTIVITY:\n            return \"MKACTIVITY\"\n        case .UNSUBSCRIBE:\n            return \"UNSUBSCRIBE\"\n        case .SOURCE:\n            return \"SOURCE\"\n        case let .RAW(value):\n            return value\n        }\n    }\n\n    public init(rawValue: String) {\n        switch rawValue {\n        case \"GET\":\n            self = .GET\n        case \"PUT\":\n            self = .PUT\n        case \"ACL\":\n            self = .ACL\n        case \"HEAD\":\n            self = .HEAD\n        case \"POST\":\n            self = .POST\n        case \"COPY\":\n            self = .COPY\n        case \"LOCK\":\n            self = .LOCK\n        case \"MOVE\":\n            self = .MOVE\n        case \"BIND\":\n            self = .BIND\n        case \"LINK\":\n            self = .LINK\n        case \"PATCH\":\n            self = .PATCH\n        case \"TRACE\":\n            self = .TRACE\n        case \"MKCOL\":\n            self = .MKCOL\n        case \"MERGE\":\n            self = .MERGE\n        case \"PURGE\":\n            self = .PURGE\n        case \"NOTIFY\":\n            self = .NOTIFY\n        case \"SEARCH\":\n            self = .SEARCH\n        case \"UNLOCK\":\n            self = .UNLOCK\n        case \"REBIND\":\n            self = .REBIND\n        case \"UNBIND\":\n            self = .UNBIND\n        case \"REPORT\":\n            self = .REPORT\n        case \"DELETE\":\n            self = .DELETE\n        case \"UNLINK\":\n            self = .UNLINK\n        case \"CONNECT\":\n            self = .CONNECT\n        case \"MSEARCH\":\n            self = .MSEARCH\n        case \"OPTIONS\":\n            self = .OPTIONS\n        case \"PROPFIND\":\n            self = .PROPFIND\n        case \"CHECKOUT\":\n            self = .CHECKOUT\n        case \"PROPPATCH\":\n            self = .PROPPATCH\n        case \"SUBSCRIBE\":\n            self = .SUBSCRIBE\n        case \"MKCALENDAR\":\n            self = .MKCALENDAR\n        case \"MKACTIVITY\":\n            self = .MKACTIVITY\n        case \"UNSUBSCRIBE\":\n            self = .UNSUBSCRIBE\n        case \"SOURCE\":\n            self = .SOURCE\n        default:\n            self = .RAW(value: rawValue)\n        }\n    }\n}\n\nextension HTTPResponseHead {\n    internal var contentLength: Int? {\n        headers.contentLength\n    }\n}\n\nextension HTTPRequestHead {\n    internal var contentLength: Int? {\n        headers.contentLength\n    }\n}\n\nextension HTTPHeaders {\n    internal var contentLength: Int? {\n        self.first(name: \"content-length\").flatMap { Int($0) }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/NIOHTTPClientUpgradeHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// Errors that may be raised by the `HTTPClientProtocolUpgrader`.\npublic struct NIOHTTPClientUpgradeError: Hashable, Error {\n\n    // Uses the open enum style to allow additional errors to be added in future.\n    private enum Code: Hashable {\n        case responseProtocolNotFound\n        case invalidHTTPOrdering\n        case upgraderDeniedUpgrade\n        case writingToHandlerDuringUpgrade\n        case writingToHandlerAfterUpgradeCompleted\n        case writingToHandlerAfterUpgradeFailed\n        case receivedResponseBeforeRequestSent\n        case receivedResponseAfterUpgradeCompleted\n    }\n\n    private var code: Code\n\n    private init(_ code: Code) {\n        self.code = code\n    }\n\n    public static let responseProtocolNotFound = NIOHTTPClientUpgradeError(.responseProtocolNotFound)\n    public static let invalidHTTPOrdering = NIOHTTPClientUpgradeError(.invalidHTTPOrdering)\n    public static let upgraderDeniedUpgrade = NIOHTTPClientUpgradeError(.upgraderDeniedUpgrade)\n    public static let writingToHandlerDuringUpgrade = NIOHTTPClientUpgradeError(.writingToHandlerDuringUpgrade)\n    public static let writingToHandlerAfterUpgradeCompleted = NIOHTTPClientUpgradeError(\n        .writingToHandlerAfterUpgradeCompleted\n    )\n    public static let writingToHandlerAfterUpgradeFailed = NIOHTTPClientUpgradeError(\n        .writingToHandlerAfterUpgradeFailed\n    )\n    public static let receivedResponseBeforeRequestSent = NIOHTTPClientUpgradeError(.receivedResponseBeforeRequestSent)\n    public static let receivedResponseAfterUpgradeCompleted = NIOHTTPClientUpgradeError(\n        .receivedResponseAfterUpgradeCompleted\n    )\n}\n\nextension NIOHTTPClientUpgradeError: CustomStringConvertible {\n    public var description: String {\n        String(describing: self.code)\n    }\n}\n\n/// An object that implements `NIOHTTPClientProtocolUpgrader` knows how to handle HTTP upgrade to\n/// a protocol on a client-side channel.\n/// It has the option of denying this upgrade based upon the server response.\npublic protocol NIOHTTPClientProtocolUpgrader {\n\n    /// The protocol this upgrader knows how to support.\n    var supportedProtocol: String { get }\n\n    /// All the header fields the protocol requires in the request to successfully upgrade.\n    /// These header fields will be added to the outbound request's \"Connection\" header field.\n    /// It is the responsibility of the custom headers call to actually add these required headers.\n    var requiredUpgradeHeaders: [String] { get }\n\n    /// Additional headers to be added to the request, beyond the \"Upgrade\" and \"Connection\" headers.\n    func addCustom(upgradeRequestHeaders: inout HTTPHeaders)\n\n    /// Gives the receiving upgrader the chance to deny the upgrade based on the upgrade HTTP response.\n    func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel\n    /// pipeline to add whatever channel handlers are required.\n    /// Until the returned `EventLoopFuture` succeeds, all received data will be buffered.\n    func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void>\n}\n\n/// A client-side channel handler that sends a HTTP upgrade handshake request to perform a HTTP-upgrade.\n/// When the first HTTP request is sent, this handler will add all appropriate headers to perform an upgrade to\n/// the a protocol. It may add headers for a set of protocols in preference order.\n/// If the upgrade fails (i.e. response is not 101 Switching Protocols), this handler simply\n/// removes itself from the pipeline. If the upgrade is successful, it upgrades the pipeline to the new protocol.\n///\n/// The request sends an order of preference to request which protocol it would like to use for the upgrade.\n/// It will only upgrade to the protocol that is returned first in the list and does not currently\n/// have the capability to upgrade to multiple simultaneous layered protocols.\npublic final class NIOHTTPClientUpgradeHandler: ChannelDuplexHandler, RemovableChannelHandler {\n\n    public typealias OutboundIn = HTTPClientRequestPart\n    public typealias OutboundOut = HTTPClientRequestPart\n\n    public typealias InboundIn = HTTPClientResponsePart\n    public typealias InboundOut = HTTPClientResponsePart\n\n    private var upgraders: [NIOHTTPClientProtocolUpgrader]\n    private let httpHandlers: [RemovableChannelHandler]\n    private let upgradeCompletionHandler: (ChannelHandlerContext) -> Void\n\n    /// Whether we've already seen the first response from our initial upgrade request.\n    private var seenFirstResponse = false\n\n    private var upgradeState: UpgradeState = .requestRequired\n\n    private var receivedMessages: CircularBuffer<NIOAny> = CircularBuffer()\n\n    /// Create a `HTTPClientUpgradeHandler`.\n    ///\n    /// - Parameter upgraders: All `HTTPClientProtocolUpgrader` objects that will add their upgrade request\n    ///     headers and handle the upgrade if there is a response for their protocol. They should be placed in\n    ///     order of the preference for the upgrade.\n    /// - Parameter httpHandlers: All `RemovableChannelHandler` objects which will be removed from the pipeline\n    ///     once the upgrade response is sent. This is used to ensure that the pipeline will be in a clean state\n    ///     after the upgrade. It should include any handlers that are directly related to handling HTTP.\n    ///     At the very least this should include the `HTTPEncoder` and `HTTPDecoder`, but should also include\n    ///     any other handler that cannot tolerate receiving non-HTTP data.\n    /// - Parameter upgradeCompletionHandler: A closure that will be fired when HTTP upgrade is complete.\n    public convenience init(\n        upgraders: [NIOHTTPClientProtocolUpgrader],\n        httpHandlers: [RemovableChannelHandler],\n        upgradeCompletionHandler: @escaping (ChannelHandlerContext) -> Void\n    ) {\n        self.init(_upgraders: upgraders, httpHandlers: httpHandlers, upgradeCompletionHandler: upgradeCompletionHandler)\n    }\n\n    private init(\n        _upgraders upgraders: [NIOHTTPClientProtocolUpgrader],\n        httpHandlers: [RemovableChannelHandler],\n        upgradeCompletionHandler: @escaping (ChannelHandlerContext) -> Void\n    ) {\n        precondition(upgraders.count > 0, \"A minimum of one protocol upgrader must be specified.\")\n\n        self.upgraders = upgraders\n        self.httpHandlers = httpHandlers\n        self.upgradeCompletionHandler = upgradeCompletionHandler\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n\n        switch self.upgradeState {\n\n        case .requestRequired:\n            let updatedData = self.addHeadersToOutboundOut(data: data)\n            context.write(updatedData, promise: promise)\n\n        case .awaitingConfirmationResponse:\n            // Still have full http stack.\n            context.write(data, promise: promise)\n\n        case .upgraderReady, .upgrading:\n            promise?.fail(NIOHTTPClientUpgradeError.writingToHandlerDuringUpgrade)\n            context.fireErrorCaught(NIOHTTPClientUpgradeError.writingToHandlerDuringUpgrade)\n\n        case .upgradingAddingHandlers:\n            // These are most likely messages immediately fired by a new protocol handler.\n            // As that is added last we can just forward them on.\n            context.write(data, promise: promise)\n\n        case .upgradeComplete:\n            // Upgrade complete and this handler should have been removed from the pipeline.\n            promise?.fail(NIOHTTPClientUpgradeError.writingToHandlerAfterUpgradeCompleted)\n            context.fireErrorCaught(NIOHTTPClientUpgradeError.writingToHandlerAfterUpgradeCompleted)\n\n        case .upgradeFailed:\n            // Upgrade failed and this handler should have been removed from the pipeline.\n            promise?.fail(NIOHTTPClientUpgradeError.writingToHandlerAfterUpgradeCompleted)\n            context.fireErrorCaught(NIOHTTPClientUpgradeError.writingToHandlerAfterUpgradeCompleted)\n        }\n    }\n\n    private func addHeadersToOutboundOut(data: NIOAny) -> NIOAny {\n\n        let interceptedOutgoingRequest = NIOHTTPClientUpgradeHandler.unwrapOutboundIn(data)\n\n        if case .head(var requestHead) = interceptedOutgoingRequest {\n\n            self.upgradeState = .awaitingConfirmationResponse\n\n            self.addConnectionHeaders(to: &requestHead)\n            self.addUpgradeHeaders(to: &requestHead)\n            return NIOHTTPClientUpgradeHandler.wrapOutboundOut(.head(requestHead))\n        }\n\n        return data\n    }\n\n    private func addConnectionHeaders(to requestHead: inout HTTPRequestHead) {\n\n        let requiredHeaders = [\"upgrade\"] + self.upgraders.flatMap { $0.requiredUpgradeHeaders }\n        requestHead.headers.add(name: \"Connection\", value: requiredHeaders.joined(separator: \",\"))\n    }\n\n    private func addUpgradeHeaders(to requestHead: inout HTTPRequestHead) {\n\n        let allProtocols = self.upgraders.map { $0.supportedProtocol.lowercased() }\n        requestHead.headers.add(name: \"Upgrade\", value: allProtocols.joined(separator: \",\"))\n\n        // Allow each upgrader the chance to add custom headers.\n        for upgrader in self.upgraders {\n            upgrader.addCustom(upgradeRequestHeaders: &requestHead.headers)\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n\n        guard !self.seenFirstResponse else {\n            // We're waiting for upgrade to complete: buffer this data.\n            self.receivedMessages.append(data)\n            return\n        }\n\n        let responsePart = NIOHTTPClientUpgradeHandler.unwrapInboundIn(data)\n\n        switch self.upgradeState {\n        case .awaitingConfirmationResponse:\n            self.firstResponseHeadReceived(context: context, responsePart: responsePart)\n        case .upgrading, .upgradingAddingHandlers:\n            if case .end = responsePart {\n                // This is the end of the first response. Swallow it, we're buffering the rest.\n                self.seenFirstResponse = true\n            }\n        case .upgraderReady(let upgrade):\n            if case .end = responsePart {\n                // This is the end of the first response, and we can upgrade. Time to kick it off.\n                self.seenFirstResponse = true\n                upgrade()\n            }\n        case .upgradeFailed:\n            // We were reentrantly called while delivering the response head. We can just pass this through.\n            context.fireChannelRead(data)\n        case .upgradeComplete:\n            //Upgrade has completed but we have not seen a whole response and still got reentrantly called.\n            context.fireErrorCaught(NIOHTTPClientUpgradeError.receivedResponseAfterUpgradeCompleted)\n        case .requestRequired:\n            //We are receiving an upgrade response and we have not requested the upgrade.\n            context.fireErrorCaught(NIOHTTPClientUpgradeError.receivedResponseBeforeRequestSent)\n        }\n    }\n\n    private func firstResponseHeadReceived(context: ChannelHandlerContext, responsePart: HTTPClientResponsePart) {\n\n        // We should decide if we're can upgrade based on the first response header: if we aren't upgrading,\n        // by the time the body comes in we should be out of the pipeline. That means that if we don't think we're\n        // upgrading, the only thing we should see is a response head. Anything else in an error.\n        guard case .head(let response) = responsePart else {\n            self.notUpgrading(context: context, data: responsePart, error: .invalidHTTPOrdering)\n            return\n        }\n\n        // Assess whether the upgrade response has accepted our upgrade request.\n        guard case .switchingProtocols = response.status else {\n            self.notUpgrading(context: context, data: responsePart, error: nil)\n            return\n        }\n\n        do {\n            let callback = try self.handleUpgrade(context: context, upgradeResponse: response)\n            self.gotUpgrader(upgrader: callback)\n        } catch {\n            let clientError = error as? NIOHTTPClientUpgradeError\n            self.notUpgrading(context: context, data: responsePart, error: clientError)\n        }\n    }\n\n    private func handleUpgrade(\n        context: ChannelHandlerContext,\n        upgradeResponse response: HTTPResponseHead\n    ) throws -> (() -> Void) {\n\n        // Ok, we have a HTTP response. Check if it's an upgrade confirmation.\n        // If it's not, we want to pass it on and remove ourselves from the channel pipeline.\n        let acceptedProtocols = response.headers[canonicalForm: \"upgrade\"]\n\n        // At the moment we only upgrade to the first protocol returned from the server.\n        guard let protocolName = acceptedProtocols.first?.lowercased() else {\n            // There are no upgrade protocols returned.\n            throw NIOHTTPClientUpgradeError.responseProtocolNotFound\n        }\n\n        return try self.handleUpgradeForProtocol(\n            context: context,\n            protocolName: protocolName,\n            response: response\n        )\n    }\n\n    /// Attempt to upgrade a single protocol.\n    private func handleUpgradeForProtocol(\n        context: ChannelHandlerContext,\n        protocolName: String,\n        response: HTTPResponseHead\n    ) throws -> (() -> Void) {\n\n        let matchingUpgrader = self.upgraders\n            .first(where: { $0.supportedProtocol.lowercased() == protocolName })\n\n        guard let upgrader = matchingUpgrader else {\n            // There is no upgrader for this protocol.\n            throw NIOHTTPClientUpgradeError.responseProtocolNotFound\n        }\n\n        guard upgrader.shouldAllowUpgrade(upgradeResponse: response) else {\n            // The upgrader says no.\n            throw NIOHTTPClientUpgradeError.upgraderDeniedUpgrade\n        }\n\n        return self.performUpgrade(context: context, upgrader: upgrader, response: response)\n    }\n\n    private func performUpgrade(\n        context: ChannelHandlerContext,\n        upgrader: NIOHTTPClientProtocolUpgrader,\n        response: HTTPResponseHead\n    ) -> () -> Void {\n\n        // Before we start the upgrade we have to remove the HTTPEncoder and HTTPDecoder handlers from the\n        // pipeline, to prevent them parsing any more data. We'll buffer the incoming data until that completes.\n        // While there are a lot of Futures involved here it's quite possible that all of this code will\n        // actually complete synchronously: we just want to program for the possibility that it won't.\n        // Once that's done, we call the internal handler, then call the upgrader code, and then finally when the\n        // upgrader code is done, we do our final cleanup steps, namely we replay the received data we\n        // buffered in the meantime and then remove ourselves from the pipeline.\n        let pipeline = context.pipeline\n        return {\n            self.upgradeState = .upgrading\n\n            self.removeHTTPHandlers(pipeline: pipeline)\n                .map {\n                    // Let the other handlers be removed before continuing with upgrade.\n                    self.upgradeCompletionHandler(context)\n                    self.upgradeState = .upgradingAddingHandlers\n                }\n                .flatMap {\n                    upgrader.upgrade(context: context, upgradeResponse: response)\n                }\n                .map {\n                    // We unbuffer any buffered data here.\n\n                    // If we received any, we fire readComplete.\n                    let fireReadComplete = self.receivedMessages.count > 0\n                    while self.receivedMessages.count > 0 {\n                        let bufferedPart = self.receivedMessages.removeFirst()\n                        context.fireChannelRead(bufferedPart)\n                    }\n                    if fireReadComplete {\n                        context.fireChannelReadComplete()\n                    }\n\n                    // We wait with the state change until _after_ the channel reads here.\n                    // This is to prevent firing writes in response to these reads after we went to .upgradeComplete\n                    // See: https://github.com/apple/swift-nio/issues/1279\n                    self.upgradeState = .upgradeComplete\n                }\n                .whenComplete { _ in\n                    context.pipeline.syncOperations.removeHandler(context: context, promise: nil)\n                }\n        }\n    }\n\n    /// Removes any extra HTTP-related handlers from the channel pipeline.\n    private func removeHTTPHandlers(pipeline: ChannelPipeline) -> EventLoopFuture<Void>.Isolated {\n        guard self.httpHandlers.count > 0 else {\n            return pipeline.eventLoop.makeSucceededIsolatedFuture(())\n        }\n\n        let removeFutures = self.httpHandlers.map { pipeline.syncOperations.removeHandler($0) }\n        return EventLoopFuture.andAllSucceed(removeFutures, on: pipeline.eventLoop).assumeIsolated()\n    }\n\n    private func gotUpgrader(upgrader: @escaping (() -> Void)) {\n\n        self.upgradeState = .upgraderReady(upgrader)\n        if self.seenFirstResponse {\n            // Ok, we're good to go, we can upgrade. Otherwise we're waiting for .end, which\n            // will trigger the upgrade.\n            upgrader()\n        }\n    }\n\n    private func notUpgrading(\n        context: ChannelHandlerContext,\n        data: HTTPClientResponsePart,\n        error: NIOHTTPClientUpgradeError?\n    ) {\n\n        self.upgradeState = .upgradeFailed\n\n        if let error = error {\n            context.fireErrorCaught(error)\n        }\n\n        assert(self.receivedMessages.isEmpty)\n        context.fireChannelRead(NIOHTTPClientUpgradeHandler.wrapInboundOut(data))\n\n        // We've delivered the data. We can now remove ourselves, which should happen synchronously.\n        context.pipeline.syncOperations.removeHandler(context: context, promise: nil)\n    }\n}\n\nextension NIOHTTPClientUpgradeHandler: @unchecked Sendable {}\n\nextension NIOHTTPClientUpgradeHandler {\n    /// The state of the upgrade handler.\n    fileprivate enum UpgradeState {\n        /// Request not sent. This will need to be sent to initiate the upgrade.\n        case requestRequired\n\n        /// Awaiting confirmation response which will allow the upgrade to zero one or more protocols.\n        case awaitingConfirmationResponse\n\n        /// The response head has been received. We have an upgrader, which means we can begin upgrade.\n        case upgraderReady(() -> Void)\n\n        /// The response head has been received. The upgrade is in process.\n        case upgrading\n\n        /// The upgrade is in process and all of the http handlers have been removed.\n        case upgradingAddingHandlers\n\n        /// The upgrade has succeeded, and we are being removed from the pipeline.\n        case upgradeComplete\n\n        /// The upgrade has failed.\n        case upgradeFailed\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/NIOHTTPObjectAggregator.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// The parts of a complete HTTP response from the view of the client.\n///\n/// A full HTTP request is made up of a response header encoded by `.head`\n/// and an optional `.body`.\npublic struct NIOHTTPServerRequestFull: Sendable {\n    public var head: HTTPRequestHead\n    public var body: ByteBuffer?\n\n    public init(head: HTTPRequestHead, body: ByteBuffer?) {\n        self.head = head\n        self.body = body\n    }\n}\n\nextension NIOHTTPServerRequestFull: Equatable {}\n\n/// The parts of a complete HTTP response from the view of the client.\n///\n/// A full HTTP response is made up of a response header encoded by `.head`\n/// and an optional `.body`.\npublic struct NIOHTTPClientResponseFull: Sendable {\n    public var head: HTTPResponseHead\n    public var body: ByteBuffer?\n\n    public init(head: HTTPResponseHead, body: ByteBuffer?) {\n        self.head = head\n        self.body = body\n    }\n}\n\nextension NIOHTTPClientResponseFull: Equatable {}\n\npublic struct NIOHTTPObjectAggregatorError: Error, Equatable {\n    private enum Base {\n        case frameTooLong\n        case connectionClosed\n        case endingIgnoredMessage\n        case unexpectedMessageHead\n        case unexpectedMessageBody\n        case unexpectedMessageEnd\n    }\n\n    private var base: Base\n\n    private init(base: Base) {\n        self.base = base\n    }\n\n    public static let frameTooLong = NIOHTTPObjectAggregatorError(base: .frameTooLong)\n    public static let connectionClosed = NIOHTTPObjectAggregatorError(base: .connectionClosed)\n    public static let endingIgnoredMessage = NIOHTTPObjectAggregatorError(base: .endingIgnoredMessage)\n    public static let unexpectedMessageHead = NIOHTTPObjectAggregatorError(base: .unexpectedMessageHead)\n    public static let unexpectedMessageBody = NIOHTTPObjectAggregatorError(base: .unexpectedMessageBody)\n    public static let unexpectedMessageEnd = NIOHTTPObjectAggregatorError(base: .unexpectedMessageEnd)\n}\n\npublic struct NIOHTTPObjectAggregatorEvent: Hashable, Sendable {\n    private enum Base {\n        case httpExpectationFailed\n        case httpFrameTooLong\n    }\n\n    private var base: Base\n\n    private init(base: Base) {\n        self.base = base\n    }\n\n    public static let httpExpectationFailed = NIOHTTPObjectAggregatorEvent(base: .httpExpectationFailed)\n    public static let httpFrameTooLong = NIOHTTPObjectAggregatorEvent(base: .httpFrameTooLong)\n}\n\n/// The state of the aggregator  connection.\ninternal enum AggregatorState {\n    /// Nothing is active on this connection, the next message we expect would be a request `.head`.\n    case idle\n\n    /// Ill-behaving client may be sending content that is too large\n    case ignoringContent\n\n    /// We are receiving and aggregating a request\n    case receiving\n\n    /// Connection should be closed\n    case closed\n\n    mutating func messageHeadReceived() throws {\n        switch self {\n        case .idle:\n            self = .receiving\n        case .ignoringContent, .receiving:\n            throw NIOHTTPObjectAggregatorError.unexpectedMessageHead\n        case .closed:\n            throw NIOHTTPObjectAggregatorError.connectionClosed\n        }\n    }\n\n    mutating func messageBodyReceived() throws {\n        switch self {\n        case .receiving:\n            ()\n        case .ignoringContent:\n            throw NIOHTTPObjectAggregatorError.frameTooLong\n        case .idle:\n            throw NIOHTTPObjectAggregatorError.unexpectedMessageBody\n        case .closed:\n            throw NIOHTTPObjectAggregatorError.connectionClosed\n        }\n    }\n\n    mutating func messageEndReceived() throws {\n        switch self {\n        case .receiving:\n            // Got the request end we were waiting for.\n            self = .idle\n        case .ignoringContent:\n            // Expected transition from a state where message contents are getting\n            // ignored because the message is too large. Throwing an error prevents\n            // the normal control flow from continuing into dispatching the completed\n            // invalid message to the next handler.\n            self = .idle\n            throw NIOHTTPObjectAggregatorError.endingIgnoredMessage\n        case .idle:\n            throw NIOHTTPObjectAggregatorError.unexpectedMessageEnd\n        case .closed:\n            throw NIOHTTPObjectAggregatorError.connectionClosed\n        }\n    }\n\n    mutating func handlingOversizeMessage() {\n        switch self {\n        case .receiving, .idle:\n            self = .ignoringContent\n        case .ignoringContent, .closed:\n            // If we are already ignoring content or connection is closed, should not get here\n            preconditionFailure(\"Unreachable state: should never handle overized message in \\(self)\")\n        }\n    }\n\n    mutating func closed() {\n        self = .closed\n    }\n}\n\n/// A `ChannelInboundHandler` that handles HTTP chunked `HTTPServerRequestPart`\n/// messages by aggregating individual message chunks into a single\n/// `NIOHTTPServerRequestFull`.\n///\n/// This is achieved by buffering the contents of all received `HTTPServerRequestPart`\n/// messages until `HTTPServerRequestPart.end` is received, then assembling the\n/// full message and firing a channel read upstream with it. It is useful for when you do not\n/// want to deal with chunked messages and just want to receive everything at once, and\n/// are happy with the additional memory used and delay handling of the message until\n/// everything has been received.\n///\n/// `NIOHTTPServerRequestAggregator` may end up sending a `HTTPResponseHead`:\n/// - Response status `413 Request Entity Too Large` when either the\n///     `content-length` or the bytes received so far exceed `maxContentLength`.\n///\n/// `NIOHTTPServerRequestAggregator` may close the connection if it is impossible\n/// to recover:\n/// - If `content-length` is too large and `keep-alive` is off.\n/// - If the bytes received exceed `maxContentLength` and the client didn't signal\n///     `content-length`\npublic final class NIOHTTPServerRequestAggregator: ChannelInboundHandler, RemovableChannelHandler {\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias InboundOut = NIOHTTPServerRequestFull\n\n    // Aggregator may generate responses of its own\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    private var fullMessageHead: HTTPRequestHead? = nil\n    private var buffer: ByteBuffer! = nil\n    private var maxContentLength: Int\n    private var closeOnExpectationFailed: Bool\n    private var state: AggregatorState\n\n    public init(maxContentLength: Int, closeOnExpectationFailed: Bool = false) {\n        precondition(maxContentLength >= 0, \"maxContentLength must not be negative\")\n        self.maxContentLength = maxContentLength\n        self.closeOnExpectationFailed = closeOnExpectationFailed\n        self.state = .idle\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let msg = NIOHTTPServerRequestAggregator.unwrapInboundIn(data)\n        var serverResponse: HTTPResponseHead? = nil\n\n        do {\n            switch msg {\n            case .head(let httpHead):\n                try self.state.messageHeadReceived()\n                serverResponse = self.beginAggregation(context: context, request: httpHead, message: msg)\n            case .body(var content):\n                try self.state.messageBodyReceived()\n                serverResponse = self.aggregate(context: context, content: &content, message: msg)\n            case .end(let trailingHeaders):\n                try self.state.messageEndReceived()\n                self.endAggregation(context: context, trailingHeaders: trailingHeaders)\n            }\n        } catch let error as NIOHTTPObjectAggregatorError {\n            context.fireErrorCaught(error)\n            // Won't be able to complete those\n            self.fullMessageHead = nil\n            self.buffer.clear()\n        } catch let error {\n            context.fireErrorCaught(error)\n        }\n\n        // Generated a server response to send back\n        if let response = serverResponse {\n            context.write(NIOHTTPServerRequestAggregator.wrapOutboundOut(.head(response)), promise: nil)\n            context.writeAndFlush(NIOHTTPServerRequestAggregator.wrapOutboundOut(.end(nil)), promise: nil)\n            if response.status == .payloadTooLarge {\n                // If indicated content length is too large\n                self.state.handlingOversizeMessage()\n                context.fireErrorCaught(NIOHTTPObjectAggregatorError.frameTooLong)\n                context.fireUserInboundEventTriggered(NIOHTTPObjectAggregatorEvent.httpFrameTooLong)\n            }\n            if !response.headers.isKeepAlive(version: response.version) {\n                context.close(promise: nil)\n                self.state.closed()\n            }\n        }\n    }\n\n    private func beginAggregation(\n        context: ChannelHandlerContext,\n        request: HTTPRequestHead,\n        message: InboundIn\n    ) -> HTTPResponseHead? {\n        self.fullMessageHead = request\n        if let contentLength = request.contentLength, contentLength > self.maxContentLength {\n            return self.handleOversizeMessage(message: message)\n        }\n        return nil\n    }\n\n    private func aggregate(\n        context: ChannelHandlerContext,\n        content: inout ByteBuffer,\n        message: InboundIn\n    ) -> HTTPResponseHead? {\n        if content.readableBytes > self.maxContentLength - self.buffer.readableBytes {\n            return self.handleOversizeMessage(message: message)\n        } else {\n            self.buffer.writeBuffer(&content)\n            return nil\n        }\n    }\n\n    private func endAggregation(context: ChannelHandlerContext, trailingHeaders: HTTPHeaders?) {\n        if var aggregated = self.fullMessageHead {\n            // Remove `Trailer` from existing header fields and append trailer fields to existing header fields\n            // See rfc7230 4.1.3 Decoding Chunked\n            if let headers = trailingHeaders {\n                aggregated.headers.remove(name: \"trailer\")\n                aggregated.headers.add(contentsOf: headers)\n            }\n\n            let fullMessage = NIOHTTPServerRequestFull(\n                head: aggregated,\n                body: self.buffer.readableBytes > 0 ? self.buffer : nil\n            )\n            self.fullMessageHead = nil\n            self.buffer.clear()\n            context.fireChannelRead(NIOAny(fullMessage))\n        }\n    }\n\n    private func handleOversizeMessage(message: InboundIn) -> HTTPResponseHead {\n        var payloadTooLargeHead = HTTPResponseHead(\n            version: self.fullMessageHead?.version ?? .http1_1,\n            status: .payloadTooLarge,\n            headers: HTTPHeaders([(\"content-length\", \"0\")])\n        )\n\n        switch message {\n        case .head(let request):\n            if !request.isKeepAlive {\n                // If keep-alive is off and, no need to leave the connection open.\n                // Send back a 413 and close the connection.\n                payloadTooLargeHead.headers.add(name: \"connection\", value: \"close\")\n            }\n        default:\n            // The client started to send data already, close because it's impossible to recover.\n            // Send back a 413 and close the connection.\n            payloadTooLargeHead.headers.add(name: \"connection\", value: \"close\")\n        }\n\n        return payloadTooLargeHead\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self.buffer = context.channel.allocator.buffer(capacity: 0)\n    }\n}\n\n@available(*, unavailable)\nextension NIOHTTPServerRequestAggregator: Sendable {}\n\n/// A `ChannelInboundHandler` that handles HTTP chunked `HTTPClientResponsePart`\n/// messages by aggregating individual message chunks into a single\n/// `NIOHTTPClientResponseFull`.\n///\n/// This is achieved by buffering the contents of all received `HTTPClientResponsePart`\n/// messages until `HTTPClientResponsePart.end` is received, then assembling the\n/// full message and firing a channel read upstream with it. Useful when you do not\n/// want to deal with chunked messages and just want to receive everything at once, and\n/// are happy with the additional memory used and delay handling of the message until\n/// everything has been received.\n///\n/// If `NIOHTTPClientResponseAggregator` encounters a message larger than\n/// `maxContentLength`, it discards the aggregated contents until the next\n/// `HTTPClientResponsePart.end` and signals that via\n/// `fireUserInboundEventTriggered`.\npublic final class NIOHTTPClientResponseAggregator: ChannelInboundHandler, RemovableChannelHandler {\n    public typealias InboundIn = HTTPClientResponsePart\n    public typealias InboundOut = NIOHTTPClientResponseFull\n\n    private var fullMessageHead: HTTPResponseHead? = nil\n    private var buffer: ByteBuffer! = nil\n    private var maxContentLength: Int\n    private var state: AggregatorState\n\n    public init(maxContentLength: Int) {\n        precondition(maxContentLength >= 0, \"maxContentLength must not be negative\")\n        self.maxContentLength = maxContentLength\n        self.state = .idle\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let msg = NIOHTTPClientResponseAggregator.unwrapInboundIn(data)\n\n        do {\n            switch msg {\n            case .head(let httpHead):\n                try self.state.messageHeadReceived()\n                try self.beginAggregation(context: context, response: httpHead)\n            case .body(var content):\n                try self.state.messageBodyReceived()\n                try self.aggregate(context: context, content: &content)\n            case .end(let trailingHeaders):\n                try self.state.messageEndReceived()\n                self.endAggregation(context: context, trailingHeaders: trailingHeaders)\n            }\n        } catch let error as NIOHTTPObjectAggregatorError {\n            context.fireErrorCaught(error)\n            // Won't be able to complete those\n            self.fullMessageHead = nil\n            self.buffer.clear()\n        } catch let error {\n            context.fireErrorCaught(error)\n        }\n    }\n\n    private func beginAggregation(context: ChannelHandlerContext, response: HTTPResponseHead) throws {\n        self.fullMessageHead = response\n        if let contentLength = response.contentLength, contentLength > self.maxContentLength {\n            self.state.handlingOversizeMessage()\n            context.fireUserInboundEventTriggered(NIOHTTPObjectAggregatorEvent.httpFrameTooLong)\n            context.fireErrorCaught(NIOHTTPObjectAggregatorError.frameTooLong)\n        }\n    }\n\n    private func aggregate(context: ChannelHandlerContext, content: inout ByteBuffer) throws {\n        if content.readableBytes > self.maxContentLength - self.buffer.readableBytes {\n            self.state.handlingOversizeMessage()\n            context.fireUserInboundEventTriggered(NIOHTTPObjectAggregatorEvent.httpFrameTooLong)\n            context.fireErrorCaught(NIOHTTPObjectAggregatorError.frameTooLong)\n        } else {\n            self.buffer.writeBuffer(&content)\n        }\n    }\n\n    private func endAggregation(context: ChannelHandlerContext, trailingHeaders: HTTPHeaders?) {\n        if var aggregated = self.fullMessageHead {\n            // Remove `Trailer` from existing header fields and append trailer fields to existing header fields\n            // See rfc7230 4.1.3 Decoding Chunked\n            if let headers = trailingHeaders {\n                aggregated.headers.remove(name: \"trailer\")\n                aggregated.headers.add(contentsOf: headers)\n            }\n\n            let fullMessage = NIOHTTPClientResponseFull(\n                head: aggregated,\n                body: self.buffer.readableBytes > 0 ? self.buffer : nil\n            )\n            self.fullMessageHead = nil\n            self.buffer.clear()\n            context.fireChannelRead(NIOAny(fullMessage))\n        }\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self.buffer = context.channel.allocator.buffer(capacity: 0)\n    }\n}\n\n@available(*, unavailable)\nextension NIOHTTPClientResponseAggregator: Sendable {}\n"
  },
  {
    "path": "Sources/NIOHTTP1/NIOTypedHTTPClientUpgradeHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// An object that implements `NIOTypedHTTPClientProtocolUpgrader` knows how to handle HTTP upgrade to\n/// a protocol on a client-side channel.\n/// It has the option of denying this upgrade based upon the server response.\n@preconcurrency\npublic protocol NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>: Sendable {\n    associatedtype UpgradeResult: Sendable\n\n    /// The protocol this upgrader knows how to support.\n    var supportedProtocol: String { get }\n\n    /// All the header fields the protocol requires in the request to successfully upgrade.\n    /// These header fields will be added to the outbound request's \"Connection\" header field.\n    /// It is the responsibility of the custom headers call to actually add these required headers.\n    var requiredUpgradeHeaders: [String] { get }\n\n    /// Additional headers to be added to the request, beyond the \"Upgrade\" and \"Connection\" headers.\n    func addCustom(upgradeRequestHeaders: inout HTTPHeaders)\n\n    /// Gives the receiving upgrader the chance to deny the upgrade based on the upgrade HTTP response.\n    func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel\n    /// pipeline to add whatever channel handlers are required.\n    /// Until the returned `EventLoopFuture` succeeds, all received data will be buffered.\n    func upgrade(channel: Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<UpgradeResult>\n}\n\n/// The upgrade configuration for the ``NIOTypedHTTPClientUpgradeHandler``.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult: Sendable>: Sendable {\n    /// The initial request head that is sent out once the channel becomes active.\n    public var upgradeRequestHead: HTTPRequestHead\n\n    /// The array of potential upgraders.\n    public var upgraders: [any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>]\n\n    /// A closure that is run once it is determined that no protocol upgrade is happening. This can be used\n    /// to configure handlers that expect HTTP.\n    public var notUpgradingCompletionHandler: @Sendable (Channel) -> EventLoopFuture<UpgradeResult>\n\n    public init(\n        upgradeRequestHead: HTTPRequestHead,\n        upgraders: [any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>],\n        notUpgradingCompletionHandler: @Sendable @escaping (Channel) -> EventLoopFuture<UpgradeResult>\n    ) {\n        precondition(upgraders.count > 0, \"A minimum of one protocol upgrader must be specified.\")\n        self.upgradeRequestHead = upgradeRequestHead\n        self.upgraders = upgraders\n        self.notUpgradingCompletionHandler = notUpgradingCompletionHandler\n    }\n}\n\n/// A client-side channel handler that sends a HTTP upgrade handshake request to perform a HTTP-upgrade.\n/// This handler will add all appropriate headers to perform an upgrade to\n/// the a protocol. It may add headers for a set of protocols in preference order.\n/// If the upgrade fails (i.e. response is not 101 Switching Protocols), this handler simply\n/// removes itself from the pipeline. If the upgrade is successful, it upgrades the pipeline to the new protocol.\n///\n/// The request sends an order of preference to request which protocol it would like to use for the upgrade.\n/// It will only upgrade to the protocol that is returned first in the list and does not currently\n/// have the capability to upgrade to multiple simultaneous layered protocols.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic final class NIOTypedHTTPClientUpgradeHandler<UpgradeResult: Sendable>: ChannelDuplexHandler,\n    RemovableChannelHandler\n{\n    public typealias OutboundIn = HTTPClientRequestPart\n    public typealias OutboundOut = HTTPClientRequestPart\n    public typealias InboundIn = HTTPClientResponsePart\n    public typealias InboundOut = HTTPClientResponsePart\n\n    /// The upgrade future which will be completed once protocol upgrading has been done.\n    public var upgradeResultFuture: EventLoopFuture<UpgradeResult> {\n        self.upgradeResultPromise.futureResult\n    }\n\n    private let upgradeRequestHead: HTTPRequestHead\n    private let httpHandlers: [RemovableChannelHandler]\n    private let notUpgradingCompletionHandler: @Sendable (Channel) -> EventLoopFuture<UpgradeResult>\n    private var stateMachine: NIOTypedHTTPClientUpgraderStateMachine<UpgradeResult>\n    private var _upgradeResultPromise: EventLoopPromise<UpgradeResult>?\n    private var upgradeResultPromise: EventLoopPromise<UpgradeResult> {\n        precondition(\n            self._upgradeResultPromise != nil,\n            \"Tried to access the upgrade result before the handler was added to a pipeline\"\n        )\n        return self._upgradeResultPromise!\n    }\n\n    /// Create a ``NIOTypedHTTPClientUpgradeHandler``.\n    ///\n    /// - Parameters:\n    ///  - httpHandlers: All `RemovableChannelHandler` objects which will be removed from the pipeline\n    ///     once the upgrade response is sent. This is used to ensure that the pipeline will be in a clean state\n    ///     after the upgrade. It should include any handlers that are directly related to handling HTTP.\n    ///     At the very least this should include the `HTTPEncoder` and `HTTPDecoder`, but should also include\n    ///     any other handler that cannot tolerate receiving non-HTTP data.\n    ///  - upgradeConfiguration: The upgrade configuration.\n    public init(\n        httpHandlers: [RemovableChannelHandler],\n        upgradeConfiguration: NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult>\n    ) {\n        self.httpHandlers = httpHandlers\n        var upgradeRequestHead = upgradeConfiguration.upgradeRequestHead\n        Self.addHeaders(\n            to: &upgradeRequestHead,\n            upgraders: upgradeConfiguration.upgraders\n        )\n        self.upgradeRequestHead = upgradeRequestHead\n        self.stateMachine = .init(upgraders: upgradeConfiguration.upgraders)\n        self.notUpgradingCompletionHandler = upgradeConfiguration.notUpgradingCompletionHandler\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self._upgradeResultPromise = context.eventLoop.makePromise(of: UpgradeResult.self)\n        if context.channel.isActive {\n            switch self.stateMachine.channelActive() {\n            case .writeUpgradeRequest:\n                self.writeUpgradeRequest(context: context)\n            case .none:\n                break\n            }\n        }\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        switch self.stateMachine.handlerRemoved() {\n        case .failUpgradePromise:\n            self.upgradeResultPromise.fail(ChannelError.inappropriateOperationForState)\n        case .none:\n            break\n        }\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n        switch self.stateMachine.channelActive() {\n        case .writeUpgradeRequest:\n            self.writeUpgradeRequest(context: context)\n        case .none:\n            break\n        }\n    }\n\n    private static func addHeaders(\n        to requestHead: inout HTTPRequestHead,\n        upgraders: [any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>]\n    ) {\n        let requiredHeaders = [\"upgrade\"] + upgraders.flatMap { $0.requiredUpgradeHeaders }\n        requestHead.headers.add(name: \"Connection\", value: requiredHeaders.joined(separator: \",\"))\n\n        let allProtocols = upgraders.map { $0.supportedProtocol.lowercased() }\n        requestHead.headers.add(name: \"Upgrade\", value: allProtocols.joined(separator: \",\"))\n\n        // Allow each upgrader the chance to add custom headers.\n        for upgrader in upgraders {\n            upgrader.addCustom(upgradeRequestHeaders: &requestHead.headers)\n        }\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        switch self.stateMachine.write() {\n        case .failWrite(let error):\n            promise?.fail(error)\n\n        case .forwardWrite:\n            context.write(data, promise: promise)\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch self.stateMachine.channelReadData(data) {\n        case .unwrapData:\n            let responsePart = NIOTypedHTTPClientUpgradeHandler.unwrapInboundIn(data)\n            self.channelRead(context: context, responsePart: responsePart)\n\n        case .fireChannelRead:\n            context.fireChannelRead(data)\n\n        case .none:\n            break\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: any Error) {\n        self.upgradeResultPromise.fail(error)\n        context.fireErrorCaught(error)\n    }\n\n    private func writeUpgradeRequest(context: ChannelHandlerContext) {\n        context.write(\n            NIOTypedHTTPClientUpgradeHandler.wrapOutboundOut(.head(self.upgradeRequestHead)),\n            promise: nil\n        )\n        context.write(NIOTypedHTTPClientUpgradeHandler.wrapOutboundOut(.body(.byteBuffer(.init()))), promise: nil)\n        context.writeAndFlush(NIOTypedHTTPClientUpgradeHandler.wrapOutboundOut(.end(nil)), promise: nil)\n    }\n\n    private func channelRead(context: ChannelHandlerContext, responsePart: HTTPClientResponsePart) {\n        switch self.stateMachine.channelReadResponsePart(responsePart) {\n        case .fireErrorCaughtAndRemoveHandler(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .runNotUpgradingInitializer:\n            self.notUpgradingCompletionHandler(context.channel)\n                .hop(to: context.eventLoop)\n                .assumeIsolated()\n                .whenComplete { result in\n                    self.upgradingHandlerCompleted(context: context, result)\n                }\n\n        case .startUpgrading(let upgrader, let responseHead):\n            self.startUpgrading(\n                context: context,\n                upgrader: upgrader,\n                responseHead: responseHead\n            )\n\n        case .none:\n            break\n        }\n    }\n\n    private func startUpgrading(\n        context: ChannelHandlerContext,\n        upgrader: any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>,\n        responseHead: HTTPResponseHead\n    ) {\n        // Before we start the upgrade we have to remove the HTTPEncoder and HTTPDecoder handlers from the\n        // pipeline, to prevent them parsing any more data. We'll buffer the incoming data until that completes.\n        let channel = context.channel\n        self.removeHTTPHandlers(pipeline: context.pipeline)\n            .flatMap {\n                upgrader.upgrade(channel: channel, upgradeResponse: responseHead)\n            }.hop(to: context.eventLoop)\n            .assumeIsolated()\n            .whenComplete { result in\n                self.upgradingHandlerCompleted(context: context, result)\n            }\n    }\n\n    private func upgradingHandlerCompleted(\n        context: ChannelHandlerContext,\n        _ result: Result<UpgradeResult, Error>\n    ) {\n        switch self.stateMachine.upgradingHandlerCompleted(result) {\n        case .fireErrorCaughtAndRemoveHandler(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .fireErrorCaughtAndStartUnbuffering(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            self.unbuffer(context: context)\n\n        case .startUnbuffering(let value):\n            self.upgradeResultPromise.succeed(value)\n            self.unbuffer(context: context)\n\n        case .removeHandler(let value):\n            self.upgradeResultPromise.succeed(value)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .none:\n            break\n        }\n    }\n\n    private func unbuffer(context: ChannelHandlerContext) {\n        while true {\n            switch self.stateMachine.unbuffer() {\n            case .fireChannelRead(let data):\n                context.fireChannelRead(data)\n\n            case .fireChannelReadCompleteAndRemoveHandler:\n                context.fireChannelReadComplete()\n                context.pipeline.syncOperations.removeHandler(self, promise: nil)\n                return\n            }\n        }\n    }\n\n    /// Removes any extra HTTP-related handlers from the channel pipeline.\n    private func removeHTTPHandlers(pipeline: ChannelPipeline) -> EventLoopFuture<Void> {\n        guard self.httpHandlers.count > 0 else {\n            return pipeline.eventLoop.makeSucceededFuture(())\n        }\n\n        let removeFutures = self.httpHandlers.map { pipeline.syncOperations.removeHandler($0) }\n        return .andAllSucceed(removeFutures, on: pipeline.eventLoop)\n    }\n}\n\n@available(*, unavailable)\nextension NIOTypedHTTPClientUpgradeHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOHTTP1/NIOTypedHTTPClientUpgraderStateMachine.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport DequeModule\nimport NIOCore\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nstruct NIOTypedHTTPClientUpgraderStateMachine<UpgradeResult> {\n    @usableFromInline\n    enum State {\n        /// The state before we received a TLSUserEvent. We are just forwarding any read at this point.\n        case initial(upgraders: [any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>])\n\n        /// The request has been sent. We are waiting for the upgrade response.\n        case awaitingUpgradeResponseHead(upgraders: [any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>])\n\n        @usableFromInline\n        struct AwaitingUpgradeResponseEnd {\n            var upgrader: any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>\n            var responseHead: HTTPResponseHead\n        }\n        /// We received the response head and are just waiting for the response end.\n        case awaitingUpgradeResponseEnd(AwaitingUpgradeResponseEnd)\n\n        @usableFromInline\n        struct Upgrading {\n            var buffer: Deque<NIOAny>\n        }\n        /// We are either running the upgrading handler.\n        case upgrading(Upgrading)\n\n        @usableFromInline\n        struct Unbuffering {\n            var buffer: Deque<NIOAny>\n        }\n        case unbuffering(Unbuffering)\n\n        case finished\n\n        case modifying\n    }\n\n    private var state: State\n\n    init(upgraders: [any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>]) {\n        self.state = .initial(upgraders: upgraders)\n    }\n\n    @usableFromInline\n    enum HandlerRemovedAction {\n        case failUpgradePromise\n    }\n\n    @inlinable\n    mutating func handlerRemoved() -> HandlerRemovedAction? {\n        switch self.state {\n        case .initial, .awaitingUpgradeResponseHead, .awaitingUpgradeResponseEnd, .upgrading, .unbuffering:\n            self.state = .finished\n            return .failUpgradePromise\n\n        case .finished:\n            return .none\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum ChannelActiveAction {\n        case writeUpgradeRequest\n    }\n\n    @inlinable\n    mutating func channelActive() -> ChannelActiveAction? {\n        switch self.state {\n        case .initial(let upgraders):\n            self.state = .awaitingUpgradeResponseHead(upgraders: upgraders)\n            return .writeUpgradeRequest\n\n        case .finished:\n            return nil\n\n        case .awaitingUpgradeResponseHead:\n            return nil\n\n        case .awaitingUpgradeResponseEnd, .unbuffering, .upgrading:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum WriteAction {\n        case failWrite(Error)\n        case forwardWrite\n    }\n\n    @usableFromInline\n    func write() -> WriteAction {\n        switch self.state {\n        case .initial, .awaitingUpgradeResponseHead, .awaitingUpgradeResponseEnd, .upgrading:\n            return .failWrite(NIOHTTPClientUpgradeError.writingToHandlerDuringUpgrade)\n\n        case .unbuffering, .finished:\n            return .forwardWrite\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum ChannelReadDataAction {\n        case unwrapData\n        case fireChannelRead\n    }\n\n    @inlinable\n    mutating func channelReadData(_ data: NIOAny) -> ChannelReadDataAction? {\n        switch self.state {\n        case .initial:\n            return .unwrapData\n\n        case .awaitingUpgradeResponseHead, .awaitingUpgradeResponseEnd:\n            return .unwrapData\n\n        case .upgrading(var upgrading):\n            // We got a read while running upgrading.\n            // We have to buffer the read to unbuffer it afterwards\n            self.state = .modifying\n            upgrading.buffer.append(data)\n            self.state = .upgrading(upgrading)\n            return nil\n\n        case .unbuffering(var unbuffering):\n            self.state = .modifying\n            unbuffering.buffer.append(data)\n            self.state = .unbuffering(unbuffering)\n            return nil\n\n        case .finished:\n            return .fireChannelRead\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum ChannelReadResponsePartAction {\n        case fireErrorCaughtAndRemoveHandler(Error)\n        case runNotUpgradingInitializer\n        case startUpgrading(\n            upgrader: any NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>,\n            responseHeaders: HTTPResponseHead\n        )\n    }\n\n    @inlinable\n    mutating func channelReadResponsePart(_ responsePart: HTTPClientResponsePart) -> ChannelReadResponsePartAction? {\n        switch self.state {\n        case .initial:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n\n        case .awaitingUpgradeResponseHead(let upgraders):\n            // We should decide if we can upgrade based on the first response header: if we aren't upgrading,\n            // by the time the body comes in we should be out of the pipeline. That means that if we don't think we're\n            // upgrading, the only thing we should see is a response head. Anything else in an error.\n            guard case .head(let response) = responsePart else {\n                self.state = .finished\n                return .fireErrorCaughtAndRemoveHandler(NIOHTTPClientUpgradeError.invalidHTTPOrdering)\n            }\n\n            // Assess whether the server has accepted our upgrade request.\n            guard case .switchingProtocols = response.status else {\n                var buffer = Deque<NIOAny>()\n                buffer.append(.init(responsePart))\n                self.state = .upgrading(.init(buffer: buffer))\n                return .runNotUpgradingInitializer\n            }\n\n            // Ok, we have a HTTP response. Check if it's an upgrade confirmation.\n            // If it's not, we want to pass it on and remove ourselves from the channel pipeline.\n            let acceptedProtocols = response.headers[canonicalForm: \"upgrade\"]\n\n            // At the moment we only upgrade to the first protocol returned from the server.\n            guard let protocolName = acceptedProtocols.first?.lowercased() else {\n                // There are no upgrade protocols returned.\n                self.state = .finished\n                return .fireErrorCaughtAndRemoveHandler(NIOHTTPClientUpgradeError.responseProtocolNotFound)\n            }\n\n            let matchingUpgrader =\n                upgraders\n                .first(where: { $0.supportedProtocol.lowercased() == protocolName })\n\n            guard let upgrader = matchingUpgrader else {\n                // There is no upgrader for this protocol.\n                self.state = .finished\n                return .fireErrorCaughtAndRemoveHandler(NIOHTTPClientUpgradeError.responseProtocolNotFound)\n            }\n\n            guard upgrader.shouldAllowUpgrade(upgradeResponse: response) else {\n                // The upgrader says no.\n                self.state = .finished\n                return .fireErrorCaughtAndRemoveHandler(NIOHTTPClientUpgradeError.upgraderDeniedUpgrade)\n            }\n\n            // We received the response head and decided that we can upgrade.\n            // We now need to wait for the response end and then we can perform the upgrade\n            self.state = .awaitingUpgradeResponseEnd(\n                .init(\n                    upgrader: upgrader,\n                    responseHead: response\n                )\n            )\n            return .none\n\n        case .awaitingUpgradeResponseEnd(let awaitingUpgradeResponseEnd):\n            switch responsePart {\n            case .head:\n                // We got two HTTP response heads.\n                self.state = .finished\n                return .fireErrorCaughtAndRemoveHandler(NIOHTTPClientUpgradeError.invalidHTTPOrdering)\n\n            case .body:\n                // We tolerate body parts to be send but just ignore them\n                return .none\n\n            case .end:\n                // We got the response end and can now run the upgrader.\n                self.state = .upgrading(.init(buffer: .init()))\n                return .startUpgrading(\n                    upgrader: awaitingUpgradeResponseEnd.upgrader,\n                    responseHeaders: awaitingUpgradeResponseEnd.responseHead\n                )\n            }\n\n        case .upgrading, .unbuffering, .finished:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum UpgradingHandlerCompletedAction {\n        case fireErrorCaughtAndStartUnbuffering(Error)\n        case removeHandler(UpgradeResult)\n        case fireErrorCaughtAndRemoveHandler(Error)\n        case startUnbuffering(UpgradeResult)\n    }\n\n    @inlinable\n    mutating func upgradingHandlerCompleted(_ result: Result<UpgradeResult, Error>) -> UpgradingHandlerCompletedAction?\n    {\n        switch self.state {\n        case .initial, .awaitingUpgradeResponseHead, .awaitingUpgradeResponseEnd, .unbuffering:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n\n        case .upgrading(let upgrading):\n            switch result {\n            case .success(let value):\n                if !upgrading.buffer.isEmpty {\n                    self.state = .unbuffering(.init(buffer: upgrading.buffer))\n                    return .startUnbuffering(value)\n                } else {\n                    self.state = .finished\n                    return .removeHandler(value)\n                }\n\n            case .failure(let error):\n                if !upgrading.buffer.isEmpty {\n                    // So we failed to upgrade. There is nothing really that we can do here.\n                    // We are unbuffering the reads but there shouldn't be any handler in the pipeline\n                    // that expects a specific type of reads anyhow.\n                    self.state = .unbuffering(.init(buffer: upgrading.buffer))\n                    return .fireErrorCaughtAndStartUnbuffering(error)\n                } else {\n                    self.state = .finished\n                    return .fireErrorCaughtAndRemoveHandler(error)\n                }\n            }\n\n        case .finished:\n            // We have to tolerate this\n            return nil\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum UnbufferAction {\n        case fireChannelRead(NIOAny)\n        case fireChannelReadCompleteAndRemoveHandler\n    }\n\n    @inlinable\n    mutating func unbuffer() -> UnbufferAction {\n        switch self.state {\n        case .initial, .awaitingUpgradeResponseHead, .awaitingUpgradeResponseEnd, .upgrading, .finished:\n            preconditionFailure(\"Invalid state \\(self.state)\")\n\n        case .unbuffering(var unbuffering):\n            self.state = .modifying\n\n            if let element = unbuffering.buffer.popFirst() {\n                self.state = .unbuffering(unbuffering)\n\n                return .fireChannelRead(element)\n            } else {\n                self.state = .finished\n\n                return .fireChannelReadCompleteAndRemoveHandler\n            }\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPClientUpgradeStateMachine\")\n\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1/NIOTypedHTTPServerUpgradeHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// An object that implements `NIOTypedHTTPServerProtocolUpgrader` knows how to handle HTTP upgrade to\n/// a protocol on a server-side channel.\n@preconcurrency\npublic protocol NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>: Sendable {\n    associatedtype UpgradeResult: Sendable\n\n    /// The protocol this upgrader knows how to support.\n    var supportedProtocol: String { get }\n\n    /// All the header fields the protocol needs in the request to successfully upgrade. These header fields\n    /// will be provided to the handler when it is asked to handle the upgrade. They will also be validated\n    /// against the inbound request's `Connection` header field.\n    var requiredUpgradeHeaders: [String] { get }\n\n    /// Builds the upgrade response headers. Should return any headers that need to be supplied to the client\n    /// in the 101 Switching Protocols response. If upgrade cannot proceed for any reason, this function should\n    /// return a failed future.\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders>\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel pipeline\n    /// to add whatever channel handlers are required. Until the returned `EventLoopFuture` succeeds, all received\n    /// data will be buffered.\n    func upgrade(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead\n    ) -> EventLoopFuture<UpgradeResult>\n}\n\n/// The upgrade configuration for the ``NIOTypedHTTPServerUpgradeHandler``.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult: Sendable>: Sendable {\n    /// The array of potential upgraders.\n    public var upgraders: [any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>]\n\n    /// A closure that is run once it is determined that no protocol upgrade is happening. This can be used\n    /// to configure handlers that expect HTTP.\n    public var notUpgradingCompletionHandler: @Sendable (Channel) -> EventLoopFuture<UpgradeResult>\n\n    public init(\n        upgraders: [any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>],\n        notUpgradingCompletionHandler: @Sendable @escaping (Channel) -> EventLoopFuture<UpgradeResult>\n    ) {\n        self.upgraders = upgraders\n        self.notUpgradingCompletionHandler = notUpgradingCompletionHandler\n    }\n}\n\n/// A server-side channel handler that receives HTTP requests and optionally performs an HTTP-upgrade.\n///\n/// Removes itself from the channel pipeline after the first inbound request on the connection, regardless of\n/// whether the upgrade succeeded or not.\n///\n/// This handler behaves a bit differently from its Netty counterpart because it does not allow upgrade\n/// on any request but the first on a connection. This is primarily to handle clients that pipeline: it's\n/// sufficiently difficult to ensure that the upgrade happens at a safe time while dealing with pipelined\n/// requests that we choose to punt on it entirely and not allow it. As it happens this is mostly fine:\n/// the odds of someone needing to upgrade midway through the lifetime of a connection are very low.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic final class NIOTypedHTTPServerUpgradeHandler<UpgradeResult: Sendable>: ChannelInboundHandler,\n    RemovableChannelHandler\n{\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias InboundOut = HTTPServerRequestPart\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    private let upgraders: [String: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>]\n    private let notUpgradingCompletionHandler: @Sendable (Channel) -> EventLoopFuture<UpgradeResult>\n    private let httpEncoder: HTTPResponseEncoder\n    private let extraHTTPHandlers: [RemovableChannelHandler]\n    private var stateMachine = NIOTypedHTTPServerUpgraderStateMachine<UpgradeResult>()\n\n    private var _upgradeResultPromise: EventLoopPromise<UpgradeResult>?\n    private var upgradeResultPromise: EventLoopPromise<UpgradeResult> {\n        precondition(\n            self._upgradeResultPromise != nil,\n            \"Tried to access the upgrade result before the handler was added to a pipeline\"\n        )\n        return self._upgradeResultPromise!\n    }\n\n    /// The upgrade future which will be completed once protocol upgrading has been done.\n    public var upgradeResultFuture: EventLoopFuture<UpgradeResult> {\n        self.upgradeResultPromise.futureResult\n    }\n\n    /// Create a ``NIOTypedHTTPServerUpgradeHandler``.\n    ///\n    /// - Parameters:\n    ///   - httpEncoder: The ``HTTPResponseEncoder`` encoding responses from this handler and which will\n    ///   be removed from the pipeline once the upgrade response is sent. This is used to ensure\n    ///   that the pipeline will be in a clean state after upgrade.\n    ///   - extraHTTPHandlers: Any other handlers that are directly related to handling HTTP. At the very least\n    ///   this should include the `HTTPDecoder`, but should also include any other handler that cannot tolerate\n    ///   receiving non-HTTP data.\n    ///   - upgradeConfiguration: The upgrade configuration.\n    public init(\n        httpEncoder: HTTPResponseEncoder,\n        extraHTTPHandlers: [RemovableChannelHandler],\n        upgradeConfiguration: NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult>\n    ) {\n        var upgraderMap = [String: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>]()\n        for upgrader in upgradeConfiguration.upgraders {\n            upgraderMap[upgrader.supportedProtocol.lowercased()] = upgrader\n        }\n        self.upgraders = upgraderMap\n        self.notUpgradingCompletionHandler = upgradeConfiguration.notUpgradingCompletionHandler\n        self.httpEncoder = httpEncoder\n        self.extraHTTPHandlers = extraHTTPHandlers\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self._upgradeResultPromise = context.eventLoop.makePromise(of: UpgradeResult.self)\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        switch self.stateMachine.handlerRemoved() {\n        case .failUpgradePromise:\n            self.upgradeResultPromise.fail(ChannelError.inappropriateOperationForState)\n        case .none:\n            break\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch self.stateMachine.channelReadData(data) {\n        case .unwrapData:\n            let requestPart = NIOTypedHTTPServerUpgradeHandler.unwrapInboundIn(data)\n            self.channelRead(context: context, requestPart: requestPart)\n\n        case .fireChannelRead:\n            context.fireChannelRead(data)\n\n        case .none:\n            break\n        }\n    }\n\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch event {\n        case let evt as ChannelEvent where evt == ChannelEvent.inputClosed:\n            // The remote peer half-closed the channel during the upgrade. Should we close the other side\n            switch self.stateMachine.inputClosed() {\n            case .close:\n                context.close(promise: nil)\n                self.upgradeResultPromise.fail(ChannelError.inputClosed)\n            case .continue:\n                break\n            case .fireInputClosedEvent:\n                context.fireUserInboundEventTriggered(event)\n            }\n\n        default:\n            context.fireUserInboundEventTriggered(event)\n        }\n    }\n\n    private func channelRead(context: ChannelHandlerContext, requestPart: HTTPServerRequestPart) {\n        switch self.stateMachine.channelReadRequestPart(requestPart) {\n        case .failUpgradePromise(let error):\n            self.upgradeResultPromise.fail(error)\n\n        case .runNotUpgradingInitializer:\n            self.notUpgradingCompletionHandler(context.channel)\n                .hop(to: context.eventLoop)\n                .assumeIsolated()\n                .whenComplete { result in\n                    self.upgradingHandlerCompleted(context: context, result, requestHeadAndProtocol: nil)\n                }\n\n        case .findUpgrader(let head, let requestedProtocols, let allHeaderNames, let connectionHeader):\n            let protocolIterator = requestedProtocols.makeIterator()\n            self.handleUpgradeForProtocol(\n                context: context,\n                protocolIterator: protocolIterator,\n                request: head,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            ).whenComplete { result in\n                self.findingUpgradeCompleted(context: context, requestHead: head, result)\n            }\n\n        case .startUpgrading(let upgrader, let requestHead, let responseHeaders, let proto):\n            self.startUpgrading(\n                context: context,\n                upgrader: upgrader,\n                requestHead: requestHead,\n                responseHeaders: responseHeaders,\n                proto: proto\n            )\n\n        case .none:\n            break\n        }\n    }\n\n    private func upgradingHandlerCompleted(\n        context: ChannelHandlerContext,\n        _ result: Result<UpgradeResult, Error>,\n        requestHeadAndProtocol: (HTTPRequestHead, String)?\n    ) {\n        context.eventLoop.assertInEventLoop()\n        switch self.stateMachine.upgradingHandlerCompleted(result) {\n        case .fireErrorCaughtAndRemoveHandler(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .fireErrorCaughtAndStartUnbuffering(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            self.unbuffer(context: context)\n\n        case .startUnbuffering(let value):\n            if let requestHeadAndProtocol = requestHeadAndProtocol {\n                context.fireUserInboundEventTriggered(\n                    HTTPServerUpgradeEvents.upgradeComplete(\n                        toProtocol: requestHeadAndProtocol.1,\n                        upgradeRequest: requestHeadAndProtocol.0\n                    )\n                )\n            }\n            self.upgradeResultPromise.succeed(value)\n            self.unbuffer(context: context)\n\n        case .removeHandler(let value):\n            if let requestHeadAndProtocol = requestHeadAndProtocol {\n                context.fireUserInboundEventTriggered(\n                    HTTPServerUpgradeEvents.upgradeComplete(\n                        toProtocol: requestHeadAndProtocol.1,\n                        upgradeRequest: requestHeadAndProtocol.0\n                    )\n                )\n            }\n            self.upgradeResultPromise.succeed(value)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .none:\n            break\n        }\n    }\n\n    /// Attempt to upgrade a single protocol.\n    ///\n    /// Will recurse through `protocolIterator` if upgrade fails.\n    private func handleUpgradeForProtocol(\n        context: ChannelHandlerContext,\n        protocolIterator: Array<String>.Iterator,\n        request: HTTPRequestHead,\n        allHeaderNames: Set<String>,\n        connectionHeader: Set<String>\n    )\n        -> EventLoopFuture<\n            (\n                upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>,\n                responseHeaders: HTTPHeaders,\n                proto: String\n            )?\n        >.Isolated\n    {\n        // We want a local copy of the protocol iterator. We'll pass it to the next invocation of the function.\n        var protocolIterator = protocolIterator\n        guard let proto = protocolIterator.next() else {\n            // We're done! No suitable protocol for upgrade.\n            return context.eventLoop.makeSucceededIsolatedFuture(nil)\n        }\n\n        guard let upgrader = self.upgraders[proto.lowercased()] else {\n            return self.handleUpgradeForProtocol(\n                context: context,\n                protocolIterator: protocolIterator,\n                request: request,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            )\n        }\n\n        let requiredHeaders = Set(upgrader.requiredUpgradeHeaders.map { $0.lowercased() })\n        guard requiredHeaders.isSubset(of: allHeaderNames) && requiredHeaders.isSubset(of: connectionHeader) else {\n            return self.handleUpgradeForProtocol(\n                context: context,\n                protocolIterator: protocolIterator,\n                request: request,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            )\n        }\n\n        let responseHeaders = self.buildUpgradeHeaders(protocol: proto)\n        return upgrader.buildUpgradeResponse(\n            channel: context.channel,\n            upgradeRequest: request,\n            initialResponseHeaders: responseHeaders\n        )\n        .hop(to: context.eventLoop)\n        .assumeIsolated()\n        .map { (upgrader, $0, proto) }\n        .flatMapError { error in\n            // No upgrade here. We want to fire the error down the pipeline, and then try another loop iteration.\n            context.fireErrorCaught(error)\n            return self.handleUpgradeForProtocol(\n                context: context,\n                protocolIterator: protocolIterator,\n                request: request,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            ).nonisolated()\n        }\n    }\n\n    private func findingUpgradeCompleted(\n        context: ChannelHandlerContext,\n        requestHead: HTTPRequestHead,\n        _ result: Result<\n            (\n                upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>,\n                responseHeaders: HTTPHeaders,\n                proto: String\n            )?,\n            Error\n        >\n    ) {\n        switch self.stateMachine.findingUpgraderCompleted(requestHead: requestHead, result) {\n        case .startUpgrading(let upgrader, let responseHeaders, let proto):\n            self.startUpgrading(\n                context: context,\n                upgrader: upgrader,\n                requestHead: requestHead,\n                responseHeaders: responseHeaders,\n                proto: proto\n            )\n\n        case .runNotUpgradingInitializer:\n            self.notUpgradingCompletionHandler(context.channel)\n                .hop(to: context.eventLoop)\n                .assumeIsolated()\n                .whenComplete { result in\n                    self.upgradingHandlerCompleted(context: context, result, requestHeadAndProtocol: nil)\n                }\n\n        case .fireErrorCaughtAndStartUnbuffering(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            self.unbuffer(context: context)\n\n        case .fireErrorCaughtAndRemoveHandler(let error):\n            self.upgradeResultPromise.fail(error)\n            context.fireErrorCaught(error)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .none:\n            break\n        }\n    }\n\n    private func startUpgrading(\n        context: ChannelHandlerContext,\n        upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>,\n        requestHead: HTTPRequestHead,\n        responseHeaders: HTTPHeaders,\n        proto: String\n    ) {\n        // Before we finish the upgrade we have to remove the HTTPDecoder and any other non-Encoder HTTP\n        // handlers from the pipeline, to prevent them parsing any more data. We'll buffer the data until\n        // that completes.\n        // While there are a lot of Futures involved here it's quite possible that all of this code will\n        // actually complete synchronously: we just want to program for the possibility that it won't.\n        // Once that's done, we send the upgrade response, then remove the HTTP encoder, then call the\n        // internal handler, then call the user code, and then finally when the user code is done we do\n        // our final cleanup steps, namely we replay the received data we buffered in the meantime and\n        // then remove ourselves from the pipeline.\n        let channel = context.channel\n        let pipeline = context.pipeline\n\n        self.removeExtraHandlers(pipeline: pipeline)\n            .assumeIsolated()\n            .flatMap {\n                self.sendUpgradeResponse(context: context, responseHeaders: responseHeaders)\n            }.flatMap {\n                pipeline.syncOperations.removeHandler(self.httpEncoder)\n            }.flatMap { () -> EventLoopFuture<UpgradeResult> in\n                upgrader.upgrade(channel: channel, upgradeRequest: requestHead)\n            }\n            .whenComplete { result in\n                self.upgradingHandlerCompleted(context: context, result, requestHeadAndProtocol: (requestHead, proto))\n            }\n    }\n\n    /// Sends the 101 Switching Protocols response for the pipeline.\n    private func sendUpgradeResponse(\n        context: ChannelHandlerContext,\n        responseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<Void> {\n        var response = HTTPResponseHead(version: .http1_1, status: .switchingProtocols)\n        response.headers = responseHeaders\n        return context.writeAndFlush(wrapOutboundOut(HTTPServerResponsePart.head(response)))\n    }\n\n    /// Builds the initial mandatory HTTP headers for HTTP upgrade responses.\n    private func buildUpgradeHeaders(`protocol`: String) -> HTTPHeaders {\n        HTTPHeaders([(\"connection\", \"upgrade\"), (\"upgrade\", `protocol`)])\n    }\n\n    /// Removes any extra HTTP-related handlers from the channel pipeline.\n    private func removeExtraHandlers(pipeline: ChannelPipeline) -> EventLoopFuture<Void> {\n        guard self.extraHTTPHandlers.count > 0 else {\n            return pipeline.eventLoop.makeSucceededFuture(())\n        }\n\n        return .andAllSucceed(\n            self.extraHTTPHandlers.map { pipeline.syncOperations.removeHandler($0) },\n            on: pipeline.eventLoop\n        )\n    }\n\n    private func unbuffer(context: ChannelHandlerContext) {\n        while true {\n            switch self.stateMachine.unbuffer() {\n            case .close:\n                context.close(promise: nil)\n\n            case .fireChannelRead(let data):\n                context.fireChannelRead(data)\n\n            case .fireChannelReadCompleteAndRemoveHandler:\n                context.fireChannelReadComplete()\n                context.pipeline.syncOperations.removeHandler(self, promise: nil)\n                return\n\n            case .fireInputClosedEvent:\n                context.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIOTypedHTTPServerUpgradeHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOHTTP1/NIOTypedHTTPServerUpgraderStateMachine.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport DequeModule\nimport NIOCore\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nstruct NIOTypedHTTPServerUpgraderStateMachine<UpgradeResult> {\n    @usableFromInline\n    enum State {\n        /// The state before we received a TLSUserEvent. We are just forwarding any read at this point.\n        case initial\n\n        enum BufferedState {\n            case data(NIOAny)\n            case inputClosed\n        }\n\n        @usableFromInline\n        struct AwaitingUpgrader {\n            var seenFirstRequest: Bool\n            var buffer: Deque<BufferedState>\n        }\n\n        /// The request head has been received. We're currently running the future chain awaiting an upgrader.\n        case awaitingUpgrader(AwaitingUpgrader)\n\n        @usableFromInline\n        struct UpgraderReady {\n            var upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>\n            var requestHead: HTTPRequestHead\n            var responseHeaders: HTTPHeaders\n            var proto: String\n            var buffer: Deque<BufferedState>\n        }\n\n        /// We have an upgrader, which means we can begin upgrade we are just waiting for the request end.\n        case upgraderReady(UpgraderReady)\n\n        @usableFromInline\n        struct Upgrading {\n            var buffer: Deque<BufferedState>\n        }\n        /// We are either running the upgrading handler.\n        case upgrading(Upgrading)\n\n        @usableFromInline\n        struct Unbuffering {\n            var buffer: Deque<BufferedState>\n        }\n        case unbuffering(Unbuffering)\n\n        case finished\n\n        case modifying\n    }\n\n    private var state = State.initial\n\n    @usableFromInline\n    enum HandlerRemovedAction {\n        case failUpgradePromise\n    }\n\n    @inlinable\n    mutating func handlerRemoved() -> HandlerRemovedAction? {\n        switch self.state {\n        case .initial, .awaitingUpgrader, .upgraderReady, .upgrading, .unbuffering:\n            self.state = .finished\n            return .failUpgradePromise\n\n        case .finished:\n            return .none\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum ChannelReadDataAction {\n        case unwrapData\n        case fireChannelRead\n    }\n\n    @inlinable\n    mutating func channelReadData(_ data: NIOAny) -> ChannelReadDataAction? {\n        switch self.state {\n        case .initial:\n            return .unwrapData\n\n        case .awaitingUpgrader(var awaitingUpgrader):\n            if awaitingUpgrader.seenFirstRequest {\n                // We should buffer the data since we have seen the full request.\n                self.state = .modifying\n                awaitingUpgrader.buffer.append(.data(data))\n                self.state = .awaitingUpgrader(awaitingUpgrader)\n                return nil\n            } else {\n                // We shouldn't buffer. This means we are still expecting HTTP parts.\n                return .unwrapData\n            }\n\n        case .upgraderReady:\n            // We have not seen the end of the HTTP request so this\n            // data is probably an HTTP request part.\n            return .unwrapData\n\n        case .unbuffering(var unbuffering):\n            self.state = .modifying\n            unbuffering.buffer.append(.data(data))\n            self.state = .unbuffering(unbuffering)\n            return nil\n\n        case .finished:\n            return .fireChannelRead\n\n        case .upgrading(var upgrading):\n            // We got a read while running ugprading.\n            // We have to buffer the read to unbuffer it afterwards\n            self.state = .modifying\n            upgrading.buffer.append(.data(data))\n            self.state = .upgrading(upgrading)\n            return nil\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum ChannelReadRequestPartAction {\n        case failUpgradePromise(Error)\n        case runNotUpgradingInitializer\n        case startUpgrading(\n            upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>,\n            requestHead: HTTPRequestHead,\n            responseHeaders: HTTPHeaders,\n            proto: String\n        )\n        case findUpgrader(\n            head: HTTPRequestHead,\n            requestedProtocols: [String],\n            allHeaderNames: Set<String>,\n            connectionHeader: Set<String>\n        )\n    }\n\n    @inlinable\n    mutating func channelReadRequestPart(_ requestPart: HTTPServerRequestPart) -> ChannelReadRequestPartAction? {\n        switch self.state {\n        case .initial:\n            guard case .head(let head) = requestPart else {\n                // The first data that we saw was not a head. This is a protocol error and we are just going to\n                // fail upgrading\n                return .failUpgradePromise(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n            }\n\n            // Ok, we have a HTTP head. Check if it's an upgrade.\n            let requestedProtocols = head.headers[canonicalForm: \"upgrade\"].map(String.init)\n            guard requestedProtocols.count > 0 else {\n                // We have to buffer now since we got the request head but are not upgrading.\n                // The user is configuring the HTTP pipeline now.\n                var buffer = Deque<State.BufferedState>()\n                buffer.append(.data(NIOAny(requestPart)))\n                self.state = .upgrading(.init(buffer: buffer))\n                return .runNotUpgradingInitializer\n            }\n\n            // We can now transition to awaiting the upgrader. This means that we are trying to\n            // find an upgrade that can handle requested protocols. We are not buffering because\n            // we are waiting for the request end.\n            self.state = .awaitingUpgrader(.init(seenFirstRequest: false, buffer: .init()))\n\n            let connectionHeader = Set(head.headers[canonicalForm: \"connection\"].map { $0.lowercased() })\n            let allHeaderNames = Set(head.headers.map { $0.name.lowercased() })\n\n            return .findUpgrader(\n                head: head,\n                requestedProtocols: requestedProtocols,\n                allHeaderNames: allHeaderNames,\n                connectionHeader: connectionHeader\n            )\n\n        case .awaitingUpgrader(let awaitingUpgrader):\n            switch (awaitingUpgrader.seenFirstRequest, requestPart) {\n            case (true, _):\n                // This is weird we are seeing more requests parts after we have seen an end\n                // Let's fail upgrading\n                return .failUpgradePromise(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n\n            case (false, .head):\n                // This is weird we are seeing another head but haven't seen the end for the request before\n                return .failUpgradePromise(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n\n            case (false, .body):\n                // This is weird we are seeing body parts for a request that indicated that it wanted\n                // to upgrade.\n                return .failUpgradePromise(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n\n            case (false, .end):\n                // Okay we got the end as expected. Just gotta store this in our state.\n                self.state = .awaitingUpgrader(.init(seenFirstRequest: true, buffer: awaitingUpgrader.buffer))\n                return nil\n            }\n\n        case .upgraderReady(let upgraderReady):\n            switch requestPart {\n            case .head:\n                // This is weird we are seeing another head but haven't seen the end for the request before\n                return .failUpgradePromise(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n\n            case .body:\n                // This is weird we are seeing body parts for a request that indicated that it wanted\n                // to upgrade.\n                return .failUpgradePromise(HTTPServerUpgradeErrors.invalidHTTPOrdering)\n\n            case .end:\n                // Okay we got the end as expected and our upgrader is ready so let's start upgrading\n                self.state = .upgrading(.init(buffer: upgraderReady.buffer))\n                return .startUpgrading(\n                    upgrader: upgraderReady.upgrader,\n                    requestHead: upgraderReady.requestHead,\n                    responseHeaders: upgraderReady.responseHeaders,\n                    proto: upgraderReady.proto\n                )\n            }\n\n        case .upgrading, .unbuffering, .finished:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum UpgradingHandlerCompletedAction {\n        case fireErrorCaughtAndStartUnbuffering(Error)\n        case removeHandler(UpgradeResult)\n        case fireErrorCaughtAndRemoveHandler(Error)\n        case startUnbuffering(UpgradeResult)\n    }\n\n    @inlinable\n    mutating func upgradingHandlerCompleted(_ result: Result<UpgradeResult, Error>) -> UpgradingHandlerCompletedAction?\n    {\n        switch self.state {\n        case .initial:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n\n        case .upgrading(let upgrading):\n            switch result {\n            case .success(let value):\n                if !upgrading.buffer.isEmpty {\n                    self.state = .unbuffering(.init(buffer: upgrading.buffer))\n                    return .startUnbuffering(value)\n                } else {\n                    self.state = .finished\n                    return .removeHandler(value)\n                }\n\n            case .failure(let error):\n                if !upgrading.buffer.isEmpty {\n                    // So we failed to upgrade. There is nothing really that we can do here.\n                    // We are unbuffering the reads but there shouldn't be any handler in the pipeline\n                    // that expects a specific type of reads anyhow.\n                    self.state = .unbuffering(.init(buffer: upgrading.buffer))\n                    return .fireErrorCaughtAndStartUnbuffering(error)\n                } else {\n                    self.state = .finished\n                    return .fireErrorCaughtAndRemoveHandler(error)\n                }\n            }\n\n        case .finished:\n            // We have to tolerate this\n            return nil\n\n        case .awaitingUpgrader, .upgraderReady, .unbuffering:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum FindingUpgraderCompletedAction {\n        case startUpgrading(\n            upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>,\n            responseHeaders: HTTPHeaders,\n            proto: String\n        )\n        case runNotUpgradingInitializer\n        case fireErrorCaughtAndStartUnbuffering(Error)\n        case fireErrorCaughtAndRemoveHandler(Error)\n    }\n\n    @inlinable\n    mutating func findingUpgraderCompleted(\n        requestHead: HTTPRequestHead,\n        _ result: Result<\n            (\n                upgrader: any NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>,\n                responseHeaders: HTTPHeaders,\n                proto: String\n            )?,\n            Error\n        >\n    ) -> FindingUpgraderCompletedAction? {\n        switch self.state {\n        case .initial, .upgraderReady:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n\n        case .awaitingUpgrader(let awaitingUpgrader):\n            switch result {\n            case .success(.some((let upgrader, let responseHeaders, let proto))):\n                if awaitingUpgrader.seenFirstRequest {\n                    // We have seen the end of the request. So we can upgrade now.\n                    self.state = .upgrading(.init(buffer: awaitingUpgrader.buffer))\n                    return .startUpgrading(upgrader: upgrader, responseHeaders: responseHeaders, proto: proto)\n                } else {\n                    // We have not yet seen the end so we have to wait until that happens\n                    self.state = .upgraderReady(\n                        .init(\n                            upgrader: upgrader,\n                            requestHead: requestHead,\n                            responseHeaders: responseHeaders,\n                            proto: proto,\n                            buffer: awaitingUpgrader.buffer\n                        )\n                    )\n                    return nil\n                }\n\n            case .success(.none):\n                // There was no upgrader to handle the request. We just run the not upgrading\n                // initializer now.\n                self.state = .upgrading(.init(buffer: awaitingUpgrader.buffer))\n                return .runNotUpgradingInitializer\n\n            case .failure(let error):\n                if !awaitingUpgrader.buffer.isEmpty {\n                    self.state = .unbuffering(.init(buffer: awaitingUpgrader.buffer))\n                    return .fireErrorCaughtAndStartUnbuffering(error)\n                } else {\n                    self.state = .finished\n                    return .fireErrorCaughtAndRemoveHandler(error)\n                }\n            }\n\n        case .upgrading, .unbuffering, .finished:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n    @usableFromInline\n    enum UnbufferAction {\n        case close\n        case fireChannelRead(NIOAny)\n        case fireChannelReadCompleteAndRemoveHandler\n        case fireInputClosedEvent\n    }\n\n    @inlinable\n    mutating func unbuffer() -> UnbufferAction {\n        switch self.state {\n        case .initial, .awaitingUpgrader, .upgraderReady, .upgrading, .finished:\n            preconditionFailure(\"Invalid state \\(self.state)\")\n\n        case .unbuffering(var unbuffering):\n            self.state = .modifying\n\n            if let element = unbuffering.buffer.popFirst() {\n                self.state = .unbuffering(unbuffering)\n                switch element {\n                case .data(let data):\n                    return .fireChannelRead(data)\n                case .inputClosed:\n                    return .fireInputClosedEvent\n                }\n            } else {\n                self.state = .finished\n\n                return .fireChannelReadCompleteAndRemoveHandler\n            }\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n\n        }\n    }\n\n    @usableFromInline\n    enum InputClosedAction {\n        case close\n        case `continue`\n        case fireInputClosedEvent\n    }\n\n    @inlinable\n    mutating func inputClosed() -> InputClosedAction {\n        switch self.state {\n        case .initial:\n            self.state = .finished\n            return .close\n\n        case .awaitingUpgrader(var awaitingUpgrader):\n            if awaitingUpgrader.seenFirstRequest {\n                // We should buffer the input close since we have seen the full request.\n                awaitingUpgrader.buffer.append(.inputClosed)\n                self.state = .awaitingUpgrader(awaitingUpgrader)\n                return .continue\n            } else {\n                // We shouldn't buffer. This means we were still expecting HTTP parts.\n                return .close\n            }\n\n        case .upgrading(var upgrading):\n            upgrading.buffer.append(.inputClosed)\n            self.state = .upgrading(upgrading)\n            return .continue\n\n        case .upgraderReady:\n            // if the state is `upgraderReady` we have received a `.head` but not an `.end`.\n            // If input is closed then there is no way to move this forward so we should\n            // close.\n            self.state = .finished\n            return .close\n\n        case .unbuffering(var unbuffering):\n            unbuffering.buffer.append(.inputClosed)\n            self.state = .unbuffering(unbuffering)\n            return .continue\n\n        case .finished:\n            return .fireInputClosedEvent\n\n        case .modifying:\n            fatalError(\"Internal inconsistency in HTTPServerUpgradeStateMachine\")\n        }\n    }\n\n}\n"
  },
  {
    "path": "Sources/NIOHTTP1Client/README.md",
    "content": "# NIOHTTP1Client\n\nThis sample application provides a simple echo client that will send a basic HTTP request, containing a single line of text, to the server and wait for a response. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOHTTP1Client  # Connects to a server on ::1, port 8888.\nswift run NIOHTTP1Client 9899  # Connects to a server on ::1, port 9899\nswift run NIOHTTP1Client /path/to/unix/socket  # Connects to a server using the given UNIX socket\nswift run NIOHTTP1Client echo.example.com 9899  # Connects to a server on echo.example.com:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOHTTP1Client/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\n\nprint(\"Please enter line to send to the server\")\nlet line = readLine(strippingNewline: true)!\n\nprivate final class HTTPEchoHandler: ChannelInboundHandler {\n    public typealias InboundIn = HTTPClientResponsePart\n    public typealias OutboundOut = HTTPClientRequestPart\n\n    public func channelActive(context: ChannelHandlerContext) {\n        // In production code, you should check if `context.remoteAddress` is actually\n        // present, as in rare situations it can be `nil`.\n        print(\"Client connected to \\(context.remoteAddress!)\")\n\n        // We are connected. It's time to send the message to the server to initialize the ping-pong sequence.\n\n        let buffer = context.channel.allocator.buffer(string: line)\n\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        headers.add(name: \"Content-Length\", value: \"\\(buffer.readableBytes)\")\n\n        // This sample only sends an echo request.\n        // The sample server has more functionality which can be easily tested by playing with the URI.\n        // For example, try \"/dynamic/count-to-ten\" or \"/dynamic/client-ip\"\n\n        let requestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/dynamic/echo\",\n            headers: headers\n        )\n\n        context.write(Self.wrapOutboundOut(.head(requestHead)), promise: nil)\n\n        context.write(Self.wrapOutboundOut(.body(.byteBuffer(buffer))), promise: nil)\n\n        context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n\n        let clientResponse = Self.unwrapInboundIn(data)\n\n        switch clientResponse {\n        case .head(let responseHead):\n            print(\"Received status: \\(responseHead.status)\")\n        case .body(let byteBuffer):\n            let string = String(buffer: byteBuffer)\n            print(\"Received: '\\(string)' back from the server.\")\n        case .end:\n            print(\"Closing channel.\")\n            context.close(promise: nil)\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n}\n\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\nlet bootstrap = ClientBootstrap(group: group)\n    // Enable SO_REUSEADDR.\n    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n    .channelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHTTPClientHandlers(\n                position: .first,\n                leftOverBytesStrategy: .fireError\n            )\n            try channel.pipeline.syncOperations.addHandler(HTTPEchoHandler())\n        }\n    }\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\n// First argument is the program path\nlet arguments = CommandLine.arguments\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\n\nlet defaultHost = \"::1\"\nlet defaultPort: Int = 8888\n\nenum ConnectTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n}\n\nlet connectTarget: ConnectTo\nswitch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {\ncase (.some(let h), _, .some(let p)):\n    // we got two arguments, let's interpret that as host and port\n    connectTarget = .ip(host: h, port: p)\ncase (.some(let portString), .none, _):\n    // couldn't parse as number, expecting unix domain socket path\n    connectTarget = .unixDomainSocket(path: portString)\ncase (_, .some(let p), _):\n    // only one argument --> port\n    connectTarget = .ip(host: defaultHost, port: p)\ndefault:\n    connectTarget = .ip(host: defaultHost, port: defaultPort)\n}\n\nlet channel = try { () -> Channel in\n    switch connectTarget {\n    case .ip(let host, let port):\n        return try bootstrap.connect(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try bootstrap.connect(unixDomainSocketPath: path).wait()\n    }\n}()\n\n// Will be closed after we echo-ed back to the server.\ntry channel.closeFuture.wait()\n\nprint(\"Client closed\")\n"
  },
  {
    "path": "Sources/NIOHTTP1Server/README.md",
    "content": "# NIOHTTP1Server\n\nThis sample application provides a HTTP server that supports a number of query methods for testing purposes. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOHTTP1Server  # Binds the server on ::1, port 8888.\nswift run NIOHTTP1Server 8988  # Binds the server on ::1, port 8988\nswift run NIOHTTP1Server /path/to/unix/socket  # Binds the server using the given UNIX socket\nswift run NIOHTTP1Server 192.168.0.5 8988  # Binds the server on 192.168.0.5:8988\n```\n\nThe final three syntaxes optionally accept an additional argument, a path to a directory of files to serve from the webserver. The first syntax does not, as that would conflict with the UNIX socket path syntax.\n\nSo, for example, to spin up a local webserver on port 80 serving a specific directory, you can run:\n\n```bash\nswift run NIOHTTP1Server localhost 80 /var/www\n```\n\n## Paths\n\nThe server has the following endpoints:\n\n- `/`: serves \"Hello world!\"\n- `/sendfile/*`: serves the file at path `*` to the client, using `sendfile`.\n- `/fileio/*`: serves the file at path `*` to the client by reading the file in to memory in chunks.\n- `/dynamic/echo`: Echoes the request body back to the client.\n- `/dynamic/echo_balloon`: Echoes the request body back to the client after buffering it entirely in memory first.\n- `/dynamic/pid`: Echoes pack the PID of the server.\n- `/dynamic/write-delay`: Echoes \"Hello world\" after a 100ms delay.\n- `/dynamic/info`: Sends information about the received request.\n- `/dynamic/trailers`: Sends the PID along with some HTTP trailers.\n- `/dynamic/continuous`: Sends a chunked body forever.\n- `/dynamic/count-to-ten`: Sends the numbers 1 through 10 in separate chunks.\n- `/dynamic/client-ip`: Sends what the server believes the client IP is.\n\n"
  },
  {
    "path": "Sources/NIOHTTP1Server/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\n\nextension String {\n    func chopPrefix(_ prefix: String) -> String? {\n        if self.unicodeScalars.starts(with: prefix.unicodeScalars) {\n            return String(self[self.index(self.startIndex, offsetBy: prefix.count)...])\n        } else {\n            return nil\n        }\n    }\n\n    func containsDotDot() -> Bool {\n        for idx in self.indices {\n            if self[idx] == \".\" && idx < self.index(before: self.endIndex) && self[self.index(after: idx)] == \".\" {\n                return true\n            }\n        }\n        return false\n    }\n}\n\nprivate func httpResponseHead(\n    request: HTTPRequestHead,\n    status: HTTPResponseStatus,\n    headers: HTTPHeaders = HTTPHeaders()\n) -> HTTPResponseHead {\n    var head = HTTPResponseHead(version: request.version, status: status, headers: headers)\n    let connectionHeaders: [String] = head.headers[canonicalForm: \"connection\"].map { $0.lowercased() }\n\n    if !connectionHeaders.contains(\"keep-alive\") && !connectionHeaders.contains(\"close\") {\n        // the user hasn't pre-set either 'keep-alive' or 'close', so we might need to add headers\n\n        switch (request.isKeepAlive, request.version.major, request.version.minor) {\n        case (true, 1, 0):\n            // HTTP/1.0 and the request has 'Connection: keep-alive', we should mirror that\n            head.headers.add(name: \"Connection\", value: \"keep-alive\")\n        case (false, 1, let n) where n >= 1:\n            // HTTP/1.1 (or treated as such) and the request has 'Connection: close', we should mirror that\n            head.headers.add(name: \"Connection\", value: \"close\")\n        default:\n            // we should match the default or are dealing with some HTTP that we don't support, let's leave as is\n            ()\n        }\n    }\n    return head\n}\n\nprivate final class HTTPHandler: ChannelInboundHandler {\n    private enum FileIOMethod {\n        case sendfile\n        case nonblockingFileIO\n    }\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias OutboundOut = HTTPServerResponsePart\n\n    private enum State {\n        case idle\n        case waitingForRequestBody\n        case sendingResponse\n\n        mutating func requestReceived() {\n            precondition(self == .idle, \"Invalid state for request received: \\(self)\")\n            self = .waitingForRequestBody\n        }\n\n        mutating func requestComplete() {\n            precondition(self == .waitingForRequestBody, \"Invalid state for request complete: \\(self)\")\n            self = .sendingResponse\n        }\n\n        mutating func responseComplete() {\n            precondition(self == .sendingResponse, \"Invalid state for response complete: \\(self)\")\n            self = .idle\n        }\n    }\n\n    private var buffer: ByteBuffer! = nil\n    private var keepAlive = false\n    private var state = State.idle\n    private let htdocsPath: String\n\n    private var infoSavedRequestHead: HTTPRequestHead?\n    private var infoSavedBodyBytes: Int = 0\n\n    private var continuousCount: Int = 0\n\n    private var handler: ((ChannelHandlerContext, HTTPServerRequestPart) -> Void)?\n    private var handlerFuture: EventLoopFuture<Void>?\n    private let fileIO: NonBlockingFileIO\n    private let defaultResponse = \"Hello World\\r\\n\"\n\n    public init(fileIO: NonBlockingFileIO, htdocsPath: String) {\n        self.htdocsPath = htdocsPath\n        self.fileIO = fileIO\n    }\n\n    func handleInfo(context: ChannelHandlerContext, request: HTTPServerRequestPart) {\n        switch request {\n        case .head(let request):\n            self.infoSavedRequestHead = request\n            self.infoSavedBodyBytes = 0\n            self.keepAlive = request.isKeepAlive\n            self.state.requestReceived()\n        case .body(buffer: let buf):\n            self.infoSavedBodyBytes += buf.readableBytes\n        case .end:\n            self.state.requestComplete()\n            let response = \"\"\"\n                HTTP method: \\(self.infoSavedRequestHead!.method)\\r\n                URL: \\(self.infoSavedRequestHead!.uri)\\r\n                body length: \\(self.infoSavedBodyBytes)\\r\n                headers: \\(self.infoSavedRequestHead!.headers)\\r\n                client: \\(context.remoteAddress?.description ?? \"zombie\")\\r\n                IO: SwiftNIO Electric Boogaloo™️\\r\\n\n                \"\"\"\n            self.buffer.clear()\n            self.buffer.writeString(response)\n            var headers = HTTPHeaders()\n            headers.add(name: \"Content-Length\", value: \"\\(response.utf8.count)\")\n            context.write(\n                Self.wrapOutboundOut(\n                    .head(httpResponseHead(request: self.infoSavedRequestHead!, status: .ok, headers: headers))\n                ),\n                promise: nil\n            )\n            context.write(Self.wrapOutboundOut(.body(.byteBuffer(self.buffer))), promise: nil)\n            self.completeResponse(context, trailers: nil, promise: nil)\n        }\n    }\n\n    func handleEcho(context: ChannelHandlerContext, request: HTTPServerRequestPart) {\n        self.handleEcho(context: context, request: request, balloonInMemory: false)\n    }\n\n    func handleEcho(context: ChannelHandlerContext, request: HTTPServerRequestPart, balloonInMemory: Bool = false) {\n        switch request {\n        case .head(let request):\n            self.keepAlive = request.isKeepAlive\n            self.infoSavedRequestHead = request\n            self.state.requestReceived()\n            if balloonInMemory {\n                self.buffer.clear()\n            } else {\n                context.writeAndFlush(\n                    Self.wrapOutboundOut(.head(httpResponseHead(request: request, status: .ok))),\n                    promise: nil\n                )\n            }\n        case .body(buffer: var buf):\n            if balloonInMemory {\n                self.buffer.writeBuffer(&buf)\n            } else {\n                context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(buf))), promise: nil)\n            }\n        case .end:\n            self.state.requestComplete()\n            if balloonInMemory {\n                var headers = HTTPHeaders()\n                headers.add(name: \"Content-Length\", value: \"\\(self.buffer.readableBytes)\")\n                context.write(\n                    Self.wrapOutboundOut(\n                        .head(httpResponseHead(request: self.infoSavedRequestHead!, status: .ok, headers: headers))\n                    ),\n                    promise: nil\n                )\n                context.write(Self.wrapOutboundOut(.body(.byteBuffer(self.buffer))), promise: nil)\n                self.completeResponse(context, trailers: nil, promise: nil)\n            } else {\n                self.completeResponse(context, trailers: nil, promise: nil)\n            }\n        }\n    }\n\n    func handleJustWrite(\n        context: ChannelHandlerContext,\n        request: HTTPServerRequestPart,\n        statusCode: HTTPResponseStatus = .ok,\n        string: String,\n        trailer: (String, String)? = nil,\n        delay: TimeAmount = .nanoseconds(0)\n    ) {\n        switch request {\n        case .head(let request):\n            self.keepAlive = request.isKeepAlive\n            self.state.requestReceived()\n            context.writeAndFlush(\n                Self.wrapOutboundOut(.head(httpResponseHead(request: request, status: statusCode))),\n                promise: nil\n            )\n        case .body(buffer: _):\n            ()\n        case .end:\n            self.state.requestComplete()\n            let loopBoundContext = context.loopBound\n            let loopBoundSelf = NIOLoopBound(self, eventLoop: context.eventLoop)\n            context.eventLoop.scheduleTask(in: delay) { () -> Void in\n                let `self` = loopBoundSelf.value\n                let context = loopBoundContext.value\n                var buf = context.channel.allocator.buffer(capacity: string.utf8.count)\n                buf.writeString(string)\n                context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(buf))), promise: nil)\n                var trailers: HTTPHeaders? = nil\n                if let trailer = trailer {\n                    trailers = HTTPHeaders()\n                    trailers?.add(name: trailer.0, value: trailer.1)\n                }\n\n                self.completeResponse(context, trailers: trailers, promise: nil)\n            }\n        }\n    }\n\n    func handleContinuousWrites(context: ChannelHandlerContext, request: HTTPServerRequestPart) {\n        switch request {\n        case .head(let request):\n            self.keepAlive = request.isKeepAlive\n            self.continuousCount = 0\n            self.state.requestReceived()\n            let eventLoop = context.eventLoop\n            let loopBoundContext = NIOLoopBound(context, eventLoop: eventLoop)\n            let loopBoundSelf = NIOLoopBound(self, eventLoop: eventLoop)\n            @Sendable func doNext() {\n                let `self` = loopBoundSelf.value\n                let context = loopBoundContext.value\n                self.buffer.clear()\n                self.continuousCount += 1\n                self.buffer.writeString(\"line \\(self.continuousCount)\\n\")\n                context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(self.buffer)))).map {\n                    eventLoop.scheduleTask(in: .milliseconds(400), doNext)\n                }.whenFailure { (_: Error) in\n                    loopBoundSelf.value.completeResponse(loopBoundContext.value, trailers: nil, promise: nil)\n                }\n            }\n            context.writeAndFlush(\n                Self.wrapOutboundOut(.head(httpResponseHead(request: request, status: .ok))),\n                promise: nil\n            )\n            doNext()\n        case .end:\n            self.state.requestComplete()\n        default:\n            break\n        }\n    }\n\n    func handleMultipleWrites(\n        context: ChannelHandlerContext,\n        request: HTTPServerRequestPart,\n        strings: [String],\n        delay: TimeAmount\n    ) {\n        switch request {\n        case .head(let request):\n            self.keepAlive = request.isKeepAlive\n            self.continuousCount = 0\n            self.state.requestReceived()\n            let eventLoop = context.eventLoop\n            let loopBoundContext = NIOLoopBound(context, eventLoop: eventLoop)\n            let loopBoundSelf = NIOLoopBound(self, eventLoop: eventLoop)\n            @Sendable func doNext() {\n                let `self` = loopBoundSelf.value\n                let context = loopBoundContext.value\n                self.buffer.clear()\n                self.buffer.writeString(strings[self.continuousCount])\n                self.continuousCount += 1\n                context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(self.buffer)))).whenSuccess {\n                    let `self` = loopBoundSelf.value\n                    let context = loopBoundContext.value\n                    if self.continuousCount < strings.count {\n                        eventLoop.scheduleTask(in: delay, doNext)\n                    } else {\n                        self.completeResponse(context, trailers: nil, promise: nil)\n                    }\n                }\n            }\n            context.writeAndFlush(\n                Self.wrapOutboundOut(.head(httpResponseHead(request: request, status: .ok))),\n                promise: nil\n            )\n            doNext()\n        case .end:\n            self.state.requestComplete()\n        default:\n            break\n        }\n    }\n\n    func dynamicHandler(request reqHead: HTTPRequestHead) -> ((ChannelHandlerContext, HTTPServerRequestPart) -> Void)? {\n        if let howLong = reqHead.uri.chopPrefix(\"/dynamic/write-delay/\") {\n            return { context, req in\n                self.handleJustWrite(\n                    context: context,\n                    request: req,\n                    string: self.defaultResponse,\n                    delay: Int64(howLong).map { .milliseconds($0) } ?? .seconds(0)\n                )\n            }\n        }\n\n        switch reqHead.uri {\n        case \"/dynamic/echo\":\n            return self.handleEcho\n        case \"/dynamic/echo_balloon\":\n            return { self.handleEcho(context: $0, request: $1, balloonInMemory: true) }\n        case \"/dynamic/pid\":\n            return { context, req in self.handleJustWrite(context: context, request: req, string: \"\\(getpid())\") }\n        case \"/dynamic/write-delay\":\n            return { context, req in\n                self.handleJustWrite(\n                    context: context,\n                    request: req,\n                    string: self.defaultResponse,\n                    delay: .milliseconds(100)\n                )\n            }\n        case \"/dynamic/info\":\n            return self.handleInfo\n        case \"/dynamic/trailers\":\n            return { context, req in\n                self.handleJustWrite(\n                    context: context,\n                    request: req,\n                    string: \"\\(getpid())\\r\\n\",\n                    trailer: (\"Trailer-Key\", \"Trailer-Value\")\n                )\n            }\n        case \"/dynamic/continuous\":\n            return self.handleContinuousWrites\n        case \"/dynamic/count-to-ten\":\n            return {\n                self.handleMultipleWrites(\n                    context: $0,\n                    request: $1,\n                    strings: (1...10).map { \"\\($0)\" },\n                    delay: .milliseconds(100)\n                )\n            }\n        case \"/dynamic/client-ip\":\n            return { context, req in\n                self.handleJustWrite(\n                    context: context,\n                    request: req,\n                    string: \"\\(context.remoteAddress.debugDescription)\"\n                )\n            }\n        default:\n            return { context, req in\n                self.handleJustWrite(context: context, request: req, statusCode: .notFound, string: \"not found\")\n            }\n        }\n    }\n\n    private func handleFile(\n        context: ChannelHandlerContext,\n        request: HTTPServerRequestPart,\n        ioMethod: FileIOMethod,\n        path: String\n    ) {\n        self.buffer.clear()\n        let eventLoop = context.eventLoop\n        let allocator = context.channel.allocator\n        let loopBoundContext = NIOLoopBound(context, eventLoop: eventLoop)\n        let loopBoundSelf = NIOLoopBound(self, eventLoop: eventLoop)\n\n        @Sendable func sendErrorResponse(request: HTTPRequestHead, _ error: Error) {\n            let context = loopBoundContext.value\n            var body = allocator.buffer(capacity: 128)\n            let response = { () -> HTTPResponseHead in\n                switch error {\n                case let e as IOError where e.errnoCode == ENOENT:\n                    body.writeStaticString(\"IOError (not found)\\r\\n\")\n                    return httpResponseHead(request: request, status: .notFound)\n                case let e as IOError:\n                    body.writeStaticString(\"IOError (other)\\r\\n\")\n                    body.writeString(e.description)\n                    body.writeStaticString(\"\\r\\n\")\n                    return httpResponseHead(request: request, status: .notFound)\n                default:\n                    body.writeString(\"\\(type(of: error)) error\\r\\n\")\n                    return httpResponseHead(request: request, status: .internalServerError)\n                }\n            }()\n            body.writeString(\"\\(error)\")\n            body.writeStaticString(\"\\r\\n\")\n            context.write(Self.wrapOutboundOut(.head(response)), promise: nil)\n            context.write(Self.wrapOutboundOut(.body(.byteBuffer(body))), promise: nil)\n            context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n            context.channel.close(promise: nil)\n        }\n\n        @Sendable func responseHead(request: HTTPRequestHead, fileRegion region: FileRegion) -> HTTPResponseHead {\n            var response = httpResponseHead(request: request, status: .ok)\n            response.headers.add(name: \"Content-Length\", value: \"\\(region.endIndex)\")\n            response.headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n            return response\n        }\n\n        switch request {\n        case .head(let request):\n            self.keepAlive = request.isKeepAlive\n            self.state.requestReceived()\n            guard !request.uri.containsDotDot() else {\n                let response = httpResponseHead(request: request, status: .forbidden)\n                context.write(Self.wrapOutboundOut(.head(response)), promise: nil)\n                self.completeResponse(context, trailers: nil, promise: nil)\n                return\n            }\n            let path = self.htdocsPath + \"/\" + path\n            let fileHandleAndRegion = self.fileIO.openFile(_deprecatedPath: path, eventLoop: context.eventLoop)\n            fileHandleAndRegion.whenFailure {\n                sendErrorResponse(request: request, $0)\n            }\n            fileHandleAndRegion.whenSuccess { [fileIO = self.fileIO] (file, region) in\n                let context = loopBoundContext.value\n                let loopBoundFile = NIOLoopBound(file, eventLoop: eventLoop)\n                switch ioMethod {\n                case .nonblockingFileIO:\n                    let responseStarted = NIOLoopBoundBox(false, eventLoop: eventLoop)\n                    let response = responseHead(request: request, fileRegion: region)\n                    if region.readableBytes == 0 {\n                        responseStarted.value = true\n                        context.write(Self.wrapOutboundOut(.head(response)), promise: nil)\n                    }\n                    return fileIO.readChunked(\n                        fileRegion: region,\n                        chunkSize: 32 * 1024,\n                        allocator: context.channel.allocator,\n                        eventLoop: context.eventLoop\n                    ) { buffer in\n                        let context = loopBoundContext.value\n                        if !responseStarted.value {\n                            responseStarted.value = true\n                            context.write(Self.wrapOutboundOut(.head(response)), promise: nil)\n                        }\n                        return context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(buffer))))\n                    }.flatMap { () -> EventLoopFuture<Void> in\n                        let context = loopBoundContext.value\n                        let `self` = loopBoundSelf.value\n                        let p = context.eventLoop.makePromise(of: Void.self)\n                        self.completeResponse(context, trailers: nil, promise: p)\n                        return p.futureResult\n                    }.flatMapError { error in\n                        let context = loopBoundContext.value\n                        let `self` = loopBoundSelf.value\n                        if !responseStarted.value {\n                            let response = httpResponseHead(request: request, status: .ok)\n                            context.write(Self.wrapOutboundOut(.head(response)), promise: nil)\n                            var buffer = context.channel.allocator.buffer(capacity: 100)\n                            buffer.writeString(\"fail: \\(error)\")\n                            context.write(Self.wrapOutboundOut(.body(.byteBuffer(buffer))), promise: nil)\n                            self.state.responseComplete()\n                            return context.writeAndFlush(Self.wrapOutboundOut(.end(nil)))\n                        } else {\n                            return context.close()\n                        }\n                    }.whenComplete { (_: Result<Void, Error>) in\n                        _ = try? loopBoundFile.value.close()\n                    }\n                case .sendfile:\n                    let context = loopBoundContext.value\n                    let response = responseHead(request: request, fileRegion: region)\n                    context.write(Self.wrapOutboundOut(.head(response)), promise: nil)\n                    context.writeAndFlush(Self.wrapOutboundOut(.body(.fileRegion(region)))).flatMap {\n                        let context = loopBoundContext.value\n                        let p = context.eventLoop.makePromise(of: Void.self)\n                        loopBoundSelf.value.completeResponse(context, trailers: nil, promise: p)\n                        return p.futureResult\n                    }.flatMapError { (_: Error) in\n                        loopBoundContext.value.close()\n                    }.whenComplete { (_: Result<Void, Error>) in\n                        _ = try? loopBoundFile.value.close()\n                    }\n                }\n            }\n        case .end:\n            self.state.requestComplete()\n        default:\n            fatalError(\"oh noes: \\(request)\")\n        }\n    }\n\n    private func completeResponse(\n        _ context: ChannelHandlerContext,\n        trailers: HTTPHeaders?,\n        promise: EventLoopPromise<Void>?\n    ) {\n        self.state.responseComplete()\n        let loopBoundContext = context.loopBound\n\n        let promise = self.keepAlive ? promise : (promise ?? context.eventLoop.makePromise())\n        if !self.keepAlive {\n            promise!.futureResult.whenComplete { (_: Result<Void, Error>) in\n                let context = loopBoundContext.value\n                context.close(promise: nil)\n            }\n        }\n        self.handler = nil\n\n        context.writeAndFlush(Self.wrapOutboundOut(.end(trailers)), promise: promise)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let reqPart = Self.unwrapInboundIn(data)\n        if let handler = self.handler {\n            handler(context, reqPart)\n            return\n        }\n\n        switch reqPart {\n        case .head(let request):\n            if request.uri.unicodeScalars.starts(with: \"/dynamic\".unicodeScalars) {\n                self.handler = self.dynamicHandler(request: request)\n                self.handler!(context, reqPart)\n                return\n            } else if let path = request.uri.chopPrefix(\"/sendfile/\") {\n                self.handler = { self.handleFile(context: $0, request: $1, ioMethod: .sendfile, path: path) }\n                self.handler!(context, reqPart)\n                return\n            } else if let path = request.uri.chopPrefix(\"/fileio/\") {\n                self.handler = { self.handleFile(context: $0, request: $1, ioMethod: .nonblockingFileIO, path: path) }\n                self.handler!(context, reqPart)\n                return\n            }\n\n            self.keepAlive = request.isKeepAlive\n            self.state.requestReceived()\n\n            var responseHead = httpResponseHead(request: request, status: HTTPResponseStatus.ok)\n            self.buffer.clear()\n            self.buffer.writeString(self.defaultResponse)\n            responseHead.headers.add(name: \"content-length\", value: \"\\(self.buffer!.readableBytes)\")\n            let response = HTTPServerResponsePart.head(responseHead)\n            context.write(Self.wrapOutboundOut(response), promise: nil)\n        case .body:\n            break\n        case .end:\n            self.state.requestComplete()\n            let content = HTTPServerResponsePart.body(.byteBuffer(buffer!.slice()))\n            context.write(Self.wrapOutboundOut(content), promise: nil)\n            self.completeResponse(context, trailers: nil, promise: nil)\n        }\n    }\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        context.flush()\n    }\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        self.buffer = context.channel.allocator.buffer(capacity: 0)\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch event {\n        case let evt as ChannelEvent where evt == ChannelEvent.inputClosed:\n            // The remote peer half-closed the channel. At this time, any\n            // outstanding response will now get the channel closed, and\n            // if we are idle or waiting for a request body to finish we\n            // will close the channel immediately.\n            switch self.state {\n            case .idle, .waitingForRequestBody:\n                context.close(promise: nil)\n            case .sendingResponse:\n                self.keepAlive = false\n            }\n        default:\n            context.fireUserInboundEventTriggered(event)\n        }\n    }\n}\n\n// First argument is the program path\nvar arguments = CommandLine.arguments.dropFirst(0)  // just to get an ArraySlice<String> from [String]\nvar allowHalfClosure = true\nif arguments.dropFirst().first == .some(\"--disable-half-closure\") {\n    allowHalfClosure = false\n    arguments = arguments.dropFirst()\n}\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\nlet arg3 = arguments.dropFirst(3).first\n\nlet defaultHost = \"::1\"\nlet defaultPort = 8888\nlet defaultHtdocs = \"/dev/null/\"\n\nenum BindTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n    case stdio\n}\n\nlet htdocs: String\nlet bindTarget: BindTo\n\nswitch (arg1, arg1.flatMap(Int.init), arg2, arg2.flatMap(Int.init), arg3) {\ncase (.some(let h), _, _, .some(let p), let maybeHtdocs):\n    // second arg an integer --> host port [htdocs]\n    bindTarget = .ip(host: h, port: p)\n    htdocs = maybeHtdocs ?? defaultHtdocs\ncase (_, .some(let p), let maybeHtdocs, _, _):\n    // first arg an integer --> port [htdocs]\n    bindTarget = .ip(host: defaultHost, port: p)\n    htdocs = maybeHtdocs ?? defaultHtdocs\ncase (.some(let portString), .none, let maybeHtdocs, .none, .none):\n    // couldn't parse as number --> uds-path-or-stdio [htdocs]\n    if portString == \"-\" {\n        bindTarget = .stdio\n    } else {\n        bindTarget = .unixDomainSocket(path: portString)\n    }\n    htdocs = maybeHtdocs ?? defaultHtdocs\ndefault:\n    htdocs = defaultHtdocs\n    bindTarget = BindTo.ip(host: defaultHost, port: defaultPort)\n}\n\nfunc childChannelInitializer(channel: Channel) -> EventLoopFuture<Void> {\n    channel.pipeline.configureHTTPServerPipeline(withErrorHandling: true).flatMapThrowing {\n        try channel.pipeline.syncOperations.addHandler(HTTPHandler(fileIO: fileIO, htdocsPath: htdocs))\n    }\n}\n\nlet fileIO = NonBlockingFileIO(threadPool: .singleton)\nlet socketBootstrap = ServerBootstrap(group: MultiThreadedEventLoopGroup.singleton)\n    // Specify backlog and enable SO_REUSEADDR for the server itself\n    .serverChannelOption(.backlog, value: 256)\n    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n    // Set the handlers that are applied to the accepted Channels\n    .childChannelInitializer(childChannelInitializer(channel:))\n\n    // Enable SO_REUSEADDR for the accepted Channels\n    .childChannelOption(.socketOption(.so_reuseaddr), value: 1)\n    .childChannelOption(.maxMessagesPerRead, value: 1)\n    .childChannelOption(.allowRemoteHalfClosure, value: allowHalfClosure)\nlet pipeBootstrap = NIOPipeBootstrap(group: MultiThreadedEventLoopGroup.singleton)\n    // Set the handlers that are applied to the accepted Channels\n    .channelInitializer(childChannelInitializer(channel:))\n\n    .channelOption(.maxMessagesPerRead, value: 1)\n    .channelOption(.allowRemoteHalfClosure, value: allowHalfClosure)\nprint(\"htdocs = \\(htdocs)\")\n\nlet channel = try { () -> Channel in\n    switch bindTarget {\n    case .ip(let host, let port):\n        return try socketBootstrap.bind(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try socketBootstrap.bind(unixDomainSocketPath: path).wait()\n    case .stdio:\n        return try pipeBootstrap.takingOwnershipOfDescriptors(input: STDIN_FILENO, output: STDOUT_FILENO).wait()\n    }\n}()\n\nlet localAddress: String\nif case .stdio = bindTarget {\n    localAddress = \"STDIO\"\n} else {\n    guard let channelLocalAddress = channel.localAddress else {\n        fatalError(\n            \"Address was unable to bind. Please check that the socket was not closed or that the address family was understood.\"\n        )\n    }\n    localAddress = \"\\(channelLocalAddress)\"\n}\nprint(\"Server started and listening on \\(localAddress), htdocs path \\(htdocs)\")\n\n// This will never unblock as we don't close the ServerChannel\ntry channel.closeFuture.wait()\n\nprint(\"Server closed\")\n"
  },
  {
    "path": "Sources/NIOMulticastChat/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport CNIOLinux\nimport CNIOOpenBSD\nimport NIOCore\nimport NIOPosix\n\n/// Implements a simple chat protocol.\nprivate final class ChatMessageDecoder: ChannelInboundHandler {\n    public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let envelope = Self.unwrapInboundIn(data)\n        var buffer = envelope.data\n\n        // To begin with, the chat messages are simply whole datagrams, no other length.\n        guard let message = buffer.readString(length: buffer.readableBytes) else {\n            print(\"Error: invalid string received\")\n            return\n        }\n\n        print(\"\\(envelope.remoteAddress): \\(message)\")\n    }\n}\n\nprivate final class ChatMessageEncoder: ChannelOutboundHandler {\n    public typealias OutboundIn = AddressedEnvelope<String>\n    public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let message = Self.unwrapOutboundIn(data)\n        let buffer = context.channel.allocator.buffer(string: message.data)\n        context.write(\n            Self.wrapOutboundOut(AddressedEnvelope(remoteAddress: message.remoteAddress, data: buffer)),\n            promise: promise\n        )\n    }\n}\n\n// We allow users to specify the interface they want to use here.\nlet targetDevice: NIONetworkDevice? = {\n    if let interfaceAddress = CommandLine.arguments.dropFirst().first,\n        let targetAddress = try? SocketAddress(ipAddress: interfaceAddress, port: 0)\n    {\n        for device in try! System.enumerateDevices() {\n            if device.address == targetAddress {\n                return device\n            }\n        }\n        fatalError(\"Could not find device for \\(interfaceAddress)\")\n    }\n    return nil\n}()\n\n// For this chat protocol we temporarily squat on 224.1.0.26. This is a reserved multicast IPv4 address,\n// so your machine is unlikely to have already joined this group. That helps properly demonstrate correct\n// operation. We use port 7654 because, well, because why not.\nlet chatMulticastGroup = try! SocketAddress(ipAddress: \"224.1.0.26\", port: 7654)\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n\n// Begin by setting up the basics of the bootstrap.\nvar datagramBootstrap = DatagramBootstrap(group: group)\n    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n    .channelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandlers(ChatMessageEncoder(), ChatMessageDecoder())\n        }\n    }\n\n// We cast our channel to MulticastChannel to obtain the multicast operations.\nlet datagramChannel =\n    try datagramBootstrap\n    .bind(host: \"0.0.0.0\", port: 7654)\n    .flatMap { channel -> EventLoopFuture<Channel> in\n        let channel = channel as! MulticastChannel\n        return channel.joinGroup(chatMulticastGroup, device: targetDevice).map { channel }\n    }.flatMap { channel -> EventLoopFuture<Channel> in\n        guard let targetDevice = targetDevice else {\n            return channel.eventLoop.makeSucceededFuture(channel)\n        }\n\n        let provider = channel as! SocketOptionProvider\n        switch targetDevice.address {\n        case .some(.v4(let addr)):\n            return provider.setIPMulticastIF(addr.address.sin_addr).map { channel }\n        case .some(.v6):\n            return provider.setIPv6MulticastIF(CUnsignedInt(targetDevice.interfaceIndex)).map { channel }\n        case .some(.unixDomainSocket):\n            preconditionFailure(\"Should not be possible to create a multicast socket on a unix domain socket\")\n        case .none:\n            preconditionFailure(\n                \"Should not be possible to create a multicast socket on an interface without an address\"\n            )\n        }\n    }.wait()\n\nprint(\"Now broadcasting, happy chatting.\\nPress ^D to exit.\")\n\nwhile let line = readLine(strippingNewline: false) {\n    datagramChannel.writeAndFlush(AddressedEnvelope(remoteAddress: chatMulticastGroup, data: line), promise: nil)\n}\n\n// Close the channel.\ntry! datagramChannel.close().wait()\ntry! group.syncShutdownGracefully()\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/Benchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\n\nprotocol Benchmark: AnyObject {\n    func setUp() throws\n    func tearDown()\n    func run() throws -> Int\n}\n\nfunc measureAndPrint<B: Benchmark>(desc: String, benchmark bench: B) throws {\n    try bench.setUp()\n    defer {\n        bench.tearDown()\n    }\n    try measureAndPrint(desc: desc) {\n        try bench.run()\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprotocol AsyncBenchmark: AnyObject, Sendable {\n    func setUp() async throws\n    func tearDown()\n    func run() async throws -> Int\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc measureAndPrint<B: AsyncBenchmark>(desc: String, benchmark bench: B) throws {\n    let group = DispatchGroup()\n    group.enter()\n    Task {\n        do {\n            try await bench.setUp()\n            defer {\n                bench.tearDown()\n            }\n            try await measureAndPrint(desc: desc) {\n                try await bench.run()\n            }\n        }\n        group.leave()\n    }\n\n    group.wait()\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ByteBufferViewContainsBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\n\nfinal class ByteBufferViewContainsBenchmark: Benchmark {\n    private let iterations: Int\n    private let bufferSize: Int\n    private var buffer: ByteBuffer\n\n    init(iterations: Int, bufferSize: Int) {\n        self.iterations = iterations\n        self.bufferSize = bufferSize\n        self.buffer = ByteBufferAllocator().buffer(capacity: self.bufferSize)\n    }\n\n    func setUp() throws {\n        self.buffer.writeBytes(Array(repeating: UInt8(ascii: \"A\"), count: self.bufferSize - 1))\n        self.buffer.writeInteger(UInt8(ascii: \"B\"))\n    }\n\n    func tearDown() {\n    }\n\n    func run() -> Int {\n        var which: UInt8 = 0\n        for _ in 1...self.iterations {\n            if self.buffer.readableBytesView.contains(UInt8(ascii: \"B\")) {\n                which = UInt8(ascii: \"B\")\n            }\n        }\n        return Int(which)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ByteBufferViewCopyToArrayBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nfinal class ByteBufferViewCopyToArrayBenchmark: Benchmark {\n    private let iterations: Int\n    private let size: Int\n    private var view: ByteBufferView\n\n    init(iterations: Int, size: Int) {\n        self.iterations = iterations\n        self.size = size\n        self.view = ByteBufferView()\n    }\n\n    func setUp() throws {\n        self.view = ByteBuffer(repeating: 0xfe, count: self.size).readableBytesView\n    }\n\n    func tearDown() {\n    }\n\n    func run() -> Int {\n        var count = 0\n        for _ in 0..<self.iterations {\n            let array = Array(self.view)\n            count &+= array.count\n        }\n\n        return count\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ByteBufferViewIteratorBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\n\nfinal class ByteBufferViewIteratorBenchmark: Benchmark {\n    private let iterations: Int\n    private let bufferSize: Int\n    private var buffer: ByteBuffer\n\n    init(iterations: Int, bufferSize: Int) {\n        self.iterations = iterations\n        self.bufferSize = bufferSize\n        self.buffer = ByteBufferAllocator().buffer(capacity: self.bufferSize)\n    }\n\n    func setUp() throws {\n        self.buffer.writeBytes(Array(repeating: UInt8(ascii: \"A\"), count: self.bufferSize - 1))\n        self.buffer.writeInteger(UInt8(ascii: \"B\"))\n    }\n\n    func tearDown() {\n    }\n\n    func run() -> Int {\n        var which: UInt8 = 0\n        for _ in 1...self.iterations {\n            for byte in self.buffer.readableBytesView {\n                if byte != UInt8(ascii: \"A\") {\n                    which = byte\n                }\n            }\n        }\n        return Int(which)\n    }\n\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ByteBufferWriteMultipleBenchmarks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nfinal class ByteBufferReadWriteMultipleIntegersBenchmark<I: FixedWidthInteger>: Benchmark {\n    private let iterations: Int\n    private let numberOfInts: Int\n    private var buffer: ByteBuffer = ByteBuffer()\n\n    init(iterations: Int, numberOfInts: Int) {\n        self.iterations = iterations\n        self.numberOfInts = numberOfInts\n    }\n\n    func setUp() throws {\n        self.buffer.reserveCapacity(self.numberOfInts * MemoryLayout<I>.size)\n    }\n\n    func tearDown() {\n    }\n\n    func run() throws -> Int {\n        var result: I = 0\n        for _ in 0..<self.iterations {\n            self.buffer.clear()\n            for i in I(0)..<I(10) {\n                self.buffer.writeInteger(i)\n            }\n            for _ in I(0)..<I(10) {\n                result = result &+ self.buffer.readInteger(as: I.self)!\n            }\n        }\n        precondition(result == I(self.iterations) * 45)\n        return self.buffer.readableBytes\n    }\n}\n\nfinal class ByteBufferMultiReadWriteTenIntegersBenchmark<I: FixedWidthInteger>: Benchmark {\n    private let iterations: Int\n    private var buffer: ByteBuffer = ByteBuffer()\n\n    init(iterations: Int) {\n        self.iterations = iterations\n    }\n\n    func setUp() throws {\n        self.buffer.reserveCapacity(10 * MemoryLayout<I>.size)\n    }\n\n    func tearDown() {\n    }\n\n    func run() throws -> Int {\n        var result: I = 0\n        for _ in 0..<self.iterations {\n            self.buffer.clear()\n            self.buffer.writeMultipleIntegers(\n                0,\n                1,\n                2,\n                3,\n                4,\n                5,\n                6,\n                7,\n                8,\n                9,\n                as: (I, I, I, I, I, I, I, I, I, I).self\n            )\n            let value = self.buffer.readMultipleIntegers(as: (I, I, I, I, I, I, I, I, I, I).self)!\n            result = result &+ value.0\n            result = result &+ value.1\n            result = result &+ value.2\n            result = result &+ value.3\n            result = result &+ value.4\n            result = result &+ value.5\n            result = result &+ value.6\n            result = result &+ value.7\n            result = result &+ value.8\n            result = result &+ value.9\n        }\n        precondition(result == I(self.iterations) * 45)\n        return self.buffer.readableBytes\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ByteToMessageDecoderDecodeManySmallsBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\n\nfinal class ByteToMessageDecoderDecodeManySmallsBenchmark: Benchmark {\n    private let iterations: Int\n    private let buffer: ByteBuffer\n    private let channel: EmbeddedChannel\n\n    init(iterations: Int, bufferSize: Int) {\n        self.iterations = iterations\n        self.buffer = ByteBuffer(repeating: 0, count: bufferSize)\n        self.channel = EmbeddedChannel(handler: ByteToMessageHandler(Decoder()))\n    }\n\n    func setUp() throws {\n        try self.channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5)).wait()\n    }\n\n    func tearDown() {\n        precondition(try! self.channel.finish().isClean)\n    }\n\n    func run() -> Int {\n        for _ in 1...self.iterations {\n            try! self.channel.writeInbound(self.buffer)\n        }\n        return Int(self.buffer.readableBytes)\n    }\n\n    struct Decoder: ByteToMessageDecoder {\n        typealias InboundOut = Never\n\n        func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n            if buffer.readSlice(length: 16) == nil {\n                return .needMoreData\n            } else {\n                return .continue\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ChannelPipelineBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\n\nfinal class ChannelPipelineBenchmark: Benchmark {\n    private final class NoOpHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n        typealias InboundIn = Any\n    }\n    private final class ConsumingHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n        typealias InboundIn = Any\n\n        func channelReadComplete(context: ChannelHandlerContext) {\n        }\n    }\n\n    private let channel: EmbeddedChannel\n    private let runCount: Int\n    private let extraHandlers = 4\n    private var handlers: [RemovableChannelHandler & Sendable] = []\n\n    init(runCount: Int) {\n        self.channel = EmbeddedChannel()\n        self.runCount = runCount\n    }\n\n    func setUp() throws {\n        for _ in 0..<self.extraHandlers {\n            let handler = NoOpHandler()\n            self.handlers.append(handler)\n            try self.channel.pipeline.addHandler(handler).wait()\n        }\n        let handler = ConsumingHandler()\n        self.handlers.append(handler)\n        try self.channel.pipeline.addHandler(handler).wait()\n    }\n\n    func tearDown() {\n        let handlersToRemove = self.handlers\n        self.handlers.removeAll()\n        for handler in handlersToRemove {\n            try! self.channel.pipeline.removeHandler(handler).wait()\n        }\n    }\n\n    func run() -> Int {\n        for _ in 0..<self.runCount {\n            self.channel.pipeline.fireChannelReadComplete()\n        }\n        return 1\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ChannelPipelineInstantiationBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\n\nfinal class ChannelPipelineInstantiationBenchmark: Benchmark {\n    private final class NoOpHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = Any\n    }\n\n    private var channel: EmbeddedChannel!\n    private let runCount: Int\n    private let handlerCount: Int\n\n    init(runCount: Int, handlerCount: Int) {\n        self.runCount = runCount\n        self.handlerCount = handlerCount\n    }\n\n    func setUp() throws {\n        self.channel = EmbeddedChannel()\n    }\n\n    func tearDown() {\n        try! self.channel.close().wait()\n        self.channel = nil\n    }\n\n    func run() -> Int {\n        for _ in 0..<self.runCount {\n            let pipeline = ChannelPipeline(channel: self.channel)\n            if self.handlerCount > 0 {\n                let syncOps = pipeline.syncOperations\n                for _ in 0..<self.handlerCount {\n                    try! syncOps.addHandler(NoOpHandler())\n                }\n            }\n        }\n        return self.runCount\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/CircularBufferCopyToArrayBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nfinal class CircularBufferViewCopyToArrayBenchmark: Benchmark {\n    private let iterations: Int\n    private let size: Int\n    private var buffer: CircularBuffer<UInt8>\n\n    init(iterations: Int, size: Int) {\n        self.iterations = iterations\n        self.size = size\n        self.buffer = CircularBuffer()\n    }\n\n    func setUp() throws {\n        self.buffer = CircularBuffer(repeating: UInt8(0xfe), count: self.size)\n    }\n\n    func tearDown() {\n    }\n\n    func run() -> Int {\n        var count = 0\n        for _ in 0..<self.iterations {\n            let array = Array(self.buffer)\n            count &+= array.count\n        }\n\n        return count\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/CircularBufferIntoByteBufferBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\n\nfinal class CircularBufferIntoByteBufferBenchmark: Benchmark {\n    private let iterations: Int\n    private let bufferSize: Int\n    private var circularBuffer: CircularBuffer<UInt8>\n    private var buffer: ByteBuffer\n\n    init(iterations: Int, bufferSize: Int) {\n        self.iterations = iterations\n        self.bufferSize = bufferSize\n        self.circularBuffer = CircularBuffer<UInt8>(initialCapacity: self.bufferSize)\n        self.buffer = ByteBufferAllocator().buffer(capacity: self.bufferSize)\n    }\n\n    func setUp() throws {\n        for i in 0..<self.bufferSize {\n            self.circularBuffer.append(UInt8(i % 256))\n        }\n    }\n\n    func tearDown() {\n    }\n\n    func run() -> Int {\n        for _ in 1...self.iterations {\n            self.buffer.writeBytes(self.circularBuffer)\n            self.buffer.setBytes(self.circularBuffer, at: 0)\n            self.buffer.clear()\n        }\n        return 1\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/DeadlineNowBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nfinal class DeadlineNowBenchmark: Benchmark {\n    private let iterations: Int\n\n    init(iterations: Int) {\n        self.iterations = iterations\n    }\n\n    func setUp() throws {\n    }\n\n    func tearDown() {\n    }\n\n    func run() -> Int {\n        var counter: UInt64 = 0\n        for _ in 0..<self.iterations {\n            let now = NIODeadline.now().uptimeNanoseconds\n            counter &+= now\n        }\n        return Int(truncatingIfNeeded: counter)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/ExecuteBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOPosix\n\nfinal class ExecuteBenchmark: Benchmark {\n    private var group: MultiThreadedEventLoopGroup!\n    private var loop: EventLoop!\n    private var dg: DispatchGroup!\n    private let numTasks: Int\n\n    init(numTasks: Int) {\n        self.numTasks = numTasks\n    }\n\n    func setUp() throws {\n        group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        loop = group.next()\n        dg = DispatchGroup()\n\n        // We are preheating the EL to avoid growing the `ScheduledTask` `PriorityQueue`\n        // during the actual test\n        try! self.loop.submit { [loop, numTasks] in\n            var counter: Int = 0\n            for _ in 0..<numTasks {\n                loop!.assumeIsolatedUnsafeUnchecked().scheduleTask(in: .nanoseconds(0)) {\n                    counter &+= 1\n                }\n            }\n        }.wait()\n    }\n\n    func tearDown() {}\n\n    func run() -> Int {\n        let counter = try! self.loop.submit { [dg, loop, numTasks] in\n            var counter = 0\n            for _ in 0..<numTasks {\n                dg!.enter()\n\n                loop!.assumeIsolatedUnsafeUnchecked().execute {\n                    counter &+= 1\n                    dg!.leave()\n                }\n            }\n            return counter\n        }.wait()\n        self.dg.wait()\n\n        return counter\n    }\n\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/LockBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\n\nfinal class NIOLockBenchmark: Benchmark, @unchecked Sendable {\n    // mutable state is protected by the lock\n\n    private let numberOfThreads: Int\n    private let lockOperationsPerThread: Int\n    private let threadPool: NIOThreadPool\n    private let group: EventLoopGroup\n    private let sem1 = DispatchSemaphore(value: 0)\n    private let sem2 = DispatchSemaphore(value: 0)\n    private let sem3 = DispatchSemaphore(value: 0)\n    private var opsDone = 0\n\n    private let lock = NIOLock()\n\n    init(numberOfThreads: Int, lockOperationsPerThread: Int) {\n        self.numberOfThreads = numberOfThreads\n        self.lockOperationsPerThread = lockOperationsPerThread\n        self.threadPool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    }\n\n    func setUp() throws {\n        self.threadPool.start()\n    }\n\n    func tearDown() {\n        try! self.threadPool.syncShutdownGracefully()\n        try! self.group.syncShutdownGracefully()\n    }\n\n    func run() throws -> Int {\n        self.lock.withLock {\n            self.opsDone = 0\n        }\n        for _ in 0..<self.numberOfThreads {\n            _ = self.threadPool.runIfActive(eventLoop: self.group.next()) {\n                self.sem1.signal()\n                self.sem2.wait()\n\n                for _ in 0..<self.lockOperationsPerThread {\n                    self.lock.withLock {\n                        self.opsDone &+= 1\n                    }\n                }\n\n                self.sem3.signal()\n            }\n        }\n        // Wait until all threads are ready.\n        for _ in 0..<self.numberOfThreads {\n            self.sem1.wait()\n        }\n        // Kick off the work.\n        for _ in 0..<self.numberOfThreads {\n            self.sem2.signal()\n        }\n        // Wait until all threads are done.\n        for _ in 0..<self.numberOfThreads {\n            self.sem3.wait()\n        }\n\n        let done = self.lock.withLock { self.opsDone }\n        precondition(done == self.numberOfThreads * self.lockOperationsPerThread)\n        return done\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/NIOAsyncSequenceProducerBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport DequeModule\nimport NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class NIOAsyncSequenceProducerBenchmark: AsyncBenchmark, NIOAsyncSequenceProducerDelegate, @unchecked Sendable {\n    fileprivate typealias SequenceProducer = NIOThrowingAsyncSequenceProducer<\n        Int, Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, NIOAsyncSequenceProducerBenchmark\n    >\n\n    private let iterations: Int\n    private var iterator: SequenceProducer.AsyncIterator!\n    private var source: SequenceProducer.Source!\n    private let elements = Array(repeating: 1, count: 1000)\n\n    init(iterations: Int) {\n        self.iterations = iterations\n    }\n\n    func setUp() async throws {\n        let producer = SequenceProducer.makeSequence(\n            backPressureStrategy: .init(lowWatermark: 100, highWatermark: 500),\n            finishOnDeinit: false,\n            delegate: self\n        )\n        self.iterator = producer.sequence.makeAsyncIterator()\n        self.source = producer.source\n    }\n    func tearDown() {\n        self.iterator = nil\n        self.source = nil\n    }\n\n    func run() async throws -> Int {\n        var counter = 0\n\n        while let i = try await self.iterator.next(), counter < self.iterations {\n            counter += i\n        }\n        return counter\n    }\n\n    func produceMore() {\n        _ = self.source.yield(contentsOf: self.elements)\n    }\n    func didTerminate() {}\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/NIOAsyncWriterSingleWritesBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport DequeModule\nimport NIOCore\n\nprivate struct NoOpDelegate: NIOAsyncWriterSinkDelegate, @unchecked Sendable {\n    typealias Element = Int\n    let counter = ManagedAtomic(0)\n\n    func didYield(contentsOf sequence: Deque<Int>) {\n        counter.wrappingIncrement(by: sequence.count, ordering: .relaxed)\n    }\n\n    func didTerminate(error: Error?) {}\n}\n\n// This is unchecked Sendable because the Sink is not Sendable but the Sink is thread safe\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class NIOAsyncWriterSingleWritesBenchmark: AsyncBenchmark, @unchecked Sendable {\n    private let iterations: Int\n    private let delegate: NoOpDelegate\n    private let writer: NIOAsyncWriter<Int, NoOpDelegate>\n    private let sink: NIOAsyncWriter<Int, NoOpDelegate>.Sink\n\n    init(iterations: Int) {\n        self.iterations = iterations\n        self.delegate = .init()\n        let newWriter = NIOAsyncWriter<Int, NoOpDelegate>.makeWriter(\n            isWritable: true,\n            finishOnDeinit: false,\n            delegate: self.delegate\n        )\n        self.writer = newWriter.writer\n        self.sink = newWriter.sink\n    }\n\n    func setUp() async throws {}\n    func tearDown() {\n        self.writer.finish()\n    }\n\n    func run() async throws -> Int {\n        for i in 0..<self.iterations {\n            try await self.writer.yield(i)\n        }\n        return self.delegate.counter.load(ordering: .sequentiallyConsistent)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/NIOThreadPoolSubmitBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOPosix\n\n/// Submit one item at a time, waiting for completion before the next.\n/// Every submit hits N sleeping threads — isolates wake-one vs wake-all.\nfinal class NIOThreadPoolSerialWakeupBenchmark: Benchmark {\n    private let numberOfThreads: Int\n    private let numberOfTasks: Int\n    private var pool: NIOThreadPool!\n\n    init(numberOfThreads: Int, numberOfTasks: Int) {\n        self.numberOfThreads = numberOfThreads\n        self.numberOfTasks = numberOfTasks\n    }\n\n    func setUp() throws {\n        self.pool = NIOThreadPool(numberOfThreads: self.numberOfThreads)\n        self.pool.start()\n    }\n\n    func tearDown() {\n        try! self.pool.syncShutdownGracefully()\n    }\n\n    func run() throws -> Int {\n        let sem = DispatchSemaphore(value: 0)\n        for _ in 0..<self.numberOfTasks {\n            self.pool.submit { state in\n                precondition(state == .active)\n                sem.signal()\n            }\n            sem.wait()\n        }\n        return self.numberOfTasks\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/RunIfActiveBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOPosix\n\nfinal class RunIfActiveBenchmark: Benchmark {\n    private var threadPool: NIOThreadPool!\n\n    private var loop: EventLoop!\n    private var dg: DispatchGroup!\n    private var counter = 0\n\n    private let numThreads: Int\n    private let numTasks: Int\n\n    init(numThreads: Int, numTasks: Int) {\n        self.numThreads = numThreads\n        self.numTasks = numTasks\n    }\n\n    func setUp() throws {\n        self.threadPool = NIOThreadPool(numberOfThreads: self.numThreads)\n        self.threadPool.start()\n\n        // Prewarm the internal NIOThreadPool request queue, to avoid CoW\n        // work during the test runs.\n        let semaphore = DispatchSemaphore(value: 0)\n        let eventLoop = MultiThreadedEventLoopGroup.singleton.any()\n        let futures = (0..<self.numTasks).map { _ in\n            self.threadPool.runIfActive(eventLoop: eventLoop) {\n                // Hold back all the work items, until they all got scheduled\n                semaphore.wait()\n            }\n        }\n\n        for _ in (0..<self.numTasks) {\n            semaphore.signal()\n        }\n\n        _ = try EventLoopFuture.whenAllSucceed(futures, on: eventLoop).wait()\n    }\n\n    func tearDown() {\n        try! self.threadPool.syncShutdownGracefully()\n    }\n\n    func run() -> Int {\n        let eventLoop = MultiThreadedEventLoopGroup.singleton.any()\n\n        let futures = (0..<self.numTasks).map { _ in\n            self.threadPool.runIfActive(eventLoop: eventLoop) {\n                // Empty work item body\n            }\n        }\n\n        _ = try! EventLoopFuture.whenAllSucceed(futures, on: eventLoop).wait()\n\n        return 0\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/SchedulingAndRunningBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOPosix\n\nfinal class SchedulingAndRunningBenchmark: Benchmark {\n    private var group: MultiThreadedEventLoopGroup!\n    private var loop: EventLoop!\n    private var dg: DispatchGroup!\n    private let numTasks: Int\n\n    init(numTasks: Int) {\n        self.numTasks = numTasks\n    }\n\n    func setUp() throws {\n        group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        loop = group.next()\n        dg = DispatchGroup()\n\n        // We are preheating the EL to avoid growing the `ScheduledTask` `PriorityQueue`\n        // during the actual test\n        try! self.loop.submit { [loop, numTasks] in\n            var counter: Int = 0\n            for _ in 0..<numTasks {\n                loop!.assumeIsolatedUnsafeUnchecked().scheduleTask(in: .nanoseconds(0)) {\n                    counter &+= 1\n                }\n            }\n        }.wait()\n    }\n\n    func tearDown() {}\n\n    func run() -> Int {\n        let counter = try! self.loop.submit { [dg, loop, numTasks] in\n            var counter: Int = 0\n            for _ in 0..<numTasks {\n                dg!.enter()\n\n                loop!.assumeIsolatedUnsafeUnchecked().scheduleTask(in: .nanoseconds(0)) {\n                    counter &+= 1\n                    dg!.leave()\n                }\n            }\n            return counter\n        }.wait()\n        self.dg.wait()\n\n        return counter\n    }\n\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/TCPThroughputBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\n/// Test measure a TCP channel throughput.\n/// Server send 100K messages to the client,\n/// measure the time from the very first message sent by the server\n/// to the last message received by the client.\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class TCPThroughputBenchmark: Benchmark {\n\n    private let messages: Int\n    private let messageSize: Int\n\n    private var group: EventLoopGroup!\n    private var serverChannel: Channel!\n    private var serverHandler: NIOLoopBound<ServerHandler>!\n    private var clientChannel: Channel!\n\n    private var message: ByteBuffer!\n    private var serverEventLoop: EventLoop!\n\n    final class ServerHandler: ChannelInboundHandler {\n        public typealias InboundIn = ByteBuffer\n        public typealias OutboundOut = ByteBuffer\n\n        private let connectionEstablishedPromise: EventLoopPromise<EventLoop>\n        private let eventLoop: EventLoop\n        private var context: ChannelHandlerContext!\n\n        init(_ connectionEstablishedPromise: EventLoopPromise<EventLoop>, eventLoop: EventLoop) {\n            self.connectionEstablishedPromise = connectionEstablishedPromise\n            self.eventLoop = eventLoop\n        }\n\n        public func channelActive(context: ChannelHandlerContext) {\n            self.context = context\n            connectionEstablishedPromise.succeed(context.eventLoop)\n        }\n\n        public func send(_ message: ByteBuffer, times count: Int) {\n            for _ in 0..<count {\n                _ = self.context.writeAndFlush(Self.wrapOutboundOut(message.slice()))\n            }\n        }\n    }\n\n    final class StreamDecoder: ByteToMessageDecoder {\n        public typealias InboundIn = ByteBuffer\n        public typealias InboundOut = ByteBuffer\n\n        public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n            if let messageSize = buffer.getInteger(at: buffer.readerIndex, as: UInt16.self) {\n                if buffer.readableBytes >= messageSize {\n                    context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: Int(messageSize))!))\n                    return .continue\n                }\n            }\n            return .needMoreData\n        }\n    }\n\n    final class ClientHandler: ChannelInboundHandler {\n        public typealias InboundIn = ByteBuffer\n        public typealias OutboundOut = ByteBuffer\n\n        private var messagesReceived: Int\n        private var expectedMessages: Int?\n        private var completionPromise: EventLoopPromise<Void>?\n\n        init() {\n            self.messagesReceived = 0\n        }\n\n        func prepareRun(expectedMessages: Int, promise: EventLoopPromise<Void>) {\n            self.expectedMessages = expectedMessages\n            self.completionPromise = promise\n        }\n\n        public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            self.messagesReceived += 1\n\n            if self.expectedMessages == self.messagesReceived {\n                let promise = self.completionPromise\n\n                self.messagesReceived = 0\n                self.expectedMessages = nil\n                self.completionPromise = nil\n\n                promise!.succeed()\n            }\n        }\n    }\n\n    public init(messages: Int, messageSize: Int) {\n        self.messages = messages\n        self.messageSize = messageSize\n    }\n\n    func setUp() throws {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 4)\n\n        let connectionEstablishedPromise: EventLoopPromise<EventLoop> = self.group.next().makePromise()\n\n        let promise = self.group.next().makePromise(of: NIOLoopBound<ServerHandler>.self)\n        self.serverChannel = try ServerBootstrap(group: self.group)\n            .childChannelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let serverHandler = ServerHandler(connectionEstablishedPromise, eventLoop: channel.eventLoop)\n                    promise.succeed(NIOLoopBound(serverHandler, eventLoop: channel.eventLoop))\n                    try channel.pipeline.syncOperations.addHandler(serverHandler)\n                }\n            }\n            .bind(host: \"127.0.0.1\", port: 0)\n            .wait()\n\n        self.clientChannel = try ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(StreamDecoder()))\n                    try channel.pipeline.syncOperations.addHandler(ClientHandler())\n                }\n            }\n            .connect(to: serverChannel.localAddress!)\n            .wait()\n\n        self.serverHandler = try promise.futureResult.wait()\n\n        var message = self.serverChannel.allocator.buffer(capacity: self.messageSize)\n        message.writeInteger(UInt16(messageSize), as: UInt16.self)\n        for idx in 0..<(self.messageSize - MemoryLayout<UInt16>.stride) {\n            message.writeInteger(UInt8(truncatingIfNeeded: idx), endianness: .little, as: UInt8.self)\n        }\n        self.message = message\n\n        self.serverEventLoop = try connectionEstablishedPromise.futureResult.wait()\n    }\n\n    func tearDown() {\n        try! self.clientChannel.close().wait()\n        try! self.serverChannel.close().wait()\n        try! self.group.syncShutdownGracefully()\n    }\n\n    func run() throws -> Int {\n        let isDonePromise = self.clientChannel.eventLoop.makePromise(of: Void.self)\n        let clientChannel = self.clientChannel!\n        let expectedMessages = self.messages\n\n        try clientChannel.eventLoop.submit {\n            try clientChannel.pipeline.syncOperations.handler(type: ClientHandler.self).prepareRun(\n                expectedMessages: expectedMessages,\n                promise: isDonePromise\n            )\n        }.wait()\n\n        let serverHandler = self.serverHandler!\n        let message = self.message!\n        let messages = self.messages\n\n        self.serverEventLoop.execute {\n            serverHandler.value.send(message, times: messages)\n        }\n        try isDonePromise.futureResult.wait()\n        return 0\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/UDPBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOPosix\n\nfinal class UDPBenchmark {\n    /// Request to send.\n    private let data: ByteBuffer\n    /// Number of requests to send in each run.\n    private let numberOfRequests: Int\n    /// Setting for `.datagramVectorReadMessageCount`\n    private let vectorReads: Int\n    /// Number of writes before each flush (for the client; the server flushes at the end\n    /// of each read cycle).\n    private let vectorWrites: Int\n\n    private var group: EventLoopGroup!\n    private var server: Channel!\n    private var client: Channel!\n    private var clientHandler: EchoHandlerClient.SendableView!\n\n    init(data: ByteBuffer, numberOfRequests: Int, vectorReads: Int, vectorWrites: Int) {\n        self.data = data\n        self.numberOfRequests = numberOfRequests\n        self.vectorReads = vectorReads\n        self.vectorWrites = vectorWrites\n    }\n}\n\nextension UDPBenchmark: Benchmark {\n    func setUp() throws {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n\n        let address = try SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0)\n        self.server = try DatagramBootstrap(group: group)\n            // zero is the same as not applying the option.\n            .channelOption(.datagramVectorReadMessageCount, value: self.vectorReads)\n            .channelInitializer { channel in\n                channel.pipeline.addHandler(EchoHandler())\n            }\n            .bind(to: address)\n            .wait()\n\n        let remoteAddress = self.server.localAddress!\n\n        self.client = try DatagramBootstrap(group: group)\n            // zero is the same as not applying the option.\n            .channelOption(.datagramVectorReadMessageCount, value: self.vectorReads)\n            .channelInitializer { [data, numberOfRequests, vectorWrites] channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let handler = EchoHandlerClient(\n                        eventLoop: channel.eventLoop,\n                        config: .init(\n                            remoteAddress: remoteAddress,\n                            request: data,\n                            requests: numberOfRequests,\n                            writesPerFlush: vectorWrites\n                        )\n                    )\n                    try channel.pipeline.syncOperations.addHandler(handler)\n                }\n            }\n            .bind(to: address)\n            .wait()\n\n        self.clientHandler = try self.client.pipeline.handler(type: EchoHandlerClient.self).map { $0.sendableView }\n            .wait()\n    }\n\n    func tearDown() {\n        try! self.client.close().wait()\n        try! self.server.close().wait()\n    }\n\n    func run() throws -> Int {\n        try self.clientHandler.run().wait()\n        return self.vectorReads &+ self.vectorWrites\n    }\n}\n\nextension UDPBenchmark {\n    final class EchoHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = AddressedEnvelope<ByteBuffer>\n        typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n        func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            // echo back the message; skip the unwrap/rewrap.\n            context.write(data, promise: nil)\n        }\n\n        func channelReadComplete(context: ChannelHandlerContext) {\n            context.flush()\n        }\n\n        func errorCaught(context: ChannelHandlerContext, error: Error) {\n            fatalError(\"EchoHandler received errorCaught\")\n        }\n    }\n\n    final class EchoHandlerClient: ChannelInboundHandler, RemovableChannelHandler {\n        typealias InboundIn = AddressedEnvelope<ByteBuffer>\n        typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n        private let eventLoop: EventLoop\n        private let config: Config\n\n        private var state = State()\n        private var context: ChannelHandlerContext?\n\n        private struct State {\n            private enum _State {\n                case stopped\n                case running(Running)\n\n                struct Running {\n                    /// Number of requests still to send.\n                    var requestsToSend: Int\n                    /// Number of responses still being waited for.\n                    var responsesToReceive: Int\n                    /// Number of writes before the next flush, i.e. flush on zero.\n                    var writesBeforeNextFlush: Int\n                    /// Number of writes before each flush.\n                    let writesPerFlush: Int\n                    /// Completed once the `requestsToSend` and outstanding have dropped to zero.\n                    let promise: EventLoopPromise<Void>\n\n                    init(requests: Int, writesPerFlush: Int, promise: EventLoopPromise<Void>) {\n                        self.requestsToSend = requests\n                        self.responsesToReceive = requests\n                        self.writesBeforeNextFlush = writesPerFlush\n                        self.writesPerFlush = writesPerFlush\n                        self.promise = promise\n                    }\n                }\n            }\n\n            private var state: _State\n\n            init() {\n                self.state = .stopped\n            }\n\n            mutating func run(requests: Int, writesPerFlush: Int, promise: EventLoopPromise<Void>) {\n                switch self.state {\n                case .stopped:\n                    let running = _State.Running(requests: requests, writesPerFlush: writesPerFlush, promise: promise)\n                    self.state = .running(running)\n                case .running:\n                    fatalError(\"Invalid state\")\n                }\n            }\n\n            enum Receive {\n                case write\n                case finished(EventLoopPromise<Void>)\n            }\n\n            mutating func receive() -> Receive {\n                switch self.state {\n                case .running(var running):\n                    running.responsesToReceive &-= 1\n                    if running.responsesToReceive == 0, running.requestsToSend == 0 {\n                        self.state = .stopped\n                        return .finished(running.promise)\n                    } else {\n                        self.state = .running(running)\n                        return .write\n                    }\n\n                case .stopped:\n                    fatalError(\"Received too many messages\")\n                }\n            }\n\n            enum Write {\n                case write(flush: Bool)\n                case doNothing\n            }\n\n            mutating func write() -> Write {\n                switch self.state {\n                case .stopped:\n                    return .doNothing\n\n                case .running(var running):\n                    guard running.requestsToSend > 0 else {\n                        return .doNothing\n                    }\n\n                    running.requestsToSend &-= 1\n                    running.writesBeforeNextFlush &-= 1\n\n                    let flush: Bool\n                    if running.writesBeforeNextFlush == 0 {\n                        running.writesBeforeNextFlush = running.writesPerFlush\n                        flush = true\n                    } else {\n                        flush = false\n                    }\n\n                    self.state = .running(running)\n                    return .write(flush: flush)\n                }\n            }\n        }\n\n        init(eventLoop: EventLoop, config: Config) {\n            self.eventLoop = eventLoop\n            self.config = config\n        }\n\n        struct Config {\n            var remoteAddress: SocketAddress\n            var request: ByteBuffer\n            var requests: Int\n            var writesPerFlush: Int\n        }\n\n        func handlerAdded(context: ChannelHandlerContext) {\n            self.context = context\n        }\n\n        func handlerRemoved(context: ChannelHandlerContext) {\n            self.context = nil\n        }\n\n        var sendableView: SendableView {\n            SendableView(handler: self, eventLoop: self.eventLoop)\n        }\n\n        struct SendableView: Sendable {\n            private let handler: NIOLoopBound<EchoHandlerClient>\n            private let eventLoop: EventLoop\n\n            init(handler: EchoHandlerClient, eventLoop: EventLoop) {\n                self.handler = NIOLoopBound(handler, eventLoop: eventLoop)\n                self.eventLoop = eventLoop\n            }\n\n            func run() -> EventLoopFuture<Void> {\n                let p = self.eventLoop.makePromise(of: Void.self)\n                self.eventLoop.execute {\n                    self.handler.value._run(promise: p)\n                }\n                return p.futureResult\n            }\n        }\n\n        private func _run(promise: EventLoopPromise<Void>) {\n            self.state.run(requests: self.config.requests, writesPerFlush: self.config.writesPerFlush, promise: promise)\n            let context = self.context!\n\n            for _ in 0..<self.config.writesPerFlush {\n                self.maybeSend(context: context)\n            }\n        }\n\n        private func maybeSend(context: ChannelHandlerContext) {\n            switch self.state.write() {\n            case .doNothing:\n                ()\n            case let .write(flush):\n                let envolope = AddressedEnvelope<ByteBuffer>(\n                    remoteAddress: self.config.remoteAddress,\n                    data: self.config.request\n                )\n                context.write(Self.wrapOutboundOut(envolope), promise: nil)\n                if flush {\n                    context.flush()\n                }\n            }\n        }\n\n        func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            switch self.state.receive() {\n            case .write:\n                self.maybeSend(context: context)\n            case .finished(let promise):\n                promise.succeed()\n            }\n        }\n\n        func errorCaught(context: ChannelHandlerContext, error: Error) {\n            fatalError(\"EchoHandlerClient received errorCaught\")\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/WebSocketFrameDecoderBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\n\nfinal class WebSocketFrameDecoderBenchmark {\n\n    private let channel: EmbeddedChannel\n    private let runCount: Int\n    private let dataSize: Int\n    private let maskingKey: WebSocketMaskingKey?\n    private var data: ByteBuffer!\n\n    init(dataSize: Int, runCount: Int, maskingKey: WebSocketMaskingKey? = nil) {\n        self.channel = EmbeddedChannel()\n        self.dataSize = dataSize\n        self.maskingKey = maskingKey\n        self.runCount = runCount\n    }\n}\n\nextension WebSocketFrameDecoderBenchmark: Benchmark {\n\n    func setUp() throws {\n        self.data = ByteBufferAllocator().webSocketFrame(size: dataSize, maskingKey: maskingKey)\n        try self.channel.pipeline.syncOperations.addHandler(\n            ByteToMessageHandler(WebSocketFrameDecoder(maxFrameSize: dataSize))\n        )\n    }\n\n    func tearDown() {\n        _ = try! self.channel.finish()\n    }\n\n    func run() throws -> Int {\n        for _ in 0..<self.runCount {\n            try self.channel.writeInbound(self.data)\n            let _: WebSocketFrame? = try self.channel.readInbound()\n        }\n        return 1\n    }\n\n}\n\nextension ByteBufferAllocator {\n    fileprivate func webSocketFrame(size: Int, maskingKey: WebSocketMaskingKey?) -> ByteBuffer {\n        var data = self.buffer(capacity: size)\n\n        // Calculate some information about the mask.\n        let maskBitMask: UInt8 = maskingKey != nil ? 0x80 : 0x00\n\n        // Time to add the extra bytes. To avoid checking this twice, we also start writing stuff out here.\n        switch size {\n        case 0...125:\n            data.writeInteger(UInt8(0x81))\n            data.writeInteger(UInt8(size) | maskBitMask)\n        case 126...Int(UInt16.max):\n            data.writeInteger(UInt8(0x81))\n            data.writeInteger(UInt8(126) | maskBitMask)\n            data.writeInteger(UInt16(size))\n        default:\n            data.writeInteger(UInt8(0x81))\n            data.writeInteger(UInt8(127) | maskBitMask)\n            data.writeInteger(UInt64(size))\n        }\n\n        if let maskingKey = maskingKey {\n            data.writeBytes(maskingKey)\n        }\n\n        data.writeBytes(repeatElement(0, count: size))\n        return data\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/WebSocketFrameEncoderBenchmark.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\n\nfinal class WebSocketFrameEncoderBenchmark {\n    private let channel: EmbeddedChannel\n    private let dataSize: Int\n    private let data: ByteBuffer\n    private let runCount: Int\n    private let dataStrategy: DataStrategy\n    private let cowStrategy: CoWStrategy\n    private var maskingKey: Optional<WebSocketMaskingKey>\n    private var frame: Optional<WebSocketFrame>\n\n    init(\n        dataSize: Int,\n        runCount: Int,\n        dataStrategy: DataStrategy,\n        cowStrategy: CoWStrategy,\n        maskingKeyStrategy: MaskingKeyStrategy\n    ) {\n        self.frame = nil\n        self.channel = EmbeddedChannel()\n        self.dataSize = dataSize\n        self.runCount = runCount\n        self.dataStrategy = dataStrategy\n        self.cowStrategy = cowStrategy\n        self.data = ByteBufferAllocator().buffer(size: dataSize, dataStrategy: dataStrategy)\n        self.maskingKey = maskingKeyStrategy == MaskingKeyStrategy.always ? [0x80, 0x08, 0x10, 0x01] : nil\n    }\n}\n\nextension WebSocketFrameEncoderBenchmark {\n    enum DataStrategy {\n        case spaceAtFront\n        case noSpaceAtFront\n    }\n}\n\nextension WebSocketFrameEncoderBenchmark {\n    enum CoWStrategy {\n        case always\n        case never\n    }\n}\n\nextension WebSocketFrameEncoderBenchmark {\n    enum MaskingKeyStrategy {\n        case always\n        case never\n    }\n}\n\nextension WebSocketFrameEncoderBenchmark: Benchmark {\n    func setUp() throws {\n        // We want the pipeline walk to have some cost.\n        try! self.channel.pipeline.syncOperations.addHandler(WriteConsumingHandler())\n        for _ in 0..<3 {\n            try! self.channel.pipeline.syncOperations.addHandler(NoOpOutboundHandler())\n        }\n        try! self.channel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder())\n        self.frame = WebSocketFrame(opcode: .binary, maskKey: self.maskingKey, data: self.data, extensionData: nil)\n    }\n\n    func tearDown() {\n        _ = try! self.channel.finish()\n    }\n\n    func run() throws -> Int {\n        switch self.cowStrategy {\n        case .always:\n            let frame = self.frame!\n            return self.runWithCoWs(frame: frame)\n        case .never:\n            return self.runWithoutCoWs()\n        }\n    }\n\n    private func runWithCoWs(frame: WebSocketFrame) -> Int {\n        for _ in 0..<self.runCount {\n            self.channel.write(frame, promise: nil)\n        }\n        return 1\n    }\n\n    private func runWithoutCoWs() -> Int {\n        for _ in 0..<self.runCount {\n            // To avoid CoWs this has to be a new buffer every time. This is expensive, sadly, so tests using this strategy\n            // must do fewer iterations.\n            let data = self.channel.allocator.buffer(size: self.dataSize, dataStrategy: self.dataStrategy)\n            let frame = WebSocketFrame(opcode: .binary, maskKey: self.maskingKey, data: data, extensionData: nil)\n            self.channel.write(frame, promise: nil)\n        }\n        return 1\n    }\n}\n\nextension ByteBufferAllocator {\n    fileprivate func buffer(size: Int, dataStrategy: WebSocketFrameEncoderBenchmark.DataStrategy) -> ByteBuffer {\n        var data: ByteBuffer\n\n        switch dataStrategy {\n        case .noSpaceAtFront:\n            data = self.buffer(capacity: size)\n        case .spaceAtFront:\n            data = self.buffer(capacity: size + 16)\n            data.moveWriterIndex(forwardBy: 16)\n            data.moveReaderIndex(forwardBy: 16)\n        }\n\n        data.writeBytes(repeatElement(0, count: size))\n        return data\n    }\n}\n\nprivate final class NoOpOutboundHandler: ChannelOutboundHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Any\n}\n\nprivate final class WriteConsumingHandler: ChannelOutboundHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Never\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        promise?.succeed(())\n    }\n}\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\n\n// swift-format-ignore: OrderedImports\n// Required due to https://github.com/swiftlang/swift/issues/76842\n\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#endif\n\nimport Dispatch\nimport NIOCore\nimport NIOEmbedded\nimport NIOFoundationCompat\nimport NIOHTTP1\n#if os(Android)\n// workaround for error: reference to var 'stdout' is not concurrency-safe because it involves shared mutable state\n@preconcurrency import NIOPosix\n#else\nimport NIOPosix\n#endif\nimport NIOWebSocket\n\n// Use unbuffered stdout to help detect exactly which test was running in the event of a crash.\nsetbuf(stdout, nil)\n\n// MARK: Test Harness\n\nfunc makeWarning() -> String {\n    var warning = \"\"\n    assert(\n        {\n            print(\"======================================================\")\n            print(\"= YOU ARE RUNNING NIOPerformanceTester IN DEBUG MODE =\")\n            print(\"======================================================\")\n            warning = \" <<< DEBUG MODE >>>\"\n            return true\n        }()\n    )\n    return warning\n}\n\nlet warning = makeWarning()\n\npublic func measure(_ fn: () throws -> Int) rethrows -> [Double] {\n    func measureOne(_ fn: () throws -> Int) rethrows -> Double {\n        let start = DispatchTime.now().uptimeNanoseconds\n        _ = try fn()\n        let end = DispatchTime.now().uptimeNanoseconds\n        return Double(end - start) / Double(TimeAmount.seconds(1).nanoseconds)\n    }\n\n    _ = try measureOne(fn)  // pre-heat and throw away\n    var measurements = Array(repeating: 0.0, count: 10)\n    for i in 0..<10 {\n        measurements[i] = try measureOne(fn)\n    }\n\n    return measurements\n}\n\nlet limitSet = CommandLine.arguments.dropFirst()\n\npublic func measureAndPrint(desc: String, fn: () throws -> Int) rethrows {\n    if limitSet.isEmpty || limitSet.contains(desc) {\n        print(\"measuring\\(warning): \\(desc): \", terminator: \"\")\n        let measurements = try measure(fn)\n        print(measurements.reduce(into: \"\") { $0.append(\"\\($1), \") })\n    } else {\n        print(\"skipping '\\(desc)', limit set = \\(limitSet)\")\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic func measure(_ fn: () async throws -> Int) async rethrows -> [Double] {\n    func measureOne(_ fn: () async throws -> Int) async rethrows -> Double {\n        let start = DispatchTime.now().uptimeNanoseconds\n        _ = try await fn()\n        let end = DispatchTime.now().uptimeNanoseconds\n        return Double(end - start) / Double(TimeAmount.seconds(1).nanoseconds)\n    }\n\n    _ = try await measureOne(fn)  // pre-heat and throw away\n    var measurements = Array(repeating: 0.0, count: 10)\n    for i in 0..<10 {\n        measurements[i] = try await measureOne(fn)\n    }\n\n    return measurements\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic func measureAndPrint(desc: String, fn: () async throws -> Int) async rethrows {\n    if limitSet.isEmpty || limitSet.contains(desc) {\n        print(\"measuring\\(warning): \\(desc): \", terminator: \"\")\n        let measurements = try await measure(fn)\n        print(measurements.reduce(into: \"\") { $0.append(\"\\($1), \") })\n    } else {\n        print(\"skipping '\\(desc)', limit set = \\(limitSet)\")\n    }\n}\n\n// MARK: Utilities\n\nprivate final class SimpleHTTPServer: ChannelInboundHandler {\n    typealias InboundIn = HTTPServerRequestPart\n    typealias OutboundOut = HTTPServerResponsePart\n\n    private var files: [String] = Array()\n    private var seenEnd: Bool = false\n    private var sentEnd: Bool = false\n    private var isOpen: Bool = true\n\n    private let cachedHead: HTTPResponseHead\n    private let cachedBody: [UInt8]\n    private let bodyLength = 1024\n    private let numberOfAdditionalHeaders = 10\n\n    init() {\n        var head = HTTPResponseHead(version: .http1_1, status: .ok)\n        head.headers.add(name: \"Content-Length\", value: \"\\(self.bodyLength)\")\n        for i in 0..<self.numberOfAdditionalHeaders {\n            head.headers.add(name: \"X-Random-Extra-Header\", value: \"\\(i)\")\n        }\n        self.cachedHead = head\n\n        var body: [UInt8] = []\n        body.reserveCapacity(self.bodyLength)\n        for i in 0..<self.bodyLength {\n            body.append(UInt8(i % Int(UInt8.max)))\n        }\n        self.cachedBody = body\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        if case .head(let req) = Self.unwrapInboundIn(data) {\n            switch req.uri {\n            case \"/perf-test-1\":\n                var buffer = context.channel.allocator.buffer(capacity: self.cachedBody.count)\n                buffer.writeBytes(self.cachedBody)\n                context.write(Self.wrapOutboundOut(.head(self.cachedHead)), promise: nil)\n                context.write(Self.wrapOutboundOut(.body(.byteBuffer(buffer))), promise: nil)\n                context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n                return\n            case \"/perf-test-2\":\n                var req = HTTPResponseHead(version: .http1_1, status: .ok)\n                for i in 1...8 {\n                    req.headers.add(name: \"X-ResponseHeader-\\(i)\", value: \"foo\")\n                }\n                req.headers.add(name: \"content-length\", value: \"0\")\n                context.write(Self.wrapOutboundOut(.head(req)), promise: nil)\n                context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n                return\n            default:\n                fatalError(\"unknown uri \\(req.uri)\")\n            }\n        }\n    }\n}\n\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\nlet serverChannel = try ServerBootstrap(group: group)\n    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n    .childChannelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withPipeliningAssistance: true)\n            try channel.pipeline.syncOperations.addHandler(SimpleHTTPServer())\n        }\n    }.bind(host: \"127.0.0.1\", port: 0).wait()\n\ndefer {\n    try! serverChannel.close().wait()\n}\n\nlet head = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/perf-test-1\", headers: [\"Host\": \"localhost\"])\n\nfinal class RepeatedRequests: ChannelInboundHandler {\n    typealias InboundIn = HTTPClientResponsePart\n    typealias OutboundOut = HTTPClientRequestPart\n\n    private let numberOfRequests: Int\n    private var remainingNumberOfRequests: Int\n    private var doneRequests = 0\n    private let isDonePromise: EventLoopPromise<Int>\n\n    init(numberOfRequests: Int, isDonePromise: EventLoopPromise<Int>) {\n        self.remainingNumberOfRequests = numberOfRequests\n        self.numberOfRequests = numberOfRequests\n        self.isDonePromise = isDonePromise\n    }\n\n    func wait() throws -> Int {\n        let reqs = try self.isDonePromise.futureResult.wait()\n        precondition(reqs == self.numberOfRequests)\n        return reqs\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        context.channel.close(promise: nil)\n        self.isDonePromise.fail(error)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let reqPart = Self.unwrapInboundIn(data)\n        if case .end(nil) = reqPart {\n            if self.remainingNumberOfRequests <= 0 {\n                context.channel.close().assumeIsolated().map {\n                    self.doneRequests\n                }.nonisolated().cascade(to: self.isDonePromise)\n            } else {\n                self.doneRequests += 1\n                self.remainingNumberOfRequests -= 1\n\n                context.write(Self.wrapOutboundOut(.head(head)), promise: nil)\n                context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n            }\n        }\n    }\n}\n\nprivate func someString(size: Int) -> String {\n    var s = \"A\"\n    for f in 1..<size {\n        s += String(\"\\(f)\".first!)\n    }\n    return s\n}\n\n// MARK: Performance Tests\n\nmeasureAndPrint(desc: \"write_http_headers\") {\n    var headers: [(String, String)] = []\n    for i in 1..<10 {\n        headers.append((\"\\(i)\", \"\\(i)\"))\n    }\n\n    var val = 0\n    for _ in 0..<1_000_000 {\n        let headers = HTTPHeaders(headers)\n        val += headers.underestimatedCount\n    }\n    return val\n}\n\nmeasureAndPrint(desc: \"http_headers_canonical_form\") {\n    let headers: HTTPHeaders = [\"key\": \"no,trimming\"]\n    var count = 0\n    for _ in 0..<100_000 {\n        count &+= headers[canonicalForm: \"key\"].count\n    }\n    return count\n}\n\nmeasureAndPrint(desc: \"http_headers_canonical_form_trimming_whitespace\") {\n    let headers: HTTPHeaders = [\"key\": \"         some   ,   trimming     \"]\n    var count = 0\n    for _ in 0..<10_000 {\n        count &+= headers[canonicalForm: \"key\"].count\n    }\n    return count\n}\n\nmeasureAndPrint(desc: \"http_headers_canonical_form_trimming_whitespace_from_short_string\") {\n    let headers: HTTPHeaders = [\"key\": \"   smallString   ,whenStripped\"]\n    var count = 0\n    for _ in 0..<10_000 {\n        count &+= headers[canonicalForm: \"key\"].count\n    }\n    return count\n}\n\nmeasureAndPrint(desc: \"http_headers_canonical_form_trimming_whitespace_from_long_string\") {\n    let headers: HTTPHeaders = [\"key\": \" moreThan15CharactersWithAndWithoutWhitespace ,anotherValue\"]\n    var count = 0\n    for _ in 0..<10_000 {\n        count &+= headers[canonicalForm: \"key\"].count\n    }\n    return count\n}\n\nmeasureAndPrint(desc: \"http_headers_description_100k\") {\n    let headers = HTTPHeaders(Array(repeating: (\"String\", \"String\"), count: 100))\n\n    for _ in 0..<100_000 {\n        let str = headers.description\n        precondition(str.utf8.count > 100)\n    }\n\n    return 0\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_12MB_short_string_literals\") {\n    let bufferSize = 12 * 1024 * 1024\n    var buffer = ByteBufferAllocator().buffer(capacity: bufferSize)\n\n    for _ in 0..<3 {\n        buffer.clear()\n        for _ in 0..<(bufferSize / 4) {\n            buffer.writeString(\"abcd\")\n        }\n    }\n\n    let readableBytes = buffer.readableBytes\n    precondition(readableBytes == bufferSize)\n    return readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_12MB_short_calculated_strings\") {\n    let bufferSize = 12 * 1024 * 1024\n    var buffer = ByteBufferAllocator().buffer(capacity: bufferSize)\n    let s = someString(size: 4)\n\n    for _ in 0..<1 {\n        buffer.clear()\n        for _ in 0..<(bufferSize / 4) {\n            buffer.writeString(s)\n        }\n    }\n\n    let readableBytes = buffer.readableBytes\n    precondition(readableBytes == bufferSize)\n    return readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_12MB_medium_string_literals\") {\n    let bufferSize = 12 * 1024 * 1024\n    var buffer = ByteBufferAllocator().buffer(capacity: bufferSize)\n\n    for _ in 0..<100 {\n        buffer.clear()\n        for _ in 0..<(bufferSize / 24) {\n            buffer.writeString(\"012345678901234567890123\")\n        }\n    }\n\n    let readableBytes = buffer.readableBytes\n    precondition(readableBytes == bufferSize)\n    return readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_12MB_medium_calculated_strings\") {\n    let bufferSize = 12 * 1024 * 1024\n    var buffer = ByteBufferAllocator().buffer(capacity: bufferSize)\n    let s = someString(size: 24)\n\n    for _ in 0..<5 {\n        buffer.clear()\n        for _ in 0..<(bufferSize / 24) {\n            buffer.writeString(s)\n        }\n    }\n\n    let readableBytes = buffer.readableBytes\n    precondition(readableBytes == bufferSize)\n    return readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_12MB_large_calculated_strings\") {\n    let bufferSize = 12 * 1024 * 1024\n    var buffer = ByteBufferAllocator().buffer(capacity: bufferSize)\n    let s = someString(size: 1024 * 1024)\n\n    for _ in 0..<5 {\n        buffer.clear()\n        for _ in 0..<12 {\n            buffer.writeString(s)\n        }\n    }\n\n    let readableBytes = buffer.readableBytes\n    precondition(readableBytes == bufferSize)\n    return readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_lots_of_rw\") {\n    let dispatchData = (\"A\" as StaticString).withUTF8Buffer { ptr in\n        DispatchData(bytes: UnsafeRawBufferPointer(start: UnsafeRawPointer(ptr.baseAddress), count: ptr.count))\n    }\n    var buffer = ByteBufferAllocator().buffer(capacity: 7 * 1024 * 1024)\n    let substring = Substring(\"A\")\n    @inline(never)\n    func doWrites(buffer: inout ByteBuffer, dispatchData: DispatchData, substring: Substring) {\n        // all of those should be 0 allocations\n\n        // buffer.writeBytes(foundationData) // see SR-7542\n        buffer.writeBytes([0x41])\n        buffer.writeBytes(dispatchData)\n        buffer.writeBytes(\"A\".utf8)\n        buffer.writeString(\"A\")\n        buffer.writeStaticString(\"A\")\n        buffer.writeInteger(0x41, as: UInt8.self)\n        buffer.writeSubstring(substring)\n    }\n    @inline(never)\n    func doReads(buffer: inout ByteBuffer) {\n        // these ones are zero allocations\n        let val = buffer.readInteger(as: UInt8.self)\n        precondition(0x41 == val, \"\\(val!)\")\n        var slice = buffer.readSlice(length: 1)\n        let sliceVal = slice!.readInteger(as: UInt8.self)\n        precondition(0x41 == sliceVal, \"\\(sliceVal!)\")\n        buffer.withUnsafeReadableBytes { ptr in\n            precondition(ptr[0] == 0x41)\n        }\n\n        // those down here should be one allocation each\n        let arr = buffer.readBytes(length: 1)\n        precondition([0x41] == arr!, \"\\(arr!)\")\n        let str = buffer.readString(length: 1)\n        precondition(\"A\" == str, \"\\(str!)\")\n    }\n    for _ in 0..<100_000 {\n        doWrites(buffer: &buffer, dispatchData: dispatchData, substring: substring)\n        doReads(buffer: &buffer)\n    }\n    return buffer.readableBytes\n}\n\nfunc writeExampleHTTPResponseAsString(buffer: inout ByteBuffer) {\n    buffer.writeString(\"HTTP/1.1 200 OK\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Connection\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"close\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Proxy-Connection\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"close\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Via\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"HTTP/1.1 localhost (IBM-PROXY-WTE)\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Date\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"Tue, 08 May 2018 13:42:56 GMT\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Server\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"Apache/2.2.15 (Red Hat)\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Strict-Transport-Security\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"max-age=15768000; includeSubDomains\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Last-Modified\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"Tue, 08 May 2018 13:39:13 GMT\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"ETag\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"357031-1809-56bb1e96a6240\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Accept-Ranges\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"bytes\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Content-Length\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"6153\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"Content-Type\")\n    buffer.writeString(\":\")\n    buffer.writeString(\" \")\n    buffer.writeString(\"text/html; charset=UTF-8\")\n    buffer.writeString(\"\\r\\n\")\n    buffer.writeString(\"\\r\\n\")\n}\n\nfunc writeExampleHTTPResponseAsStaticString(buffer: inout ByteBuffer) {\n    buffer.writeStaticString(\"HTTP/1.1 200 OK\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Connection\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"close\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Proxy-Connection\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"close\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Via\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"HTTP/1.1 localhost (IBM-PROXY-WTE)\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Date\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"Tue, 08 May 2018 13:42:56 GMT\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Server\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"Apache/2.2.15 (Red Hat)\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Strict-Transport-Security\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"max-age=15768000; includeSubDomains\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Last-Modified\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"Tue, 08 May 2018 13:39:13 GMT\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"ETag\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"357031-1809-56bb1e96a6240\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Accept-Ranges\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"bytes\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Content-Length\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"6153\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"Content-Type\")\n    buffer.writeStaticString(\":\")\n    buffer.writeStaticString(\" \")\n    buffer.writeStaticString(\"text/html; charset=UTF-8\")\n    buffer.writeStaticString(\"\\r\\n\")\n    buffer.writeStaticString(\"\\r\\n\")\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_http_response_ascii_only_as_string\") {\n    var buffer = ByteBufferAllocator().buffer(capacity: 16 * 1024)\n    for _ in 0..<20_000 {\n        writeExampleHTTPResponseAsString(buffer: &buffer)\n        buffer.writeString(htmlASCIIOnly)\n        buffer.clear()\n    }\n    return buffer.readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_http_response_ascii_only_as_staticstring\") {\n    var buffer = ByteBufferAllocator().buffer(capacity: 16 * 1024)\n    for _ in 0..<20_000 {\n        writeExampleHTTPResponseAsStaticString(buffer: &buffer)\n        buffer.writeStaticString(htmlASCIIOnlyStaticString)\n        buffer.clear()\n    }\n    return buffer.readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_http_response_some_nonascii_as_string\") {\n    var buffer = ByteBufferAllocator().buffer(capacity: 16 * 1024)\n    for _ in 0..<20_000 {\n        writeExampleHTTPResponseAsString(buffer: &buffer)\n        buffer.writeString(htmlMostlyASCII)\n        buffer.clear()\n    }\n    return buffer.readableBytes\n}\n\nmeasureAndPrint(desc: \"bytebuffer_write_http_response_some_nonascii_as_staticstring\") {\n    var buffer = ByteBufferAllocator().buffer(capacity: 16 * 1024)\n    for _ in 0..<20_000 {\n        writeExampleHTTPResponseAsStaticString(buffer: &buffer)\n        buffer.writeStaticString(htmlMostlyASCIIStaticString)\n        buffer.clear()\n    }\n    return buffer.readableBytes\n}\n\ntry measureAndPrint(desc: \"no-net_http1_1k_reqs_1_conn\") {\n    final class MeasuringHandler: ChannelDuplexHandler {\n        typealias InboundIn = Never\n        typealias InboundOut = ByteBuffer\n        typealias OutboundIn = ByteBuffer\n\n        private var requestBuffer: ByteBuffer!\n        private var expectedResponseBuffer: ByteBuffer?\n        private var remainingNumberOfRequests: Int\n\n        private let completionHandler: (Int) -> Void\n        private let numberOfRequests: Int\n\n        init(numberOfRequests: Int, completionHandler: @escaping (Int) -> Void) {\n            self.completionHandler = completionHandler\n            self.numberOfRequests = numberOfRequests\n            self.remainingNumberOfRequests = numberOfRequests\n        }\n\n        func handlerAdded(context: ChannelHandlerContext) {\n            self.requestBuffer = context.channel.allocator.buffer(capacity: 512)\n            self.requestBuffer.writeString(\n                \"\"\"\n                GET /perf-test-2 HTTP/1.1\\r\n                Host: example.com\\r\n                X-Some-Header-1: foo\\r\n                X-Some-Header-2: foo\\r\n                X-Some-Header-3: foo\\r\n                X-Some-Header-4: foo\\r\n                X-Some-Header-5: foo\\r\n                X-Some-Header-6: foo\\r\n                X-Some-Header-7: foo\\r\n                X-Some-Header-8: foo\\r\\n\\r\\n\n                \"\"\"\n            )\n        }\n\n        func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n            var buf = Self.unwrapOutboundIn(data)\n            if self.expectedResponseBuffer == nil {\n                self.expectedResponseBuffer = buf\n            }\n            precondition(buf == self.expectedResponseBuffer, \"got \\(buf.readString(length: buf.readableBytes)!)\")\n            let channel = context.channel\n            self.remainingNumberOfRequests -= 1\n            if self.remainingNumberOfRequests > 0 {\n                context.eventLoop.assumeIsolated().execute {\n                    self.kickOff(channel: channel)\n                }\n            } else {\n                self.completionHandler(self.numberOfRequests)\n            }\n        }\n\n        func kickOff(channel: Channel) {\n            try! (channel as! EmbeddedChannel).writeInbound(self.requestBuffer)\n        }\n    }\n\n    let eventLoop = EmbeddedEventLoop()\n    let channel = EmbeddedChannel(handler: nil, loop: eventLoop)\n    var done = false\n    let desiredRequests = 1_000\n    var requestsDone = -1\n    let measuringHandler = MeasuringHandler(numberOfRequests: desiredRequests) { reqs in\n        requestsDone = reqs\n        done = true\n    }\n\n    let sync = channel.pipeline.syncOperations\n    try sync.configureHTTPServerPipeline(\n        withPipeliningAssistance: true,\n        withErrorHandling: true\n    )\n\n    try sync.addHandler(SimpleHTTPServer())\n    try sync.addHandler(measuringHandler, position: .first)\n\n    measuringHandler.kickOff(channel: channel)\n\n    while !done {\n        eventLoop.run()\n    }\n    _ = try channel.finish()\n    precondition(requestsDone == desiredRequests)\n    return requestsDone\n}\n\nmeasureAndPrint(desc: \"http1_1k_reqs_1_conn\") {\n    let isDone = group.next().makePromise(of: Int.self)\n    let clientChannel = try! ClientBootstrap(group: group)\n        .channelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                let repeatedRequestsHandler = RepeatedRequests(numberOfRequests: 1_000, isDonePromise: isDone)\n                let sync = channel.pipeline.syncOperations\n                try sync.addHTTPClientHandlers()\n                try sync.addHandler(repeatedRequestsHandler)\n            }\n        }\n        .connect(to: serverChannel.localAddress!)\n        .wait()\n\n    try! clientChannel.eventLoop.flatSubmit {\n        let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n        clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n        clientChannel.pipeline.syncOperations.writeAndFlush(NIOAny(HTTPClientRequestPart.end(nil)), promise: promise)\n        return promise.futureResult\n    }.wait()\n    return try! isDone.futureResult.wait()\n}\n\nmeasureAndPrint(desc: \"http1_1k_reqs_100_conns\") {\n    var reqs: [Int] = []\n    let numConns = 100\n    let numReqs = 1_000\n    let reqsPerConn = numReqs / numConns\n    reqs.reserveCapacity(reqsPerConn)\n    for _ in 0..<numConns {\n        let isDone = group.next().makePromise(of: Int.self)\n\n        let clientChannel = try! ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let repeatedRequestsHandler = RepeatedRequests(numberOfRequests: reqsPerConn, isDonePromise: isDone)\n                    let sync = channel.pipeline.syncOperations\n                    try sync.addHTTPClientHandlers()\n                    try sync.addHandler(repeatedRequestsHandler)\n                }\n            }\n            .connect(to: serverChannel.localAddress!)\n            .wait()\n\n        try! clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n        reqs.append(try! isDone.futureResult.wait())\n    }\n    return reqs.reduce(0, +) / numConns\n}\n\nmeasureAndPrint(desc: \"future_whenallsucceed_100k_immediately_succeeded_off_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<100_000)\n    let futures = expected.map { loop.makeSucceededFuture($0) }\n    let allSucceeded = try! EventLoopFuture.whenAllSucceed(futures, on: loop).wait()\n    return allSucceeded.count\n}\n\nmeasureAndPrint(desc: \"future_whenallsucceed_100k_immediately_succeeded_on_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<100_000)\n    let allSucceeded = try! loop.makeSucceededFuture(()).flatMap { _ -> EventLoopFuture<[Int]> in\n        let futures = expected.map { loop.makeSucceededFuture($0) }\n        return EventLoopFuture.whenAllSucceed(futures, on: loop)\n    }.wait()\n    return allSucceeded.count\n}\n\nmeasureAndPrint(desc: \"future_whenallsucceed_10k_deferred_off_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<10_000)\n    let promises = expected.map { _ in loop.makePromise(of: Int.self) }\n    let allSucceeded = EventLoopFuture.whenAllSucceed(promises.map { $0.futureResult }, on: loop)\n    for (index, promise) in promises.enumerated() {\n        promise.succeed(index)\n    }\n    return try! allSucceeded.wait().count\n}\n\nmeasureAndPrint(desc: \"future_whenallsucceed_10k_deferred_on_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<10_000)\n    let promises = expected.map { _ in loop.makePromise(of: Int.self) }\n    let allSucceeded = try! loop.makeSucceededFuture(()).flatMap { _ -> EventLoopFuture<[Int]> in\n        let result = EventLoopFuture.whenAllSucceed(promises.map { $0.futureResult }, on: loop)\n        for (index, promise) in promises.enumerated() {\n            promise.succeed(index)\n        }\n        return result\n    }.wait()\n    return allSucceeded.count\n}\n\nmeasureAndPrint(desc: \"future_whenallcomplete_100k_immediately_succeeded_off_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<100_000)\n    let futures = expected.map { loop.makeSucceededFuture($0) }\n    let allSucceeded = try! EventLoopFuture.whenAllComplete(futures, on: loop).wait()\n    return allSucceeded.count\n}\n\nmeasureAndPrint(desc: \"future_whenallcomplete_100k_immediately_succeeded_on_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<100_000)\n    let allSucceeded = try! loop.makeSucceededFuture(()).flatMap { _ -> EventLoopFuture<[Result<Int, Error>]> in\n        let futures = expected.map { loop.makeSucceededFuture($0) }\n        return EventLoopFuture.whenAllComplete(futures, on: loop)\n    }.wait()\n    return allSucceeded.count\n}\n\nmeasureAndPrint(desc: \"future_whenallcomplete_10k_deferred_off_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<10_000)\n    let promises = expected.map { _ in loop.makePromise(of: Int.self) }\n    let allSucceeded = EventLoopFuture.whenAllComplete(promises.map { $0.futureResult }, on: loop)\n    for (index, promise) in promises.enumerated() {\n        promise.succeed(index)\n    }\n    return try! allSucceeded.wait().count\n}\n\nmeasureAndPrint(desc: \"future_whenallcomplete_100k_deferred_on_loop\") {\n    let loop = group.next()\n    let expected = Array(0..<100_000)\n    let promises = expected.map { _ in loop.makePromise(of: Int.self) }\n    let allSucceeded = try! loop.makeSucceededFuture(()).flatMap { _ -> EventLoopFuture<[Result<Int, Error>]> in\n        let result = EventLoopFuture.whenAllComplete(promises.map { $0.futureResult }, on: loop)\n        for (index, promise) in promises.enumerated() {\n            promise.succeed(index)\n        }\n        return result\n    }.wait()\n    return allSucceeded.count\n}\n\nmeasureAndPrint(desc: \"future_reduce_10k_futures\") {\n    let el1 = group.next()\n\n    let futures = (1...10_000).map { i in el1.makeSucceededFuture(i) }\n    return try! EventLoopFuture<Int>.reduce(0, futures, on: el1, { $0 + $1 }).wait()\n}\n\nmeasureAndPrint(desc: \"future_reduce_into_10k_futures\") {\n    let el1 = group.next()\n\n    let futures = (1...10_000).map { i in el1.makeSucceededFuture(i) }\n    return try! EventLoopFuture<Int>.reduce(into: 0, futures, on: el1, { $0 += $1 }).wait()\n}\n\ntry measureAndPrint(desc: \"el_in_eventloop_100M\") {\n    let el1 = group.next()\n\n    let inEL = try el1.submit {\n        var inEL = 0\n        for _ in 0..<100_000_000 {\n            inEL = inEL &+ (el1.inEventLoop ? 1 : 0)\n        }\n        return inEL\n    }.wait()\n    precondition(inEL == 100_000_000)\n    return inEL\n}\n\nmeasureAndPrint(desc: \"el_not_in_eventloop_100M\") {\n    let el1 = group.next()\n\n    var inEL = 0\n    for _ in 0..<100_000_000 {\n        inEL = inEL &+ (el1.inEventLoop ? 1 : 0)\n    }\n    precondition(inEL == 0)\n    return inEL\n}\n\ntry measureAndPrint(desc: \"channel_pipeline_1m_events\", benchmark: ChannelPipelineBenchmark(runCount: 1_000_000))\n\ntry measureAndPrint(\n    desc: \"channel_pipeline_init_no_handlers_1m\",\n    benchmark: ChannelPipelineInstantiationBenchmark(runCount: 1_000_000, handlerCount: 0)\n)\ntry measureAndPrint(\n    desc: \"channel_pipeline_init_1_handler_1m\",\n    benchmark: ChannelPipelineInstantiationBenchmark(runCount: 1_000_000, handlerCount: 1)\n)\ntry measureAndPrint(\n    desc: \"channel_pipeline_init_3_handlers_1m\",\n    benchmark: ChannelPipelineInstantiationBenchmark(runCount: 1_000_000, handlerCount: 3)\n)\ntry measureAndPrint(\n    desc: \"channel_pipeline_init_10_handlers_1m\",\n    benchmark: ChannelPipelineInstantiationBenchmark(runCount: 1_000_000, handlerCount: 10)\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_50b_space_at_front_100k_frames_cow\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 50,\n        runCount: 100_000,\n        dataStrategy: .spaceAtFront,\n        cowStrategy: .always,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_50b_space_at_front_1m_frames_cow_masking\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 50,\n        runCount: 1_000_000,\n        dataStrategy: .spaceAtFront,\n        cowStrategy: .always,\n        maskingKeyStrategy: .always\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_1kb_space_at_front_1m_frames_cow\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 1024,\n        runCount: 1_000_000,\n        dataStrategy: .spaceAtFront,\n        cowStrategy: .always,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_50b_no_space_at_front_100k_frames_cow\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 50,\n        runCount: 100_000,\n        dataStrategy: .noSpaceAtFront,\n        cowStrategy: .always,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_1kb_no_space_at_front_100k_frames_cow\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 1024,\n        runCount: 100_000,\n        dataStrategy: .noSpaceAtFront,\n        cowStrategy: .always,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_50b_space_at_front_100k_frames\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 50,\n        runCount: 100_000,\n        dataStrategy: .spaceAtFront,\n        cowStrategy: .never,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_50b_space_at_front_10k_frames_masking\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 50,\n        runCount: 10_000,\n        dataStrategy: .spaceAtFront,\n        cowStrategy: .never,\n        maskingKeyStrategy: .always\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_1kb_space_at_front_10k_frames\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 1024,\n        runCount: 10_000,\n        dataStrategy: .spaceAtFront,\n        cowStrategy: .never,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_50b_no_space_at_front_100k_frames\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 50,\n        runCount: 100_000,\n        dataStrategy: .noSpaceAtFront,\n        cowStrategy: .never,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_encode_1kb_no_space_at_front_10k_frames\",\n    benchmark: WebSocketFrameEncoderBenchmark(\n        dataSize: 1024,\n        runCount: 10_000,\n        dataStrategy: .noSpaceAtFront,\n        cowStrategy: .never,\n        maskingKeyStrategy: .never\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_decode_125b_10k_frames\",\n    benchmark: WebSocketFrameDecoderBenchmark(\n        dataSize: 125,\n        runCount: 10_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_decode_125b_with_a_masking_key_10k_frames\",\n    benchmark: WebSocketFrameDecoderBenchmark(\n        dataSize: 125,\n        runCount: 10_000,\n        maskingKey: [0x80, 0x08, 0x10, 0x01]\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_decode_64kb_10k_frames\",\n    benchmark: WebSocketFrameDecoderBenchmark(\n        dataSize: Int(UInt16.max),\n        runCount: 10_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_decode_64kb_with_a_masking_key_10k_frames\",\n    benchmark: WebSocketFrameDecoderBenchmark(\n        dataSize: Int(UInt16.max),\n        runCount: 10_000,\n        maskingKey: [0x80, 0x08, 0x10, 0x01]\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_decode_64kb_+1_10k_frames\",\n    benchmark: WebSocketFrameDecoderBenchmark(\n        dataSize: Int(UInt16.max) + 1,\n        runCount: 10_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"websocket_decode_64kb_+1_with_a_masking_key_10k_frames\",\n    benchmark: WebSocketFrameDecoderBenchmark(\n        dataSize: Int(UInt16.max) + 1,\n        runCount: 10_000,\n        maskingKey: [0x80, 0x08, 0x10, 0x01]\n    )\n)\n\ntry measureAndPrint(\n    desc: \"circular_buffer_into_byte_buffer_1kb\",\n    benchmark: CircularBufferIntoByteBufferBenchmark(\n        iterations: 10_000,\n        bufferSize: 1024\n    )\n)\n\ntry measureAndPrint(\n    desc: \"circular_buffer_into_byte_buffer_1mb\",\n    benchmark: CircularBufferIntoByteBufferBenchmark(\n        iterations: 20,\n        bufferSize: 1024 * 1024\n    )\n)\n\ntry measureAndPrint(\n    desc: \"byte_buffer_view_iterator_1mb\",\n    benchmark: ByteBufferViewIteratorBenchmark(\n        iterations: 20,\n        bufferSize: 1024 * 1024\n    )\n)\n\ntry measureAndPrint(\n    desc: \"byte_buffer_view_contains_12mb\",\n    benchmark: ByteBufferViewContainsBenchmark(\n        iterations: 5,\n        bufferSize: 12 * 1024 * 1024\n    )\n)\n\ntry measureAndPrint(\n    desc: \"byte_to_message_decoder_decode_many_small\",\n    benchmark: ByteToMessageDecoderDecodeManySmallsBenchmark(\n        iterations: 200,\n        bufferSize: 16384\n    )\n)\n\nmeasureAndPrint(desc: \"generate_10k_random_request_keys\") {\n    let numKeys = 10_000\n    return (0..<numKeys).reduce(\n        into: 0,\n        { result, _ in\n            result &+= NIOWebSocketClientUpgrader.randomRequestKey().count\n        }\n    )\n}\n\ntry measureAndPrint(\n    desc: \"bytebuffer_rw_10_uint32s\",\n    benchmark: ByteBufferReadWriteMultipleIntegersBenchmark<UInt32>(\n        iterations: 100_000,\n        numberOfInts: 10\n    )\n)\n\ntry measureAndPrint(\n    desc: \"bytebuffer_multi_rw_10_uint32s\",\n    benchmark: ByteBufferMultiReadWriteTenIntegersBenchmark<UInt32>(\n        iterations: 1_000_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"lock_1_thread_10M_ops\",\n    benchmark: NIOLockBenchmark(\n        numberOfThreads: 1,\n        lockOperationsPerThread: 10_000_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"lock_2_threads_10M_ops\",\n    benchmark: NIOLockBenchmark(\n        numberOfThreads: 2,\n        lockOperationsPerThread: 5_000_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"lock_4_threads_10M_ops\",\n    benchmark: NIOLockBenchmark(\n        numberOfThreads: 4,\n        lockOperationsPerThread: 2_500_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"lock_8_threads_10M_ops\",\n    benchmark: NIOLockBenchmark(\n        numberOfThreads: 8,\n        lockOperationsPerThread: 1_250_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"schedule_and_run_100k_tasks\",\n    benchmark: SchedulingAndRunningBenchmark(numTasks: 100_000)\n)\n\ntry measureAndPrint(\n    desc: \"execute_100k_tasks\",\n    benchmark: ExecuteBenchmark(numTasks: 100_000)\n)\n\ntry measureAndPrint(\n    desc: \"runIfActive_1_thread_100k_tasks\",\n    benchmark: RunIfActiveBenchmark(numThreads: 1, numTasks: 100_000)\n)\n\ntry measureAndPrint(\n    desc: \"runIfActive_8_threads_100k_tasks\",\n    benchmark: RunIfActiveBenchmark(numThreads: 8, numTasks: 100_000)\n)\n\ntry measureAndPrint(\n    desc: \"bytebufferview_copy_to_array_100k_times_1kb\",\n    benchmark: ByteBufferViewCopyToArrayBenchmark(\n        iterations: 100_000,\n        size: 1024\n    )\n)\n\ntry measureAndPrint(\n    desc: \"circularbuffer_copy_to_array_10k_times_1kb\",\n    benchmark: CircularBufferViewCopyToArrayBenchmark(\n        iterations: 10_000,\n        size: 1024\n    )\n)\n\ntry measureAndPrint(\n    desc: \"deadline_now_1M_times\",\n    benchmark: DeadlineNowBenchmark(\n        iterations: 1_000_000\n    )\n)\n\nif #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {\n    try measureAndPrint(\n        desc: \"asyncwriter_single_writes_1M_times\",\n        benchmark: NIOAsyncWriterSingleWritesBenchmark(\n            iterations: 1_000_000\n        )\n    )\n\n    try measureAndPrint(\n        desc: \"asyncsequenceproducer_consume_1M_times\",\n        benchmark: NIOAsyncSequenceProducerBenchmark(\n            iterations: 1_000_000\n        )\n    )\n}\n\ntry measureAndPrint(\n    desc: \"udp_10k_writes\",\n    benchmark: UDPBenchmark(\n        data: ByteBuffer(repeating: 42, count: 1000),\n        numberOfRequests: 10_000,\n        vectorReads: 1,\n        vectorWrites: 1\n    )\n)\n\ntry measureAndPrint(\n    desc: \"udp_10k_vector_writes\",\n    benchmark: UDPBenchmark(\n        data: ByteBuffer(repeating: 42, count: 1000),\n        numberOfRequests: 10_000,\n        vectorReads: 1,\n        vectorWrites: 10\n    )\n)\n\ntry measureAndPrint(\n    desc: \"udp_10k_vector_reads\",\n    benchmark: UDPBenchmark(\n        data: ByteBuffer(repeating: 42, count: 1000),\n        numberOfRequests: 10_000,\n        vectorReads: 10,\n        vectorWrites: 1\n    )\n)\n\ntry measureAndPrint(\n    desc: \"udp_10k_vector_reads_and_writes\",\n    benchmark: UDPBenchmark(\n        data: ByteBuffer(repeating: 42, count: 1000),\n        numberOfRequests: 10_000,\n        vectorReads: 10,\n        vectorWrites: 10\n    )\n)\n\nif #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) {\n    try measureAndPrint(\n        desc: \"tcp_100k_messages_throughput\",\n        benchmark: TCPThroughputBenchmark(messages: 100_000, messageSize: 500)\n    )\n}\n\ntry measureAndPrint(\n    desc: \"thread_pool_serial_wakeup_4_threads_10k\",\n    benchmark: NIOThreadPoolSerialWakeupBenchmark(\n        numberOfThreads: 4,\n        numberOfTasks: 10_000\n    )\n)\n\ntry measureAndPrint(\n    desc: \"thread_pool_serial_wakeup_16_threads_10k\",\n    benchmark: NIOThreadPoolSerialWakeupBenchmark(\n        numberOfThreads: 16,\n        numberOfTasks: 10_000\n    )\n)\n"
  },
  {
    "path": "Sources/NIOPerformanceTester/resources.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// generated using:\n//     curl -s https://swift.org/ | iconv -c -f utf-8 -t ascii | pbcopy\nlet htmlASCIIOnly: String = \"\"\"\n    <!DOCTYPE html>\n    <html lang=\"en\">\n\n    <head>\n    <meta charset=\"utf-8\" />\n    <title>Swift.org - Welcome to Swift.org</title>\n    <meta name=\"author\" content=\"Apple Inc.\" />\n    <meta name=\"viewport\" content=\"width=device-width initial-scale=1\" />\n    <link rel=\"license\" href=\"/LICENSE.txt\" />\n    <link rel=\"stylesheet\" media=\"all\" href=\"/assets/stylesheets/application.css\" />\n    <link rel=\"shortcut icon\" sizes=\"16x16 24x24 32x32 48x48 64x64\" type=\"image/vnd.microsoft.icon\" href=\"/favicon.ico\" />\n    <link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/apple-touch-icon-57x57.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"/apple-touch-icon-72x72.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/apple-touch-icon-76x76.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"/apple-touch-icon-114x114.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/apple-touch-icon-120x120.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"/apple-touch-icon-144x144.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/apple-touch-icon-152x152.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon-180x180.png\" />\n    <link rel=\"mask-icon\" href=\"/assets/images/icon-swift.svg\" color=\"#F05339\" />\n\n    <link rel=\"alternate\" type=\"application/atom+xml\" title=\"Swift.org (Atom Feed)\" href=\"/atom.xml\" />\n\n\n\n    <link rel=\"canonical\" href=\"https://swift.org/\" />\n\n\n    <meta name=\"twitter:card\" content=\"summary\" />\n    <meta name=\"twitter:site\" content=\"@SwiftLang\" />\n\n    <meta name=\"twitter:title\" content=\"Swift.org\" />\n    <meta name=\"twitter:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n\n    <meta property=\"og:site_name\" content=\"Swift.org\" />\n    <meta property=\"og:image\" content=\"https://swift.org/touch-icon-ipad-180x180.png\" />\n\n    <meta property=\"og:title\" content=\"Swift.org\" />\n    <meta property=\"og:url\" content=\"https://swift.org\" />\n    <meta property=\"og:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n    </head>\n\n    <body>\n\n    <nav role=\"navigation\">\n    <header role=\"banner\">\n    <h1 id=\"logo\">\n    <a href=\"/\" title=\"Swift.org\" role=\"img\" aria-label=\"Swift.org\">\n    Swift.org\n    </a>\n    </h1>\n    </header>\n\n    <div id=\"menu-toggle\" class=\"menu-toggle open\"></div>\n\n    <ul>\n\n\n    <li>\n\n    <a href=\"/about/\">About Swift</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/blog/\">Blog</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/download/\">Download</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/getting-started/\">Getting Started</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/documentation/\">Documentation</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/migration-guide-swift4/\">Migrating to Swift 4</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-code/\">Source Code</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/community/\">Community</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/contributing/\">Contributing</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/continuous-integration/\">Continuous Integration</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-compatibility/\">Source Compatibility</a>\n\n    </li>\n    </ul>\n\n\n    <h2>Focus Areas</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/abi-stability/\">ABI Stability</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/server-apis/\">Server APIs <small><small><small><i>(Work Group)</i></small></small></small></a>\n    </li>\n    </ul>\n\n    <h2>Projects</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/compiler-stdlib/\">Compiler and Standard Library</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/package-manager/\">Package Manager</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/core-libraries/\">Core Libraries</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/lldb/\">REPL, Debugger &amp; Playgrounds</a>\n\n    </li>\n\n    </ul>\n    </nav>\n\n\n    <main role=\"main\">\n    <h1 id=\"welcome-to-swiftorg\">Welcome to Swift.org</h1>\n\n    <p>Welcome to the Swift community. Together we are working to build a programming language to empower everyone to turn their ideas into apps on any platform.</p>\n\n    <p>Announced in 2014, the Swift programming language has quickly become one of the fastest growing languages in history. Swift makes it easy to write software that is incredibly fast and safe by design. Our goals for Swift are ambitious: we want to make programming simple things easy, and difficult things possible.</p>\n\n    <p>For students, learning Swift has been a great introduction to modern programming concepts and best practices. And because it is open, their Swift skills will be able to be applied to an even broader range of platforms, from mobile devices to the desktop to the cloud.</p>\n\n    </main>\n\n    <footer role=\"contentinfo\">\n    <aside>\n    <a href=\"/atom.xml\" title=\"Subscribe to Site Updates\"><i class=\"feed\"></i></a>\n    <a href=\"https://twitter.com/swiftlang\" rel=\"nofollow\" title=\"Follow @SwiftLang on Twitter\"><i class=\"twitter\"></i></a>\n    </aside>\n\n    <p class=\"copyright\">Copyright  2018 Apple Inc. All rights reserved.</p>\n    <p class=\"trademark\">Swift and the Swift logo are trademarks of Apple Inc.</p>\n    <p class=\"privacy\">\n    <a href=\"//www.apple.com/privacy/privacy-policy/\">Privacy Policy</a>\n    <a href=\"//www.apple.com/legal/privacy/en-ww/cookies/\">Cookies</a>\n    </p>\n    </footer>\n\n\n    <script type=\"text/javascript\">\n    var s_account=\"dappswiftorg\";\n    </script>\n    <script type=\"text/javascript\" src=\"/assets/javascripts/vendor/s_code_h.js\"></script>\n    <script src=\"/assets/javascripts/application.js\"></script>\n    <script type=\"text/javascript\">\n    s.pageName=AC.Tracking.pageName();\n    var s_code=s.t();if(s_code)document.write(s_code);\n    </script>\n    </body>\n    </html>\n    \"\"\"\n\n// generated using:\n//     curl -s https://swift.org/ | pbcopy\nlet htmlMostlyASCII: String = \"\"\"\n    <!DOCTYPE html>\n    <html lang=\"en\">\n\n    <head>\n    <meta charset=\"utf-8\" />\n    <title>Swift.org - Welcome to Swift.org</title>\n    <meta name=\"author\" content=\"Apple Inc.\" />\n    <meta name=\"viewport\" content=\"width=device-width initial-scale=1\" />\n    <link rel=\"license\" href=\"/LICENSE.txt\" />\n    <link rel=\"stylesheet\" media=\"all\" href=\"/assets/stylesheets/application.css\" />\n    <link rel=\"shortcut icon\" sizes=\"16x16 24x24 32x32 48x48 64x64\" type=\"image/vnd.microsoft.icon\" href=\"/favicon.ico\" />\n    <link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/apple-touch-icon-57x57.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"/apple-touch-icon-72x72.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/apple-touch-icon-76x76.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"/apple-touch-icon-114x114.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/apple-touch-icon-120x120.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"/apple-touch-icon-144x144.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/apple-touch-icon-152x152.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon-180x180.png\" />\n    <link rel=\"mask-icon\" href=\"/assets/images/icon-swift.svg\" color=\"#F05339\" />\n\n    <link rel=\"alternate\" type=\"application/atom+xml\" title=\"Swift.org (Atom Feed)\" href=\"/atom.xml\" />\n\n\n\n    <link rel=\"canonical\" href=\"https://swift.org/\" />\n\n\n    <meta name=\"twitter:card\" content=\"summary\" />\n    <meta name=\"twitter:site\" content=\"@SwiftLang\" />\n\n    <meta name=\"twitter:title\" content=\"Swift.org\" />\n    <meta name=\"twitter:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n\n    <meta property=\"og:site_name\" content=\"Swift.org\" />\n    <meta property=\"og:image\" content=\"https://swift.org/touch-icon-ipad-180x180.png\" />\n\n    <meta property=\"og:title\" content=\"Swift.org\" />\n    <meta property=\"og:url\" content=\"https://swift.org\" />\n    <meta property=\"og:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n    </head>\n\n    <body>\n\n    <nav role=\"navigation\">\n    <header role=\"banner\">\n    <h1 id=\"logo\">\n    <a href=\"/\" title=\"Swift.org\" role=\"img\" aria-label=\"Swift.org\">\n    Swift.org\n    </a>\n    </h1>\n    </header>\n\n    <div id=\"menu-toggle\" class=\"menu-toggle open\"></div>\n\n    <ul>\n\n\n    <li>\n\n    <a href=\"/about/\">About Swift</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/blog/\">Blog</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/download/\">Download</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/getting-started/\">Getting Started</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/documentation/\">Documentation</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/migration-guide-swift4/\">Migrating to Swift 4</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-code/\">Source Code</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/community/\">Community</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/contributing/\">Contributing</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/continuous-integration/\">Continuous Integration</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-compatibility/\">Source Compatibility</a>\n\n    </li>\n    </ul>\n\n\n    <h2>Focus Areas</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/abi-stability/\">ABI Stability</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/server-apis/\">Server APIs <small><small><small><i>(Work Group)</i></small></small></small></a>\n    </li>\n    </ul>\n\n    <h2>Projects</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/compiler-stdlib/\">Compiler and Standard Library</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/package-manager/\">Package Manager</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/core-libraries/\">Core Libraries</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/lldb/\">REPL, Debugger &amp; Playgrounds</a>\n\n    </li>\n\n    </ul>\n    </nav>\n\n\n    <main role=\"main\">\n    <h1 id=\"welcome-to-swiftorg\">Welcome to Swift.org</h1>\n\n    <p>Welcome to the Swift community. Together we are working to build a programming language to empower everyone to turn their ideas into apps on any platform.</p>\n\n    <p>Announced in 2014, the Swift programming language has quickly become one of the fastest growing languages in history. Swift makes it easy to write software that is incredibly fast and safe by design. Our goals for Swift are ambitious: we want to make programming simple things easy, and difficult things possible.</p>\n\n    <p>For students, learning Swift has been a great introduction to modern programming concepts and best practices. And because it is open, their Swift skills will be able to be applied to an even broader range of platforms, from mobile devices to the desktop to the cloud.</p>\n\n    </main>\n\n    <footer role=\"contentinfo\">\n    <aside>\n    <a href=\"/atom.xml\" title=\"Subscribe to Site Updates\"><i class=\"feed\"></i></a>\n    <a href=\"https://twitter.com/swiftlang\" rel=\"nofollow\" title=\"Follow @SwiftLang on Twitter\"><i class=\"twitter\"></i></a>\n    </aside>\n\n    <p class=\"copyright\">Copyright © 2018 Apple Inc. All rights reserved.</p>\n    <p class=\"trademark\">Swift and the Swift logo are trademarks of Apple Inc.</p>\n    <p class=\"privacy\">\n    <a href=\"//www.apple.com/privacy/privacy-policy/\">Privacy Policy</a>\n    <a href=\"//www.apple.com/legal/privacy/en-ww/cookies/\">Cookies</a>\n    </p>\n    </footer>\n\n\n    <script type=\"text/javascript\">\n    var s_account=\"dappswiftorg\";\n    </script>\n    <script type=\"text/javascript\" src=\"/assets/javascripts/vendor/s_code_h.js\"></script>\n    <script src=\"/assets/javascripts/application.js\"></script>\n    <script type=\"text/javascript\">\n    s.pageName=AC.Tracking.pageName();\n    var s_code=s.t();if(s_code)document.write(s_code);\n    </script>\n    </body>\n    </html>\n    \"\"\"\n\n// generated using:\n//     curl -s https://swift.org/ | iconv -c -f utf-8 -t ascii | pbcopy\nlet htmlASCIIOnlyStaticString: StaticString = \"\"\"\n    <!DOCTYPE html>\n    <html lang=\"en\">\n\n    <head>\n    <meta charset=\"utf-8\" />\n    <title>Swift.org - Welcome to Swift.org</title>\n    <meta name=\"author\" content=\"Apple Inc.\" />\n    <meta name=\"viewport\" content=\"width=device-width initial-scale=1\" />\n    <link rel=\"license\" href=\"/LICENSE.txt\" />\n    <link rel=\"stylesheet\" media=\"all\" href=\"/assets/stylesheets/application.css\" />\n    <link rel=\"shortcut icon\" sizes=\"16x16 24x24 32x32 48x48 64x64\" type=\"image/vnd.microsoft.icon\" href=\"/favicon.ico\" />\n    <link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/apple-touch-icon-57x57.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"/apple-touch-icon-72x72.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/apple-touch-icon-76x76.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"/apple-touch-icon-114x114.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/apple-touch-icon-120x120.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"/apple-touch-icon-144x144.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/apple-touch-icon-152x152.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon-180x180.png\" />\n    <link rel=\"mask-icon\" href=\"/assets/images/icon-swift.svg\" color=\"#F05339\" />\n\n    <link rel=\"alternate\" type=\"application/atom+xml\" title=\"Swift.org (Atom Feed)\" href=\"/atom.xml\" />\n\n\n\n    <link rel=\"canonical\" href=\"https://swift.org/\" />\n\n\n    <meta name=\"twitter:card\" content=\"summary\" />\n    <meta name=\"twitter:site\" content=\"@SwiftLang\" />\n\n    <meta name=\"twitter:title\" content=\"Swift.org\" />\n    <meta name=\"twitter:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n\n    <meta property=\"og:site_name\" content=\"Swift.org\" />\n    <meta property=\"og:image\" content=\"https://swift.org/touch-icon-ipad-180x180.png\" />\n\n    <meta property=\"og:title\" content=\"Swift.org\" />\n    <meta property=\"og:url\" content=\"https://swift.org\" />\n    <meta property=\"og:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n    </head>\n\n    <body>\n\n    <nav role=\"navigation\">\n    <header role=\"banner\">\n    <h1 id=\"logo\">\n    <a href=\"/\" title=\"Swift.org\" role=\"img\" aria-label=\"Swift.org\">\n    Swift.org\n    </a>\n    </h1>\n    </header>\n\n    <div id=\"menu-toggle\" class=\"menu-toggle open\"></div>\n\n    <ul>\n\n\n    <li>\n\n    <a href=\"/about/\">About Swift</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/blog/\">Blog</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/download/\">Download</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/getting-started/\">Getting Started</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/documentation/\">Documentation</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/migration-guide-swift4/\">Migrating to Swift 4</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-code/\">Source Code</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/community/\">Community</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/contributing/\">Contributing</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/continuous-integration/\">Continuous Integration</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-compatibility/\">Source Compatibility</a>\n\n    </li>\n    </ul>\n\n\n    <h2>Focus Areas</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/abi-stability/\">ABI Stability</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/server-apis/\">Server APIs <small><small><small><i>(Work Group)</i></small></small></small></a>\n    </li>\n    </ul>\n\n    <h2>Projects</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/compiler-stdlib/\">Compiler and Standard Library</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/package-manager/\">Package Manager</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/core-libraries/\">Core Libraries</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/lldb/\">REPL, Debugger &amp; Playgrounds</a>\n\n    </li>\n\n    </ul>\n    </nav>\n\n\n    <main role=\"main\">\n    <h1 id=\"welcome-to-swiftorg\">Welcome to Swift.org</h1>\n\n    <p>Welcome to the Swift community. Together we are working to build a programming language to empower everyone to turn their ideas into apps on any platform.</p>\n\n    <p>Announced in 2014, the Swift programming language has quickly become one of the fastest growing languages in history. Swift makes it easy to write software that is incredibly fast and safe by design. Our goals for Swift are ambitious: we want to make programming simple things easy, and difficult things possible.</p>\n\n    <p>For students, learning Swift has been a great introduction to modern programming concepts and best practices. And because it is open, their Swift skills will be able to be applied to an even broader range of platforms, from mobile devices to the desktop to the cloud.</p>\n\n    </main>\n\n    <footer role=\"contentinfo\">\n    <aside>\n    <a href=\"/atom.xml\" title=\"Subscribe to Site Updates\"><i class=\"feed\"></i></a>\n    <a href=\"https://twitter.com/swiftlang\" rel=\"nofollow\" title=\"Follow @SwiftLang on Twitter\"><i class=\"twitter\"></i></a>\n    </aside>\n\n    <p class=\"copyright\">Copyright  2018 Apple Inc. All rights reserved.</p>\n    <p class=\"trademark\">Swift and the Swift logo are trademarks of Apple Inc.</p>\n    <p class=\"privacy\">\n    <a href=\"//www.apple.com/privacy/privacy-policy/\">Privacy Policy</a>\n    <a href=\"//www.apple.com/legal/privacy/en-ww/cookies/\">Cookies</a>\n    </p>\n    </footer>\n\n\n    <script type=\"text/javascript\">\n    var s_account=\"dappswiftorg\";\n    </script>\n    <script type=\"text/javascript\" src=\"/assets/javascripts/vendor/s_code_h.js\"></script>\n    <script src=\"/assets/javascripts/application.js\"></script>\n    <script type=\"text/javascript\">\n    s.pageName=AC.Tracking.pageName();\n    var s_code=s.t();if(s_code)document.write(s_code);\n    </script>\n    </body>\n    </html>\n    \"\"\"\n\n// generated using:\n//     curl -s https://swift.org/ | pbcopy\nlet htmlMostlyASCIIStaticString: StaticString = \"\"\"\n    <!DOCTYPE html>\n    <html lang=\"en\">\n\n    <head>\n    <meta charset=\"utf-8\" />\n    <title>Swift.org - Welcome to Swift.org</title>\n    <meta name=\"author\" content=\"Apple Inc.\" />\n    <meta name=\"viewport\" content=\"width=device-width initial-scale=1\" />\n    <link rel=\"license\" href=\"/LICENSE.txt\" />\n    <link rel=\"stylesheet\" media=\"all\" href=\"/assets/stylesheets/application.css\" />\n    <link rel=\"shortcut icon\" sizes=\"16x16 24x24 32x32 48x48 64x64\" type=\"image/vnd.microsoft.icon\" href=\"/favicon.ico\" />\n    <link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/apple-touch-icon-57x57.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"/apple-touch-icon-72x72.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/apple-touch-icon-76x76.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"/apple-touch-icon-114x114.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/apple-touch-icon-120x120.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"/apple-touch-icon-144x144.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/apple-touch-icon-152x152.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon-180x180.png\" />\n    <link rel=\"mask-icon\" href=\"/assets/images/icon-swift.svg\" color=\"#F05339\" />\n\n    <link rel=\"alternate\" type=\"application/atom+xml\" title=\"Swift.org (Atom Feed)\" href=\"/atom.xml\" />\n\n\n\n    <link rel=\"canonical\" href=\"https://swift.org/\" />\n\n\n    <meta name=\"twitter:card\" content=\"summary\" />\n    <meta name=\"twitter:site\" content=\"@SwiftLang\" />\n\n    <meta name=\"twitter:title\" content=\"Swift.org\" />\n    <meta name=\"twitter:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n\n    <meta property=\"og:site_name\" content=\"Swift.org\" />\n    <meta property=\"og:image\" content=\"https://swift.org/touch-icon-ipad-180x180.png\" />\n\n    <meta property=\"og:title\" content=\"Swift.org\" />\n    <meta property=\"og:url\" content=\"https://swift.org\" />\n    <meta property=\"og:description\" content=\"Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.\" />\n\n    </head>\n\n    <body>\n\n    <nav role=\"navigation\">\n    <header role=\"banner\">\n    <h1 id=\"logo\">\n    <a href=\"/\" title=\"Swift.org\" role=\"img\" aria-label=\"Swift.org\">\n    Swift.org\n    </a>\n    </h1>\n    </header>\n\n    <div id=\"menu-toggle\" class=\"menu-toggle open\"></div>\n\n    <ul>\n\n\n    <li>\n\n    <a href=\"/about/\">About Swift</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/blog/\">Blog</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/download/\">Download</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/getting-started/\">Getting Started</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/documentation/\">Documentation</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/migration-guide-swift4/\">Migrating to Swift 4</a>\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-code/\">Source Code</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/community/\">Community</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/contributing/\">Contributing</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/continuous-integration/\">Continuous Integration</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/source-compatibility/\">Source Compatibility</a>\n\n    </li>\n    </ul>\n\n\n    <h2>Focus Areas</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/abi-stability/\">ABI Stability</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/server-apis/\">Server APIs <small><small><small><i>(Work Group)</i></small></small></small></a>\n    </li>\n    </ul>\n\n    <h2>Projects</h2>\n    <ul>\n\n\n    <li>\n\n    <a href=\"/compiler-stdlib/\">Compiler and Standard Library</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/package-manager/\">Package Manager</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/core-libraries/\">Core Libraries</a>\n\n    </li>\n\n\n\n    <li>\n\n    <a href=\"/lldb/\">REPL, Debugger &amp; Playgrounds</a>\n\n    </li>\n\n    </ul>\n    </nav>\n\n\n    <main role=\"main\">\n    <h1 id=\"welcome-to-swiftorg\">Welcome to Swift.org</h1>\n\n    <p>Welcome to the Swift community. Together we are working to build a programming language to empower everyone to turn their ideas into apps on any platform.</p>\n\n    <p>Announced in 2014, the Swift programming language has quickly become one of the fastest growing languages in history. Swift makes it easy to write software that is incredibly fast and safe by design. Our goals for Swift are ambitious: we want to make programming simple things easy, and difficult things possible.</p>\n\n    <p>For students, learning Swift has been a great introduction to modern programming concepts and best practices. And because it is open, their Swift skills will be able to be applied to an even broader range of platforms, from mobile devices to the desktop to the cloud.</p>\n\n    </main>\n\n    <footer role=\"contentinfo\">\n    <aside>\n    <a href=\"/atom.xml\" title=\"Subscribe to Site Updates\"><i class=\"feed\"></i></a>\n    <a href=\"https://twitter.com/swiftlang\" rel=\"nofollow\" title=\"Follow @SwiftLang on Twitter\"><i class=\"twitter\"></i></a>\n    </aside>\n\n    <p class=\"copyright\">Copyright © 2018 Apple Inc. All rights reserved.</p>\n    <p class=\"trademark\">Swift and the Swift logo are trademarks of Apple Inc.</p>\n    <p class=\"privacy\">\n    <a href=\"//www.apple.com/privacy/privacy-policy/\">Privacy Policy</a>\n    <a href=\"//www.apple.com/legal/privacy/en-ww/cookies/\">Cookies</a>\n    </p>\n    </footer>\n\n\n    <script type=\"text/javascript\">\n    var s_account=\"dappswiftorg\";\n    </script>\n    <script type=\"text/javascript\" src=\"/assets/javascripts/vendor/s_code_h.js\"></script>\n    <script src=\"/assets/javascripts/application.js\"></script>\n    <script type=\"text/javascript\">\n    s.pageName=AC.Tracking.pageName();\n    var s_code=s.t();if(s_code)document.write(s_code);\n    </script>\n    </body>\n    </html>\n    \"\"\"\n"
  },
  {
    "path": "Sources/NIOPosix/BSDSocketAPICommon.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if os(Windows)\nimport ucrt\n\nimport let WinSDK.INVALID_SOCKET\n\nimport let WinSDK.IP_RECVTOS\nimport let WinSDK.IPV6_RECVTCLASS\n\nimport let WinSDK.SOCK_DGRAM\nimport let WinSDK.SOCK_STREAM\nimport let WinSDK.SOCK_RAW\n\nimport struct WinSDK.socklen_t\n#endif\n\nprotocol _SocketShutdownProtocol {\n    var cValue: CInt { get }\n}\n\n@usableFromInline\ninternal enum Shutdown: _SocketShutdownProtocol, Sendable {\n    case RD\n    case WR\n    case RDWR\n}\n\nextension NIOBSDSocket {\n    #if os(Windows)\n    public static let invalidHandle: Handle = INVALID_SOCKET\n    #else\n    public static let invalidHandle: Handle = -1\n    #endif\n}\n\nextension NIOBSDSocket {\n    /// Specifies the type of socket.\n    @usableFromInline\n    internal struct SocketType: RawRepresentable, Sendable {\n        public typealias RawValue = CInt\n        public var rawValue: RawValue\n        public init(rawValue: RawValue) {\n            self.rawValue = rawValue\n        }\n    }\n}\n\nextension NIOBSDSocket.SocketType: Equatable {\n}\n\nextension NIOBSDSocket.SocketType: Hashable {\n}\n\n// Socket Types\nextension NIOBSDSocket.SocketType {\n    /// Supports datagrams, which are connectionless, unreliable messages of a\n    /// fixed (typically small) maximum length.\n    #if os(Linux) && !canImport(Musl)\n    internal static let datagram: NIOBSDSocket.SocketType =\n        NIOBSDSocket.SocketType(rawValue: CInt(SOCK_DGRAM.rawValue))\n    #else\n    internal static let datagram: NIOBSDSocket.SocketType =\n        NIOBSDSocket.SocketType(rawValue: SOCK_DGRAM)\n    #endif\n\n    /// Supports reliable, two-way, connection-based byte streams without\n    /// duplication of data and without preservation of boundaries.\n    #if os(Linux) && !canImport(Musl)\n    internal static let stream: NIOBSDSocket.SocketType =\n        NIOBSDSocket.SocketType(rawValue: CInt(SOCK_STREAM.rawValue))\n    #else\n    internal static let stream: NIOBSDSocket.SocketType =\n        NIOBSDSocket.SocketType(rawValue: SOCK_STREAM)\n    #endif\n\n    #if os(Linux) && !canImport(Musl)\n    internal static let raw: NIOBSDSocket.SocketType =\n        NIOBSDSocket.SocketType(rawValue: CInt(SOCK_RAW.rawValue))\n    #else\n    internal static let raw: NIOBSDSocket.SocketType =\n        NIOBSDSocket.SocketType(rawValue: SOCK_RAW)\n    #endif\n}\n\n// IPv4 Options\n#if !os(OpenBSD)\nextension NIOBSDSocket.Option {\n    /// Request that we are passed type of service details when receiving\n    /// datagrams.\n    ///\n    /// Not public as the way to request this is to use\n    /// `ChannelOptions.explicitCongestionNotification` which works for both\n    /// IPv4 and IPv6.\n    static let ip_recv_tos: NIOBSDSocket.Option =\n        NIOBSDSocket.Option(rawValue: IP_RECVTOS)\n\n    /// Request that we are passed destination address and the receiving interface index when\n    /// receiving datagrams.\n    ///\n    /// This option is not public as the way to request this is to use\n    /// `ChannelOptions.receivePacketInfo` which works for both\n    /// IPv4 and IPv6.\n    static let ip_recv_pktinfo: NIOBSDSocket.Option =\n        NIOBSDSocket.Option(rawValue: Posix.IP_RECVPKTINFO)\n}\n#endif\n\n// IPv6 Options\nextension NIOBSDSocket.Option {\n    /// Request that we are passed traffic class details when receiving\n    /// datagrams.\n    ///\n    /// Not public as the way to request this is to use\n    /// `ChannelOptions.explicitCongestionNotification` which works for both\n    /// IPv4 and IPv6.\n    static let ipv6_recv_tclass: NIOBSDSocket.Option =\n        NIOBSDSocket.Option(rawValue: IPV6_RECVTCLASS)\n\n    #if !os(OpenBSD)\n    /// Request that we are passed destination address and the receiving interface index when\n    /// receiving datagrams.\n    ///\n    /// This option is not public as the way to request this is to use\n    /// `ChannelOptions.receivePacketInfo` which works for both\n    /// IPv4 and IPv6.\n    static let ipv6_recv_pktinfo: NIOBSDSocket.Option =\n        NIOBSDSocket.Option(rawValue: Posix.IPV6_RECVPKTINFO)\n    #endif\n}\n\nextension NIOBSDSocket {\n    /// Defines a protocol subtype.\n    ///\n    /// Protocol subtypes are the third argument passed to the `socket` system call.\n    /// They aren't necessarily protocols in their own right: for example, ``mptcp``\n    /// is not. They act to modify the socket type instead: thus, ``mptcp`` acts\n    /// to modify `SOCK_STREAM` to ask for ``mptcp`` support.\n    public struct ProtocolSubtype: RawRepresentable, Hashable, Sendable {\n        public typealias RawValue = CInt\n\n        /// The underlying value of the protocol subtype.\n        public var rawValue: RawValue\n\n        /// Construct a protocol subtype from its underlying value.\n        @inlinable\n        public init(rawValue: RawValue) {\n            self.rawValue = rawValue\n        }\n    }\n}\n\nextension NIOBSDSocket.ProtocolSubtype {\n    /// Refers to the \"default\" protocol subtype for a given socket type.\n    public static var `default`: NIOBSDSocket.ProtocolSubtype {\n        Self(rawValue: 0)\n    }\n\n    /// The protocol subtype for MPTCP.\n    ///\n    /// - Returns: nil if MPTCP is not supported.\n    @inlinable\n    public static var mptcp: Self? {\n        #if os(Linux)\n        // Defined by the linux kernel, this is IPPROTO_MPTCP.\n        return .init(rawValue: 262)\n        #else\n        return nil\n        #endif\n    }\n}\n\nextension NIOBSDSocket.ProtocolSubtype {\n    /// Construct a protocol subtype from an IP protocol.\n    @inlinable\n    public init(_ protocol: NIOIPProtocol) {\n        self.rawValue = CInt(`protocol`.rawValue)\n    }\n}\n\n/// This protocol defines the methods that are expected to be found on\n/// `NIOBSDSocket`. While defined as a protocol there is no expectation that any\n/// object other than `NIOBSDSocket` will implement this protocol: instead, this\n/// protocol acts as a reference for what new supported operating systems must\n/// implement.\nprotocol _BSDSocketProtocol {\n    static func accept(\n        socket s: NIOBSDSocket.Handle,\n        address addr: UnsafeMutablePointer<sockaddr>?,\n        address_len addrlen: UnsafeMutablePointer<socklen_t>?\n    ) throws -> NIOBSDSocket.Handle?\n\n    static func bind(\n        socket s: NIOBSDSocket.Handle,\n        address addr: UnsafePointer<sockaddr>,\n        address_len namelen: socklen_t\n    ) throws\n\n    static func close(socket s: NIOBSDSocket.Handle) throws\n\n    static func connect(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafePointer<sockaddr>,\n        address_len namelen: socklen_t\n    ) throws -> Bool\n\n    static func getpeername(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafeMutablePointer<sockaddr>,\n        address_len namelen: UnsafeMutablePointer<socklen_t>\n    ) throws\n\n    static func getsockname(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafeMutablePointer<sockaddr>,\n        address_len namelen: UnsafeMutablePointer<socklen_t>\n    ) throws\n\n    static func getsockopt(\n        socket: NIOBSDSocket.Handle,\n        level: NIOBSDSocket.OptionLevel,\n        option_name optname: NIOBSDSocket.Option,\n        option_value optval: UnsafeMutableRawPointer,\n        option_len optlen: UnsafeMutablePointer<socklen_t>\n    ) throws\n\n    static func listen(socket s: NIOBSDSocket.Handle, backlog: CInt) throws\n\n    static func recv(\n        socket s: NIOBSDSocket.Handle,\n        buffer buf: UnsafeMutableRawPointer,\n        length len: size_t\n    ) throws -> IOResult<size_t>\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    static func recvmsg(\n        socket: NIOBSDSocket.Handle,\n        msgHdr: UnsafeMutablePointer<msghdr>,\n        flags: CInt\n    )\n        throws -> IOResult<size_t>\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    static func sendmsg(\n        socket: NIOBSDSocket.Handle,\n        msgHdr: UnsafePointer<msghdr>,\n        flags: CInt\n    )\n        throws -> IOResult<size_t>\n\n    static func send(\n        socket s: NIOBSDSocket.Handle,\n        buffer buf: UnsafeRawPointer,\n        length len: size_t\n    ) throws -> IOResult<size_t>\n\n    static func setsockopt(\n        socket: NIOBSDSocket.Handle,\n        level: NIOBSDSocket.OptionLevel,\n        option_name optname: NIOBSDSocket.Option,\n        option_value optval: UnsafeRawPointer,\n        option_len optlen: socklen_t\n    ) throws\n\n    static func shutdown(socket: NIOBSDSocket.Handle, how: Shutdown) throws\n\n    static func socket(\n        domain af: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype\n    ) throws -> NIOBSDSocket.Handle\n\n    static func recvmmsg(\n        socket: NIOBSDSocket.Handle,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt,\n        timeout: UnsafeMutablePointer<timespec>?\n    ) throws -> IOResult<Int>\n\n    static func sendmmsg(\n        socket: NIOBSDSocket.Handle,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt\n    ) throws -> IOResult<Int>\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    static func pread(\n        socket: NIOBSDSocket.Handle,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<size_t>\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    static func pwrite(\n        socket: NIOBSDSocket.Handle,\n        pointer: UnsafeRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<size_t>\n\n    #if !os(Windows)\n    // NOTE: We do not support this on Windows as WSAPoll behaves differently\n    // from poll with reporting of failed connections (Connect Report 309411),\n    // which recommended that you use NetAPI instead.\n    //\n    // This is safe to exclude as this is a testing-only API.\n    static func poll(\n        fds: UnsafeMutablePointer<pollfd>,\n        nfds: nfds_t,\n        timeout: CInt\n    ) throws -> CInt\n    #endif\n\n    static func sendfile(\n        socket s: NIOBSDSocket.Handle,\n        fd: CInt,\n        offset: off_t,\n        len: off_t\n    ) throws -> IOResult<Int>\n\n    // MARK: non-BSD APIs added by NIO\n\n    static func setNonBlocking(socket: NIOBSDSocket.Handle) throws\n\n    static func cleanupUnixDomainSocket(atPath path: String) throws\n}\n\n/// If this extension is hitting a compile error, your platform is missing one\n/// of the functions defined above!\nextension NIOBSDSocket: _BSDSocketProtocol {}\n\n/// This protocol defines the methods that are expected to be found on\n/// `NIOBSDControlMessage`. While defined as a protocol there is no expectation\n/// that any object other than `NIOBSDControlMessage` will implement this\n/// protocol: instead, this protocol acts as a reference for what new supported\n/// operating systems must implement.\nprotocol _BSDSocketControlMessageProtocol {\n    static func firstHeader(\n        inside msghdr: UnsafePointer<msghdr>\n    )\n        -> UnsafeMutablePointer<cmsghdr>?\n\n    static func nextHeader(\n        inside msghdr: UnsafeMutablePointer<msghdr>,\n        after: UnsafeMutablePointer<cmsghdr>\n    )\n        -> UnsafeMutablePointer<cmsghdr>?\n\n    static func data(\n        for header: UnsafePointer<cmsghdr>\n    )\n        -> UnsafeRawBufferPointer?\n\n    static func data(\n        for header: UnsafeMutablePointer<cmsghdr>\n    )\n        -> UnsafeMutableRawBufferPointer?\n\n    static func length(payloadSize: size_t) -> size_t\n\n    static func space(payloadSize: size_t) -> size_t\n}\n\n/// If this extension is hitting a compile error, your platform is missing one\n/// of the functions defined above!\nenum NIOBSDSocketControlMessage: _BSDSocketControlMessageProtocol {}\n\n/// The requested UDS path exists and has wrong type (not a socket).\npublic struct UnixDomainSocketPathWrongType: Error {}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/BSDSocketAPIPosix.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if os(Linux) || os(Android) || os(FreeBSD) || canImport(Darwin) || os(OpenBSD)\n\nextension Shutdown {\n    internal var cValue: CInt {\n        switch self {\n        case .RD:\n            return CInt(Posix.SHUT_RD)\n        case .WR:\n            return CInt(Posix.SHUT_WR)\n        case .RDWR:\n            return CInt(Posix.SHUT_RDWR)\n        }\n    }\n}\n\n// MARK: Implementation of _BSDSocketProtocol for POSIX systems\nextension NIOBSDSocket {\n    static func accept(\n        socket s: NIOBSDSocket.Handle,\n        address addr: UnsafeMutablePointer<sockaddr>?,\n        address_len addrlen: UnsafeMutablePointer<socklen_t>?\n    ) throws -> NIOBSDSocket.Handle? {\n        try Posix.accept(descriptor: s, addr: addr, len: addrlen)\n    }\n\n    static func bind(\n        socket s: NIOBSDSocket.Handle,\n        address addr: UnsafePointer<sockaddr>,\n        address_len namelen: socklen_t\n    ) throws {\n        try Posix.bind(descriptor: s, ptr: addr, bytes: Int(namelen))\n    }\n\n    static func close(socket s: NIOBSDSocket.Handle) throws {\n        try Posix.close(descriptor: s)\n    }\n\n    static func connect(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafePointer<sockaddr>,\n        address_len namelen: socklen_t\n    ) throws -> Bool {\n        try Posix.connect(descriptor: s, addr: name, size: namelen)\n    }\n\n    static func getpeername(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafeMutablePointer<sockaddr>,\n        address_len namelen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        try Posix.getpeername(socket: s, address: name, addressLength: namelen)\n    }\n\n    static func getsockname(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafeMutablePointer<sockaddr>,\n        address_len namelen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        try Posix.getsockname(socket: s, address: name, addressLength: namelen)\n    }\n\n    static func getsockopt(\n        socket: NIOBSDSocket.Handle,\n        level: NIOBSDSocket.OptionLevel,\n        option_name optname: NIOBSDSocket.Option,\n        option_value optval: UnsafeMutableRawPointer,\n        option_len optlen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        try Posix.getsockopt(\n            socket: socket,\n            level: level.rawValue,\n            optionName: optname.rawValue,\n            optionValue: optval,\n            optionLen: optlen\n        )\n    }\n\n    static func listen(socket s: NIOBSDSocket.Handle, backlog: CInt) throws {\n        try Posix.listen(descriptor: s, backlog: backlog)\n    }\n\n    static func recv(\n        socket s: NIOBSDSocket.Handle,\n        buffer buf: UnsafeMutableRawPointer,\n        length len: size_t\n    ) throws -> IOResult<size_t> {\n        try Posix.read(descriptor: s, pointer: buf, size: len)\n    }\n\n    static func recvmsg(\n        socket: NIOBSDSocket.Handle,\n        msgHdr: UnsafeMutablePointer<msghdr>,\n        flags: CInt\n    )\n        throws -> IOResult<size_t>\n    {\n        try Posix.recvmsg(descriptor: socket, msgHdr: msgHdr, flags: flags)\n    }\n\n    static func sendmsg(\n        socket: NIOBSDSocket.Handle,\n        msgHdr: UnsafePointer<msghdr>,\n        flags: CInt\n    )\n        throws -> IOResult<size_t>\n    {\n        try Posix.sendmsg(descriptor: socket, msgHdr: msgHdr, flags: flags)\n    }\n\n    static func send(\n        socket s: NIOBSDSocket.Handle,\n        buffer buf: UnsafeRawPointer,\n        length len: size_t\n    ) throws -> IOResult<size_t> {\n        try Posix.write(descriptor: s, pointer: buf, size: len)\n    }\n\n    static func writev(\n        socket s: NIOBSDSocket.Handle,\n        iovecs: UnsafeBufferPointer<IOVector>\n    ) throws -> IOResult<Int> {\n        try Posix.writev(descriptor: s, iovecs: iovecs)\n    }\n\n    static func setsockopt(\n        socket: NIOBSDSocket.Handle,\n        level: NIOBSDSocket.OptionLevel,\n        option_name optname: NIOBSDSocket.Option,\n        option_value optval: UnsafeRawPointer,\n        option_len optlen: socklen_t\n    ) throws {\n        try Posix.setsockopt(\n            socket: socket,\n            level: level.rawValue,\n            optionName: optname.rawValue,\n            optionValue: optval,\n            optionLen: optlen\n        )\n    }\n\n    static func shutdown(socket: NIOBSDSocket.Handle, how: Shutdown) throws {\n        try Posix.shutdown(descriptor: socket, how: how)\n    }\n\n    static func socket(\n        domain af: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype\n    ) throws -> NIOBSDSocket.Handle {\n        try Posix.socket(domain: af, type: type, protocolSubtype: protocolSubtype)\n    }\n\n    static func recvmmsg(\n        socket: NIOBSDSocket.Handle,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt,\n        timeout: UnsafeMutablePointer<timespec>?\n    ) throws -> IOResult<Int> {\n        try Posix.recvmmsg(\n            sockfd: socket,\n            msgvec: msgvec,\n            vlen: vlen,\n            flags: flags,\n            timeout: timeout\n        )\n    }\n\n    static func sendmmsg(\n        socket: NIOBSDSocket.Handle,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt\n    ) throws -> IOResult<Int> {\n        try Posix.sendmmsg(\n            sockfd: socket,\n            msgvec: msgvec,\n            vlen: vlen,\n            flags: flags\n        )\n    }\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    static func pread(\n        socket: NIOBSDSocket.Handle,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<size_t> {\n        try Posix.pread(\n            descriptor: socket,\n            pointer: pointer,\n            size: size,\n            offset: offset\n        )\n    }\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    static func pwrite(\n        socket: NIOBSDSocket.Handle,\n        pointer: UnsafeRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<size_t> {\n        try Posix.pwrite(descriptor: socket, pointer: pointer, size: size, offset: offset)\n    }\n\n    static func poll(\n        fds: UnsafeMutablePointer<pollfd>,\n        nfds: nfds_t,\n        timeout: CInt\n    ) throws -> CInt {\n        try Posix.poll(fds: fds, nfds: nfds, timeout: timeout)\n    }\n\n    static func sendfile(\n        socket s: NIOBSDSocket.Handle,\n        fd: CInt,\n        offset: off_t,\n        len: off_t\n    ) throws -> IOResult<Int> {\n        try Posix.sendfile(descriptor: s, fd: fd, offset: offset, count: size_t(len))\n    }\n\n    static func setNonBlocking(socket: NIOBSDSocket.Handle) throws {\n        try Posix.setNonBlocking(socket: socket)\n    }\n\n    static func cleanupUnixDomainSocket(atPath path: String) throws {\n        do {\n            var sb: stat = stat()\n            try withUnsafeMutablePointer(to: &sb) { sbPtr in\n                try Posix.stat(pathname: path, outStat: sbPtr)\n            }\n\n            // Only unlink the existing file if it is a socket\n            if sb.st_mode & S_IFSOCK == S_IFSOCK {\n                try Posix.unlink(pathname: path)\n            } else {\n                throw UnixDomainSocketPathWrongType()\n            }\n        } catch let err as IOError {\n            // If the filepath did not exist, we consider it cleaned up\n            if err.errnoCode == ENOENT {\n                return\n            }\n            throw err\n        }\n    }\n}\n\n#if canImport(Darwin)\nimport CNIODarwin\nprivate let CMSG_FIRSTHDR = CNIODarwin_CMSG_FIRSTHDR\nprivate let CMSG_NXTHDR = CNIODarwin_CMSG_NXTHDR\nprivate let CMSG_DATA = CNIODarwin_CMSG_DATA\nprivate let CMSG_DATA_MUTABLE = CNIODarwin_CMSG_DATA_MUTABLE\nprivate let CMSG_SPACE = CNIODarwin_CMSG_SPACE\nprivate let CMSG_LEN = CNIODarwin_CMSG_LEN\n#elseif os(OpenBSD)\nimport CNIOOpenBSD\nprivate let CMSG_FIRSTHDR = CNIOOpenBSD_CMSG_FIRSTHDR\nprivate let CMSG_NXTHDR = CNIOOpenBSD_CMSG_NXTHDR\nprivate let CMSG_DATA = CNIOOpenBSD_CMSG_DATA\nprivate let CMSG_DATA_MUTABLE = CNIOOpenBSD_CMSG_DATA_MUTABLE\nprivate let CMSG_SPACE = CNIOOpenBSD_CMSG_SPACE\nprivate let CMSG_LEN = CNIOOpenBSD_CMSG_LEN\n#else\nimport CNIOLinux\nprivate let CMSG_FIRSTHDR = CNIOLinux_CMSG_FIRSTHDR\nprivate let CMSG_NXTHDR = CNIOLinux_CMSG_NXTHDR\nprivate let CMSG_DATA = CNIOLinux_CMSG_DATA\nprivate let CMSG_DATA_MUTABLE = CNIOLinux_CMSG_DATA_MUTABLE\nprivate let CMSG_SPACE = CNIOLinux_CMSG_SPACE\nprivate let CMSG_LEN = CNIOLinux_CMSG_LEN\n#endif\n\n// MARK: _BSDSocketControlMessageProtocol implementation\nextension NIOBSDSocketControlMessage {\n    static func firstHeader(\n        inside msghdr: UnsafePointer<msghdr>\n    )\n        -> UnsafeMutablePointer<cmsghdr>?\n    {\n        CMSG_FIRSTHDR(msghdr)\n    }\n\n    static func nextHeader(\n        inside msghdr: UnsafeMutablePointer<msghdr>,\n        after: UnsafeMutablePointer<cmsghdr>\n    )\n        -> UnsafeMutablePointer<cmsghdr>?\n    {\n        CMSG_NXTHDR(msghdr, after)\n    }\n\n    static func data(\n        for header: UnsafePointer<cmsghdr>\n    )\n        -> UnsafeRawBufferPointer?\n    {\n        let data = CMSG_DATA(header)\n        let length =\n            size_t(header.pointee.cmsg_len) - NIOBSDSocketControlMessage.length(payloadSize: 0)\n        return UnsafeRawBufferPointer(start: data, count: Int(length))\n    }\n\n    static func data(\n        for header: UnsafeMutablePointer<cmsghdr>\n    )\n        -> UnsafeMutableRawBufferPointer?\n    {\n        let data = CMSG_DATA_MUTABLE(header)\n        let length =\n            size_t(header.pointee.cmsg_len) - NIOBSDSocketControlMessage.length(payloadSize: 0)\n        return UnsafeMutableRawBufferPointer(start: data, count: Int(length))\n    }\n\n    static func length(payloadSize: size_t) -> size_t {\n        CMSG_LEN(payloadSize)\n    }\n\n    static func space(payloadSize: size_t) -> size_t {\n        CMSG_SPACE(payloadSize)\n    }\n}\n\nextension NIOBSDSocket {\n    static func setUDPSegmentSize(_ segmentSize: CInt, socket: NIOBSDSocket.Handle) throws {\n        #if os(Linux)\n        var segmentSize = segmentSize\n        try Self.setsockopt(\n            socket: socket,\n            level: .udp,\n            option_name: .udp_segment,\n            option_value: &segmentSize,\n            option_len: socklen_t(MemoryLayout<CInt>.size)\n        )\n        #else\n        throw ChannelError._operationUnsupported\n        #endif\n    }\n\n    static func getUDPSegmentSize(socket: NIOBSDSocket.Handle) throws -> CInt {\n        #if os(Linux)\n        var segmentSize: CInt = 0\n        var optionLength = socklen_t(MemoryLayout<CInt>.size)\n        try withUnsafeMutablePointer(to: &segmentSize) { segmentSizeBytes in\n            try Self.getsockopt(\n                socket: socket,\n                level: .udp,\n                option_name: .udp_segment,\n                option_value: segmentSizeBytes,\n                option_len: &optionLength\n            )\n        }\n        return segmentSize\n        #else\n        throw ChannelError._operationUnsupported\n        #endif\n    }\n\n    static func setUDPReceiveOffload(_ enabled: Bool, socket: NIOBSDSocket.Handle) throws {\n        #if os(Linux)\n        var isEnabled: CInt = enabled ? 1 : 0\n        try Self.setsockopt(\n            socket: socket,\n            level: .udp,\n            option_name: .udp_gro,\n            option_value: &isEnabled,\n            option_len: socklen_t(MemoryLayout<CInt>.size)\n        )\n        #else\n        throw ChannelError._operationUnsupported\n        #endif\n    }\n\n    static func getUDPReceiveOffload(socket: NIOBSDSocket.Handle) throws -> Bool {\n        #if os(Linux)\n        var enabled: CInt = 0\n        var optionLength = socklen_t(MemoryLayout<CInt>.size)\n        try withUnsafeMutablePointer(to: &enabled) { enabledBytes in\n            try Self.getsockopt(\n                socket: socket,\n                level: .udp,\n                option_name: .udp_gro,\n                option_value: enabledBytes,\n                option_len: &optionLength\n            )\n        }\n        return enabled != 0\n        #else\n        throw ChannelError._operationUnsupported\n        #endif\n    }\n}\n\nextension msghdr {\n    var control_ptr: UnsafeMutableRawBufferPointer {\n        set {\n            self.msg_control = newValue.baseAddress\n            self.msg_controllen = numericCast(newValue.count)\n        }\n        get {\n            UnsafeMutableRawBufferPointer(start: self.msg_control, count: Int(self.msg_controllen))\n        }\n    }\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/BSDSocketAPIWindows.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if os(Windows)\nimport ucrt\n\nimport let WinSDK.AF_INET\nimport let WinSDK.AF_INET6\nimport let WinSDK.AF_UNIX\n\nimport let WinSDK.FIONBIO\n\nimport let WinSDK.INET_ADDRSTRLEN\nimport let WinSDK.INET6_ADDRSTRLEN\n\nimport let WinSDK.INVALID_HANDLE_VALUE\nimport let WinSDK.INVALID_SOCKET\n\nimport let WinSDK.IPPROTO_IP\nimport let WinSDK.IPPROTO_IPV6\nimport let WinSDK.IPPROTO_TCP\n\nimport let WinSDK.IP_ADD_MEMBERSHIP\nimport let WinSDK.IP_DROP_MEMBERSHIP\nimport let WinSDK.IP_MULTICAST_IF\nimport let WinSDK.IP_MULTICAST_LOOP\nimport let WinSDK.IP_MULTICAST_TTL\n\nimport let WinSDK.IPV6_JOIN_GROUP\nimport let WinSDK.IPV6_LEAVE_GROUP\nimport let WinSDK.IPV6_MULTICAST_HOPS\nimport let WinSDK.IPV6_MULTICAST_IF\nimport let WinSDK.IPV6_MULTICAST_LOOP\nimport let WinSDK.IPV6_V6ONLY\n\nimport let WinSDK.PF_INET\nimport let WinSDK.PF_INET6\nimport let WinSDK.PF_UNIX\n\nimport let WinSDK.TCP_NODELAY\n\nimport let WinSDK.SD_BOTH\nimport let WinSDK.SD_RECEIVE\nimport let WinSDK.SD_SEND\n\nimport let WinSDK.SO_ERROR\nimport let WinSDK.SO_KEEPALIVE\nimport let WinSDK.SO_LINGER\nimport let WinSDK.SO_RCVBUF\nimport let WinSDK.SO_RCVTIMEO\nimport let WinSDK.SO_REUSEADDR\nimport let WinSDK.SO_REUSE_UNICASTPORT\n\nimport let WinSDK.SOL_SOCKET\n\nimport let WinSDK.SOCK_DGRAM\nimport let WinSDK.SOCK_STREAM\n\nimport let WinSDK.SOCKET_ERROR\n\nimport let WinSDK.TF_USE_KERNEL_APC\n\nimport func WinSDK.accept\nimport func WinSDK.bind\nimport func WinSDK.closesocket\nimport func WinSDK.connect\nimport func WinSDK.getpeername\nimport func WinSDK.getsockname\nimport func WinSDK.ioctlsocket\nimport func WinSDK.listen\nimport func WinSDK.shutdown\nimport func WinSDK.socket\nimport func WinSDK.GetLastError\nimport func WinSDK.ReadFile\nimport func WinSDK.TransmitFile\nimport func WinSDK.WriteFile\nimport func WinSDK.WSAGetLastError\nimport func WinSDK.WSAIoctl\nimport func WinSDK.WSASend\n\nimport struct WinSDK.socklen_t\nimport struct WinSDK.u_long\n\nimport struct WinSDK.ADDRESS_FAMILY\nimport struct WinSDK.DWORD\nimport struct WinSDK.HANDLE\nimport struct WinSDK.IN_ADDR\nimport struct WinSDK.LINGER\nimport struct WinSDK.OVERLAPPED\nimport struct WinSDK.SOCKADDR\nimport struct WinSDK.SOCKADDR_IN\nimport struct WinSDK.SOCKADDR_IN6\nimport struct WinSDK.SOCKADDR_UN\nimport struct WinSDK.SOCKADDR_STORAGE\nimport struct WinSDK.WSACMSGHDR\nimport struct WinSDK.WSAMSG\n\nimport typealias WinSDK.LPFN_WSARECVMSG\n\ninternal typealias cmsghdr = WSACMSGHDR\ninternal typealias msghdr = WSAMSG\ninternal typealias in_addr = IN_ADDR\ninternal typealias in_port_t = USHORT\ninternal typealias sa_family_t = ADDRESS_FAMILY\npublic typealias sockaddr = SOCKADDR\ninternal typealias sockaddr_in = SOCKADDR_IN\ninternal typealias sockaddr_in6 = SOCKADDR_IN6\ninternal typealias sockaddr_un = SOCKADDR_UN\ninternal typealias sockaddr_storage = SOCKADDR_STORAGE\n\nprivate var IOC_IN: DWORD {\n    0x8000_0000\n}\n\nprivate var IOC_OUT: DWORD {\n    0x4000_0000\n}\n\nprivate var IOC_INOUT: DWORD {\n    IOC_IN | IOC_OUT\n}\n\nprivate var IOC_WS2: DWORD {\n    0x0800_0000\n}\n\nprivate func _WSAIORW(_ x: DWORD, _ y: DWORD) -> DWORD {\n    IOC_INOUT | x | y\n}\n\nprivate var SIO_GET_EXTENSION_FUNCTION_POINTER: DWORD {\n    _WSAIORW(IOC_WS2, 6)\n}\n\nprivate var WSAID_WSARECVMSG: _GUID {\n    _GUID(\n        Data1: 0xf689_d7c8,\n        Data2: 0x6f1f,\n        Data3: 0x436b,\n        Data4: (0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22)\n    )\n}\n\nprivate var WSAID_WSASENDMSG: _GUID {\n    _GUID(\n        Data1: 0xa441_e712,\n        Data2: 0x754f,\n        Data3: 0x43ca,\n        Data4: (0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d)\n    )\n}\n\n// TODO(compnerd) rather than query the `WSARecvMsg` and `WSASendMsg` on each\n// message, we should query that and cache the value.  This requires\n// understanding the lifetime validity of the pointer.\n// TODO(compnerd) create a simpler shared wrapper to query the extension\n// function from WinSock and de-duplicate the operations in\n// `NIOBSDSocketAPI.recvmsg` and `NIOBSDSocketAPI.sendmsg`.\n\nimport CNIOWindows\n\nextension Shutdown {\n    internal var cValue: CInt {\n        switch self {\n        case .RD:\n            return WinSDK.SD_RECEIVE\n        case .WR:\n            return WinSDK.SD_SEND\n        case .RDWR:\n            return WinSDK.SD_BOTH\n        }\n    }\n}\n\n// MARK: _BSDSocketProtocol implementation\nextension NIOBSDSocket {\n    @inline(never)\n    static func accept(\n        socket s: NIOBSDSocket.Handle,\n        address addr: UnsafeMutablePointer<sockaddr>?,\n        address_len addrlen: UnsafeMutablePointer<socklen_t>?\n    ) throws -> NIOBSDSocket.Handle? {\n        let socket: NIOBSDSocket.Handle = WinSDK.accept(s, addr, addrlen)\n        if socket == WinSDK.INVALID_SOCKET {\n            throw IOError(winsock: WSAGetLastError(), reason: \"accept\")\n        }\n        return socket\n    }\n\n    @inline(never)\n    static func bind(\n        socket s: NIOBSDSocket.Handle,\n        address addr: UnsafePointer<sockaddr>,\n        address_len namelen: socklen_t\n    ) throws {\n        if WinSDK.bind(s, addr, namelen) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"bind\")\n        }\n    }\n\n    @inline(never)\n    static func close(socket s: NIOBSDSocket.Handle) throws {\n        if WinSDK.closesocket(s) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"close\")\n        }\n    }\n\n    @inline(never)\n    static func connect(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafePointer<sockaddr>,\n        address_len namelen: socklen_t\n    ) throws -> Bool {\n        if WinSDK.connect(s, name, namelen) == SOCKET_ERROR {\n            let iResult = WSAGetLastError()\n            if iResult == WSAEWOULDBLOCK { return true }\n            throw IOError(winsock: WSAGetLastError(), reason: \"connect\")\n        }\n        return true\n    }\n\n    @inline(never)\n    static func getpeername(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafeMutablePointer<sockaddr>,\n        address_len namelen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        if WinSDK.getpeername(s, name, namelen) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"getpeername\")\n        }\n    }\n\n    @inline(never)\n    static func getsockname(\n        socket s: NIOBSDSocket.Handle,\n        address name: UnsafeMutablePointer<sockaddr>,\n        address_len namelen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        if WinSDK.getsockname(s, name, namelen) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"getsockname\")\n        }\n    }\n\n    @inline(never)\n    static func getsockopt(\n        socket: NIOBSDSocket.Handle,\n        level: NIOBSDSocket.OptionLevel,\n        option_name optname: NIOBSDSocket.Option,\n        option_value optval: UnsafeMutableRawPointer,\n        option_len optlen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        if CNIOWindows_getsockopt(\n            socket,\n            level.rawValue,\n            optname.rawValue,\n            optval,\n            optlen\n        ) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"getsockopt\")\n        }\n    }\n\n    @inline(never)\n    static func listen(socket s: NIOBSDSocket.Handle, backlog: CInt) throws {\n        if WinSDK.listen(s, backlog) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"listen\")\n        }\n    }\n\n    @inline(never)\n    static func recv(\n        socket s: NIOBSDSocket.Handle,\n        buffer buf: UnsafeMutableRawPointer,\n        length len: size_t\n    ) throws -> IOResult<size_t> {\n        let iResult: CInt = CNIOWindows_recv(s, buf, CInt(len), 0)\n        if iResult == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"recv\")\n        }\n        return .processed(size_t(iResult))\n    }\n\n    @inline(never)\n    static func recvmsg(\n        socket s: NIOBSDSocket.Handle,\n        msgHdr lpMsg: UnsafeMutablePointer<msghdr>,\n        flags: CInt\n    )\n        throws -> IOResult<size_t>\n    {\n        // TODO(compnerd) see comment above\n        var InBuffer = WSAID_WSARECVMSG\n        var pfnWSARecvMsg: LPFN_WSARECVMSG?\n        var cbBytesReturned: DWORD = 0\n        if WinSDK.WSAIoctl(\n            s,\n            SIO_GET_EXTENSION_FUNCTION_POINTER,\n            &InBuffer,\n            DWORD(MemoryLayout.stride(ofValue: InBuffer)),\n            &pfnWSARecvMsg,\n            DWORD(MemoryLayout.stride(ofValue: pfnWSARecvMsg)),\n            &cbBytesReturned,\n            nil,\n            nil\n        ) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"WSAIoctl\")\n        }\n\n        guard let WSARecvMsg = pfnWSARecvMsg else {\n            throw IOError(\n                windows: DWORD(ERROR_INVALID_FUNCTION),\n                reason: \"recvmsg\"\n            )\n        }\n\n        var dwNumberOfBytesRecvd: DWORD = 0\n        // FIXME(compnerd) is the socket guaranteed to not be overlapped?\n        if WSARecvMsg(s, lpMsg, &dwNumberOfBytesRecvd, nil, nil) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"recvmsg\")\n        }\n        return .processed(size_t(dwNumberOfBytesRecvd))\n    }\n\n    @inline(never)\n    static func sendmsg(\n        socket Handle: NIOBSDSocket.Handle,\n        msgHdr lpMsg: UnsafePointer<msghdr>,\n        flags dwFlags: CInt\n    ) throws -> IOResult<size_t> {\n        // TODO(compnerd) see comment above\n        var InBuffer = WSAID_WSASENDMSG\n        var pfnWSASendMsg: LPFN_WSASENDMSG?\n        var cbBytesReturned: DWORD = 0\n        if WinSDK.WSAIoctl(\n            Handle,\n            SIO_GET_EXTENSION_FUNCTION_POINTER,\n            &InBuffer,\n            DWORD(MemoryLayout.stride(ofValue: InBuffer)),\n            &pfnWSASendMsg,\n            DWORD(MemoryLayout.stride(ofValue: pfnWSASendMsg)),\n            &cbBytesReturned,\n            nil,\n            nil\n        ) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"WSAIoctl\")\n        }\n\n        guard let WSASendMsg = pfnWSASendMsg else {\n            throw IOError(\n                windows: DWORD(ERROR_INVALID_FUNCTION),\n                reason: \"sendmsg\"\n            )\n        }\n\n        let lpMsg: LPWSAMSG = UnsafeMutablePointer<WSAMSG>(mutating: lpMsg)\n        var NumberOfBytesSent: DWORD = 0\n        // FIXME(compnerd) is the socket guaranteed to not be overlapped?\n        if WSASendMsg(\n            Handle,\n            lpMsg,\n            DWORD(dwFlags),\n            &NumberOfBytesSent,\n            nil,\n            nil\n        ) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"sendmsg\")\n        }\n        return .processed(size_t(NumberOfBytesSent))\n    }\n\n    @inline(never)\n    static func send(\n        socket s: NIOBSDSocket.Handle,\n        buffer buf: UnsafeRawPointer,\n        length len: size_t\n    ) throws -> IOResult<size_t> {\n        let iResult: CInt = CNIOWindows_send(s, buf, CInt(len), 0)\n        if iResult == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"send\")\n        }\n        return .processed(size_t(iResult))\n    }\n\n    @inline(never)\n    static func writev(\n        socket s: NIOBSDSocket.Handle,\n        iovecs: UnsafeBufferPointer<IOVector>\n    ) throws -> IOResult<Int> {\n        var bytesSent: DWORD = 0\n        let ptr = UnsafeMutablePointer(mutating: iovecs.baseAddress)\n        let result = WSASend(s, ptr, UInt32(iovecs.count), &bytesSent, 0, nil, nil)\n        if result == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"WSASend\")\n        }\n        return .processed(Int(bytesSent))\n    }\n\n    @inline(never)\n    static func setsockopt(\n        socket: NIOBSDSocket.Handle,\n        level: NIOBSDSocket.OptionLevel,\n        option_name optname: NIOBSDSocket.Option,\n        option_value optval: UnsafeRawPointer,\n        option_len optlen: socklen_t\n    ) throws {\n        if CNIOWindows_setsockopt(\n            socket,\n            level.rawValue,\n            optname.rawValue,\n            optval,\n            optlen\n        ) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"setsockopt\")\n        }\n    }\n\n    @inline(never)\n    static func shutdown(socket: NIOBSDSocket.Handle, how: Shutdown) throws {\n        if WinSDK.shutdown(socket, how.cValue) == SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"shutdown\")\n        }\n    }\n\n    @inline(never)\n    static func socket(\n        domain af: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype\n    ) throws -> NIOBSDSocket.Handle {\n        let socket: NIOBSDSocket.Handle = WinSDK.socket(af.rawValue, type.rawValue, protocolSubtype.rawValue)\n        if socket == WinSDK.INVALID_SOCKET {\n            throw IOError(winsock: WSAGetLastError(), reason: \"socket\")\n        }\n        return socket\n    }\n\n    @inline(never)\n    static func recvmmsg(\n        socket: NIOBSDSocket.Handle,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt,\n        timeout: UnsafeMutablePointer<timespec>?\n    )\n        throws -> IOResult<Int>\n    {\n        .processed(Int(CNIOWindows_recvmmsg(socket, msgvec, vlen, flags, timeout)))\n    }\n\n    @inline(never)\n    static func sendmmsg(\n        socket: NIOBSDSocket.Handle,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt\n    )\n        throws -> IOResult<Int>\n    {\n        .processed(Int(CNIOWindows_sendmmsg(socket, msgvec, vlen, flags)))\n    }\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    @inline(never)\n    static func pread(\n        socket: NIOBSDSocket.Handle,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<size_t> {\n        var ovlOverlapped: OVERLAPPED = OVERLAPPED()\n        ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffff_ffff)\n        ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffff_ffff)\n        var nNumberOfBytesRead: DWORD = 0\n        if !ReadFile(\n            HANDLE(bitPattern: UInt(socket)),\n            pointer,\n            DWORD(size),\n            &nNumberOfBytesRead,\n            &ovlOverlapped\n        ) {\n            throw IOError(windows: GetLastError(), reason: \"ReadFile\")\n        }\n        return .processed(size_t(nNumberOfBytesRead))\n    }\n\n    // NOTE: this should return a `ssize_t`, however, that is not a standard\n    // type, and defining that type is difficult.  Opt to return a `size_t`\n    // which is the same size, but is unsigned.\n    @inline(never)\n    static func pwrite(\n        socket: NIOBSDSocket.Handle,\n        pointer: UnsafeRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<size_t> {\n        var ovlOverlapped: OVERLAPPED = OVERLAPPED()\n        ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffff_ffff)\n        ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffff_ffff)\n        var nNumberOfBytesWritten: DWORD = 0\n        if !WriteFile(\n            HANDLE(bitPattern: UInt(socket)),\n            pointer,\n            DWORD(size),\n            &nNumberOfBytesWritten,\n            &ovlOverlapped\n        ) {\n            throw IOError(windows: GetLastError(), reason: \"WriteFile\")\n        }\n        return .processed(size_t(nNumberOfBytesWritten))\n    }\n\n    @inline(never)\n    static func sendfile(\n        socket s: NIOBSDSocket.Handle,\n        fd: CInt,\n        offset: off_t,\n        len nNumberOfBytesToWrite: off_t\n    )\n        throws -> IOResult<Int>\n    {\n        let hFile: HANDLE = HANDLE(bitPattern: ucrt._get_osfhandle(fd))!\n        if hFile == INVALID_HANDLE_VALUE {\n            throw IOError(errnoCode: EBADF, reason: \"_get_osfhandle\")\n        }\n\n        var ovlOverlapped: OVERLAPPED = OVERLAPPED()\n        ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffff_ffff)\n        ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffff_ffff)\n        if !TransmitFile(\n            s,\n            hFile,\n            DWORD(nNumberOfBytesToWrite),\n            0,\n            &ovlOverlapped,\n            nil,\n            DWORD(TF_USE_KERNEL_APC)\n        ) {\n            throw IOError(winsock: WSAGetLastError(), reason: \"TransmitFile\")\n        }\n\n        return .processed(Int(nNumberOfBytesToWrite))\n    }\n\n    // The protocol subtype for MPTCP.\n    // Returns nil if mptcp is not supported.\n    static var mptcpProtocolSubtype: Int? {\n        // MPTCP not supported on Windows.\n        nil\n    }\n}\n\nextension NIOBSDSocket {\n    @inline(never)\n    static func setNonBlocking(socket: NIOBSDSocket.Handle) throws {\n        var ulMode: u_long = 1\n        if WinSDK.ioctlsocket(socket, FIONBIO, &ulMode) == SOCKET_ERROR {\n            let iResult = WSAGetLastError()\n            if iResult == WSAEINVAL {\n                throw NIOFcntlFailedError()\n            }\n            throw IOError(winsock: WSAGetLastError(), reason: \"ioctlsocket\")\n        }\n    }\n\n    static func cleanupUnixDomainSocket(atPath path: String) throws {\n        guard\n            let hFile =\n                (path.withCString(encodedAs: UTF16.self) {\n                    CreateFileW(\n                        $0,\n                        GENERIC_READ,\n                        DWORD(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),\n                        nil,\n                        DWORD(OPEN_EXISTING),\n                        DWORD(FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS),\n                        nil\n                    )\n                })\n        else {\n            throw IOError(windows: DWORD(EBADF), reason: \"CreateFileW\")\n        }\n        defer { CloseHandle(hFile) }\n\n        let ftFileType = GetFileType(hFile)\n        let dwError = GetLastError()\n        guard dwError == NO_ERROR, ftFileType != FILE_TYPE_DISK else {\n            throw IOError(windows: dwError, reason: \"GetFileType\")\n        }\n\n        var fiInformation: BY_HANDLE_FILE_INFORMATION =\n            BY_HANDLE_FILE_INFORMATION()\n        guard GetFileInformationByHandle(hFile, &fiInformation) else {\n            throw IOError(windows: GetLastError(), reason: \"GetFileInformationByHandle\")\n        }\n\n        guard fiInformation.dwFileAttributes & DWORD(FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT\n        else {\n            throw UnixDomainSocketPathWrongType()\n        }\n\n        var nBytesWritten: DWORD = 0\n        var dbReparseDataBuffer: CNIOWindows_REPARSE_DATA_BUFFER =\n            CNIOWindows_REPARSE_DATA_BUFFER()\n        try withUnsafeMutablePointer(to: &dbReparseDataBuffer) {\n            if !DeviceIoControl(\n                hFile,\n                FSCTL_GET_REPARSE_POINT,\n                nil,\n                0,\n                $0,\n                DWORD(MemoryLayout<CNIOWindows_REPARSE_DATA_BUFFER>.stride),\n                &nBytesWritten,\n                nil\n            ) {\n                throw IOError(windows: GetLastError(), reason: \"DeviceIoControl\")\n            }\n        }\n\n        guard dbReparseDataBuffer.ReparseTag == IO_REPARSE_TAG_AF_UNIX else {\n            throw UnixDomainSocketPathWrongType()\n        }\n\n        var fdi: FILE_DISPOSITION_INFO_EX = FILE_DISPOSITION_INFO_EX()\n        fdi.Flags = DWORD(FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS)\n\n        if !SetFileInformationByHandle(\n            hFile,\n            FileDispositionInfoEx,\n            &fdi,\n            DWORD(MemoryLayout<FILE_DISPOSITION_INFO_EX>.stride)\n        ) {\n            throw IOError(windows: GetLastError(), reason: \"GetFileInformationByHandle\")\n        }\n    }\n}\n\n// MARK: _BSDSocketControlMessageProtocol implementation\nextension NIOBSDSocketControlMessage {\n    static func firstHeader(\n        inside msghdr: UnsafePointer<msghdr>\n    )\n        -> UnsafeMutablePointer<cmsghdr>?\n    {\n        CNIOWindows_CMSG_FIRSTHDR(msghdr)\n    }\n\n    static func nextHeader(\n        inside msghdr: UnsafeMutablePointer<msghdr>,\n        after: UnsafeMutablePointer<cmsghdr>\n    )\n        -> UnsafeMutablePointer<cmsghdr>?\n    {\n        CNIOWindows_CMSG_NXTHDR(msghdr, after)\n    }\n\n    static func data(\n        for header: UnsafePointer<cmsghdr>\n    )\n        -> UnsafeRawBufferPointer?\n    {\n        let data = CNIOWindows_CMSG_DATA(header)\n        let length =\n            size_t(header.pointee.cmsg_len) - NIOBSDSocketControlMessage.length(payloadSize: 0)\n        return UnsafeRawBufferPointer(start: data, count: Int(length))\n    }\n\n    static func data(\n        for header: UnsafeMutablePointer<cmsghdr>\n    )\n        -> UnsafeMutableRawBufferPointer?\n    {\n        let data = CNIOWindows_CMSG_DATA_MUTABLE(header)\n        let length =\n            size_t(header.pointee.cmsg_len) - NIOBSDSocketControlMessage.length(payloadSize: 0)\n        return UnsafeMutableRawBufferPointer(start: data, count: Int(length))\n    }\n\n    static func length(payloadSize: size_t) -> size_t {\n        CNIOWindows_CMSG_LEN(payloadSize)\n    }\n\n    static func space(payloadSize: size_t) -> size_t {\n        CNIOWindows_CMSG_SPACE(payloadSize)\n    }\n}\n\nextension NIOBSDSocket {\n    static func setUDPSegmentSize(_ segmentSize: CInt, socket: NIOBSDSocket.Handle) throws {\n        throw ChannelError.operationUnsupported\n    }\n\n    static func getUDPSegmentSize(socket: NIOBSDSocket.Handle) throws -> CInt {\n        throw ChannelError.operationUnsupported\n    }\n\n    static func setUDPReceiveOffload(_ enabled: Bool, socket: NIOBSDSocket.Handle) throws {\n        throw ChannelError.operationUnsupported\n    }\n\n    static func getUDPReceiveOffload(socket: NIOBSDSocket.Handle) throws -> Bool {\n        throw ChannelError.operationUnsupported\n    }\n}\n\nextension IOVector {\n    // An initializer thats maps `ByteBuffer`` derived pointers to WSABUF. This allows us to use the\n    // same initializer, that we use for iovecs on Windows.\n    init(iov_base: UnsafeMutableRawPointer!, iov_len: UInt32) {\n        self = WSABUF(\n            len: iov_len,\n            buf: iov_base.assumingMemoryBound(to: Int8.self)\n        )\n    }\n\n    var iov_len: UInt32 {\n        set {\n            self.len = newValue\n        }\n        get {\n            self.len\n        }\n    }\n\n    var iov_base: UnsafeMutableRawPointer {\n        set {\n            self.buf = newValue.assumingMemoryBound(to: Int8.self)\n        }\n        get {\n            UnsafeMutableRawPointer(self.buf)\n        }\n    }\n}\n\nextension WSAMSG {\n    var msg_name: UnsafeMutableRawPointer? {\n        set {\n            self.name = newValue?.assumingMemoryBound(to: sockaddr.self)\n        }\n        get {\n            UnsafeMutableRawPointer(self.name)\n        }\n    }\n\n    var msg_namelen: socklen_t {\n        set {\n            self.namelen = newValue\n        }\n        get {\n            self.namelen\n        }\n    }\n\n    var msg_iov: UnsafeMutablePointer<IOVector> {\n        set {\n            self.lpBuffers = newValue\n        }\n        get {\n            self.lpBuffers\n        }\n    }\n\n    var msg_iovlen: UInt32 {\n        set {\n            self.dwBufferCount = newValue\n        }\n        get {\n            self.dwBufferCount\n        }\n    }\n\n    var control_ptr: UnsafeMutableRawBufferPointer {\n        set {\n            self.Control.buf = newValue.baseAddress?.bindMemory(to: CHAR.self, capacity: newValue.count)\n            self.Control.len = numericCast(newValue.count)\n        }\n        get {\n            UnsafeMutableRawBufferPointer(start: self.Control.buf, count: Int(self.Control.len))\n        }\n    }\n\n    var msg_flags: Int {\n        set {\n            self.dwFlags = numericCast(newValue)\n        }\n        get {\n            Int(self.dwFlags)\n        }\n    }\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/BaseSocket.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport CNIOLinux\nimport CNIOOpenBSD\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n#if os(Windows)\nimport let WinSDK.EAFNOSUPPORT\nimport let WinSDK.EBADF\n\nimport struct WinSDK.socklen_t\n#endif\n\n@usableFromInline\nprotocol Registration {\n    /// The `SelectorEventSet` in which the `Registration` is interested.\n    var interested: SelectorEventSet { get set }\n    var registrationID: SelectorRegistrationID { get set }\n}\n\n// sockaddr_storage is basically just a boring data structure that we can\n// convert to being something sensible. These functions copy the data as\n// needed.\n//\n// Annoyingly, these functions are mutating. This is required to work around\n// https://bugs.swift.org/browse/SR-2749 on Ubuntu 14.04: basically, we need to\n// avoid getting the Swift compiler to copy the sockaddr_storage for any reason:\n// only our rebinding copy here is allowed.\nextension sockaddr_storage {\n    mutating func withMutableSockAddr<R>(_ body: (UnsafeMutablePointer<sockaddr>, Int) throws -> R) rethrows -> R {\n        try withUnsafeMutableBytes(of: &self) { p in\n            try body(p.baseAddress!.assumingMemoryBound(to: sockaddr.self), p.count)\n        }\n    }\n\n    /// Converts the `socketaddr_storage` to a `sockaddr_in`.\n    ///\n    /// This will crash if `ss_family` != AF_INET!\n    func convert() -> sockaddr_in {\n        precondition(self.ss_family == NIOBSDSocket.AddressFamily.inet.rawValue)\n        return withUnsafeBytes(of: self) {\n            $0.load(as: sockaddr_in.self)\n        }\n    }\n\n    /// Converts the `socketaddr_storage` to a `sockaddr_in6`.\n    ///\n    /// This will crash if `ss_family` != AF_INET6!\n    func convert() -> sockaddr_in6 {\n        precondition(self.ss_family == NIOBSDSocket.AddressFamily.inet6.rawValue)\n        return withUnsafeBytes(of: self) {\n            $0.load(as: sockaddr_in6.self)\n        }\n    }\n\n    /// Converts the `socketaddr_storage` to a `sockaddr_un`.\n    ///\n    /// This will crash if `ss_family` != AF_UNIX!\n    func convert() -> sockaddr_un {\n        precondition(self.ss_family == NIOBSDSocket.AddressFamily.unix.rawValue)\n        return withUnsafeBytes(of: self) {\n            $0.load(as: sockaddr_un.self)\n        }\n    }\n\n    /// Converts the `socketaddr_storage` to a `SocketAddress`.\n    func convert() throws -> SocketAddress {\n        switch NIOBSDSocket.AddressFamily(rawValue: CInt(self.ss_family)) {\n        case .inet:\n            let sockAddr: sockaddr_in = self.convert()\n            return SocketAddress(sockAddr)\n        case .inet6:\n            let sockAddr: sockaddr_in6 = self.convert()\n            return SocketAddress(sockAddr)\n        case .unix:\n            return SocketAddress(self.convert() as sockaddr_un)\n        default:\n            throw SocketAddressError.unsupported\n        }\n    }\n}\n\n/// A helper extension for working with sockaddr pointers.\nextension UnsafeMutablePointer where Pointee == sockaddr {\n    /// Converts the `sockaddr` to a `SocketAddress`.\n    func convert() -> SocketAddress? {\n        let addressBytes = UnsafeRawPointer(self)\n        switch NIOBSDSocket.AddressFamily(rawValue: CInt(pointee.sa_family)) {\n        case .inet:\n            return SocketAddress(addressBytes.load(as: sockaddr_in.self))\n        case .inet6:\n            return SocketAddress(addressBytes.load(as: sockaddr_in6.self))\n        case .unix:\n            return SocketAddress(addressBytes.load(as: sockaddr_un.self))\n        default:\n            return nil\n        }\n    }\n}\n\n/// Base class for sockets.\n///\n/// This should not be created directly but one of its sub-classes should be used, like `ServerSocket` or `Socket`.\nclass BaseSocket: BaseSocketProtocol {\n    typealias SelectableType = BaseSocket\n\n    private var descriptor: NIOBSDSocket.Handle\n    public var isOpen: Bool {\n        #if os(Windows)\n        return descriptor != NIOBSDSocket.invalidHandle\n        #else\n        return descriptor >= 0\n        #endif\n    }\n\n    /// Returns the local bound `SocketAddress` of the socket.\n    ///\n    /// - Returns: The local bound address.\n    /// - Throws: An `IOError` if the retrieval of the address failed.\n    func localAddress() throws -> SocketAddress {\n        try get_addr {\n            try NIOBSDSocket.getsockname(socket: $0, address: $1, address_len: $2)\n        }\n    }\n\n    /// Returns the connected `SocketAddress` of the socket.\n    ///\n    /// - Returns: The connected address.\n    /// - Throws: An `IOError` if the retrieval of the address failed.\n    func remoteAddress() throws -> SocketAddress {\n        try get_addr {\n            try NIOBSDSocket.getpeername(socket: $0, address: $1, address_len: $2)\n        }\n    }\n\n    /// Internal helper function for retrieval of a `SocketAddress`.\n    private func get_addr(\n        _ body: (NIOBSDSocket.Handle, UnsafeMutablePointer<sockaddr>, UnsafeMutablePointer<socklen_t>) throws -> Void\n    ) throws -> SocketAddress {\n        var addr = sockaddr_storage()\n\n        try addr.withMutableSockAddr { addressPtr, size in\n            var size = socklen_t(size)\n\n            try self.withUnsafeHandle {\n                try body($0, addressPtr, &size)\n            }\n        }\n        return try addr.convert()\n    }\n\n    /// Create a new socket and return the file descriptor of it.\n    ///\n    /// - Parameters:\n    ///   - protocolFamily: The protocol family to use (usually `AF_INET6` or `AF_INET`).\n    ///   - type: The type of the socket to create.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Returns: the file descriptor of the socket that was created.\n    /// - Throws: An `IOError` if creation of the socket failed.\n    static func makeSocket(\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype,\n        setNonBlocking: Bool = false\n    ) throws -> NIOBSDSocket.Handle {\n        var sockType: CInt = type.rawValue\n        #if os(Linux)\n        if setNonBlocking {\n            sockType = type.rawValue | Linux.SOCK_NONBLOCK\n        }\n        #endif\n        let sock = try NIOBSDSocket.socket(\n            domain: protocolFamily,\n            type: NIOBSDSocket.SocketType(rawValue: sockType),\n            protocolSubtype: protocolSubtype\n        )\n        #if !os(Linux)\n        if setNonBlocking {\n            do {\n                try NIOBSDSocket.setNonBlocking(socket: sock)\n            } catch {\n                // best effort close\n                try? NIOBSDSocket.close(socket: sock)\n                throw error\n            }\n        }\n        #endif\n        if protocolFamily == .inet6 {\n            var zero: Int32 = 0\n            do {\n                try NIOBSDSocket.setsockopt(\n                    socket: sock,\n                    level: .ipv6,\n                    option_name: .ipv6_v6only,\n                    option_value: &zero,\n                    option_len: socklen_t(MemoryLayout.size(ofValue: zero))\n                )\n            } catch let e as IOError {\n                if e.errnoCode != EAFNOSUPPORT {\n                    // Ignore error that may be thrown by close.\n                    _ = try? NIOBSDSocket.close(socket: sock)\n                    throw e\n                }\n                // we couldn't enable dual IP4/6 support, that's okay too.\n            } catch let e {\n                fatalError(\"Unexpected error type \\(e)\")\n            }\n        }\n        return sock\n    }\n\n    /// Cleanup the unix domain socket.\n    ///\n    /// Deletes the associated file if it exists and has socket type. Does nothing if pathname does not exist.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The pathname of the UDS.\n    /// - Throws: An `UnixDomainSocketPathWrongType` if the pathname exists and is not a socket.\n    static func cleanupSocket(unixDomainSocketPath: String) throws {\n        try NIOBSDSocket.cleanupUnixDomainSocket(atPath: unixDomainSocketPath)\n    }\n\n    /// Create a new instance.\n    ///\n    /// The ownership of the passed in descriptor is transferred to this class. A user must call `close` to close the underlying\n    /// file descriptor once it's not needed / used anymore.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The file descriptor to wrap.\n    init(socket descriptor: NIOBSDSocket.Handle) throws {\n        #if os(Windows)\n        precondition(descriptor != NIOBSDSocket.invalidHandle, \"invalid socket\")\n        #else\n        precondition(descriptor >= 0, \"invalid socket\")\n        #endif\n        self.descriptor = descriptor\n        do {\n            try self.ignoreSIGPIPE()\n        } catch {\n            // We have to unset the fd here, otherwise we'll crash with \"leaking open BaseSocket\"\n            self.descriptor = NIOBSDSocket.invalidHandle\n            throw error\n        }\n    }\n\n    deinit {\n        assert(!self.isOpen, \"leak of open BaseSocket\")\n    }\n\n    func ignoreSIGPIPE() throws {\n        try BaseSocket.ignoreSIGPIPE(socket: self.descriptor)\n    }\n\n    /// Set the socket as non-blocking.\n    ///\n    /// All I/O operations will not block and so may return before the actual action could be completed.\n    ///\n    /// throws: An `IOError` if the operation failed.\n    final func setNonBlocking() throws {\n        try self.withUnsafeHandle {\n            try NIOBSDSocket.setNonBlocking(socket: $0)\n        }\n    }\n\n    /// Set the given socket option.\n    ///\n    /// This basically just delegates to `setsockopt` syscall.\n    ///\n    /// - Parameters:\n    ///   - level: The protocol level (see `man setsockopt`).\n    ///   - name: The name of the option to set.\n    ///   - value: The value for the option.\n    /// - Throws: An `IOError` if the operation failed.\n    func setOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option, value: T) throws {\n        if level == .tcp && name == .tcp_nodelay {\n            switch try? self.localAddress().protocol {\n            case .some(.inet), .some(.inet6): break\n            // Setting TCP_NODELAY on UNIX domain sockets will fail. Previously we had a bug where we would ignore\n            // most socket options settings so for the time being we'll just ignore this. Let's revisit for NIO 2.0.\n            case .some(.unix): return\n            // We'll also ignore this option on socket protocol families that NIO doesn't explicitly support.\n            case .some(_), .none: return\n            }\n        }\n        return try withUnsafeBytes(of: value) { (valueBuffer: UnsafeRawBufferPointer) in\n            try self.withUnsafeHandle {\n                try NIOBSDSocket.setsockopt(\n                    socket: $0,\n                    level: level,\n                    option_name: name,\n                    option_value: valueBuffer.baseAddress!,\n                    option_len: socklen_t(valueBuffer.count)\n                )\n            }\n        }\n    }\n\n    /// Get the given socket option value.\n    ///\n    /// This basically just delegates to `getsockopt` syscall.\n    ///\n    /// - Parameters:\n    ///   - level: The protocol level (see `man getsockopt`).\n    ///   - name: The name of the option to set.\n    /// - Throws: An `IOError` if the operation failed.\n    func getOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) throws -> T {\n        try self.withUnsafeHandle { fd in\n            var length = socklen_t(MemoryLayout<T>.size)\n            let storage = UnsafeMutableRawBufferPointer.allocate(\n                byteCount: MemoryLayout<T>.stride,\n                alignment: MemoryLayout<T>.alignment\n            )\n            // write zeroes into the memory as Linux's getsockopt doesn't zero them out\n            storage.initializeMemory(as: UInt8.self, repeating: 0)\n            let val = storage.bindMemory(to: T.self).baseAddress!\n            // initialisation will be done by getsockopt\n            defer {\n                val.deinitialize(count: 1)\n                storage.deallocate()\n            }\n\n            try NIOBSDSocket.getsockopt(\n                socket: fd,\n                level: level,\n                option_name: name,\n                option_value: val,\n                option_len: &length\n            )\n            return val.pointee\n        }\n    }\n\n    /// Bind the socket to the given `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to which the socket should be bound.\n    /// - Throws: An `IOError` if the operation failed.\n    func bind(to address: SocketAddress) throws {\n        try self.withUnsafeHandle { fd in\n            try address.withSockAddr {\n                try NIOBSDSocket.bind(socket: fd, address: $0, address_len: socklen_t($1))\n            }\n        }\n    }\n\n    /// Close the socket.\n    ///\n    /// After the socket was closed all other methods will throw an `IOError` when called.\n    ///\n    /// - Throws: An `IOError` if the operation failed.\n    func close() throws {\n        try NIOBSDSocket.close(socket: try self.takeDescriptorOwnership())\n    }\n\n    /// Takes the file descriptor's ownership.\n    ///\n    /// After this call, `BaseSocket` considers itself to be closed and the caller is responsible for actually closing\n    /// the underlying file descriptor.\n    ///\n    /// - Throws: An `IOError` if the operation failed.\n    final func takeDescriptorOwnership() throws -> NIOBSDSocket.Handle {\n        try self.withUnsafeHandle {\n            self.descriptor = NIOBSDSocket.invalidHandle\n            return $0\n        }\n    }\n}\n\nextension BaseSocket: Selectable {\n    func withUnsafeHandle<T>(_ body: (NIOBSDSocket.Handle) throws -> T) throws -> T {\n        guard self.isOpen else {\n            throw IOError(errnoCode: EBADF, reason: \"file descriptor already closed!\")\n        }\n        return try body(self.descriptor)\n    }\n}\n\nextension BaseSocket: CustomStringConvertible {\n    var description: String {\n        \"BaseSocket { fd=\\(self.descriptor) }\"\n    }\n}\n\n// MARK: Workarounds for SR-14268\n// We need these free functions to expose our extension methods, because otherwise\n// the compiler falls over when we try to access them from test code. As these functions\n// exist purely to make the behaviours accessible from test code, we name them truly awfully.\nfunc __testOnly_convertSockAddr(_ addr: sockaddr_storage) -> sockaddr_in {\n    addr.convert()\n}\n\nfunc __testOnly_convertSockAddr(_ addr: sockaddr_storage) -> sockaddr_in6 {\n    addr.convert()\n}\n\nfunc __testOnly_convertSockAddr(_ addr: sockaddr_storage) -> sockaddr_un {\n    addr.convert()\n}\n\nfunc __testOnly_convertSockAddr(_ addr: sockaddr_storage) throws -> SocketAddress {\n    try addr.convert()\n}\n\nfunc __testOnly_withMutableSockAddr<ReturnType>(\n    _ addr: inout sockaddr_storage,\n    _ body: (UnsafeMutablePointer<sockaddr>, Int) throws -> ReturnType\n) rethrows -> ReturnType {\n    try addr.withMutableSockAddr(body)\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/BaseSocketChannel+AccessibleTransport.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nextension BaseSocketChannel where SocketType: BaseSocket {\n    /// The underlying transport type backing this channel.\n    typealias Transport = NIOBSDSocket.Handle\n\n    /// Provides scoped access to the socket file handle.\n    func withUnsafeTransport<Result>(_ body: (_ transport: NIOBSDSocket.Handle) throws -> Result) throws -> Result {\n        try self.socket.withUnsafeHandle(body)\n    }\n}\n\nextension BaseSocketChannel where SocketType: PipePair {\n    /// The underlying transport type backing this channel.\n    typealias Transport = NIOBSDSocket.PipeHandle\n\n    /// Provides scoped access to the pipe file descriptors.\n    func withUnsafeTransport<Result>(_ body: (_ transport: NIOBSDSocket.PipeHandle) throws -> Result) throws -> Result {\n        try body(\n            NIOBSDSocket.PipeHandle(\n                input: self.socket.input?.fileDescriptor ?? NIOBSDSocket.invalidHandle,\n                output: self.socket.output?.fileDescriptor ?? NIOBSDSocket.invalidHandle\n            )\n        )\n    }\n}\n\nextension SocketChannel: NIOTransportAccessibleChannelCore {}\nextension ServerSocketChannel: NIOTransportAccessibleChannelCore {}\nextension DatagramChannel: NIOTransportAccessibleChannelCore {}\nextension PipeChannel: NIOTransportAccessibleChannelCore {}\n"
  },
  {
    "path": "Sources/NIOPosix/BaseSocketChannel+SocketOptionProvider.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\nextension BaseSocketChannel: SocketOptionProvider {\n    #if !os(Windows)\n    func unsafeSetSocketOption<Value: Sendable>(\n        level: SocketOptionLevel,\n        name: SocketOptionName,\n        value: Value\n    ) -> EventLoopFuture<Void> {\n        unsafeSetSocketOption(\n            level: NIOBSDSocket.OptionLevel(rawValue: CInt(level)),\n            name: NIOBSDSocket.Option(rawValue: CInt(name)),\n            value: value\n        )\n    }\n    #endif\n\n    func unsafeSetSocketOption<Value: Sendable>(\n        level: NIOBSDSocket.OptionLevel,\n        name: NIOBSDSocket.Option,\n        value: Value\n    ) -> EventLoopFuture<Void> {\n        if eventLoop.inEventLoop {\n            let promise = eventLoop.makePromise(of: Void.self)\n            executeAndComplete(promise) {\n                try setSocketOption0(level: level, name: name, value: value)\n            }\n            return promise.futureResult\n        } else {\n            return eventLoop.submit {\n                try self.setSocketOption0(level: level, name: name, value: value)\n            }\n        }\n    }\n\n    #if !os(Windows)\n    func unsafeGetSocketOption<Value: Sendable>(\n        level: SocketOptionLevel,\n        name: SocketOptionName\n    ) -> EventLoopFuture<Value> {\n        unsafeGetSocketOption(\n            level: NIOBSDSocket.OptionLevel(rawValue: CInt(level)),\n            name: NIOBSDSocket.Option(rawValue: CInt(name))\n        )\n    }\n    #endif\n\n    func unsafeGetSocketOption<Value: Sendable>(\n        level: NIOBSDSocket.OptionLevel,\n        name: NIOBSDSocket.Option\n    ) -> EventLoopFuture<Value> {\n        if eventLoop.inEventLoop {\n            let promise = eventLoop.makePromise(of: Value.self)\n            executeAndComplete(promise) {\n                try getSocketOption0(level: level, name: name)\n            }\n            return promise.futureResult\n        } else {\n            return eventLoop.submit {\n                try self.getSocketOption0(level: level, name: name)\n            }\n        }\n    }\n\n    func setSocketOption0<Value>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option, value: Value) throws {\n        try self.socket.setOption(level: level, name: name, value: value)\n    }\n\n    func getSocketOption0<Value>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) throws -> Value {\n        try self.socket.getOption(level: level, name: name)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/BaseSocketChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\n\nprivate struct SocketChannelLifecycleManager {\n    // MARK: Types\n    private enum State {\n        case fresh\n        case preRegistered  // register() has been run but the selector doesn't know about it yet\n        case fullyRegistered  // fully registered, ie. the selector knows about it\n        case preActivation  // activated, but we have not fired channelActivated yet\n        case fullyActivated  // fully activated, i.e., the signal has been fired\n        case closed\n    }\n\n    private enum Event {\n        case beginActivation\n        case finishActivation\n        case beginRegistration\n        case finishRegistration\n        case close\n    }\n\n    // MARK: properties\n    private let eventLoop: EventLoop\n    // this is queried from the Channel, ie. must be thread-safe\n    internal let isActiveAtomic: ManagedAtomic<Bool>\n    // these are only to be accessed on the EventLoop\n\n    // have we seen the `.readEOF` notification\n    // note: this can be `false` on a deactivated channel, we might just have torn it down.\n    var hasSeenEOFNotification: Bool = false\n\n    // Should we support transition from `active` to `active`, used by datagram sockets.\n    let supportsReconnect: Bool\n\n    private var currentState: State = .fresh {\n        didSet {\n            self.eventLoop.assertInEventLoop()\n            switch (oldValue, self.currentState) {\n            case (_, .preActivation):\n                self.isActiveAtomic.store(true, ordering: .relaxed)\n            case (.preActivation, .fullyActivated):\n                ()  // Stay active\n            case (.preActivation, _), (.fullyActivated, _):\n                self.isActiveAtomic.store(false, ordering: .relaxed)\n            default:\n                ()\n            }\n        }\n    }\n\n    // MARK: API\n    // isActiveAtomic needs to be injected as it's accessed from arbitrary threads and `SocketChannelLifecycleManager` is usually held mutable\n    internal init(\n        eventLoop: EventLoop,\n        isActiveAtomic: ManagedAtomic<Bool>,\n        supportReconnect: Bool\n    ) {\n        self.eventLoop = eventLoop\n        self.isActiveAtomic = isActiveAtomic\n        self.supportsReconnect = supportReconnect\n    }\n\n    // this is called from Channel's deinit, so don't assert we're on the EventLoop!\n    internal var canBeDestroyed: Bool {\n        self.currentState == .closed\n    }\n\n    // we need to return a closure here and to not suffer from a potential allocation for that this must be inlined\n    @inline(__always)\n    internal mutating func beginRegistration() -> ((EventLoopPromise<Void>?, ChannelPipeline) -> Void) {\n        self.moveState(event: .beginRegistration)\n    }\n\n    // we need to return a closure here and to not suffer from a potential allocation for that this must be inlined\n    @inline(__always)\n    internal mutating func finishRegistration() -> ((EventLoopPromise<Void>?, ChannelPipeline) -> Void) {\n        self.moveState(event: .finishRegistration)\n    }\n\n    // we need to return a closure here and to not suffer from a potential allocation for that this must be inlined\n    @inline(__always)\n    internal mutating func close() -> ((EventLoopPromise<Void>?, ChannelPipeline) -> Void) {\n        self.moveState(event: .close)\n    }\n\n    // we need to return a closure here and to not suffer from a potential allocation for that this must be inlined\n    @inline(__always)\n    internal mutating func beginActivation() -> ((EventLoopPromise<Void>?, ChannelPipeline) -> Void) {\n        self.moveState(event: .beginActivation)\n    }\n\n    @inline(__always)\n    internal mutating func finishActivation() -> ((EventLoopPromise<Void>?, ChannelPipeline) -> Void) {\n        self.moveState(event: .finishActivation)\n    }\n\n    // MARK: private API\n    // we need to return a closure here and to not suffer from a potential allocation for that this must be inlined\n    @inline(__always)\n    private mutating func moveState(event: Event) -> ((EventLoopPromise<Void>?, ChannelPipeline) -> Void) {\n        self.eventLoop.assertInEventLoop()\n\n        switch (self.currentState, event) {\n        // origin: .fresh\n        case (.fresh, .beginRegistration):\n            self.currentState = .preRegistered\n            return { promise, pipeline in\n                promise?.succeed(())\n                pipeline.syncOperations.fireChannelRegistered()\n            }\n\n        case (.fresh, .close):\n            self.currentState = .closed\n            return { (promise, _: ChannelPipeline) in\n                promise?.succeed(())\n            }\n\n        // origin: .preRegistered\n        case (.preRegistered, .finishRegistration):\n            self.currentState = .fullyRegistered\n            return { (promise, _: ChannelPipeline) in\n                promise?.succeed(())\n            }\n\n        // origin: .fullyRegistered\n        case (.fullyRegistered, .beginActivation):\n            self.currentState = .preActivation\n            return { promise, pipeline in\n                promise?.succeed(())\n            }\n\n        // origin: .preRegistered || .fullyRegistered\n        case (.preRegistered, .close), (.fullyRegistered, .close):\n            self.currentState = .closed\n            return { promise, pipeline in\n                promise?.succeed(())\n                pipeline.syncOperations.fireChannelUnregistered()\n            }\n\n        // origin: .preActivation\n        case (.preActivation, .finishActivation):\n            self.currentState = .fullyActivated\n            return { promise, pipeline in\n                assert(promise == nil)\n                pipeline.syncOperations.fireChannelActive()\n            }\n\n        case (.preActivation, .close):\n            self.currentState = .closed\n            return { promise, pipeline in\n                promise?.succeed(())\n                // Don't fire channelInactive here.\n                pipeline.syncOperations.fireChannelUnregistered()\n            }\n\n        case (.preActivation, .beginActivation) where self.supportsReconnect:\n            return { promise, pipeline in\n                promise?.succeed(())\n            }\n\n        // origin: .fullyActivated\n        case (.fullyActivated, .close):\n            self.currentState = .closed\n            return { promise, pipeline in\n                promise?.succeed(())\n                pipeline.syncOperations.fireChannelInactive()\n                pipeline.syncOperations.fireChannelUnregistered()\n            }\n\n        case (.fullyActivated, .beginActivation) where self.supportsReconnect:\n            return { promise, pipeline in\n                promise?.succeed(())\n            }\n\n        case (.fullyActivated, .finishActivation) where self.supportsReconnect:\n            return { promise, pipeline in\n                assert(promise == nil)\n            }\n\n        // bad transitions\n        case (.fresh, .beginActivation),  // should go through .registered first\n            (.fresh, .finishActivation),  // should go through .registerd first\n            (.preRegistered, .beginActivation),  // need to first be fully registered\n            (.preRegistered, .finishActivation),  // need to first be fully registered\n            (.preRegistered, .beginRegistration),  // already registered\n            (.fullyRegistered, .beginRegistration),  // already registered\n            (.fullyRegistered, .finishActivation),  // need to activate first\n            (.preActivation, .beginActivation),  // already activated\n            (.preActivation, .beginRegistration),  // already fully registered (and activated)\n            (.preActivation, .finishRegistration),  // already fully registered (and activated)\n            (.fullyActivated, .beginActivation),  // need to activate first\n            (.fullyActivated, .beginRegistration),  // already fully registered\n            (.fullyActivated, .finishRegistration),  // already fully registered\n            (.fullyActivated, .finishActivation),  // already signaled\n            (.fullyRegistered, .finishRegistration),  // already fully registered\n            (.fresh, .finishRegistration),  // need to register lazily first\n            (.closed, _):  // already closed\n            self.badTransition(event: event)\n        }\n    }\n\n    private func badTransition(event: Event) -> Never {\n        preconditionFailure(\"illegal transition: state=\\(self.currentState), event=\\(event)\")\n    }\n\n    // MARK: convenience properties\n    internal var isActive: Bool {\n        self.eventLoop.assertInEventLoop()\n        switch self.currentState {\n        case .preActivation, .fullyActivated:\n            return true\n        case .fresh, .preRegistered, .fullyRegistered, .closed:\n            return false\n        }\n    }\n\n    internal var isPreRegistered: Bool {\n        self.eventLoop.assertInEventLoop()\n        switch self.currentState {\n        case .fresh, .closed:\n            return false\n        case .preRegistered, .fullyRegistered, .preActivation, .fullyActivated:\n            return true\n        }\n    }\n\n    internal var isRegisteredFully: Bool {\n        self.eventLoop.assertInEventLoop()\n        switch self.currentState {\n        case .fresh, .closed, .preRegistered:\n            return false\n        case .fullyRegistered, .preActivation, .fullyActivated:\n            return true\n        }\n    }\n\n    /// Returns whether the underlying file descriptor is open. This property will always be true (even before registration)\n    /// until the Channel is closed.\n    internal var isOpen: Bool {\n        self.eventLoop.assertInEventLoop()\n        return self.currentState != .closed\n    }\n}\n\n/// The base class for all socket-based channels in NIO.\n///\n/// There are many types of specialised socket-based channel in NIO. Each of these\n/// has different logic regarding how exactly they read from and write to the network.\n/// However, they share a great deal of common logic around the managing of their\n/// file descriptors.\n///\n/// For this reason, `BaseSocketChannel` exists to provide a common core implementation of\n/// the `SelectableChannel` protocol. It uses a number of private functions to provide hooks\n/// for subclasses to implement the specific logic to handle their writes and reads.\nclass BaseSocketChannel<SocketType: BaseSocketProtocol>: SelectableChannel, ChannelCore, @unchecked Sendable {\n    typealias SelectableType = SocketType.SelectableType\n\n    struct AddressCache {\n        // deliberately lets because they must always be updated together (so forcing `init` is useful).\n        let local: SocketAddress?\n        let remote: SocketAddress?\n\n        init(local: SocketAddress?, remote: SocketAddress?) {\n            self.local = local\n            self.remote = remote\n        }\n    }\n\n    // MARK: - Stored Properties\n    // MARK: Constants & atomics (accessible everywhere)\n    public let parent: Channel?\n    internal let socket: SocketType\n    private let closePromise: EventLoopPromise<Void>\n    internal let selectableEventLoop: SelectableEventLoop\n    private let _offEventLoopLock = NIOLock()\n    private let isActiveAtomic: ManagedAtomic<Bool> = .init(false)\n    // just a thread-safe way of having something to print about the socket from any thread\n    internal let socketDescription: String\n\n    // MARK: Variables, on EventLoop thread only\n    var readPending = false\n    var pendingConnect: Optional<EventLoopPromise<Void>>\n    var recvBufferPool: NIOPooledRecvBufferAllocator\n    var maxMessagesPerRead: UInt = 4\n    private var inFlushNow: Bool = false  // Guard against re-entrance of flushNow() method.\n    private var autoRead: Bool = true\n\n    // MARK: Variables that are really constant\n    // this is really a constant (set in .init) but needs `self` to be constructed and\n    // therefore a `var`. Do not change as this needs to accessed from arbitrary threads\n    private var _pipeline: ChannelPipeline! = nil\n\n    // MARK: Special variables, please read comments.\n    // For reads guarded by _either_ `self._offEventLoopLock` or the EL thread\n    // Writes are guarded by _offEventLoopLock _and_ the EL thread.\n    // PLEASE don't use these directly and use the non-underscored computed properties instead.\n    private var _addressCache = AddressCache(local: nil, remote: nil)  // please use `self.addressesCached` instead\n    private var _bufferAllocatorCache: ByteBufferAllocator  // please use `self.bufferAllocatorCached` instead.\n\n    // MARK: - Computed properties\n    // This is called from arbitrary threads.\n    internal var addressesCached: AddressCache {\n        get {\n            if self.eventLoop.inEventLoop {\n                return self._addressCache\n            } else {\n                return self._offEventLoopLock.withLock {\n                    self._addressCache\n                }\n            }\n        }\n        set {\n            self.eventLoop.preconditionInEventLoop()\n            self._offEventLoopLock.withLock {\n                self._addressCache = newValue\n            }\n        }\n    }\n\n    // This is called from arbitrary threads.\n    private var bufferAllocatorCached: ByteBufferAllocator {\n        get {\n            if self.eventLoop.inEventLoop {\n                return self._bufferAllocatorCache\n            } else {\n                return self._offEventLoopLock.withLock {\n                    self._bufferAllocatorCache\n                }\n            }\n        }\n        set {\n            self.eventLoop.preconditionInEventLoop()\n            self._offEventLoopLock.withLock {\n                self._bufferAllocatorCache = newValue\n            }\n        }\n    }\n\n    // We start with the invalid empty set of selector events we're interested in. This is to make sure we later on\n    // (in `becomeFullyRegistered0`) seed the initial event correctly.\n    internal var interestedEvent: SelectorEventSet = [] {\n        didSet {\n            assert(self.interestedEvent.contains(.reset), \"impossible to unregister for reset\")\n        }\n    }\n\n    private var lifecycleManager: SocketChannelLifecycleManager {\n        didSet {\n            self.eventLoop.assertInEventLoop()\n        }\n    }\n\n    private var bufferAllocator: ByteBufferAllocator = ByteBufferAllocator() {\n        didSet {\n            self.eventLoop.assertInEventLoop()\n            self.bufferAllocatorCached = self.bufferAllocator\n        }\n    }\n\n    public final var _channelCore: ChannelCore { self }\n\n    // This is `Channel` API so must be thread-safe.\n    public final var localAddress: SocketAddress? {\n        self.addressesCached.local\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    public final var remoteAddress: SocketAddress? {\n        self.addressesCached.remote\n    }\n\n    /// `false` if the whole `Channel` is closed and so no more IO operation can be done.\n    var isOpen: Bool {\n        self.eventLoop.assertInEventLoop()\n        return self.lifecycleManager.isOpen\n    }\n\n    var isRegistered: Bool {\n        self.eventLoop.assertInEventLoop()\n        return self.lifecycleManager.isPreRegistered\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    public var isActive: Bool {\n        self.isActiveAtomic.load(ordering: .relaxed)\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    public final var closeFuture: EventLoopFuture<Void> {\n        self.closePromise.futureResult\n    }\n\n    public final var eventLoop: EventLoop {\n        selectableEventLoop\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    public var isWritable: Bool {\n        true\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    public final var allocator: ByteBufferAllocator {\n        self.bufferAllocatorCached\n    }\n\n    // This is `Channel` API so must be thread-safe.\n    public final var pipeline: ChannelPipeline {\n        self._pipeline\n    }\n\n    // MARK: Methods to override in subclasses.\n    func writeToSocket() throws -> OverallWriteResult {\n        fatalError(\"must be overridden\")\n    }\n\n    /// Read data from the underlying socket and dispatch it to the `ChannelPipeline`\n    ///\n    /// - Returns: `true` if any data was read, `false` otherwise.\n    @discardableResult func readFromSocket() throws -> ReadResult {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    // MARK: - Datatypes\n\n    /// Indicates if a selectable should registered or not for IO notifications.\n    enum IONotificationState {\n        /// We should be registered for IO notifications.\n        case register\n\n        /// We should not be registered for IO notifications.\n        case unregister\n    }\n\n    enum ReadResult {\n        /// Nothing was read by the read operation.\n        case none\n\n        /// Some data was read by the read operation.\n        case some\n    }\n\n    /// Returned by the `private func readable0()` to inform the caller about the current state of the underlying read stream.\n    /// This is mostly useful when receiving `.readEOF` as we then need to drain the read stream fully (ie. until we receive EOF or error of course)\n    private enum ReadStreamState: Equatable {\n        /// Everything seems normal\n        case normal(ReadResult)\n\n        /// We saw EOF.\n        case eof\n\n        /// A read error was received.\n        case error\n    }\n\n    /// Begin connection of the underlying socket.\n    ///\n    /// - Parameters:\n    ///   - to: The `SocketAddress` to connect to.\n    /// - Returns: `true` if the socket connected synchronously, `false` otherwise.\n    func connectSocket(to address: SocketAddress) throws -> Bool {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    /// Begin connection of the underlying socket.\n    ///\n    /// - Parameters:\n    ///   - to: The `VsockAddress` to connect to.\n    /// - Returns: `true` if the socket connected synchronously, `false` otherwise.\n    func connectSocket(to address: VsockAddress) throws -> Bool {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    enum ConnectTarget {\n        case socketAddress(SocketAddress)\n        case vsockAddress(VsockAddress)\n    }\n\n    /// Begin connection of the underlying socket.\n    ///\n    /// - Parameters:\n    ///   - to: The target to connect to.\n    /// - Returns: `true` if the socket connected synchronously, `false` otherwise.\n    final func connectSocket(to target: ConnectTarget) throws -> Bool {\n        switch target {\n        case .socketAddress(let address):\n            return try self.connectSocket(to: address)\n        case .vsockAddress(let address):\n            return try self.connectSocket(to: address)\n        }\n    }\n\n    /// Make any state changes needed to complete the connection process.\n    func finishConnectSocket() throws {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    /// Returns if there are any flushed, pending writes to be sent over the network.\n    func hasFlushedPendingWrites() -> Bool {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    /// Buffer a write in preparation for a flush.\n    func bufferPendingWrite(data: NIOAny, promise: EventLoopPromise<Void>?) {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    /// Mark a flush point. This is called when flush is received, and instructs\n    /// the implementation to record the flush.\n    func markFlushPoint() {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    /// Called when closing, to instruct the specific implementation to discard all pending\n    /// writes.\n    func cancelWritesOnClose(error: Error) {\n        fatalError(\"this must be overridden by sub class\")\n    }\n\n    // MARK: Common base socket logic.\n    init(\n        socket: SocketType,\n        parent: Channel?,\n        eventLoop: SelectableEventLoop,\n        recvAllocator: RecvByteBufferAllocator,\n        supportReconnect: Bool\n    ) throws {\n        self._bufferAllocatorCache = self.bufferAllocator\n        self.socket = socket\n        self.selectableEventLoop = eventLoop\n        self.closePromise = eventLoop.makePromise()\n        self.parent = parent\n        self.recvBufferPool = .init(capacity: Int(self.maxMessagesPerRead), recvAllocator: recvAllocator)\n        // As the socket may already be connected we should ensure we start with the correct addresses cached.\n        self._addressCache = .init(local: try? socket.localAddress(), remote: try? socket.remoteAddress())\n        self.lifecycleManager = SocketChannelLifecycleManager(\n            eventLoop: eventLoop,\n            isActiveAtomic: self.isActiveAtomic,\n            supportReconnect: supportReconnect\n        )\n        self.socketDescription = socket.description\n        self.pendingConnect = nil\n        self._pipeline = ChannelPipeline(channel: self)\n    }\n\n    deinit {\n        assert(\n            self.lifecycleManager.canBeDestroyed,\n            \"leak of open Channel, state: \\(String(describing: self.lifecycleManager))\"\n        )\n    }\n\n    public final func localAddress0() throws -> SocketAddress {\n        self.eventLoop.assertInEventLoop()\n        guard self.isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n        return try self.socket.localAddress()\n    }\n\n    public final func remoteAddress0() throws -> SocketAddress {\n        self.eventLoop.assertInEventLoop()\n        guard self.isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n        return try self.socket.remoteAddress()\n    }\n\n    /// Flush data to the underlying socket and return if this socket needs to be registered for write notifications.\n    ///\n    /// This method can be called re-entrantly but it will return immediately because the first call is responsible\n    /// for sending all flushed writes, even the ones that are accumulated whilst `flushNow()` is running.\n    ///\n    /// - Returns: If this socket should be registered for write notifications. Ie. `IONotificationState.register` if\n    ///            _not_ all data could be written, so notifications are necessary; and `IONotificationState.unregister`\n    ///             if everything was written and we don't need to be notified about writability at the moment.\n    func flushNow() -> IONotificationState {\n        self.eventLoop.assertInEventLoop()\n\n        // Guard against re-entry as data that will be put into `pendingWrites` will just be picked up by\n        // `writeToSocket`.\n        guard !self.inFlushNow else {\n            return .unregister\n        }\n\n        assert(!self.inFlushNow)\n        self.inFlushNow = true\n        defer {\n            self.inFlushNow = false\n        }\n\n        var newWriteRegistrationState: IONotificationState = .unregister\n        while newWriteRegistrationState == .unregister && self.hasFlushedPendingWrites() && self.isOpen {\n            let writeResult: OverallWriteResult\n            do {\n                assert(self.lifecycleManager.isActive)\n                writeResult = try self.writeToSocket()\n                if writeResult.writabilityChange {\n                    // We went from not writable to writable.\n                    self.pipeline.syncOperations.fireChannelWritabilityChanged()\n                }\n            } catch let err {\n                // If there is a write error we should try drain the inbound before closing the socket as there may be some data pending.\n                // We ignore any error that is thrown as we will use the original err to close the channel and notify the user.\n                if self.readIfNeeded0() {\n                    assert(self.lifecycleManager.isActive)\n\n                    // We need to continue reading until there is nothing more to be read from the socket as we will not have another chance to drain it.\n                    var readAtLeastOnce = false\n                    while let read = try? self.readFromSocket(), read == .some {\n                        readAtLeastOnce = true\n                    }\n                    if readAtLeastOnce && self.lifecycleManager.isActive {\n                        self.pipeline.fireChannelReadComplete()\n                    }\n                }\n\n                self.close0(error: err, mode: .all, promise: nil)\n\n                // we handled all writes\n                return .unregister\n            }\n\n            switch writeResult.writeResult {\n            case .couldNotWriteEverything:\n                newWriteRegistrationState = .register\n            case .writtenCompletely(let closeState):\n                newWriteRegistrationState = .unregister\n                switch closeState {\n                case .open:\n                    ()\n                case .readyForClose:\n                    self.close0(error: ChannelError.outputClosed, mode: .output, promise: nil)\n                case .closed:\n                    ()  // we can be flushed before becoming active\n                }\n            }\n\n            if !self.isOpen || !self.hasFlushedPendingWrites() {\n                // No further writes, unregister. We won't re-enter the loop as both of these would have to be true.\n                newWriteRegistrationState = .unregister\n            }\n        }\n\n        assert(\n            (newWriteRegistrationState == .register && self.hasFlushedPendingWrites())\n                || (newWriteRegistrationState == .unregister && !self.hasFlushedPendingWrites()),\n            \"illegal flushNow decision: \\(newWriteRegistrationState) and \\(self.hasFlushedPendingWrites())\"\n        )\n        return newWriteRegistrationState\n    }\n\n    public final func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void> {\n        if eventLoop.inEventLoop {\n            let promise = eventLoop.makePromise(of: Void.self)\n            executeAndComplete(promise) { try self.setOption0(option, value: value) }\n            return promise.futureResult\n        } else {\n            return eventLoop.submit { try self.setOption0(option, value: value) }\n        }\n    }\n\n    func setOption0<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case let option as ChannelOptions.Types.SocketOption:\n            try self.setSocketOption0(level: option.optionLevel, name: option.optionName, value: value)\n        case _ as ChannelOptions.Types.AllocatorOption:\n            bufferAllocator = value as! ByteBufferAllocator\n        case _ as ChannelOptions.Types.RecvAllocatorOption:\n            self.recvBufferPool.recvAllocator = value as! RecvByteBufferAllocator\n        case _ as ChannelOptions.Types.AutoReadOption:\n            let auto = value as! Bool\n            let old = self.autoRead\n            self.autoRead = auto\n\n            // We only want to call read0() or pauseRead0() if we already registered to the EventLoop if not this will be automatically done\n            // once register0 is called. Beside this we also only need to do it when the value actually change.\n            if self.lifecycleManager.isPreRegistered && old != auto {\n                if auto {\n                    read0()\n                } else {\n                    pauseRead0()\n                }\n            }\n        case _ as ChannelOptions.Types.MaxMessagesPerReadOption:\n            self.maxMessagesPerRead = value as! UInt\n            self.recvBufferPool.updateCapacity(to: Int(self.maxMessagesPerRead))\n        default:\n            fatalError(\"option \\(option) not supported\")\n        }\n    }\n\n    public func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value> {\n        if eventLoop.inEventLoop {\n            do {\n                return self.eventLoop.makeSucceededFuture(try self.getOption0(option))\n            } catch {\n                return self.eventLoop.makeFailedFuture(error)\n            }\n        } else {\n            return self.eventLoop.submit { try self.getOption0(option) }\n        }\n    }\n\n    func getOption0<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case let option as ChannelOptions.Types.SocketOption:\n            return try self.getSocketOption0(level: option.optionLevel, name: option.optionName)\n        case _ as ChannelOptions.Types.AllocatorOption:\n            return bufferAllocator as! Option.Value\n        case _ as ChannelOptions.Types.RecvAllocatorOption:\n            return self.recvBufferPool.recvAllocator as! Option.Value\n        case _ as ChannelOptions.Types.AutoReadOption:\n            return autoRead as! Option.Value\n        case _ as ChannelOptions.Types.MaxMessagesPerReadOption:\n            return maxMessagesPerRead as! Option.Value\n        default:\n            fatalError(\"option \\(option) not supported\")\n        }\n    }\n\n    /// Triggers a `ChannelPipeline.read()` if `autoRead` is enabled.`\n    ///\n    /// - Returns: `true` if `readPending` is `true`, `false` otherwise.\n    @discardableResult func readIfNeeded0() -> Bool {\n        self.eventLoop.assertInEventLoop()\n        if !self.lifecycleManager.isActive {\n            return false\n        }\n\n        if !readPending && autoRead {\n            self.pipeline.syncOperations.read()\n        }\n        return readPending\n    }\n\n    // Methods invoked from the HeadHandler of the ChannelPipeline\n    public func bind0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n            return\n        }\n\n        executeAndComplete(promise) {\n            try socket.bind(to: address)\n            self.updateCachedAddressesFromSocket(updateRemote: false)\n        }\n    }\n\n    public final func write0(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            // Channel was already closed, fail the promise and not even queue it.\n            promise?.fail(ChannelError._ioOnClosedChannel)\n            return\n        }\n\n        bufferPendingWrite(data: data, promise: promise)\n    }\n\n    private func registerForWritable() {\n        self.eventLoop.assertInEventLoop()\n\n        guard !self.interestedEvent.contains(.write) else {\n            // nothing to do if we were previously interested in write\n            return\n        }\n        self.safeReregister(interested: self.interestedEvent.union(.write))\n    }\n\n    func unregisterForWritable() {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.interestedEvent.contains(.write) else {\n            // nothing to do if we were not previously interested in write\n            return\n        }\n        self.safeReregister(interested: self.interestedEvent.subtracting(.write))\n    }\n\n    public final func flush0() {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            return\n        }\n\n        self.markFlushPoint()\n\n        guard self.lifecycleManager.isActive else {\n            return\n        }\n\n        if !isWritePending() && flushNow() == .register {\n            assert(self.lifecycleManager.isPreRegistered)\n            registerForWritable()\n        }\n    }\n\n    public func read0() {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            return\n        }\n        readPending = true\n\n        if self.lifecycleManager.isPreRegistered {\n            registerForReadable()\n        }\n    }\n\n    private final func pauseRead0() {\n        self.eventLoop.assertInEventLoop()\n\n        if self.lifecycleManager.isPreRegistered {\n            unregisterForReadable()\n        }\n    }\n\n    private final func registerForReadable() {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isRegisteredFully)\n\n        guard !self.lifecycleManager.hasSeenEOFNotification else {\n            // we have seen an EOF notification before so there's no point in registering for reads\n            return\n        }\n\n        guard !self.interestedEvent.contains(.read) else {\n            return\n        }\n\n        self.safeReregister(interested: self.interestedEvent.union(.read))\n    }\n\n    private final func registerForReadEOF() {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isRegisteredFully)\n\n        guard !self.lifecycleManager.hasSeenEOFNotification else {\n            // we have seen an EOF notification before so there's no point in registering for reads\n            return\n        }\n\n        guard !self.interestedEvent.contains(.readEOF) else {\n            return\n        }\n\n        self.safeReregister(interested: self.interestedEvent.union(.readEOF))\n    }\n\n    internal final func unregisterForReadable() {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isRegisteredFully)\n\n        guard self.interestedEvent.contains(.read) else {\n            return\n        }\n\n        self.safeReregister(interested: self.interestedEvent.subtracting(.read))\n    }\n\n    /// Closes the this `BaseChannelChannel` and fulfills `promise` with the result of the _close_ operation.\n    /// So unless either the deregistration or the close itself fails, `promise` will be succeeded regardless of\n    /// `error`. `error` is used to fail outstanding writes (if any) and the `connectPromise` if set.\n    ///\n    /// - Parameters:\n    ///    - error: The error to fail the outstanding (if any) writes/connect with.\n    ///    - mode: The close mode, must be `.all` for `BaseSocketChannel`\n    ///    - promise: The promise that gets notified about the result of the deregistration/close operations.\n    public func close0(error: Error, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            promise?.fail(ChannelError._alreadyClosed)\n            return\n        }\n\n        guard mode == .all else {\n            promise?.fail(ChannelError._operationUnsupported)\n            return\n        }\n\n        // === BEGIN: No user callouts ===\n\n        // this is to register all error callouts as all the callouts must happen after we transition out state\n        var errorCallouts: [(ChannelPipeline) -> Void] = []\n\n        self.interestedEvent = .reset\n        do {\n            try selectableEventLoop.deregister(channel: self)\n        } catch let err {\n            errorCallouts.append { pipeline in\n                pipeline.syncOperations.fireErrorCaught(err)\n            }\n        }\n\n        let p: EventLoopPromise<Void>?\n        do {\n            try socket.close()\n            p = promise\n        } catch {\n            errorCallouts.append { (_: ChannelPipeline) in\n                promise?.fail(error)\n                // Set p to nil as we want to ensure we pass nil to becomeInactive0(...) so we not try to notify the promise again.\n            }\n            p = nil\n        }\n\n        // Transition our internal state.\n        let callouts = self.lifecycleManager.close()\n\n        // === END: No user callouts (now that our state is reconciled, we can call out to user code.) ===\n\n        // this must be the first to call out as it transitions the PendingWritesManager into the closed state\n        // and we assert elsewhere that the PendingWritesManager has the same idea of 'open' as we have in here.\n        self.cancelWritesOnClose(error: error)\n\n        // this should be a no-op as we shouldn't have any\n        for callout in errorCallouts {\n            callout(self.pipeline)\n        }\n\n        if let connectPromise = self.pendingConnect {\n            self.pendingConnect = nil\n            connectPromise.fail(error)\n        }\n\n        callouts(p, self.pipeline)\n\n        eventLoop.execute {\n            // ensure this is executed in a delayed fashion as the users code may still traverse the pipeline\n            self.removeHandlers(pipeline: self.pipeline)\n\n            self.closePromise.succeed(())\n\n            // Now reset the addresses as we notified all handlers / futures.\n            self.unsetCachedAddressesFromSocket()\n        }\n    }\n\n    public final func register0(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n            return\n        }\n\n        guard !self.lifecycleManager.isPreRegistered else {\n            promise?.fail(ChannelError._inappropriateOperationForState)\n            return\n        }\n\n        guard self.selectableEventLoop.isOpen else {\n            let error = EventLoopError._shutdown\n            self.pipeline.syncOperations.fireErrorCaught(error)\n            // `close0`'s error is about the result of the `close` operation, ...\n            self.close0(error: error, mode: .all, promise: nil)\n            // ... therefore we need to fail the registration `promise` separately.\n            promise?.fail(error)\n            return\n        }\n\n        // we can't fully register yet as epoll would give us EPOLLHUP if bind/connect wasn't called yet.\n        self.lifecycleManager.beginRegistration()(promise, self.pipeline)\n    }\n\n    public final func registerAlreadyConfigured0(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n        assert(self.isOpen)\n        assert(!self.lifecycleManager.isActive)\n        let registerPromise = self.eventLoop.makePromise(of: Void.self)\n        self.register0(promise: registerPromise)\n        registerPromise.futureResult.whenFailure { (_: Error) in\n            self.close(promise: nil)\n        }\n        registerPromise.futureResult.cascadeFailure(to: promise)\n\n        if self.lifecycleManager.isPreRegistered {\n            // we expect kqueue/epoll registration to always succeed which is basically true, except for errors that\n            // should be fatal (EBADF, EFAULT, ESRCH, ENOMEM) and a two 'table full' (EMFILE, ENFILE) error kinds which\n            // we don't handle yet but might do in the future (#469).\n            try! becomeFullyRegistered0()\n            if self.lifecycleManager.isRegisteredFully {\n                self.becomeActive0(promise: promise)\n            }\n        }\n    }\n\n    public func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?) {\n        switch event {\n        case let event as VsockChannelEvents.ConnectToAddress:\n            self.connect0(to: .vsockAddress(event.address), promise: promise)\n        default:\n            promise?.fail(ChannelError._operationUnsupported)\n        }\n    }\n\n    // Methods invoked from the EventLoop itself\n    public final func writable() {\n        self.eventLoop.assertInEventLoop()\n        assert(self.isOpen)\n\n        self.finishConnect()  // If we were connecting, that has finished.\n\n        switch self.flushNow() {\n        case .unregister:\n            // Everything was written or connect was complete, let's unregister from writable.\n            self.finishWritable()\n        case .register:\n            assert(!self.isOpen || self.interestedEvent.contains(.write))\n            ()  // nothing to do because given that we just received `writable`, we're still registered for writable.\n        }\n    }\n\n    private func finishConnect() {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isPreRegistered)\n\n        if let connectPromise = self.pendingConnect {\n            assert(!self.lifecycleManager.isActive)\n\n            do {\n                try self.finishConnectSocket()\n            } catch {\n                assert(!self.lifecycleManager.isActive)\n                // close0 fails the connectPromise itself so no need to do it here\n                self.close0(error: error, mode: .all, promise: nil)\n                return\n            }\n            // now this has succeeded, becomeActive0 will actually fulfill this.\n            self.pendingConnect = nil\n            // We already know what the local address is.\n            self.updateCachedAddressesFromSocket(updateLocal: false, updateRemote: true)\n            self.becomeActive0(promise: connectPromise)\n        } else {\n            assert(self.lifecycleManager.isActive)\n        }\n    }\n\n    private func finishWritable() {\n        self.eventLoop.assertInEventLoop()\n\n        if self.isOpen {\n            assert(self.lifecycleManager.isPreRegistered)\n            assert(!self.hasFlushedPendingWrites())\n            self.unregisterForWritable()\n        }\n    }\n\n    func writeEOF() {\n        fatalError(\"\\(self) received writeEOF which is unexpected\")\n    }\n\n    func readEOF() {\n        assert(!self.lifecycleManager.hasSeenEOFNotification)\n        self.lifecycleManager.hasSeenEOFNotification = true\n\n        // we can't be not active but still registered here; this would mean that we got a notification about a\n        // channel before we're ready to receive them.\n        assert(\n            self.lifecycleManager.isRegisteredFully,\n            \"illegal state: \\(self): active: \\(self.lifecycleManager.isActive), registered: \\(self.lifecycleManager.isRegisteredFully)\"\n        )\n\n        self.readEOF0()\n\n        assert(!self.interestedEvent.contains(.read))\n        assert(!self.interestedEvent.contains(.readEOF))\n    }\n\n    final func readEOF0() {\n        if self.lifecycleManager.isRegisteredFully {\n            // we're unregistering from `readEOF` here as we want this to be one-shot. We're then synchronously\n            // reading all input until the EOF that we're guaranteed to see. After that `readEOF` becomes uninteresting\n            // and would anyway fire constantly.\n            self.safeReregister(interested: self.interestedEvent.subtracting(.readEOF))\n\n            loop: while self.lifecycleManager.isActive {\n                switch self.readable0() {\n                case .eof:\n                    // on EOF we stop the loop and we're done with our processing for `readEOF`.\n                    // we could both be registered & active (if our channel supports half-closure) or unregistered & inactive (if it doesn't).\n                    break loop\n                case .error:\n                    // we should be unregistered and inactive now (as `readable0` would've called close).\n                    assert(!self.lifecycleManager.isActive)\n                    assert(!self.lifecycleManager.isPreRegistered)\n                    break loop\n                case .normal(.none):\n                    preconditionFailure(\"got .readEOF and read returned not reading any bytes, nor EOF.\")\n                case .normal(.some):\n                    // normal, note that there is no guarantee we're still active (as the user might have closed in callout)\n                    continue loop\n                }\n            }\n        }\n    }\n\n    // this _needs_ to synchronously cause the fd to be unregistered because we cannot unregister from `reset`. In\n    // other words: Failing to unregister the whole selector will cause NIO to spin at 100% CPU constantly delivering\n    // the `reset` event.\n    final func reset() {\n        self.readEOF0()\n\n        if self.socket.isOpen {\n            assert(self.lifecycleManager.isPreRegistered)\n            let error: IOError\n            // if the socket is still registered (and therefore open), let's try to get the actual socket error from the socket\n            do {\n                let result: Int32 = try self.socket.getOption(level: .socket, name: .so_error)\n                if result != 0 {\n                    // we have a socket error, let's forward\n                    // this path will be executed on Linux (EPOLLERR) & Darwin (ev.fflags != 0) for\n                    // stream sockets, and most (but not all) errors on datagram sockets\n                    error = IOError(errnoCode: result, reason: \"connection reset (error set)\")\n                } else {\n                    // we don't have a socket error, this must be connection reset without an error then\n                    // this path should only be executed on Linux (EPOLLHUP, no EPOLLERR)\n                    #if os(Linux)\n                    let message: String = \"connection reset (no error set)\"\n                    #else\n                    let message: String =\n                        \"BUG IN SwiftNIO (possibly #572), please report! Connection reset (no error set).\"\n                    #endif\n                    error = IOError(errnoCode: ECONNRESET, reason: message)\n                }\n                self.close0(error: error, mode: .all, promise: nil)\n            } catch {\n                self.close0(error: error, mode: .all, promise: nil)\n            }\n        }\n        assert(!self.lifecycleManager.isPreRegistered)\n    }\n\n    public final func readable() {\n        assert(\n            !self.lifecycleManager.hasSeenEOFNotification,\n            \"got a read notification after having already seen .readEOF\"\n        )\n        self.readable0()\n    }\n\n    @discardableResult\n    private final func readable0() -> ReadStreamState {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isActive)\n\n        defer {\n            if self.isOpen && !self.readPending {\n                unregisterForReadable()\n            }\n        }\n\n        let readResult: ReadResult\n        do {\n            readResult = try self.readFromSocket()\n        } catch let err {\n            let readStreamState: ReadStreamState\n            // ChannelError.eof is not something we want to fire through the pipeline as it just means the remote\n            // peer closed / shutdown the connection.\n            if let channelErr = err as? ChannelError, channelErr == ChannelError.eof {\n                readStreamState = .eof\n\n                if self.lifecycleManager.isActive {\n                    // Directly call getOption0 as we are already on the EventLoop and so not need to create an extra future.\n                    //\n                    // getOption0 can only fail if the channel is not active anymore but we assert further up that it is. If\n                    // that's not the case this is a precondition failure and we would like to know.\n                    let allowRemoteHalfClosure = try! self.getOption0(.allowRemoteHalfClosure)\n\n                    // For EOF, we always fire read complete.\n                    self.pipeline.syncOperations.fireChannelReadComplete()\n\n                    if allowRemoteHalfClosure {\n                        // If we want to allow half closure we will just mark the input side of the Channel\n                        // as closed.\n                        if self.shouldCloseOnReadError(err) {\n                            self.close0(error: err, mode: .input, promise: nil)\n                        }\n                        self.readPending = false\n                        return .eof\n                    }\n                }\n            } else {\n                readStreamState = .error\n                self.pipeline.syncOperations.fireErrorCaught(err)\n            }\n\n            if self.shouldCloseOnReadError(err) {\n                self.close0(error: err, mode: .all, promise: nil)\n                return readStreamState\n            } else {\n                // This is non-fatal, so continue as normal.\n                // This constitutes \"some\" as we did get at least an error from the socket.\n                readResult = .some\n            }\n        }\n        // This assert needs to be disabled for io_uring, as the io_uring backend does not have the implicit synchronisation between\n        // modifications to the poll mask and the actual returned events on the completion queue that kqueue and epoll has.\n        // For kqueue and epoll, there is an implicit synchronisation point such that after a modification of the poll mask has been\n        // issued, the next call to reap events will be sure to not include events which does not match the new poll mask.\n        // Specifically for this assert, it means that we will be guaranteed to never receive a POLLIN notification unless there are\n        // bytes available to read.\n\n        // For a fully asynchronous backend like io_uring, there are no such implicit synchronisation point, so after we have\n        // submitted the asynchronous event to change the poll mask, we may still reap pending asynchronous replies for the old\n        // poll mask, and thus receive a POLLIN even though we have modified the mask visavi the kernel.\n        // Which would trigger the assert.\n\n        // The only way to avoid that race, would be to use heavy handed synchronisation primitives like IOSQE_IO_DRAIN (basically\n        // flushing all pending requests and wait for a fake event result to sync up) which would be awful for performance,\n        // so better skip the assert() for io_uring instead.\n        #if !SWIFTNIO_USE_IO_URING\n        assert(readResult == .some)\n        #endif\n        if self.lifecycleManager.isActive {\n            self.pipeline.syncOperations.fireChannelReadComplete()\n        }\n        self.readIfNeeded0()\n        return .normal(readResult)\n    }\n\n    /// Returns `true` if the `Channel` should be closed as result of the given `Error` which happened during `readFromSocket`.\n    ///\n    /// - Parameters:\n    ///   - err: The `Error` which was thrown by `readFromSocket`.\n    /// - Returns: `true` if the `Channel` should be closed, `false` otherwise.\n    func shouldCloseOnReadError(_ err: Error) -> Bool {\n        true\n    }\n\n    /// Handles an error reported by the selector.\n    ///\n    /// Default behaviour is to treat this as if it were a reset.\n    func error() -> ErrorResult {\n        self.reset()\n        return .fatal\n    }\n\n    internal final func updateCachedAddressesFromSocket(updateLocal: Bool = true, updateRemote: Bool = true) {\n        self.eventLoop.assertInEventLoop()\n        assert(updateLocal || updateRemote)\n        let cached = self.addressesCached\n        let local = updateLocal ? try? self.localAddress0() : cached.local\n        let remote = updateRemote ? try? self.remoteAddress0() : cached.remote\n        self.addressesCached = AddressCache(local: local, remote: remote)\n    }\n\n    internal final func unsetCachedAddressesFromSocket() {\n        self.eventLoop.assertInEventLoop()\n        self.addressesCached = AddressCache(local: nil, remote: nil)\n    }\n\n    public final func connect0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.connect0(to: .socketAddress(address), promise: promise)\n    }\n\n    internal final func connect0(to target: ConnectTarget, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n            return\n        }\n\n        guard pendingConnect == nil else {\n            promise?.fail(ChannelError._connectPending)\n            return\n        }\n\n        guard self.lifecycleManager.isPreRegistered else {\n            promise?.fail(ChannelError._inappropriateOperationForState)\n            return\n        }\n\n        do {\n            if try !self.connectSocket(to: target) {\n                // We aren't connected, we'll get the remote address later.\n                self.updateCachedAddressesFromSocket(updateLocal: true, updateRemote: false)\n                if promise != nil {\n                    self.pendingConnect = promise\n                } else {\n                    self.pendingConnect = eventLoop.makePromise()\n                }\n                try self.becomeFullyRegistered0()\n                self.registerForWritable()\n            } else {\n                self.updateCachedAddressesFromSocket()\n                self.becomeActive0(promise: promise)\n            }\n        } catch let error {\n            assert(self.lifecycleManager.isPreRegistered)\n            // We would like to have this assertion here, but we want to be able to go through this\n            // code path in cases where connect() is being called on channels that are already active.\n            //assert(!self.lifecycleManager.isActive)\n            // We're going to set the promise as the pending connect promise, and let close0 fail it for us.\n            self.pendingConnect = promise\n            self.close0(error: error, mode: .all, promise: nil)\n        }\n    }\n\n    public func channelRead0(_ data: NIOAny) {\n        // Do nothing by default\n        // note: we can't assert that we're active here as TailChannelHandler will call this on channelRead\n    }\n\n    public func errorCaught0(error: Error) {\n        // Do nothing\n    }\n\n    private func isWritePending() -> Bool {\n        self.interestedEvent.contains(.write)\n    }\n\n    private final func safeReregister(interested: SelectorEventSet) {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isRegisteredFully)\n\n        guard self.isOpen else {\n            assert(self.interestedEvent == .reset, \"interestedEvent=\\(self.interestedEvent) even though we're closed\")\n            return\n        }\n        if interested == interestedEvent {\n            // we don't need to update and so cause a syscall if we already are registered with the correct event\n            return\n        }\n        interestedEvent = interested\n        do {\n            try selectableEventLoop.reregister(channel: self)\n        } catch let err {\n            self.pipeline.syncOperations.fireErrorCaught(err)\n            self.close0(error: err, mode: .all, promise: nil)\n        }\n    }\n\n    private func safeRegister(interested: SelectorEventSet) throws {\n        self.eventLoop.assertInEventLoop()\n        assert(!self.lifecycleManager.isRegisteredFully)\n\n        guard self.isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        self.interestedEvent = interested\n        do {\n            try self.selectableEventLoop.register(channel: self)\n        } catch {\n            self.pipeline.syncOperations.fireErrorCaught(error)\n            self.close0(error: error, mode: .all, promise: nil)\n            throw error\n        }\n    }\n\n    final func becomeFullyRegistered0() throws {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isPreRegistered)\n        assert(!self.lifecycleManager.isRegisteredFully)\n\n        // The initial set of interested events must not contain `.readEOF` because when connect doesn't return\n        // synchronously, kevent might send us a `readEOF` because the `writable` event that marks the connect as completed.\n        // See SocketChannelTest.testServerClosesTheConnectionImmediately for a regression test.\n        try self.safeRegister(interested: [.reset, .error])\n        self.lifecycleManager.finishRegistration()(nil, self.pipeline)\n    }\n\n    final func becomeActive0(promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n        assert(self.lifecycleManager.isPreRegistered)\n        if !self.lifecycleManager.isRegisteredFully {\n            do {\n                try self.becomeFullyRegistered0()\n                assert(self.lifecycleManager.isRegisteredFully)\n            } catch {\n                self.close0(error: error, mode: .all, promise: promise)\n                return\n            }\n        }\n        self.lifecycleManager.beginActivation()(promise, self.pipeline)\n        guard self.lifecycleManager.isActive else {\n            // the channel got closed in the promise succeed closure\n            return\n        }\n        // if the channel wasn't closed, continue to fully activate\n        self.lifecycleManager.finishActivation()(nil, self.pipeline)\n        guard self.lifecycleManager.isOpen else {\n            // in the user callout for `channelActive` the channel got closed.\n            return\n        }\n        self.registerForReadEOF()\n\n        // Flush any pending writes. If after the flush we're still open, make sure\n        // our registration is appropriate.\n        switch self.flushNow() {\n        case .register:\n            if self.lifecycleManager.isOpen && !self.interestedEvent.contains(.write) {\n                self.registerForWritable()\n            }\n        case .unregister:\n            if self.lifecycleManager.isOpen && self.interestedEvent.contains(.write) {\n                self.unregisterForWritable()\n            }\n        }\n\n        self.readIfNeeded0()\n    }\n\n    func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        fatalError(\"must override\")\n    }\n\n    func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws {\n        fatalError(\"must override\")\n    }\n\n    func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        fatalError(\"must override\")\n    }\n}\n\nextension BaseSocketChannel {\n    public struct SynchronousOptions: NIOSynchronousChannelOptions {\n        @usableFromInline  // should be private\n        internal let _channel: BaseSocketChannel<SocketType>\n\n        @inlinable  // should be fileprivate\n        internal init(_channel channel: BaseSocketChannel<SocketType>) {\n            self._channel = channel\n        }\n\n        @inlinable\n        public func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n            try self._channel.setOption0(option, value: value)\n        }\n\n        @inlinable\n        public func getOption<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n            try self._channel.getOption0(option)\n        }\n    }\n\n    public final var syncOptions: NIOSynchronousChannelOptions? {\n        SynchronousOptions(_channel: self)\n    }\n}\n\n/// Execute the given function and synchronously complete the given `EventLoopPromise` (if not `nil`).\nfunc executeAndComplete<Value: Sendable>(_ promise: EventLoopPromise<Value>?, _ body: () throws -> Value) {\n    do {\n        let result = try body()\n        promise?.succeed(result)\n    } catch let e {\n        promise?.fail(e)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/BaseStreamSocketChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\nclass BaseStreamSocketChannel<Socket: SocketProtocol>: BaseSocketChannel<Socket>, @unchecked Sendable {\n    internal var connectTimeoutScheduled: Optional<Scheduled<Void>>\n    private var allowRemoteHalfClosure: Bool = false\n    private var inputShutdown: Bool = false\n    private var outputShutdown: Bool = false\n    private let pendingWrites: PendingStreamWritesManager\n\n    init(\n        socket: Socket,\n        parent: Channel?,\n        eventLoop: SelectableEventLoop,\n        recvAllocator: RecvByteBufferAllocator\n    ) throws {\n        self.pendingWrites = PendingStreamWritesManager(bufferPool: eventLoop.bufferPool)\n        self.connectTimeoutScheduled = nil\n        try super.init(\n            socket: socket,\n            parent: parent,\n            eventLoop: eventLoop,\n            recvAllocator: recvAllocator,\n            supportReconnect: false\n        )\n    }\n\n    deinit {\n        // We should never have any pending writes left as otherwise we may leak callbacks\n        assert(self.pendingWrites.isEmpty)\n    }\n\n    // MARK: BaseSocketChannel's must override API that might be further refined by subclasses\n    override func setOption0<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.AllowRemoteHalfClosureOption:\n            self.allowRemoteHalfClosure = value as! Bool\n        case _ as ChannelOptions.Types.WriteSpinOption:\n            self.pendingWrites.writeSpinCount = value as! UInt\n        case _ as ChannelOptions.Types.WriteBufferWaterMarkOption:\n            self.pendingWrites.waterMark = value as! ChannelOptions.Types.WriteBufferWaterMark\n        default:\n            try super.setOption0(option, value: value)\n        }\n    }\n\n    override func getOption0<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.AllowRemoteHalfClosureOption:\n            return self.allowRemoteHalfClosure as! Option.Value\n        case _ as ChannelOptions.Types.WriteSpinOption:\n            return self.pendingWrites.writeSpinCount as! Option.Value\n        case _ as ChannelOptions.Types.WriteBufferWaterMarkOption:\n            return self.pendingWrites.waterMark as! Option.Value\n        case _ as ChannelOptions.Types.BufferedWritableBytesOption:\n            return Int(self.pendingWrites.bufferedBytes) as! Option.Value\n        default:\n            return try super.getOption0(option)\n        }\n    }\n\n    // Hook for customizable socket shutdown processing for subclasses, e.g. PipeChannel\n    func shutdownSocket(mode: CloseMode) throws {\n        switch mode {\n        case .output:\n            try self.socket.shutdown(how: .WR)\n            self.outputShutdown = true\n        case .input:\n            try socket.shutdown(how: .RD)\n            self.inputShutdown = true\n        case .all:\n            break\n        }\n    }\n\n    // MARK: BaseSocketChannel's must override API that cannot be further refined by subclasses\n    // This is `Channel` API so must be thread-safe.\n    final override public var isWritable: Bool {\n        self.pendingWrites.isWritable\n    }\n\n    final override var isOpen: Bool {\n        self.eventLoop.assertInEventLoop()\n        assert(super.isOpen == self.pendingWrites.isOpen)\n        return super.isOpen\n    }\n\n    final override func readFromSocket() throws -> ReadResult {\n        self.eventLoop.assertInEventLoop()\n        var result = ReadResult.none\n        for _ in 1...self.maxMessagesPerRead {\n            guard self.isOpen && !self.inputShutdown else {\n                throw ChannelError._eof\n            }\n\n            let (buffer, readResult) = try self.recvBufferPool.buffer(allocator: self.allocator) { buffer in\n                try buffer.withMutableWritePointer { pointer in\n                    try self.socket.read(pointer: pointer)\n                }\n            }\n\n            // Reset reader and writerIndex and so allow to have the buffer filled again. This is better here than at\n            // the end of the loop to not do an allocation when the loop exits.\n            switch readResult {\n            case .processed(let bytesRead):\n                if bytesRead > 0 {\n                    self.recvBufferPool.record(actualReadBytes: bytesRead)\n                    self.readPending = false\n\n                    assert(self.isActive)\n                    self.pipeline.syncOperations.fireChannelRead(NIOAny(buffer))\n                    result = .some\n\n                    if buffer.writableBytes > 0 {\n                        // If we did not fill the whole buffer with read(...) we should stop reading and wait until we get notified again.\n                        // Otherwise chances are good that the next read(...) call will either read nothing or only a very small amount of data.\n                        // Also this will allow us to call fireChannelReadComplete() which may give the user the chance to flush out all pending\n                        // writes.\n                        return result\n                    }\n                } else {\n                    if self.inputShutdown {\n                        // We received a EOF because we called shutdown on the fd by ourself, unregister from the Selector and return\n                        self.readPending = false\n                        self.unregisterForReadable()\n                        return result\n                    }\n                    // end-of-file\n                    throw ChannelError._eof\n                }\n            case .wouldBlock(let bytesRead):\n                assert(bytesRead == 0)\n                return result\n            }\n        }\n        return result\n    }\n\n    final override func writeToSocket() throws -> OverallWriteResult {\n        let result = try self.pendingWrites.triggerAppropriateWriteOperations(\n            scalarBufferWriteOperation: { ptr in\n                guard ptr.count > 0 else {\n                    // No need to call write if the buffer is empty.\n                    return .processed(0)\n                }\n                // normal write\n                return try self.socket.write(pointer: ptr)\n            },\n            vectorBufferWriteOperation: { ptrs in\n                // Gathering write\n                try self.socket.writev(iovecs: ptrs)\n            },\n            scalarFileWriteOperation: { descriptor, index, endIndex in\n                try self.socket.sendFile(fd: descriptor, offset: index, count: endIndex - index)\n            }\n        )\n        return result\n    }\n\n    final override func close0(error: Error, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        do {\n            switch mode {\n            case .output:\n                if self.outputShutdown {\n                    promise?.fail(ChannelError._outputClosed)\n                    return\n                }\n                if self.inputShutdown {\n                    // Escalate to full closure\n                    self.close0(error: error, mode: .all, promise: promise)\n                    return\n                }\n\n                let result = self.pendingWrites.closeOutbound(promise)\n                switch result {\n                case .pending:\n                    ()  // promise is stored in `pendingWrites` state for completing later\n\n                case .readyForClose(let closePromise), .closed(let closePromise):\n                    // Shutdown the socket only when the pending writes are dealt with ...\n                    // ... or if we think we are already closed - just to make sure it *is* closed / to match the old behavior\n                    do {\n                        try self.shutdownSocket(mode: mode)\n                        closePromise?.succeed(())\n                    } catch let err {\n                        closePromise?.fail(err)\n                    }\n                    self.unregisterForWritable()\n                    self.pipeline.fireUserInboundEventTriggered(ChannelEvent.outputClosed)\n\n                case .errored(let err, let closePromise):\n                    assertionFailure(\"Close errored: \\(err)\")\n                    closePromise?.fail(err)\n\n                    // Escalate to full closure\n                    // promise is nil here because we have used the supplied promise to convey failure of the half-close\n                    self.close0(error: err, mode: .all, promise: nil)\n                }\n\n            case .input:\n                if self.inputShutdown {\n                    promise?.fail(ChannelError._inputClosed)\n                    return\n                }\n                if self.outputShutdown {\n                    // Escalate to full closure\n                    self.close0(error: error, mode: .all, promise: promise)\n                    return\n                }\n                switch error {\n                case ChannelError.eof:\n                    // No need to explicit call socket.shutdown(...) as we received an EOF and the call would only cause\n                    // ENOTCON\n                    self.inputShutdown = true\n                    break\n                default:\n                    try self.shutdownSocket(mode: mode)\n                }\n                self.unregisterForReadable()\n                promise?.succeed(())\n\n                self.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n\n            case .all:\n                if let timeout = self.connectTimeoutScheduled {\n                    self.connectTimeoutScheduled = nil\n                    timeout.cancel()\n                }\n                super.close0(error: error, mode: mode, promise: promise)\n            }\n        } catch let err {\n            promise?.fail(err)\n        }\n    }\n\n    final override func hasFlushedPendingWrites() -> Bool {\n        self.pendingWrites.isFlushPending\n    }\n\n    final override func markFlushPoint() {\n        // Even if writable() will be called later by the EventLoop we still need to mark the flush checkpoint so we are sure all the flushed messages\n        // are actually written once writable() is called.\n        self.pendingWrites.markFlushCheckpoint()\n    }\n\n    final override func cancelWritesOnClose(error: Error) {\n        if let eventLoopPromise = self.pendingWrites.failAll(error: error) {\n            eventLoopPromise.fail(error)\n        }\n    }\n\n    @discardableResult\n    final override func readIfNeeded0() -> Bool {\n        if self.inputShutdown {\n            return false\n        }\n        return super.readIfNeeded0()\n    }\n\n    final override public func read0() {\n        if self.inputShutdown {\n            return\n        }\n        super.read0()\n    }\n\n    final override func bufferPendingWrite(data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if self.outputShutdown {\n            promise?.fail(ChannelError._outputClosed)\n            return\n        }\n\n        let data = self.unwrapData(data, as: IOData.self)\n\n        if !self.pendingWrites.add(data: data, promise: promise) {\n            self.pipeline.syncOperations.fireChannelWritabilityChanged()\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Bootstrap.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport CNIOLinux\nimport CNIOOpenBSD\nimport NIOCore\n\n#if os(Windows)\nimport ucrt\n\nimport func WinSDK.GetFileType\n\nimport let WinSDK.FILE_TYPE_PIPE\nimport let WinSDK.INVALID_HANDLE_VALUE\n\nimport struct WinSDK.DWORD\nimport struct WinSDK.HANDLE\n#endif\n\n/// The type of all `channelInitializer` callbacks.\ninternal typealias ChannelInitializerCallback = @Sendable (Channel) -> EventLoopFuture<Void>\n\n/// Common functionality for all NIO on sockets bootstraps.\ninternal enum NIOOnSocketsBootstraps {\n    internal static func isCompatible(group: EventLoopGroup) -> Bool {\n        group is SelectableEventLoop || group is MultiThreadedEventLoopGroup\n    }\n}\n\n/// A `ServerBootstrap` is an easy way to bootstrap a `ServerSocketChannel` when creating network servers.\n///\n/// Example:\n///\n/// ```swift\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\n///     defer {\n///         try! group.syncShutdownGracefully()\n///     }\n///     let bootstrap = ServerBootstrap(group: group)\n///         // Specify backlog and enable SO_REUSEADDR for the server itself\n///         .serverChannelOption(.backlog, value: 256)\n///         .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n///\n///         // Set the handlers that are applied to the accepted child `Channel`s.\n///         .childChannelInitializer { channel in\n///            channel.eventLoop.makeCompletedFuture {\n///                // Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.\n///                try channel.pipeline.syncOperations.addHandler(BackPressureHandler())\n///                try channel.pipeline.syncOperations.addHandler(MyChannelHandler())\n///            }\n///         }\n///\n///         // Enable SO_REUSEADDR for the accepted Channels\n///         .childChannelOption(.socketOption(.so_reuseaddr), value: 1)\n///         .childChannelOption(.maxMessagesPerRead, value: 16)\n///         .childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator())\n///     let channel = try! bootstrap.bind(host: host, port: port).wait()\n///     /* the server will now be accepting connections */\n///\n///     try! channel.closeFuture.wait() // wait forever as we never close the Channel\n/// ```\n///\n/// The `EventLoopFuture` returned by `bind` will fire with a `ServerSocketChannel`. This is the channel that owns the listening socket.\n/// Each time it accepts a new connection it will fire a `SocketChannel` through the `ChannelPipeline` via `fireChannelRead`: as a result,\n/// the `ServerSocketChannel` operates on `Channel`s as inbound messages. Outbound messages are not supported on a `ServerSocketChannel`\n/// which means that each write attempt will fail.\n///\n/// Accepted `SocketChannel`s operate on `ByteBuffer` as inbound data, and `IOData` as outbound data.\npublic final class ServerBootstrap {\n\n    private let group: EventLoopGroup\n    private let childGroup: EventLoopGroup\n    private var serverChannelInit: Optional<ChannelInitializerCallback>\n    private var childChannelInit: Optional<ChannelInitializerCallback>\n    @usableFromInline\n    internal var _serverChannelOptions: ChannelOptions.Storage\n    @usableFromInline\n    internal var _childChannelOptions: ChannelOptions.Storage\n    private var enableMPTCP: Bool\n\n    /// Create a `ServerBootstrap` on the `EventLoopGroup` `group`.\n    ///\n    /// The `EventLoopGroup` `group` must be compatible, otherwise the program will crash. `ServerBootstrap` is\n    /// compatible only with `MultiThreadedEventLoopGroup` as well as the `EventLoop`s returned by\n    /// `MultiThreadedEventLoopGroup.next`. See `init(validatingGroup:childGroup:)` for a fallible initializer for\n    /// situations where it's impossible to tell ahead of time if the `EventLoopGroup`s are compatible or not.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use for the `bind` of the `ServerSocketChannel` and to accept new `SocketChannel`s with.\n    public convenience init(group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            preconditionFailure(\n                \"ServerBootstrap is only compatible with MultiThreadedEventLoopGroup and \"\n                    + \"SelectableEventLoop. You tried constructing one with \\(group) which is incompatible.\"\n            )\n        }\n        self.init(validatingGroup: group, childGroup: group)!\n    }\n\n    /// Create a `ServerBootstrap` on the `EventLoopGroup` `group` which accepts `Channel`s on `childGroup`.\n    ///\n    /// The `EventLoopGroup`s `group` and `childGroup` must be compatible, otherwise the program will crash.\n    /// `ServerBootstrap` is compatible only with `MultiThreadedEventLoopGroup` as well as the `EventLoop`s returned by\n    /// `MultiThreadedEventLoopGroup.next`. See `init(validatingGroup:childGroup:)` for a fallible initializer for\n    /// situations where it's impossible to tell ahead of time if the `EventLoopGroup`s are compatible or not.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use for the `bind` of the `ServerSocketChannel` and to accept new `SocketChannel`s with.\n    ///   - childGroup: The `EventLoopGroup` to run the accepted `SocketChannel`s on.\n    public convenience init(group: EventLoopGroup, childGroup: EventLoopGroup) {\n        guard\n            NIOOnSocketsBootstraps.isCompatible(group: group) && NIOOnSocketsBootstraps.isCompatible(group: childGroup)\n        else {\n            preconditionFailure(\n                \"ServerBootstrap is only compatible with MultiThreadedEventLoopGroup and \"\n                    + \"SelectableEventLoop. You tried constructing one with group: \\(group) and \"\n                    + \"childGroup: \\(childGroup) at least one of which is incompatible.\"\n            )\n        }\n        self.init(validatingGroup: group, childGroup: childGroup)!\n\n    }\n\n    /// Create a `ServerBootstrap` on the `EventLoopGroup` `group` which accepts `Channel`s on `childGroup`, validating\n    /// that the `EventLoopGroup`s are compatible with `ServerBootstrap`.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use for the `bind` of the `ServerSocketChannel` and to accept new `SocketChannel`s with.\n    ///   - childGroup: The `EventLoopGroup` to run the accepted `SocketChannel`s on. If `nil`, `group` is used.\n    public init?(validatingGroup group: EventLoopGroup, childGroup: EventLoopGroup? = nil) {\n        let childGroup = childGroup ?? group\n        guard\n            NIOOnSocketsBootstraps.isCompatible(group: group) && NIOOnSocketsBootstraps.isCompatible(group: childGroup)\n        else {\n            return nil\n        }\n\n        self.group = group\n        self.childGroup = childGroup\n        self._serverChannelOptions = ChannelOptions.Storage()\n        self._childChannelOptions = ChannelOptions.Storage()\n        self.serverChannelInit = nil\n        self.childChannelInit = nil\n        self._serverChannelOptions.append(key: .tcpOption(.tcp_nodelay), value: 1)\n        self.enableMPTCP = false\n    }\n\n    /// Initialize the `ServerSocketChannel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// The `ServerSocketChannel` uses the accepted `Channel`s as inbound messages.\n    ///\n    /// - Note: To set the initializer for the accepted `SocketChannel`s, look at `ServerBootstrap.childChannelInitializer`.\n    ///\n    /// - Parameters:\n    ///   - initializer: A closure that initializes the provided `Channel`.\n    @preconcurrency\n    public func serverChannelInitializer(_ initializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self\n    {\n        self.serverChannelInit = initializer\n        return self\n    }\n\n    /// Initialize the accepted `SocketChannel`s with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`. Note that if the `initializer` fails then the error will be\n    /// fired in the *parent* channel.\n    ///\n    /// - warning: The `initializer` will be invoked once for every accepted connection. Therefore it's usually the\n    ///            right choice to instantiate stateful `ChannelHandler`s within the closure to make sure they are not\n    ///            accidentally shared across `Channel`s. There are expert use-cases where stateful handler need to be\n    ///            shared across `Channel`s in which case the user is responsible to synchronise the state access\n    ///            appropriately.\n    ///\n    /// The accepted `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.\n    ///\n    /// - Parameters:\n    ///   - initializer: A closure that initializes the provided `Channel`.\n    @preconcurrency\n    public func childChannelInitializer(_ initializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self {\n        self.childChannelInit = initializer\n        return self\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the `ServerSocketChannel`.\n    ///\n    /// - Note: To specify options for the accepted `SocketChannel`s, look at `ServerBootstrap.childChannelOption`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    @inlinable\n    public func serverChannelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self {\n        self._serverChannelOptions.append(key: option, value: value)\n        return self\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the accepted `SocketChannel`s.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    @inlinable\n    public func childChannelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self {\n        self._childChannelOptions.append(key: option, value: value)\n        return self\n    }\n\n    /// Specifies a timeout to apply to a bind attempt. Currently unsupported.\n    ///\n    /// - Parameters:\n    ///   - timeout: The timeout that will apply to the bind attempt.\n    public func bindTimeout(_ timeout: TimeAmount) -> Self {\n        self\n    }\n\n    /// Enables multi-path TCP support.\n    ///\n    /// This option is only supported on some systems, and will lead to bind\n    /// failing if the system does not support it. Users are recommended to\n    /// only enable this in response to configuration or feature detection.\n    ///\n    /// > Note: Enabling this setting will re-enable Nagle's algorithm, even if it\n    /// > had been disabled. This is a temporary workaround for a Linux kernel\n    /// > limitation.\n    ///\n    /// - Parameters:\n    ///   - value: Whether to enable MPTCP or not.\n    public func enableMPTCP(_ value: Bool) -> Self {\n        self.enableMPTCP = value\n\n        // This is a temporary workaround until we get some stable Linux kernel\n        // versions that support TCP_NODELAY and MPTCP.\n        if value {\n            self._serverChannelOptions.remove(key: .tcpOption(.tcp_nodelay))\n        }\n\n        return self\n    }\n\n    /// Bind the `ServerSocketChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - port: The port to bind on.\n    public func bind(host: String, port: Int) -> EventLoopFuture<Channel> {\n        bind0 {\n            try SocketAddress.makeAddressResolvingHost(host, port: port)\n        }\n    }\n\n    /// Bind the `ServerSocketChannel` to `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    public func bind(to address: SocketAddress) -> EventLoopFuture<Channel> {\n        bind0 { address }\n    }\n\n    /// Bind the `ServerSocketChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The _Unix domain socket_ path to bind to. `unixDomainSocketPath` must not exist, it will be created by the system.\n    public func bind(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n        bind0 {\n            try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n        }\n    }\n\n    /// Bind the `ServerSocketChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. The`unixDomainSocketPath` must not exist,\n    ///     unless `cleanupExistingSocketFile`is set to `true`.\n    ///   - cleanupExistingSocketFile: Whether to cleanup an existing socket file at `unixDomainSocketPath`.\n    public func bind(unixDomainSocketPath: String, cleanupExistingSocketFile: Bool) -> EventLoopFuture<Channel> {\n        if cleanupExistingSocketFile {\n            do {\n                try BaseSocket.cleanupSocket(unixDomainSocketPath: unixDomainSocketPath)\n            } catch {\n                return group.next().makeFailedFuture(error)\n            }\n        }\n\n        return self.bind(unixDomainSocketPath: unixDomainSocketPath)\n    }\n\n    /// Bind the `ServerSocketChannel` to a VSOCK socket.\n    ///\n    /// - Parameters:\n    ///   - vsockAddress: The VSOCK socket address to bind on.\n    public func bind(to vsockAddress: VsockAddress) -> EventLoopFuture<Channel> {\n        func makeChannel(\n            _ eventLoop: SelectableEventLoop,\n            _ childEventLoopGroup: EventLoopGroup,\n            _ enableMPTCP: Bool\n        ) throws -> ServerSocketChannel {\n            try ServerSocketChannel(\n                eventLoop: eventLoop,\n                group: childEventLoopGroup,\n                protocolFamily: .vsock,\n                enableMPTCP: enableMPTCP\n            )\n        }\n        return bind0(makeServerChannel: makeChannel) { (eventLoop, serverChannel) in\n            serverChannel.register().flatMap {\n                let promise = eventLoop.makePromise(of: Void.self)\n                serverChannel.triggerUserOutboundEvent0(\n                    VsockChannelEvents.BindToAddress(vsockAddress),\n                    promise: promise\n                )\n                return promise.futureResult\n            }\n        }\n    }\n\n    #if !os(Windows)\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The _Unix file descriptor_ representing the bound stream socket.\n    @available(*, deprecated, renamed: \"withBoundSocket(_:)\")\n    public func withBoundSocket(descriptor: CInt) -> EventLoopFuture<Channel> {\n        withBoundSocket(descriptor)\n    }\n    #endif\n\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the bound stream socket.\n    public func withBoundSocket(_ socket: NIOBSDSocket.Handle) -> EventLoopFuture<Channel> {\n        func makeChannel(\n            _ eventLoop: SelectableEventLoop,\n            _ childEventLoopGroup: EventLoopGroup,\n            _ enableMPTCP: Bool\n        ) throws -> ServerSocketChannel {\n            if enableMPTCP {\n                throw ChannelError._operationUnsupported\n            }\n            return try ServerSocketChannel(socket: socket, eventLoop: eventLoop, group: childEventLoopGroup)\n        }\n        return bind0(makeServerChannel: makeChannel) { (eventLoop, serverChannel) in\n            let promise = eventLoop.makePromise(of: Void.self)\n            serverChannel.registerAlreadyConfigured0(promise: promise)\n            return promise.futureResult\n        }\n    }\n\n    private func bind0(_ makeSocketAddress: () throws -> SocketAddress) -> EventLoopFuture<Channel> {\n        let address: SocketAddress\n        do {\n            address = try makeSocketAddress()\n        } catch {\n            return group.next().makeFailedFuture(error)\n        }\n        func makeChannel(\n            _ eventLoop: SelectableEventLoop,\n            _ childEventLoopGroup: EventLoopGroup,\n            _ enableMPTCP: Bool\n        ) throws -> ServerSocketChannel {\n            try ServerSocketChannel(\n                eventLoop: eventLoop,\n                group: childEventLoopGroup,\n                protocolFamily: address.protocol,\n                enableMPTCP: enableMPTCP\n            )\n        }\n\n        return bind0(makeServerChannel: makeChannel) { (eventLoop, serverChannel) in\n            serverChannel.registerAndDoSynchronously { serverChannel in\n                serverChannel.bind(to: address)\n            }\n        }\n    }\n\n    private func bind0(\n        makeServerChannel: (_ eventLoop: SelectableEventLoop, _ childGroup: EventLoopGroup, _ enableMPTCP: Bool) throws\n            -> ServerSocketChannel,\n        _ register: @escaping @Sendable (EventLoop, ServerSocketChannel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        let eventLoop = self.group.next()\n        let childEventLoopGroup = self.childGroup\n        let serverChannelOptions = self._serverChannelOptions\n        let serverChannelInit = self.serverChannelInit ?? { _ in eventLoop.makeSucceededFuture(()) }\n        let childChannelInit = self.childChannelInit\n        let childChannelOptions = self._childChannelOptions\n\n        let serverChannel: ServerSocketChannel\n        do {\n            serverChannel = try makeServerChannel(\n                eventLoop as! SelectableEventLoop,\n                childEventLoopGroup,\n                self.enableMPTCP\n            )\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        return eventLoop.submit {\n            serverChannelOptions.applyAllChannelOptions(to: serverChannel).flatMap {\n                serverChannelInit(serverChannel)\n            }.flatMap {\n                do {\n                    try serverChannel.pipeline.syncOperations.addHandler(\n                        AcceptHandler(\n                            childChannelInitializer: childChannelInit,\n                            childChannelOptions: childChannelOptions\n                        ),\n                        name: \"AcceptHandler\"\n                    )\n                    return register(eventLoop, serverChannel)\n                } catch {\n                    return eventLoop.makeFailedFuture(error)\n                }\n            }.map {\n                serverChannel as Channel\n            }.flatMapError { error in\n                serverChannel.close0(error: error, mode: .all, promise: nil)\n                return eventLoop.makeFailedFuture(error)\n            }\n        }.flatMap {\n            $0\n        }\n    }\n\n    final class AcceptHandler: ChannelInboundHandler {\n        public typealias InboundIn = SocketChannel\n        public typealias InboundOut = SocketChannel\n\n        private let childChannelInit: (@Sendable (Channel) -> EventLoopFuture<Void>)?\n        private let childChannelOptions: ChannelOptions.Storage\n\n        init(\n            childChannelInitializer: (@Sendable (Channel) -> EventLoopFuture<Void>)?,\n            childChannelOptions: ChannelOptions.Storage\n        ) {\n            self.childChannelInit = childChannelInitializer\n            self.childChannelOptions = childChannelOptions\n        }\n\n        func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n            if event is ChannelShouldQuiesceEvent {\n                let loopBoundContext = context.loopBound\n                context.channel.close().whenFailure { error in\n                    let context = loopBoundContext.value\n                    context.fireErrorCaught(error)\n                }\n            }\n            context.fireUserInboundEventTriggered(event)\n        }\n\n        func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            let accepted = AcceptHandler.unwrapInboundIn(data)\n            let ctxEventLoop = context.eventLoop\n            let childEventLoop = accepted.eventLoop\n            let childChannelInit = self.childChannelInit ?? { (_: Channel) in childEventLoop.makeSucceededFuture(()) }\n            let childChannelOptions = self.childChannelOptions\n\n            @inline(__always)\n            @Sendable\n            func setupChildChannel() -> EventLoopFuture<Void> {\n                childChannelOptions.applyAllChannelOptions(to: accepted).flatMap { () -> EventLoopFuture<Void> in\n                    childEventLoop.assertInEventLoop()\n                    return childChannelInit(accepted)\n                }\n            }\n\n            @inline(__always)\n            func fireThroughPipeline(_ future: EventLoopFuture<Void>, context: ChannelHandlerContext) {\n                // Strictly these asserts are redundant with future.assumeIsolated(), but as this code\n                // has guarantees that can be quite hard to follow we keep them here.\n                ctxEventLoop.assertInEventLoop()\n                assert(ctxEventLoop === context.eventLoop)\n                future.assumeIsolated().flatMap { (_) -> EventLoopFuture<Void> in\n                    guard context.channel.isActive else {\n                        return ctxEventLoop.makeFailedFuture(ChannelError._ioOnClosedChannel)\n                    }\n                    context.fireChannelRead(AcceptHandler.wrapInboundOut(accepted))\n                    return context.eventLoop.makeSucceededFuture(())\n                }.whenFailure { error in\n                    self.closeAndFire(context: context, accepted: accepted, err: error)\n                }\n            }\n\n            if childEventLoop === ctxEventLoop {\n                fireThroughPipeline(setupChildChannel(), context: context)\n            } else {\n                fireThroughPipeline(\n                    childEventLoop.flatSubmit {\n                        setupChildChannel()\n                    }.hop(to: ctxEventLoop),\n                    context: context\n                )\n            }\n        }\n\n        private func closeAndFire(context: ChannelHandlerContext, accepted: SocketChannel, err: Error) {\n            accepted.close(promise: nil)\n            if context.eventLoop.inEventLoop {\n                context.fireErrorCaught(err)\n            } else {\n                let loopBoundContext = context.loopBound\n                context.eventLoop.execute {\n                    let context = loopBoundContext.value\n                    context.fireErrorCaught(err)\n                }\n            }\n        }\n    }\n}\n\n// MARK: Async bind methods\n\nextension ServerBootstrap {\n    /// Bind the `ServerSocketChannel` to the `host` and `port` parameters.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - port: The port to bind on.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - childChannelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        host: String,\n        port: Int,\n        serverBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        childChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> NIOAsyncChannel<Output, Never> {\n        let address = try SocketAddress.makeAddressResolvingHost(host, port: port)\n\n        return try await bind(\n            to: address,\n            serverBackPressureStrategy: serverBackPressureStrategy,\n            childChannelInitializer: childChannelInitializer\n        )\n    }\n\n    /// Bind the `ServerSocketChannel` to the `address` parameter.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - childChannelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        to address: SocketAddress,\n        serverBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        childChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> NIOAsyncChannel<Output, Never> {\n        try await bind0(\n            makeServerChannel: { eventLoop, childEventLoopGroup, enableMPTCP in\n                try ServerSocketChannel(\n                    eventLoop: eventLoop,\n                    group: childEventLoopGroup,\n                    protocolFamily: address.protocol,\n                    enableMPTCP: enableMPTCP\n                )\n            },\n            serverBackPressureStrategy: serverBackPressureStrategy,\n            childChannelInitializer: childChannelInitializer,\n            registration: { serverChannel in\n                serverChannel.registerAndDoSynchronously { serverChannel in\n                    serverChannel.bind(to: address)\n                }\n            }\n        ).get()\n    }\n\n    /// Bind the `ServerSocketChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. The`unixDomainSocketPath` must not exist,\n    ///     unless `cleanupExistingSocketFile`is set to `true`.\n    ///   - cleanupExistingSocketFile: Whether to cleanup an existing socket file at `unixDomainSocketPath`.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - childChannelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        unixDomainSocketPath: String,\n        cleanupExistingSocketFile: Bool = false,\n        serverBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        childChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> NIOAsyncChannel<Output, Never> {\n        if cleanupExistingSocketFile {\n            try BaseSocket.cleanupSocket(unixDomainSocketPath: unixDomainSocketPath)\n        }\n\n        let address = try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n\n        return try await self.bind(\n            to: address,\n            serverBackPressureStrategy: serverBackPressureStrategy,\n            childChannelInitializer: childChannelInitializer\n        )\n    }\n\n    /// Bind the `ServerSocketChannel` to a VSOCK socket.\n    ///\n    /// - Parameters:\n    ///   - vsockAddress: The VSOCK socket address to bind on.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - childChannelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        to vsockAddress: VsockAddress,\n        serverBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        childChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> NIOAsyncChannel<Output, Never> {\n        func makeChannel(\n            _ eventLoop: SelectableEventLoop,\n            _ childEventLoopGroup: EventLoopGroup,\n            _ enableMPTCP: Bool\n        ) throws -> ServerSocketChannel {\n            try ServerSocketChannel(\n                eventLoop: eventLoop,\n                group: childEventLoopGroup,\n                protocolFamily: .vsock,\n                enableMPTCP: enableMPTCP\n            )\n        }\n\n        return try await self.bind0(\n            makeServerChannel: makeChannel,\n            serverBackPressureStrategy: serverBackPressureStrategy,\n            childChannelInitializer: childChannelInitializer\n        ) { channel in\n            channel.register().flatMap {\n                let promise = channel.eventLoop.makePromise(of: Void.self)\n                channel.triggerUserOutboundEvent0(\n                    VsockChannelEvents.BindToAddress(vsockAddress),\n                    promise: promise\n                )\n                return promise.futureResult\n            }\n        }.get()\n    }\n\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the bound stream socket.\n    ///   - cleanupExistingSocketFile: Unused.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - childChannelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        _ socket: NIOBSDSocket.Handle,\n        cleanupExistingSocketFile: Bool = false,\n        serverBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,\n        childChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> NIOAsyncChannel<Output, Never> {\n        try await bind0(\n            makeServerChannel: { eventLoop, childEventLoopGroup, enableMPTCP in\n                if enableMPTCP {\n                    throw ChannelError._operationUnsupported\n                }\n                return try ServerSocketChannel(\n                    socket: socket,\n                    eventLoop: eventLoop,\n                    group: childEventLoopGroup\n                )\n            },\n            serverBackPressureStrategy: serverBackPressureStrategy,\n            childChannelInitializer: childChannelInitializer,\n            registration: { serverChannel in\n                let promise = serverChannel.eventLoop.makePromise(of: Void.self)\n                serverChannel.registerAlreadyConfigured0(promise: promise)\n                return promise.futureResult\n            }\n        ).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func bind0<ChannelInitializerResult>(\n        makeServerChannel: @escaping (SelectableEventLoop, EventLoopGroup, Bool) throws -> ServerSocketChannel,\n        serverBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark?,\n        childChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        registration: @escaping @Sendable (ServerSocketChannel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<NIOAsyncChannel<ChannelInitializerResult, Never>> {\n        let eventLoop = self.group.next()\n        let childEventLoopGroup = self.childGroup\n        let serverChannelOptions = self._serverChannelOptions\n        let serverChannelInit = self.serverChannelInit ?? { _ in eventLoop.makeSucceededFuture(()) }\n        let childChannelInit = self.childChannelInit\n        let childChannelOptions = self._childChannelOptions\n\n        let serverChannel: ServerSocketChannel\n        do {\n            serverChannel = try makeServerChannel(\n                eventLoop as! SelectableEventLoop,\n                childEventLoopGroup,\n                self.enableMPTCP\n            )\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        return eventLoop.submit {\n            serverChannelOptions.applyAllChannelOptions(to: serverChannel).flatMap {\n                serverChannelInit(serverChannel)\n            }.flatMap { (_) -> EventLoopFuture<NIOAsyncChannel<ChannelInitializerResult, Never>> in\n                do {\n                    try serverChannel.pipeline.syncOperations.addHandler(\n                        AcceptBackoffHandler(shouldForwardIOErrorCaught: false),\n                        name: \"AcceptBackOffHandler\"\n                    )\n                    try serverChannel.pipeline.syncOperations.addHandler(\n                        AcceptHandler(\n                            childChannelInitializer: childChannelInit,\n                            childChannelOptions: childChannelOptions\n                        ),\n                        name: \"AcceptHandler\"\n                    )\n                    let asyncChannel = try NIOAsyncChannel<ChannelInitializerResult, Never>\n                        ._wrapAsyncChannelWithTransformations(\n                            wrappingChannelSynchronously: serverChannel,\n                            backPressureStrategy: serverBackPressureStrategy,\n                            channelReadTransformation: { channel -> EventLoopFuture<ChannelInitializerResult> in\n                                // The channelReadTransformation is run on the EL of the server channel\n                                // We have to make sure that we execute child channel initializer on the\n                                // EL of the child channel.\n                                channel.eventLoop.flatSubmit {\n                                    childChannelInitializer(channel)\n                                }\n                            }\n                        )\n                    return registration(serverChannel)\n                        .map { (_) -> NIOAsyncChannel<ChannelInitializerResult, Never> in asyncChannel\n                        }\n                } catch {\n                    return eventLoop.makeFailedFuture(error)\n                }\n            }.flatMapError { error -> EventLoopFuture<NIOAsyncChannel<ChannelInitializerResult, Never>> in\n                serverChannel.close0(error: error, mode: .all, promise: nil)\n                return eventLoop.makeFailedFuture(error)\n            }\n        }.flatMap {\n            $0\n        }\n    }\n}\n\n@available(*, unavailable)\nextension ServerBootstrap: Sendable {}\n\nextension Channel {\n    fileprivate func registerAndDoSynchronously(\n        _ body: @escaping (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Void> {\n        // this is pretty delicate at the moment:\n        // In many cases `body` must be _synchronously_ follow `register`, otherwise in our current\n        // implementation, `epoll` will send us `EPOLLHUP`. To have it run synchronously, we need to invoke the\n        // `flatMap` on the eventloop that the `register` will succeed on.\n        self.eventLoop.assertInEventLoop()\n        return self.register().assumeIsolated().flatMap {\n            body(self)\n        }.nonisolated()\n    }\n}\n\n/// A `ClientBootstrap` is an easy way to bootstrap a `SocketChannel` when creating network clients.\n///\n/// Usually you re-use a `ClientBootstrap` once you set it up and called `connect` multiple times on it.\n/// This way you ensure that the same `EventLoop`s will be shared across all your connections.\n///\n/// Example:\n///\n/// ```swift\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///     defer {\n///         try! group.syncShutdownGracefully()\n///     }\n///     let bootstrap = ClientBootstrap(group: group)\n///         // Enable SO_REUSEADDR.\n///         .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n///         .channelInitializer { channel in\n///             // always instantiate the handler _within_ the closure as\n///             // it may be called multiple times (for example if the hostname\n///             // resolves to both IPv4 and IPv6 addresses, cf. Happy Eyeballs).\n///             channel.pipeline.addHandler(MyChannelHandler())\n///         }\n///     try! bootstrap.connect(host: \"example.org\", port: 12345).wait()\n///     /* the Channel is now connected */\n/// ```\n///\n/// The connected `SocketChannel` will operate on `ByteBuffer` as inbound and on `IOData` as outbound messages.\npublic final class ClientBootstrap: NIOClientTCPBootstrapProtocol {\n    private let group: EventLoopGroup\n    private var protocolHandlers: Optional<@Sendable () -> [ChannelHandler]>\n    private var _channelInitializer: ChannelInitializerCallback\n    private var channelInitializer: ChannelInitializerCallback {\n        if let protocolHandlers = self.protocolHandlers {\n            let channelInitializer = _channelInitializer\n            return { channel in\n                channelInitializer(channel).hop(to: channel.eventLoop).flatMapThrowing {\n                    try channel.pipeline.syncOperations.addHandlers(protocolHandlers(), position: .first)\n                }\n            }\n        } else {\n            return self._channelInitializer\n        }\n    }\n    @usableFromInline\n    internal var _channelOptions: ChannelOptions.Storage\n    private var connectTimeout: TimeAmount = TimeAmount.seconds(10)\n    private var resolver: Optional<Resolver & Sendable>\n    private var bindTarget: Optional<SocketAddress>\n    private var enableMPTCP: Bool\n\n    /// Create a `ClientBootstrap` on the `EventLoopGroup` `group`.\n    ///\n    /// The `EventLoopGroup` `group` must be compatible, otherwise the program will crash. `ClientBootstrap` is\n    /// compatible only with `MultiThreadedEventLoopGroup` as well as the `EventLoop`s returned by\n    /// `MultiThreadedEventLoopGroup.next`. See `init(validatingGroup:)` for a fallible initializer for\n    /// situations where it's impossible to tell ahead of time if the `EventLoopGroup` is compatible or not.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public convenience init(group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            preconditionFailure(\n                \"ClientBootstrap is only compatible with MultiThreadedEventLoopGroup and \"\n                    + \"SelectableEventLoop. You tried constructing one with \\(group) which is incompatible.\"\n            )\n        }\n        self.init(validatingGroup: group)!\n    }\n\n    /// Create a `ClientBootstrap` on the `EventLoopGroup` `group`, validating that `group` is compatible.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public init?(validatingGroup group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            return nil\n        }\n        self.group = group\n        self._channelOptions = ChannelOptions.Storage()\n        self._channelOptions.append(key: .tcpOption(.tcp_nodelay), value: 1)\n        self._channelInitializer = { channel in channel.eventLoop.makeSucceededFuture(()) }\n        self.protocolHandlers = nil\n        self.resolver = nil\n        self.bindTarget = nil\n        self.enableMPTCP = false\n    }\n\n    /// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// The connected `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.\n    ///\n    /// - warning: The `handler` closure may be invoked _multiple times_ so it's usually the right choice to instantiate\n    ///            `ChannelHandler`s within `handler`. The reason `handler` may be invoked multiple times is that to\n    ///            successfully set up a connection multiple connections might be setup in the process. Assuming a\n    ///            hostname that resolves to both IPv4 and IPv6 addresses, NIO will follow\n    ///            [_Happy Eyeballs_](https://en.wikipedia.org/wiki/Happy_Eyeballs) and race both an IPv4 and an IPv6\n    ///            connection. It is possible that both connections get fully established before the IPv4 connection\n    ///            will be closed again because the IPv6 connection 'won the race'. Therefore the `channelInitializer`\n    ///            might be called multiple times and it's important not to share stateful `ChannelHandler`s in more\n    ///            than one `Channel`.\n    ///\n    /// - Parameters:\n    ///   - handler: A closure that initializes the provided `Channel`.\n    @preconcurrency\n    public func channelInitializer(_ handler: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self {\n        self._channelInitializer = handler\n        return self\n    }\n\n    /// Sets the protocol handlers that will be added to the front of the `ChannelPipeline` right after the\n    /// `channelInitializer` has been called.\n    ///\n    /// Per bootstrap, you can only set the `protocolHandlers` once. Typically, `protocolHandlers` are used for the TLS\n    /// implementation. Most notably, `NIOClientTCPBootstrap`, NIO's \"universal bootstrap\" abstraction, uses\n    /// `protocolHandlers` to add the required `ChannelHandler`s for many TLS implementations.\n    @preconcurrency\n    public func protocolHandlers(_ handlers: @escaping @Sendable () -> [ChannelHandler]) -> Self {\n        precondition(self.protocolHandlers == nil, \"protocol handlers can only be set once\")\n        self.protocolHandlers = handlers\n        return self\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the `SocketChannel`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    @inlinable\n    public func channelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self {\n        self._channelOptions.append(key: option, value: value)\n        return self\n    }\n\n    /// Specifies a timeout to apply to a connection attempt.\n    ///\n    /// - Parameters:\n    ///   - timeout: The timeout that will apply to the connection attempt.\n    public func connectTimeout(_ timeout: TimeAmount) -> Self {\n        self.connectTimeout = timeout\n        return self\n    }\n\n    /// Specifies the `Resolver` to use or `nil` if the default should be used.\n    ///\n    /// - Parameters:\n    ///   - resolver: The resolver that will be used during the connection attempt.\n    @preconcurrency\n    public func resolver(_ resolver: (Resolver & Sendable)?) -> Self {\n        self.resolver = resolver\n        return self\n    }\n\n    /// Enables multi-path TCP support.\n    ///\n    /// This option is only supported on some systems, and will lead to bind\n    /// failing if the system does not support it. Users are recommended to\n    /// only enable this in response to configuration or feature detection.\n    ///\n    /// > Note: Enabling this setting will re-enable Nagle's algorithm, even if it\n    /// > had been disabled. This is a temporary workaround for a Linux kernel\n    /// > limitation.\n    ///\n    /// - Parameters:\n    ///   - value: Whether to enable MPTCP or not.\n    public func enableMPTCP(_ value: Bool) -> Self {\n        self.enableMPTCP = value\n\n        // This is a temporary workaround until we get some stable Linux kernel\n        // versions that support TCP_NODELAY and MPTCP.\n        if value {\n            self._channelOptions.remove(key: .tcpOption(.tcp_nodelay))\n        }\n\n        return self\n    }\n\n    /// Bind the `SocketChannel` to `address`.\n    ///\n    /// Using `bind` is not necessary unless you need the local address to be bound to a specific address.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    public func bind(to address: SocketAddress) -> ClientBootstrap {\n        self.bindTarget = address\n        return self\n    }\n\n    func makeSocketChannel(\n        eventLoop: EventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily\n    ) throws -> SocketChannel {\n        try Self.makeSocketChannel(\n            eventLoop: eventLoop,\n            protocolFamily: protocolFamily,\n            enableMPTCP: self.enableMPTCP\n        )\n    }\n\n    static func makeSocketChannel(\n        eventLoop: EventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        enableMPTCP: Bool\n    ) throws -> SocketChannel {\n        try SocketChannel(\n            eventLoop: eventLoop as! SelectableEventLoop,\n            protocolFamily: protocolFamily,\n            enableMPTCP: enableMPTCP\n        )\n    }\n\n    /// Specify the `host` and `port` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Note: Makes use of Happy Eyeballs.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    public func connect(host: String, port: Int) -> EventLoopFuture<Channel> {\n        let loop = self.group.next()\n        let resolver =\n            self.resolver\n            ?? GetaddrinfoResolver(\n                loop: loop,\n                aiSocktype: .stream,\n                aiProtocol: .tcp\n            )\n        let enableMPTCP = self.enableMPTCP\n        let channelInitializer = self.channelInitializer\n        let channelOptions = self._channelOptions\n        let bindTarget = self.bindTarget\n\n        let connector = HappyEyeballsConnector(\n            resolver: resolver,\n            loop: loop,\n            host: host,\n            port: port,\n            connectTimeout: self.connectTimeout\n        ) { eventLoop, protocolFamily in\n            Self.initializeAndRegisterNewChannel(\n                eventLoop: eventLoop,\n                protocolFamily: protocolFamily,\n                enableMPTCP: enableMPTCP,\n                channelInitializer: channelInitializer,\n                channelOptions: channelOptions,\n                bindTarget: bindTarget\n            ) {\n                $0.eventLoop.makeSucceededFuture(())\n            }\n        }\n        return connector.resolveAndConnect()\n    }\n\n    private static func connect(\n        freshChannel channel: Channel,\n        address: SocketAddress,\n        connectTimeout: TimeAmount\n    ) -> EventLoopFuture<Void> {\n        let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n        channel.connect(to: address, promise: connectPromise)\n        let cancelTask = channel.eventLoop.scheduleTask(in: connectTimeout) {\n            connectPromise.fail(ChannelError.connectTimeout(connectTimeout))\n            channel.close(promise: nil)\n        }\n\n        connectPromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            cancelTask.cancel()\n        }\n        return connectPromise.futureResult\n    }\n\n    internal func testOnly_connect(\n        injectedChannel: SocketChannel,\n        to address: SocketAddress\n    ) -> EventLoopFuture<Channel> {\n        let connectTimeout = self.connectTimeout\n        return self.initializeAndRegisterChannel(injectedChannel) { channel in\n            Self.connect(freshChannel: channel, address: address, connectTimeout: connectTimeout)\n        }\n    }\n\n    /// Specify the `address` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - address: The address to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    public func connect(to address: SocketAddress) -> EventLoopFuture<Channel> {\n        let connectTimeout = self.connectTimeout\n\n        return self.initializeAndRegisterNewChannel(\n            eventLoop: self.group.next(),\n            protocolFamily: address.protocol\n        ) { channel in\n            Self.connect(freshChannel: channel, address: address, connectTimeout: connectTimeout)\n        }\n    }\n\n    /// Specify the `unixDomainSocket` path to connect to for the UDS `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The _Unix domain socket_ path to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` to deliver the `Channel` when connected.\n    public func connect(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n        do {\n            let address = try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n            return self.connect(to: address)\n        } catch {\n            return self.group.next().makeFailedFuture(error)\n        }\n    }\n\n    /// Specify the VSOCK address to connect to for the `Channel`.\n    ///\n    /// - Parameters:\n    ///   - address: The VSOCK address to connect to.\n    /// - Returns: An `EventLoopFuture<Channel>` for when the `Channel` is connected.\n    public func connect(to address: VsockAddress) -> EventLoopFuture<Channel> {\n        let connectTimeout = self.connectTimeout\n        return self.initializeAndRegisterNewChannel(\n            eventLoop: self.group.next(),\n            protocolFamily: .vsock\n        ) { channel in\n            let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n            channel.triggerUserOutboundEvent(VsockChannelEvents.ConnectToAddress(address), promise: connectPromise)\n\n            let cancelTask = channel.eventLoop.scheduleTask(in: connectTimeout) {\n                connectPromise.fail(ChannelError.connectTimeout(connectTimeout))\n                channel.close(promise: nil)\n            }\n            connectPromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n                cancelTask.cancel()\n            }\n\n            return connectPromise.futureResult\n        }\n    }\n\n    #if !os(Windows)\n    /// Use the existing connected socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The _Unix file descriptor_ representing the connected stream socket.\n    /// - Returns: an `EventLoopFuture<Channel>` to deliver the `Channel`.\n    @available(*, deprecated, renamed: \"withConnectedSocket(_:)\")\n    public func withConnectedSocket(descriptor: CInt) -> EventLoopFuture<Channel> {\n        self.withConnectedSocket(descriptor)\n    }\n    #endif\n\n    /// Use the existing connected socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the connected stream socket.\n    /// - Returns: an `EventLoopFuture<Channel>` to deliver the `Channel`.\n    public func withConnectedSocket(_ socket: NIOBSDSocket.Handle) -> EventLoopFuture<Channel> {\n        let eventLoop = group.next()\n        let channelInitializer = self.channelInitializer\n        let options = self._channelOptions\n\n        let channel: SocketChannel\n        do {\n            channel = try SocketChannel(eventLoop: eventLoop as! SelectableEventLoop, socket: socket)\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        @Sendable\n        func setupChannel() -> EventLoopFuture<Channel> {\n            eventLoop.assertInEventLoop()\n            return options.applyAllChannelOptions(to: channel).flatMap {\n                channelInitializer(channel)\n            }.flatMap {\n                eventLoop.assertInEventLoop()\n                let promise = eventLoop.makePromise(of: Void.self)\n                channel.registerAlreadyConfigured0(promise: promise)\n                return promise.futureResult\n            }.map {\n                channel\n            }.flatMapError { error in\n                channel.close0(error: error, mode: .all, promise: nil)\n                return channel.eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit { setupChannel() }\n        }\n    }\n\n    private func initializeAndRegisterNewChannel(\n        eventLoop: EventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        _ body: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        Self.initializeAndRegisterNewChannel(\n            eventLoop: eventLoop,\n            protocolFamily: protocolFamily,\n            enableMPTCP: self.enableMPTCP,\n            channelInitializer: self.channelInitializer,\n            channelOptions: self._channelOptions,\n            bindTarget: self.bindTarget,\n            body\n        )\n    }\n\n    private static func initializeAndRegisterNewChannel(\n        eventLoop: EventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        enableMPTCP: Bool,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void>,\n        channelOptions: ChannelOptions.Storage,\n        bindTarget: SocketAddress?,\n        _ body: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        let channel: SocketChannel\n        do {\n            channel = try Self.makeSocketChannel(\n                eventLoop: eventLoop,\n                protocolFamily: protocolFamily,\n                enableMPTCP: enableMPTCP\n            )\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n        return Self.initializeAndRegisterChannel(\n            channel,\n            channelInitializer: channelInitializer,\n            channelOptions: channelOptions,\n            bindTarget: bindTarget,\n            body\n        )\n    }\n\n    private func initializeAndRegisterChannel(\n        _ channel: SocketChannel,\n        _ body: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        Self.initializeAndRegisterChannel(\n            channel,\n            channelInitializer: self.channelInitializer,\n            channelOptions: self._channelOptions,\n            bindTarget: self.bindTarget,\n            body\n        )\n    }\n\n    private static func initializeAndRegisterChannel(\n        _ channel: SocketChannel,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void>,\n        channelOptions: ChannelOptions.Storage,\n        bindTarget: SocketAddress?,\n        _ body: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        let eventLoop = channel.eventLoop\n\n        @inline(__always)\n        @Sendable\n        func setupChannel() -> EventLoopFuture<Channel> {\n            eventLoop.assertInEventLoop()\n            return channelOptions.applyAllChannelOptions(to: channel).flatMap {\n                if let bindTarget = bindTarget {\n                    return channel.bind(to: bindTarget).flatMap {\n                        channelInitializer(channel)\n                    }\n                } else {\n                    return channelInitializer(channel)\n                }\n            }.flatMap {\n                eventLoop.assertInEventLoop()\n                return channel.registerAndDoSynchronously(body)\n            }.map {\n                channel\n            }.flatMapError { error in\n                channel.close0(error: error, mode: .all, promise: nil)\n                return channel.eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n    }\n}\n\n// MARK: Async connect methods\n\nextension ClientBootstrap {\n    /// Specify the `host` and `port` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        host: String,\n        port: Int,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        let eventLoop = self.group.next()\n        return try await self.connect(\n            host: host,\n            port: port,\n            eventLoop: eventLoop,\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    /// Specify the `address` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - address: The address to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        to address: SocketAddress,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        let eventLoop = self.group.next()\n        let connectTimeout = self.connectTimeout\n        return try await self.initializeAndRegisterNewChannel(\n            eventLoop: eventLoop,\n            protocolFamily: address.protocol,\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            },\n            { channel in\n                Self.connect(freshChannel: channel, address: address, connectTimeout: connectTimeout)\n            }\n        ).get().1\n    }\n\n    /// Specify the `unixDomainSocket` path to connect to for the UDS `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The _Unix domain socket_ path to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        unixDomainSocketPath: String,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        let address = try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n        return try await self.connect(\n            to: address,\n            channelInitializer: channelInitializer\n        )\n    }\n\n    /// Specify the VSOCK address to connect to for the `Channel`.\n    ///\n    /// - Parameters:\n    ///   - address: The VSOCK address to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        to address: VsockAddress,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        let connectTimeout = self.connectTimeout\n        return try await self.initializeAndRegisterNewChannel(\n            eventLoop: self.group.next(),\n            protocolFamily: NIOBSDSocket.ProtocolFamily.vsock,\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { result, eventLoop in\n                eventLoop.makeSucceededFuture(result)\n            }\n        ) { channel in\n            let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n            channel.triggerUserOutboundEvent(VsockChannelEvents.ConnectToAddress(address), promise: connectPromise)\n\n            let cancelTask = channel.eventLoop.scheduleTask(in: connectTimeout) {\n                connectPromise.fail(ChannelError.connectTimeout(connectTimeout))\n                channel.close(promise: nil)\n            }\n            connectPromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n                cancelTask.cancel()\n            }\n\n            return connectPromise.futureResult\n        }.get().1\n    }\n\n    /// Use the existing connected socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the connected stream socket.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withConnectedSocket<Output: Sendable>(\n        _ socket: NIOBSDSocket.Handle,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        let eventLoop = group.next()\n        return try await self.withConnectedSocket(\n            eventLoop: eventLoop,\n            socket: socket,\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    func connect<ChannelInitializerResult: Sendable, PostRegistrationTransformationResult: Sendable>(\n        host: String,\n        port: Int,\n        eventLoop: EventLoop,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) async throws -> PostRegistrationTransformationResult {\n        let resolver =\n            self.resolver\n            ?? GetaddrinfoResolver(\n                loop: eventLoop,\n                aiSocktype: .stream,\n                aiProtocol: .tcp\n            )\n\n        let enableMPTCP = self.enableMPTCP\n        let bootstrapChannelInitializer = self.channelInitializer\n        let channelOptions = self._channelOptions\n        let bindTarget = self.bindTarget\n\n        let connector = HappyEyeballsConnector<PostRegistrationTransformationResult>(\n            resolver: resolver,\n            loop: eventLoop,\n            host: host,\n            port: port,\n            connectTimeout: self.connectTimeout\n        ) { eventLoop, protocolFamily in\n            Self.initializeAndRegisterNewChannel(\n                eventLoop: eventLoop,\n                protocolFamily: protocolFamily,\n                enableMPTPCP: enableMPTCP,\n                bootstrapChannelInitializer: bootstrapChannelInitializer,\n                channelOptions: channelOptions,\n                bindTarget: bindTarget,\n                channelInitializer: channelInitializer,\n                postRegisterTransformation: postRegisterTransformation\n            ) {\n                $0.eventLoop.makeSucceededFuture(())\n            }\n        }\n        return try await connector.resolveAndConnect().map { $0.1 }.get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func withConnectedSocket<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        eventLoop: EventLoop,\n        socket: NIOBSDSocket.Handle,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) async throws -> PostRegistrationTransformationResult {\n        let channel = try SocketChannel(eventLoop: eventLoop as! SelectableEventLoop, socket: socket)\n\n        return try await self.initializeAndRegisterChannel(\n            channel: channel,\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                let promise = eventLoop.makePromise(of: Void.self)\n                channel.registerAlreadyConfigured0(promise: promise)\n                return promise.futureResult\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func initializeAndRegisterNewChannel<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        eventLoop: EventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >,\n        _ body: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<(Channel, PostRegistrationTransformationResult)> {\n        let channel: SocketChannel\n        do {\n            channel = try self.makeSocketChannel(eventLoop: eventLoop, protocolFamily: protocolFamily)\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n        return self.initializeAndRegisterChannel(\n            channel: channel,\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                channel.registerAndDoSynchronously(body)\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).map { (channel, $0) }\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private static func initializeAndRegisterNewChannel<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        eventLoop: EventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        enableMPTPCP: Bool,\n        bootstrapChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void>,\n        channelOptions: ChannelOptions.Storage,\n        bindTarget: SocketAddress?,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >,\n        _ body: @escaping @Sendable (Channel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<(Channel, PostRegistrationTransformationResult)> {\n        let channel: SocketChannel\n        do {\n            channel = try Self.makeSocketChannel(\n                eventLoop: eventLoop,\n                protocolFamily: protocolFamily,\n                enableMPTCP: enableMPTPCP\n            )\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n        return Self.initializeAndRegisterChannel(\n            channel: channel,\n            bootstrapChannelInitializer: bootstrapChannelInitializer,\n            channelOptions: channelOptions,\n            bindTarget: bindTarget,\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                channel.registerAndDoSynchronously(body)\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).map { (channel, $0) }\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func initializeAndRegisterChannel<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        channel: SocketChannel,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        registration: @escaping @Sendable (SocketChannel) -> EventLoopFuture<Void>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) -> EventLoopFuture<PostRegistrationTransformationResult> {\n        Self.initializeAndRegisterChannel(\n            channel: channel,\n            bootstrapChannelInitializer: self.channelInitializer,\n            channelOptions: self._channelOptions,\n            bindTarget: self.bindTarget,\n            channelInitializer: channelInitializer,\n            registration: registration,\n            postRegisterTransformation: postRegisterTransformation\n        )\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private static func initializeAndRegisterChannel<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        channel: SocketChannel,\n        bootstrapChannelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void>,\n        channelOptions: ChannelOptions.Storage,\n        bindTarget: SocketAddress?,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        registration: @escaping @Sendable (SocketChannel) -> EventLoopFuture<Void>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) -> EventLoopFuture<PostRegistrationTransformationResult> {\n        let channelInitializer = { @Sendable channel in\n            bootstrapChannelInitializer(channel).hop(to: channel.eventLoop)\n                .assumeIsolated()\n                .flatMap { channelInitializer(channel) }\n                .nonisolated()\n        }\n        let eventLoop = channel.eventLoop\n\n        @inline(__always)\n        @Sendable\n        func setupChannel() -> EventLoopFuture<PostRegistrationTransformationResult> {\n            eventLoop.assertInEventLoop()\n            return\n                channelOptions\n                .applyAllChannelOptions(to: channel)\n                .assumeIsolated()\n                .flatMap {\n                    if let bindTarget = bindTarget {\n                        return\n                            channel\n                            .bind(to: bindTarget)\n                            .flatMap {\n                                channelInitializer(channel)\n                            }\n                    } else {\n                        return channelInitializer(channel)\n                    }\n                }.flatMap { (result: ChannelInitializerResult) in\n                    eventLoop.assertInEventLoop()\n                    return registration(channel).map {\n                        result\n                    }\n                }.flatMap {\n                    (result: ChannelInitializerResult) -> EventLoopFuture<PostRegistrationTransformationResult> in\n                    postRegisterTransformation(result, eventLoop)\n                }.flatMapError { error in\n                    eventLoop.assertInEventLoop()\n                    channel.close0(error: error, mode: .all, promise: nil)\n                    return channel.eventLoop.makeFailedFuture(error)\n                }\n                .nonisolated()\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension ClientBootstrap: Sendable {}\n\n/// A `DatagramBootstrap` is an easy way to bootstrap a `DatagramChannel` when creating datagram clients\n/// and servers.\n///\n/// Example:\n///\n/// ```swift\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///     defer {\n///         try! group.syncShutdownGracefully()\n///     }\n///     let bootstrap = DatagramBootstrap(group: group)\n///         // Enable SO_REUSEADDR.\n///         .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n///         .channelInitializer { channel in\n///             channel.pipeline.addHandler(MyChannelHandler())\n///         }\n///     let channel = try! bootstrap.bind(host: \"127.0.0.1\", port: 53).wait()\n///     /* the Channel is now ready to send/receive datagrams */\n///\n///     try channel.closeFuture.wait()  // Wait until the channel un-binds.\n/// ```\n///\n/// The `DatagramChannel` will operate on `AddressedEnvelope<ByteBuffer>` as inbound and outbound messages.\npublic final class DatagramBootstrap {\n\n    private let group: EventLoopGroup\n    private var channelInitializer: Optional<ChannelInitializerCallback>\n    @usableFromInline\n    internal var _channelOptions: ChannelOptions.Storage\n    private var proto: NIOBSDSocket.ProtocolSubtype = .default\n\n    /// Create a `DatagramBootstrap` on the `EventLoopGroup` `group`.\n    ///\n    /// The `EventLoopGroup` `group` must be compatible, otherwise the program will crash. `DatagramBootstrap` is\n    /// compatible only with `MultiThreadedEventLoopGroup` as well as the `EventLoop`s returned by\n    /// `MultiThreadedEventLoopGroup.next`. See `init(validatingGroup:)` for a fallible initializer for\n    /// situations where it's impossible to tell ahead of time if the `EventLoopGroup` is compatible or not.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public convenience init(group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            preconditionFailure(\n                \"DatagramBootstrap is only compatible with MultiThreadedEventLoopGroup and \"\n                    + \"SelectableEventLoop. You tried constructing one with \\(group) which is incompatible.\"\n            )\n        }\n        self.init(validatingGroup: group)!\n    }\n\n    /// Create a `DatagramBootstrap` on the `EventLoopGroup` `group`, validating that `group` is compatible.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public init?(validatingGroup group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            return nil\n        }\n        self._channelOptions = ChannelOptions.Storage()\n        self.group = group\n        self.channelInitializer = nil\n    }\n\n    /// Initialize the bound `DatagramChannel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - handler: A closure that initializes the provided `Channel`.\n    @preconcurrency\n    public func channelInitializer(_ handler: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self {\n        self.channelInitializer = handler\n        return self\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the `DatagramChannel`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    @inlinable\n    public func channelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self {\n        self._channelOptions.append(key: option, value: value)\n        return self\n    }\n\n    public func protocolSubtype(_ subtype: NIOBSDSocket.ProtocolSubtype) -> Self {\n        self.proto = subtype\n        return self\n    }\n\n    #if !os(Windows)\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The _Unix file descriptor_ representing the bound datagram socket.\n    @available(*, deprecated, renamed: \"withBoundSocket(_:)\")\n    public func withBoundSocket(descriptor: CInt) -> EventLoopFuture<Channel> {\n        self.withBoundSocket(descriptor)\n    }\n    #endif\n\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the bound datagram socket.\n    public func withBoundSocket(_ socket: NIOBSDSocket.Handle) -> EventLoopFuture<Channel> {\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(eventLoop: eventLoop, socket: socket)\n        }\n        return withNewChannel(makeChannel: makeChannel) { eventLoop, channel in\n            let promise = eventLoop.makePromise(of: Void.self)\n            channel.registerAlreadyConfigured0(promise: promise)\n            return promise.futureResult\n        }\n    }\n\n    /// Bind the `DatagramChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - port: The port to bind on.\n    public func bind(host: String, port: Int) -> EventLoopFuture<Channel> {\n        bind0 {\n            try SocketAddress.makeAddressResolvingHost(host, port: port)\n        }\n    }\n\n    /// Bind the `DatagramChannel` to `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    public func bind(to address: SocketAddress) -> EventLoopFuture<Channel> {\n        bind0 { address }\n    }\n\n    /// Bind the `DatagramChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. `path` must not exist, it will be created by the system.\n    public func bind(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n        bind0 {\n            try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n        }\n    }\n\n    /// Bind the `DatagramChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. The`unixDomainSocketPath` must not exist,\n    ///     unless `cleanupExistingSocketFile`is set to `true`.\n    ///   - cleanupExistingSocketFile: Whether to cleanup an existing socket file at `unixDomainSocketPath`.\n    public func bind(unixDomainSocketPath: String, cleanupExistingSocketFile: Bool) -> EventLoopFuture<Channel> {\n        if cleanupExistingSocketFile {\n            do {\n                try BaseSocket.cleanupSocket(unixDomainSocketPath: unixDomainSocketPath)\n            } catch {\n                return group.next().makeFailedFuture(error)\n            }\n        }\n\n        return self.bind(unixDomainSocketPath: unixDomainSocketPath)\n    }\n\n    private func bind0(_ makeSocketAddress: () throws -> SocketAddress) -> EventLoopFuture<Channel> {\n        let subtype = self.proto\n        let address: SocketAddress\n        do {\n            address = try makeSocketAddress()\n        } catch {\n            return group.next().makeFailedFuture(error)\n        }\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: subtype\n            )\n        }\n        return withNewChannel(makeChannel: makeChannel) { _, channel in\n            channel.register().flatMap {\n                channel.bind(to: address)\n            }\n        }\n    }\n\n    /// Connect the `DatagramChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    public func connect(host: String, port: Int) -> EventLoopFuture<Channel> {\n        connect0 {\n            try SocketAddress.makeAddressResolvingHost(host, port: port)\n        }\n    }\n\n    /// Connect the `DatagramChannel` to `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to connect to.\n    public func connect(to address: SocketAddress) -> EventLoopFuture<Channel> {\n        connect0 { address }\n    }\n\n    /// Connect the `DatagramChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to connect to. `path` must not exist, it will be created by the system.\n    public func connect(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n        connect0 {\n            try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n        }\n    }\n\n    private func connect0(_ makeSocketAddress: () throws -> SocketAddress) -> EventLoopFuture<Channel> {\n        let subtype = self.proto\n        let address: SocketAddress\n        do {\n            address = try makeSocketAddress()\n        } catch {\n            return group.next().makeFailedFuture(error)\n        }\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: subtype\n            )\n        }\n        return withNewChannel(makeChannel: makeChannel) { _, channel in\n            channel.register().flatMap {\n                channel.connect(to: address)\n            }\n        }\n    }\n\n    private func withNewChannel(\n        makeChannel: (_ eventLoop: SelectableEventLoop) throws -> DatagramChannel,\n        _ bringup: @escaping @Sendable (EventLoop, DatagramChannel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        let eventLoop = self.group.next()\n        let channelInitializer = self.channelInitializer ?? { @Sendable _ in eventLoop.makeSucceededFuture(()) }\n        let channelOptions = self._channelOptions\n\n        let channel: DatagramChannel\n        do {\n            channel = try makeChannel(eventLoop as! SelectableEventLoop)\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        @Sendable\n        func setupChannel() -> EventLoopFuture<Channel> {\n            eventLoop.assertInEventLoop()\n            return channelOptions.applyAllChannelOptions(to: channel).flatMap {\n                channelInitializer(channel)\n            }.flatMap {\n                eventLoop.assertInEventLoop()\n                return bringup(eventLoop, channel)\n            }.map {\n                channel\n            }.flatMapError { error in\n                eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n    }\n}\n\n// MARK: Async connect/bind methods\n\nextension DatagramBootstrap {\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the bound stream socket.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withBoundSocket<Output: Sendable>(\n        _ socket: NIOBSDSocket.Handle,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(eventLoop: eventLoop, socket: socket)\n        }\n        return try await self.makeConfiguredChannel(\n            makeChannel: makeChannel(_:),\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                let promise = channel.eventLoop.makePromise(of: Void.self)\n                channel.registerAlreadyConfigured0(promise: promise)\n                return promise.futureResult\n            },\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        ).get()\n    }\n\n    /// Bind the `DatagramChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - port: The port to bind on.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        host: String,\n        port: Int,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.bind0(\n            makeSocketAddress: {\n                try SocketAddress.makeAddressResolvingHost(host, port: port)\n            },\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    /// Bind the `DatagramChannel` to the `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        to address: SocketAddress,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.bind0(\n            makeSocketAddress: {\n                address\n            },\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    /// Bind the `DatagramChannel` to the `unixDomainSocketPath`.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. The`unixDomainSocketPath` must not exist,\n    ///     unless `cleanupExistingSocketFile`is set to `true`.\n    ///   - cleanupExistingSocketFile: Whether to cleanup an existing socket file at `unixDomainSocketPath`.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        unixDomainSocketPath: String,\n        cleanupExistingSocketFile: Bool = false,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        if cleanupExistingSocketFile {\n            try BaseSocket.cleanupSocket(unixDomainSocketPath: unixDomainSocketPath)\n        }\n\n        return try await self.bind0(\n            makeSocketAddress: {\n                try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n            },\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    /// Connect the `DatagramChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        host: String,\n        port: Int,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.connect0(\n            makeSocketAddress: {\n                try SocketAddress.makeAddressResolvingHost(host, port: port)\n            },\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    /// Connect the `DatagramChannel` to the `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        to address: SocketAddress,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.connect0(\n            makeSocketAddress: {\n                address\n            },\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    /// Connect the `DatagramChannel` to the `unixDomainSocketPath`.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to connect to. `path` must not exist, it will be created by the system.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        unixDomainSocketPath: String,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.connect0(\n            makeSocketAddress: {\n                try SocketAddress(unixDomainSocketPath: unixDomainSocketPath)\n            },\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { output, eventLoop in\n                eventLoop.makeSucceededFuture(output)\n            }\n        )\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func connect0<ChannelInitializerResult: Sendable, PostRegistrationTransformationResult: Sendable>(\n        makeSocketAddress: () throws -> SocketAddress,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) async throws -> PostRegistrationTransformationResult {\n        let address = try makeSocketAddress()\n        let subtype = self.proto\n\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: subtype\n            )\n        }\n\n        return try await self.makeConfiguredChannel(\n            makeChannel: makeChannel(_:),\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                channel.register().flatMap {\n                    channel.connect(to: address)\n                }\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func bind0<ChannelInitializerResult: Sendable, PostRegistrationTransformationResult: Sendable>(\n        makeSocketAddress: () throws -> SocketAddress,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) async throws -> PostRegistrationTransformationResult {\n        let address = try makeSocketAddress()\n        let subtype = self.proto\n\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: subtype\n            )\n        }\n\n        return try await self.makeConfiguredChannel(\n            makeChannel: makeChannel(_:),\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                channel.register().flatMap {\n                    channel.bind(to: address)\n                }\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func makeConfiguredChannel<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        makeChannel: (_ eventLoop: SelectableEventLoop) throws -> DatagramChannel,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        registration: @escaping @Sendable (Channel) -> EventLoopFuture<Void>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) -> EventLoopFuture<PostRegistrationTransformationResult> {\n        let eventLoop = self.group.next()\n        let bootstrapChannelInitializer =\n            self.channelInitializer ?? { @Sendable _ in eventLoop.makeSucceededFuture(()) }\n        let channelInitializer = { @Sendable (channel: Channel) -> EventLoopFuture<ChannelInitializerResult> in\n            bootstrapChannelInitializer(channel)\n                .hop(to: channel.eventLoop)\n                .assumeIsolated()\n                .flatMap { channelInitializer(channel) }\n                .nonisolated()\n        }\n        let channelOptions = self._channelOptions\n\n        let channel: DatagramChannel\n        do {\n            channel = try makeChannel(eventLoop as! SelectableEventLoop)\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        @Sendable\n        func setupChannel() -> EventLoopFuture<PostRegistrationTransformationResult> {\n            eventLoop.assertInEventLoop()\n            return channelOptions.applyAllChannelOptions(to: channel).flatMap {\n                channelInitializer(channel)\n            }.flatMap { (result: ChannelInitializerResult) in\n                eventLoop.assertInEventLoop()\n                return registration(channel).map {\n                    result\n                }\n            }.flatMap { (result: ChannelInitializerResult) -> EventLoopFuture<PostRegistrationTransformationResult> in\n                postRegisterTransformation(result, eventLoop)\n            }.flatMapError { error in\n                eventLoop.assertInEventLoop()\n                channel.close0(error: error, mode: .all, promise: nil)\n                return channel.eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension DatagramBootstrap: Sendable {}\n\n/// A `NIOPipeBootstrap` is an easy way to bootstrap a `PipeChannel` which uses two (uni-directional) UNIX pipes\n/// and makes a `Channel` out of them.\n///\n/// Example bootstrapping a `Channel` using `stdin` and `stdout`:\n///\n///     let channel = try NIOPipeBootstrap(group: group)\n///                       .channelInitializer { channel in\n///                           channel.pipeline.addHandler(MyChannelHandler())\n///                       }\n///                       .takingOwnershipOfDescriptors(input: STDIN_FILENO, output: STDOUT_FILENO)\n///\npublic final class NIOPipeBootstrap {\n    private let group: EventLoopGroup\n    private var channelInitializer: Optional<ChannelInitializerCallback>\n    @usableFromInline\n    internal var _channelOptions: ChannelOptions.Storage\n    private let hooks: any NIOPipeBootstrapHooks\n\n    /// Create a `NIOPipeBootstrap` on the `EventLoopGroup` `group`.\n    ///\n    /// The `EventLoopGroup` `group` must be compatible, otherwise the program will crash. `NIOPipeBootstrap` is\n    /// compatible only with `MultiThreadedEventLoopGroup` as well as the `EventLoop`s returned by\n    /// `MultiThreadedEventLoopGroup.next`. See `init(validatingGroup:)` for a fallible initializer for\n    /// situations where it's impossible to tell ahead of time if the `EventLoopGroup`s are compatible or not.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public convenience init(group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            preconditionFailure(\n                \"NIOPipeBootstrap is only compatible with MultiThreadedEventLoopGroup and \"\n                    + \"SelectableEventLoop. You tried constructing one with \\(group) which is incompatible.\"\n            )\n        }\n        self.init(validatingGroup: group)!\n    }\n\n    /// Create a `NIOPipeBootstrap` on the `EventLoopGroup` `group`, validating that `group` is compatible.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public init?(validatingGroup group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            return nil\n        }\n\n        self._channelOptions = ChannelOptions.Storage()\n        self.group = group\n        self.channelInitializer = nil\n        self.hooks = DefaultNIOPipeBootstrapHooks()\n    }\n\n    /// Initialiser for hooked testing\n    init?(validatingGroup group: EventLoopGroup, hooks: any NIOPipeBootstrapHooks) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            return nil\n        }\n\n        self._channelOptions = ChannelOptions.Storage()\n        self.group = group\n        self.channelInitializer = nil\n        self.hooks = hooks\n    }\n\n    /// Initialize the connected `PipeChannel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// The connected `Channel` will operate on `ByteBuffer` as inbound and outbound messages. Please note that\n    /// `IOData.fileRegion` is _not_ supported for `PipeChannel`s because `sendfile` only works on sockets.\n    ///\n    /// - Parameters:\n    ///   - handler: A closure that initializes the provided `Channel`.\n    @preconcurrency\n    public func channelInitializer(_ handler: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self {\n        self.channelInitializer = handler\n        return self\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the `PipeChannel`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    @inlinable\n    public func channelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self {\n        self._channelOptions.append(key: option, value: value)\n        return self\n    }\n\n    private func validateFileDescriptorIsNotAFile(_ descriptor: CInt) throws {\n        #if os(Windows)\n        // NOTE: this is a *non-owning* handle, do *NOT* call `CloseHandle`\n        let hFile: HANDLE = HANDLE(bitPattern: _get_osfhandle(descriptor))!\n        if hFile == INVALID_HANDLE_VALUE {\n            throw IOError(errnoCode: EBADF, reason: \"_get_osfhandle\")\n        }\n\n        // The check here is different from other platforms as the file types on\n        // Windows are different.  SOCKETs and files are different domains, and\n        // as a result we know that the descriptor is not a socket.  The only\n        // other type of file it could be is either character or disk, neither\n        // of which support the operations here.\n        switch GetFileType(hFile) {\n        case DWORD(FILE_TYPE_PIPE):\n            break\n        default:\n            throw ChannelError._operationUnsupported\n        }\n        #else\n        var s: stat = .init()\n        try withUnsafeMutablePointer(to: &s) { ptr in\n            try Posix.fstat(descriptor: descriptor, outStat: ptr)\n        }\n        switch s.st_mode & S_IFMT {\n        case S_IFREG, S_IFDIR, S_IFLNK, S_IFBLK:\n            throw ChannelError._operationUnsupported\n        default:\n            ()  // Let's default to ok\n        }\n        #endif\n    }\n\n    /// Create the `PipeChannel` with the provided file descriptor which is used for both input & output.\n    ///\n    /// This method is useful for specialilsed use-cases where you want to use `NIOPipeBootstrap` for say a serial line.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `inputOutput` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations with `inputOutput`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing it.\n    ///\n    /// - Parameters:\n    ///   - inputOutput: The _Unix file descriptor_ for the input & output.\n    /// - Returns: an `EventLoopFuture<Channel>` to deliver the `Channel`.\n    public func takingOwnershipOfDescriptor(inputOutput: CInt) -> EventLoopFuture<Channel> {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        let inputFD = inputOutput\n        let outputFD = try! Posix.dup(descriptor: inputOutput)\n\n        return self.takingOwnershipOfDescriptors(input: inputFD, output: outputFD).flatMapErrorThrowing { error in\n            try! Posix.close(descriptor: outputFD)\n            throw error\n        }\n        #endif\n    }\n\n    /// Create the `PipeChannel` with the provided input and output file descriptors.\n    ///\n    /// The input and output file descriptors must be distinct. If you have a single file descriptor, consider using\n    /// `ClientBootstrap.withConnectedSocket(descriptor:)` if it's a socket or\n    /// `NIOPipeBootstrap.takingOwnershipOfDescriptor` if it is not a socket.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `input` and `output`\n    ///         when the `Channel` becomes inactive. You _must not_ do any further operations `input` or\n    ///         `output`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptors and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - input: The _Unix file descriptor_ for the input (ie. the read side).\n    ///   - output: The _Unix file descriptor_ for the output (ie. the write side).\n    /// - Returns: an `EventLoopFuture<Channel>` to deliver the `Channel`.\n    public func takingOwnershipOfDescriptors(input: CInt, output: CInt) -> EventLoopFuture<Channel> {\n        self._takingOwnershipOfDescriptors(input: input, output: output)\n    }\n\n    /// Create the `PipeChannel` with the provided input file descriptor.\n    ///\n    /// The input file descriptor must be distinct.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `input` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations to `input`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - input: The _Unix file descriptor_ for the input (ie. the read side).\n    /// - Returns: an `EventLoopFuture<Channel>` to deliver the `Channel`.\n    public func takingOwnershipOfDescriptor(\n        input: CInt\n    ) -> EventLoopFuture<Channel> {\n        self._takingOwnershipOfDescriptors(input: input, output: nil)\n    }\n\n    /// Create the `PipeChannel` with the provided output file descriptor.\n    ///\n    /// The output file descriptor must be distinct.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `output` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations to `output`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - output: The _Unix file descriptor_ for the output (ie. the write side).\n    /// - Returns: an `EventLoopFuture<Channel>` to deliver the `Channel`.\n    public func takingOwnershipOfDescriptor(\n        output: CInt\n    ) -> EventLoopFuture<Channel> {\n        self._takingOwnershipOfDescriptors(input: nil, output: output)\n    }\n\n    private func _takingOwnershipOfDescriptors(input: CInt?, output: CInt?) -> EventLoopFuture<Channel> {\n        self._takingOwnershipOfDescriptors(\n            input: input,\n            output: output\n        ) { channel in\n            channel.eventLoop.makeSucceededFuture(channel)\n        }\n    }\n\n    @available(*, deprecated, renamed: \"takingOwnershipOfDescriptor(inputOutput:)\")\n    public func withInputOutputDescriptor(_ fileDescriptor: CInt) -> EventLoopFuture<Channel> {\n        self.takingOwnershipOfDescriptor(inputOutput: fileDescriptor)\n    }\n\n    @available(*, deprecated, renamed: \"takingOwnershipOfDescriptors(input:output:)\")\n    public func withPipes(inputDescriptor: CInt, outputDescriptor: CInt) -> EventLoopFuture<Channel> {\n        self.takingOwnershipOfDescriptors(input: inputDescriptor, output: outputDescriptor)\n    }\n}\n\n// MARK: Arbitrary payload\n\nextension NIOPipeBootstrap {\n    /// Create the `PipeChannel` with the provided file descriptor which is used for both input & output.\n    ///\n    /// This method is useful for specialilsed use-cases where you want to use `NIOPipeBootstrap` for say a serial line.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `inputOutput` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations with `inputOutput`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing it.\n    ///\n    /// - Parameters:\n    ///   - inputOutput: The _Unix file descriptor_ for the input & output.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func takingOwnershipOfDescriptor<Output: Sendable>(\n        inputOutput: CInt,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        let inputFD = inputOutput\n        let outputFD = try! Posix.dup(descriptor: inputOutput)\n\n        do {\n            return try await self.takingOwnershipOfDescriptors(\n                input: inputFD,\n                output: outputFD,\n                channelInitializer: channelInitializer\n            )\n        } catch {\n            try! Posix.close(descriptor: outputFD)\n            throw error\n        }\n        #endif\n    }\n\n    /// Create the `PipeChannel` with the provided input and output file descriptors.\n    ///\n    /// The input and output file descriptors must be distinct.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `input` and `output`\n    ///         when the `Channel` becomes inactive. You _must not_ do any further operations `input` or\n    ///         `output`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptors and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - input: The _Unix file descriptor_ for the input (ie. the read side).\n    ///   - output: The _Unix file descriptor_ for the output (ie. the write side).\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func takingOwnershipOfDescriptors<Output: Sendable>(\n        input: CInt,\n        output: CInt,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self._takingOwnershipOfDescriptors(\n            input: input,\n            output: output,\n            channelInitializer: channelInitializer\n        )\n    }\n\n    /// Create the `PipeChannel` with the provided input file descriptor.\n    ///\n    /// The input file descriptor must be distinct.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `input` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations to `input`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - input: The _Unix file descriptor_ for the input (ie. the read side).\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func takingOwnershipOfDescriptor<Output: Sendable>(\n        input: CInt,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self._takingOwnershipOfDescriptors(\n            input: input,\n            output: nil,\n            channelInitializer: channelInitializer\n        )\n    }\n\n    /// Create the `PipeChannel` with the provided output file descriptor.\n    ///\n    /// The output file descriptor must be distinct.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `output` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations to `output`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - output: The _Unix file descriptor_ for the output (ie. the write side).\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func takingOwnershipOfDescriptor<Output: Sendable>(\n        output: CInt,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self._takingOwnershipOfDescriptors(\n            input: nil,\n            output: output,\n            channelInitializer: channelInitializer\n        )\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    func _takingOwnershipOfDescriptors<ChannelInitializerResult: Sendable>(\n        input: CInt?,\n        output: CInt?,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>\n    ) async throws -> ChannelInitializerResult {\n        try await self._takingOwnershipOfDescriptors(\n            input: input,\n            output: output,\n            channelInitializer: channelInitializer\n        ).get()\n    }\n\n    func _takingOwnershipOfDescriptors<ChannelInitializerResult: Sendable>(\n        input: CInt?,\n        output: CInt?,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>\n    ) -> EventLoopFuture<ChannelInitializerResult> {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        precondition(\n            input ?? 0 >= 0 && output ?? 0 >= 0 && input != output,\n            \"illegal file descriptor pair. The file descriptors \\(String(describing: input)), \\(String(describing: output)) \"\n                + \"must be distinct and both positive integers.\"\n        )\n        precondition(!(input == nil && output == nil), \"Either input or output has to be set\")\n        let eventLoop = group.next()\n        let channelOptions = self._channelOptions\n\n        let channel: PipeChannel\n        let pipeChannelInput: SelectablePipeHandle?\n        let pipeChannelOutput: SelectablePipeHandle?\n        let hasNoInputPipe: Bool\n        let hasNoOutputPipe: Bool\n        let bootstrapChannelInitializer = self.channelInitializer\n        do {\n            if let input = input {\n                try self.validateFileDescriptorIsNotAFile(input)\n            }\n            if let output = output {\n                try self.validateFileDescriptorIsNotAFile(output)\n            }\n\n            pipeChannelInput = input.flatMap { SelectablePipeHandle(takingOwnershipOfDescriptor: $0) }\n            pipeChannelOutput = output.flatMap { SelectablePipeHandle(takingOwnershipOfDescriptor: $0) }\n            hasNoInputPipe = pipeChannelInput == nil\n            hasNoOutputPipe = pipeChannelOutput == nil\n            do {\n                channel = try self.hooks.makePipeChannel(\n                    eventLoop: eventLoop as! SelectableEventLoop,\n                    input: pipeChannelInput,\n                    output: pipeChannelOutput\n                )\n            } catch {\n                // Release file handles back to the caller in case of failure.\n                _ = try? pipeChannelInput?.takeDescriptorOwnership()\n                _ = try? pipeChannelOutput?.takeDescriptorOwnership()\n                throw error\n            }\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        @Sendable\n        func setupChannel() -> EventLoopFuture<ChannelInitializerResult> {\n            eventLoop.assertInEventLoop()\n            return channelOptions.applyAllChannelOptions(to: channel).flatMap {\n                if let bootstrapChannelInitializer {\n                    bootstrapChannelInitializer(channel)\n                } else {\n                    channel.eventLoop.makeSucceededVoidFuture()\n                }\n            }\n            .flatMap {\n                _ -> EventLoopFuture<ChannelInitializerResult> in\n                channelInitializer(channel)\n            }.flatMap { result in\n                eventLoop.assertInEventLoop()\n                let promise = eventLoop.makePromise(of: Void.self)\n                channel.registerAlreadyConfigured0(promise: promise)\n                return promise.futureResult.map { result }\n            }.flatMap { result -> EventLoopFuture<ChannelInitializerResult> in\n                if hasNoInputPipe {\n                    return channel.close(mode: .input).map { result }\n                }\n                if hasNoOutputPipe {\n                    return channel.close(mode: .output).map { result }\n                }\n                return channel.selectableEventLoop.makeSucceededFuture(result)\n            }.flatMapError { error in\n                channel.close0(error: error, mode: .all, promise: nil)\n                return channel.eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n        #endif\n    }\n}\n\n@available(*, unavailable)\nextension NIOPipeBootstrap: Sendable {}\n\nprotocol NIOPipeBootstrapHooks {\n    func makePipeChannel(\n        eventLoop: SelectableEventLoop,\n        input: SelectablePipeHandle?,\n        output: SelectablePipeHandle?\n    ) throws -> PipeChannel\n}\n\nprivate struct DefaultNIOPipeBootstrapHooks: NIOPipeBootstrapHooks {\n    func makePipeChannel(\n        eventLoop: SelectableEventLoop,\n        input: SelectablePipeHandle?,\n        output: SelectablePipeHandle?\n    ) throws -> PipeChannel {\n        try PipeChannel(eventLoop: eventLoop, input: input, output: output)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/ControlMessage.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if canImport(Darwin)\nimport CNIODarwin\n#elseif os(Linux) || os(FreeBSD) || os(Android)\nimport CNIOLinux\n#elseif os(OpenBSD)\nimport CNIOOpenBSD\nimport Glibc\n#elseif os(Windows)\nimport CNIOWindows\n#endif\n\n#if os(Windows)\nprivate let _IPPROTO_IP = WinSDK.IPPROTO_IPV4.rawValue\nprivate let _IPPROTO_IPV6 = WinSDK.IPPROTO_IPV6.rawValue\n#else\nprivate let _IPPROTO_IP = IPPROTO_IP\nprivate let _IPPROTO_IPV6 = IPPROTO_IPV6\n#endif\n\n/// Memory for use as `cmsghdr` and associated data.\n/// Supports multiple messages each with enough storage for multiple `cmsghdr`\nstruct UnsafeControlMessageStorage: Collection {\n    let bytesPerMessage: Int\n    var buffer: UnsafeMutableRawBufferPointer\n    private let deallocateBuffer: Bool\n\n    /// Initialise which includes allocating memory\n    /// - Parameters:\n    ///   - bytesPerMessage: How many bytes have been allocated for each supported message.\n    ///   - buffer: The memory allocated to use for control messages.\n    ///   - deallocateBuffer: buffer owning indicator\n    private init(bytesPerMessage: Int, buffer: UnsafeMutableRawBufferPointer, deallocateBuffer: Bool) {\n        self.bytesPerMessage = bytesPerMessage\n        self.buffer = buffer\n        self.deallocateBuffer = deallocateBuffer\n    }\n\n    // Guess that 4 Int32 payload messages is enough for anyone.\n    static var bytesPerMessage: Int { NIOBSDSocketControlMessage.space(payloadSize: MemoryLayout<Int32>.stride) * 4 }\n\n    /// Allocate new memory - Caller must call `deallocate` when no longer required.\n    /// - Parameters:\n    ///   - msghdrCount: How many `msghdr` structures will be fed from this buffer - we assume 4 Int32 cmsgs for each.\n    static func allocate(msghdrCount: Int) -> UnsafeControlMessageStorage {\n        let bytesPerMessage = Self.bytesPerMessage\n        let buffer = UnsafeMutableRawBufferPointer.allocate(\n            byteCount: bytesPerMessage * msghdrCount,\n            alignment: MemoryLayout<cmsghdr>.alignment\n        )\n        return UnsafeControlMessageStorage(bytesPerMessage: bytesPerMessage, buffer: buffer, deallocateBuffer: true)\n    }\n\n    /// Create an instance not owning the buffer\n    /// - Parameters:\n    ///   - bytesPerMessage: How many bytes have been allocated for each supported message.\n    ///   - buffer: The memory allocated to use for control messages.\n    static func makeNotOwning(\n        bytesPerMessage: Int,\n        buffer: UnsafeMutableRawBufferPointer\n    ) -> UnsafeControlMessageStorage {\n        precondition(buffer.count >= bytesPerMessage)\n        return UnsafeControlMessageStorage(bytesPerMessage: bytesPerMessage, buffer: buffer, deallocateBuffer: false)\n    }\n\n    mutating func deallocate() {\n        if self.deallocateBuffer {\n            self.buffer.deallocate()\n            self.buffer = UnsafeMutableRawBufferPointer(\n                start: UnsafeMutableRawPointer(bitPattern: 0x7ead_beef),\n                count: 0\n            )\n        }\n    }\n\n    /// Get the part of the buffer for use with a message.\n    public subscript(position: Int) -> UnsafeMutableRawBufferPointer {\n        UnsafeMutableRawBufferPointer(\n            rebasing: self.buffer[\n                (position * self.bytesPerMessage)..<((position + 1) * self.bytesPerMessage)\n            ]\n        )\n    }\n\n    var startIndex: Int { 0 }\n\n    var endIndex: Int { self.buffer.count / self.bytesPerMessage }\n\n    func index(after: Int) -> Int {\n        after + 1\n    }\n}\n\n/// Representation of a `cmsghdr` and associated data.\n/// Unsafe as captures pointers and must not escape the scope where those pointers are valid.\nstruct UnsafeControlMessage {\n    var level: CInt\n    var type: CInt\n    var data: UnsafeRawBufferPointer?\n}\n\n/// Collection representation of `cmsghdr` structures and associated data from `recvmsg`\n/// Unsafe as captures pointers held in msghdr structure which must not escape scope of validity.\nstruct UnsafeControlMessageCollection {\n    private var messageHeader: msghdr\n\n    init(messageHeader: msghdr) {\n        self.messageHeader = messageHeader\n    }\n}\n\n// Add the `Collection` functionality to UnsafeControlMessageCollection.\nextension UnsafeControlMessageCollection: Collection {\n    typealias Element = UnsafeControlMessage\n\n    struct Index: Equatable, Comparable {\n        fileprivate var cmsgPointer: UnsafeMutablePointer<cmsghdr>?\n\n        static func < (\n            lhs: UnsafeControlMessageCollection.Index,\n            rhs: UnsafeControlMessageCollection.Index\n        ) -> Bool {\n            // nil is high, as that's the end of the collection.\n            switch (lhs.cmsgPointer, rhs.cmsgPointer) {\n            case (.some(let lhs), .some(let rhs)):\n                return lhs < rhs\n            case (.some, .none):\n                return true\n            case (.none, .some), (.none, .none):\n                return false\n            }\n        }\n\n        fileprivate init(cmsgPointer: UnsafeMutablePointer<cmsghdr>?) {\n            self.cmsgPointer = cmsgPointer\n        }\n    }\n\n    var startIndex: Index {\n        var messageHeader = self.messageHeader\n        return withUnsafePointer(to: &messageHeader) { messageHeaderPtr in\n            let firstCMsg = NIOBSDSocketControlMessage.firstHeader(inside: messageHeaderPtr)\n            return Index(cmsgPointer: firstCMsg)\n        }\n    }\n\n    var endIndex: Index { Index(cmsgPointer: nil) }\n\n    func index(after: Index) -> Index {\n        var msgHdr = messageHeader\n        return withUnsafeMutablePointer(to: &msgHdr) { messageHeaderPtr in\n            Index(\n                cmsgPointer: NIOBSDSocketControlMessage.nextHeader(\n                    inside: messageHeaderPtr,\n                    after: after.cmsgPointer!\n                )\n            )\n        }\n    }\n\n    public subscript(position: Index) -> Element {\n        let cmsg = position.cmsgPointer!\n        return UnsafeControlMessage(\n            level: cmsg.pointee.cmsg_level,\n            type: cmsg.pointee.cmsg_type,\n            data: NIOBSDSocketControlMessage.data(for: cmsg)\n        )\n    }\n}\n\n/// Small struct to link a buffer used for control bytes and the processing of those bytes.\nstruct UnsafeReceivedControlBytes {\n    var controlBytesBuffer: UnsafeMutableRawBufferPointer\n    /// Set when a message is received which is using the controlBytesBuffer - the lifetime will be tied to that of `controlBytesBuffer`\n    var receivedControlMessages: UnsafeControlMessageCollection?\n\n    init(controlBytesBuffer: UnsafeMutableRawBufferPointer) {\n        self.controlBytesBuffer = controlBytesBuffer\n    }\n}\n\n/// Extract information from a collection of control messages.\nstruct ControlMessageParser {\n    var ecnValue: NIOExplicitCongestionNotificationState = .transportNotCapable  // Default\n    var packetInfo: NIOPacketInfo? = nil\n    var segmentSize: Int? = nil\n\n    init(parsing controlMessagesReceived: UnsafeControlMessageCollection) {\n        for controlMessage in controlMessagesReceived {\n            self.receiveMessage(controlMessage)\n        }\n    }\n\n    #if canImport(Darwin)\n    private static let ipv4TosType = IP_RECVTOS\n    #else\n    private static let ipv4TosType = IP_TOS  // Linux\n    #endif\n\n    static func _readCInt(data: UnsafeRawBufferPointer) -> CInt {\n        assert(data.count == MemoryLayout<CInt>.size)\n        precondition(data.count >= MemoryLayout<CInt>.size)\n        var readValue = CInt(0)\n        withUnsafeMutableBytes(of: &readValue) { valuePtr in\n            valuePtr.copyMemory(from: data)\n        }\n        return readValue\n    }\n\n    private mutating func receiveMessage(_ controlMessage: UnsafeControlMessage) {\n        if controlMessage.level == _IPPROTO_IP {\n            self.receiveIPv4Message(controlMessage)\n        } else if controlMessage.level == _IPPROTO_IPV6 {\n            self.receiveIPv6Message(controlMessage)\n        } else if controlMessage.level == Posix.SOL_UDP {\n            self.receiveUDPMessage(controlMessage)\n        }\n    }\n\n    private mutating func receiveIPv4Message(_ controlMessage: UnsafeControlMessage) {\n        if controlMessage.type == ControlMessageParser.ipv4TosType {\n            if let data = controlMessage.data {\n                assert(data.count == 1)\n                precondition(data.count >= 1)\n                let readValue = CInt(data[0])\n                self.ecnValue = .init(receivedValue: readValue)\n            }\n        } else if controlMessage.type == Posix.IP_PKTINFO {\n            #if !os(OpenBSD)\n            if let data = controlMessage.data {\n                let info = data.load(as: in_pktinfo.self)\n                var addr = sockaddr_in()\n                addr.sin_family = sa_family_t(NIOBSDSocket.AddressFamily.inet.rawValue)\n                addr.sin_port = in_port_t(0)\n                addr.sin_addr = info.ipi_addr\n                self.packetInfo = NIOPacketInfo(\n                    destinationAddress: SocketAddress(addr, host: \"\"),\n                    interfaceIndex: Int(info.ipi_ifindex)\n                )\n            }\n            #endif\n        }\n    }\n\n    private mutating func receiveIPv6Message(_ controlMessage: UnsafeControlMessage) {\n        if controlMessage.type == IPV6_TCLASS {\n            if let data = controlMessage.data {\n                let readValue = ControlMessageParser._readCInt(data: data)\n                self.ecnValue = .init(receivedValue: readValue)\n            }\n        } else if controlMessage.type == Posix.IPV6_PKTINFO {\n            if let data = controlMessage.data {\n                let info = data.load(as: in6_pktinfo.self)\n                var addr = sockaddr_in6()\n                addr.sin6_family = sa_family_t(NIOBSDSocket.AddressFamily.inet6.rawValue)\n                addr.sin6_port = in_port_t(0)\n                addr.sin6_flowinfo = 0\n                addr.sin6_addr = info.ipi6_addr\n                addr.sin6_scope_id = 0\n                self.packetInfo = NIOPacketInfo(\n                    destinationAddress: SocketAddress(addr, host: \"\"),\n                    interfaceIndex: Int(info.ipi6_ifindex)\n                )\n            }\n        }\n    }\n\n    private mutating func receiveUDPMessage(_ controlMessage: UnsafeControlMessage) {\n        #if os(Linux)\n        if controlMessage.type == .init(NIOBSDSocket.Option.udp_gro.rawValue) {\n            if let data = controlMessage.data {\n                let readValue = ControlMessageParser._readCInt(data: data)\n                self.segmentSize = Int(readValue)\n            }\n        }\n        #endif\n    }\n}\n\nextension NIOExplicitCongestionNotificationState {\n    /// Initialise a NIOExplicitCongestionNotificationState from a value received via either TCLASS or TOS cmsg.\n    init(receivedValue: CInt) {\n        switch receivedValue & Posix.IPTOS_ECN_MASK {\n        case Posix.IPTOS_ECN_ECT1:\n            self = .transportCapableFlag1\n        case Posix.IPTOS_ECN_ECT0:\n            self = .transportCapableFlag0\n        case Posix.IPTOS_ECN_CE:\n            self = .congestionExperienced\n        default:\n            self = .transportNotCapable\n        }\n    }\n}\n\nextension CInt {\n    /// Create a CInt encoding of ExplicitCongestionNotification suitable for sending in TCLASS or TOS cmsg.\n    init(ecnValue: NIOExplicitCongestionNotificationState) {\n        switch ecnValue {\n        case .transportNotCapable:\n            self = Posix.IPTOS_ECN_NOTECT\n        case .transportCapableFlag0:\n            self = Posix.IPTOS_ECN_ECT0\n        case .transportCapableFlag1:\n            self = Posix.IPTOS_ECN_ECT1\n        case .congestionExperienced:\n            self = Posix.IPTOS_ECN_CE\n        }\n    }\n}\n\nstruct UnsafeOutboundControlBytes {\n    private var controlBytes: UnsafeMutableRawBufferPointer\n    private var writePosition: UnsafeMutableRawBufferPointer.Index\n\n    /// This structure must not outlive `controlBytes`\n    init(controlBytes: UnsafeMutableRawBufferPointer) {\n        self.controlBytes = controlBytes\n        self.writePosition = controlBytes.startIndex\n    }\n\n    mutating func appendControlMessage(level: CInt, type: CInt, payload: CInt) {\n        self.appendGenericControlMessage(level: level, type: type, payload: payload)\n    }\n\n    /// Appends a control message.\n    /// PayloadType needs to be trivial (eg CInt)\n    private mutating func appendGenericControlMessage<PayloadType>(\n        level: CInt,\n        type: CInt,\n        payload: PayloadType\n    ) {\n        let writableBuffer = UnsafeMutableRawBufferPointer(\n            rebasing: self.controlBytes[writePosition...]\n        )\n\n        let requiredSize = NIOBSDSocketControlMessage.space(payloadSize: MemoryLayout.stride(ofValue: payload))\n        precondition(writableBuffer.count >= requiredSize, \"Insufficient size for cmsghdr and data\")\n\n        let bufferBase = writableBuffer.baseAddress!\n        // Binding to cmsghdr is safe here as this is the only place where we bind to non-Raw.\n        let cmsghdrPtr = bufferBase.bindMemory(to: cmsghdr.self, capacity: 1)\n        cmsghdrPtr.pointee.cmsg_level = level\n        cmsghdrPtr.pointee.cmsg_type = type\n        cmsghdrPtr.pointee.cmsg_len = .init(\n            NIOBSDSocketControlMessage.length(payloadSize: MemoryLayout.size(ofValue: payload))\n        )\n\n        let dataPointer = NIOBSDSocketControlMessage.data(for: cmsghdrPtr)!\n        precondition(dataPointer.count >= MemoryLayout<PayloadType>.stride)\n        dataPointer.storeBytes(of: payload, as: PayloadType.self)\n\n        self.writePosition += requiredSize\n    }\n\n    /// The result is only valid while this is valid.\n    var validControlBytes: UnsafeMutableRawBufferPointer {\n        if writePosition == 0 {\n            return UnsafeMutableRawBufferPointer(start: nil, count: 0)\n        }\n        return UnsafeMutableRawBufferPointer(rebasing: self.controlBytes[0..<self.writePosition])\n    }\n\n}\n\nextension UnsafeOutboundControlBytes {\n    /// Add a message describing the explicit congestion state if requested in metadata and valid for this protocol.\n    ///  Parameters:\n    ///   - metadata:   Metadata from the addressed envelope which will describe any desired state.\n    ///   - protocolFamily:  The type of protocol to encode for.\n    internal mutating func appendExplicitCongestionState(\n        metadata: AddressedEnvelope<ByteBuffer>.Metadata?,\n        protocolFamily: NIOBSDSocket.ProtocolFamily?\n    ) {\n        guard let metadata = metadata else { return }\n\n        switch protocolFamily {\n        case .some(.inet):\n            self.appendControlMessage(\n                level: .init(IPPROTO_IP),\n                type: IP_TOS,\n                payload: CInt(ecnValue: metadata.ecnState)\n            )\n        case .some(.inet6):\n            self.appendControlMessage(\n                level: .init(_IPPROTO_IPV6),\n                type: IPV6_TCLASS,\n                payload: CInt(ecnValue: metadata.ecnState)\n            )\n        default:\n            // Nothing to do - if we get here the user is probably making a mistake.\n            break\n        }\n    }\n\n    /// Appends a UDP segment size control message for Generic Segmentation Offload (GSO).\n    ///\n    /// - Parameter metadata: Metadata from the addressed envelope which may contain a segment size.\n    /// - Warning: This will `fatalError` if called with a segmentSize on non-Linux platforms.\n    ///   Callers should validate platform support before enqueueing writes with segmentSize.\n    internal mutating func appendUDPSegmentSize(metadata: AddressedEnvelope<ByteBuffer>.Metadata?) {\n        guard let metadata = metadata, let segmentSize = metadata.segmentSize else { return }\n\n        #if os(Linux)\n        self.appendGenericControlMessage(\n            level: Posix.SOL_UDP,\n            type: .init(NIOBSDSocket.Option.udp_segment.rawValue),\n            payload: UInt16(segmentSize)\n        )\n        #else\n        fatalError(\"UDP segment size is only supported on Linux\")\n        #endif\n    }\n}\n\nextension AddressedEnvelope.Metadata {\n    /// It's assumed the caller has checked that congestion information is required before calling.\n    internal init(from controlMessagesReceived: UnsafeControlMessageCollection) {\n        let controlMessageReceiver = ControlMessageParser(parsing: controlMessagesReceived)\n        self.init(\n            ecnState: controlMessageReceiver.ecnValue,\n            packetInfo: controlMessageReceiver.packetInfo,\n            segmentSize: controlMessageReceiver.segmentSize\n        )\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/DatagramVectorReadManager.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport CNIODarwin\nimport CNIOLinux\nimport CNIOOpenBSD\nimport NIOCore\n\n#if canImport(WinSDK)\nimport WinSDK\nimport CNIOWindows\n#endif\n\n/// An object that manages issuing vector reads for datagram channels.\n///\n/// Datagram channels have slightly complex read semantics, as high-throughput datagram\n/// channels would like to use gathering reads to minimise syscall overhead. This requires\n/// managing memory carefully, as well as includes some complex logic that needs to be\n/// carefully arranged. For this reason, we store this logic on this separate struct\n/// that makes understanding the code a lot simpler.\nstruct DatagramVectorReadManager {\n    enum ReadResult {\n        case some(reads: [AddressedEnvelope<ByteBuffer>], totalSize: Int)\n        case none\n    }\n\n    /// The number of messages that will be read in each syscall.\n    var messageCount: Int {\n        get {\n            self.messageVector.count\n        }\n        set {\n            precondition(newValue >= 0)\n            self.messageVector.deinitializeAndDeallocate()\n            self.ioVector.deinitializeAndDeallocate()\n            self.sockaddrVector.deinitializeAndDeallocate()\n            self.controlMessageStorage.deallocate()\n\n            self.messageVector = .allocateAndInitialize(\n                repeating: MMsgHdr(msg_hdr: msghdr(), msg_len: 0),\n                count: newValue\n            )\n            self.ioVector = .allocateAndInitialize(repeating: IOVector(), count: newValue)\n            self.sockaddrVector = .allocateAndInitialize(repeating: sockaddr_storage(), count: newValue)\n            self.controlMessageStorage = UnsafeControlMessageStorage.allocate(msghdrCount: newValue)\n        }\n    }\n\n    /// The vector of MMsgHdrs that are used for the gathering reads.\n    private var messageVector: UnsafeMutableBufferPointer<MMsgHdr>\n\n    /// The vector of iovec structures needed by msghdr structures.\n    private var ioVector: UnsafeMutableBufferPointer<IOVector>\n\n    /// The vector of sockaddr structures used for saving addresses.\n    private var sockaddrVector: UnsafeMutableBufferPointer<sockaddr_storage>\n\n    /// Storage to use for `cmsghdr` data when reading messages.\n    private var controlMessageStorage: UnsafeControlMessageStorage\n\n    // FIXME(cory): Right now there's no good API for specifying the various parameters of multi-read, especially how\n    // it should interact with RecvByteBufferAllocator. For now I'm punting on this to see if I can get it working,\n    // but we should design it back.\n    fileprivate init(\n        messageVector: UnsafeMutableBufferPointer<MMsgHdr>,\n        ioVector: UnsafeMutableBufferPointer<IOVector>,\n        sockaddrVector: UnsafeMutableBufferPointer<sockaddr_storage>,\n        controlMessageStorage: UnsafeControlMessageStorage\n    ) {\n        self.messageVector = messageVector\n        self.ioVector = ioVector\n        self.sockaddrVector = sockaddrVector\n        self.controlMessageStorage = controlMessageStorage\n    }\n\n    /// Performs a socket vector read.\n    ///\n    /// This method takes a single byte buffer and segments it into `messageCount` pieces. It then\n    /// prepares and issues a single recvmmsg syscall, instructing the kernel to write multiple datagrams\n    /// into that single buffer. Assuming that some datagrams have been successfully read, it then slices\n    /// that large buffer up into multiple buffers, prepares a series of AddressedEnvelope structures\n    /// appropriately, and then returns that result to the caller.\n    ///\n    /// - warning: If buffer is not at least 1.5kB times `messageCount`, this will almost certainly lead to\n    ///     dropped data. Caution should be taken to ensure that the RecvByteBufferAllocator is allocating an\n    ///     appropriate amount of memory.\n    /// - warning: Unlike most of the rest of SwiftNIO, the read managers use withVeryUnsafeMutableBytes to\n    ///     obtain a pointer to the entire buffer storage. This is because they assume they own the entire\n    ///     buffer.\n    ///\n    /// - Parameters:\n    ///   - socket: The underlying socket from which to read.\n    ///   - buffer: The single large buffer into which reads will be written.\n    ///   - parseControlMessages: Should control messages be reported up using metadata.\n    func readFromSocket(\n        socket: Socket,\n        buffer: inout ByteBuffer,\n        parseControlMessages: Bool\n    ) throws -> ReadResult {\n        assert(buffer.readerIndex == 0, \"Buffer was not cleared between calls to readFromSocket!\")\n\n        let messageSize = buffer.capacity / self.messageCount\n\n        let result = try buffer.withVeryUnsafeMutableBytes { bufferPointer -> IOResult<Int> in\n            for i in 0..<self.messageCount {\n                // TODO(cory): almost all of this except for the iovec could be done at allocation time. Maybe we should?\n\n                // First we set up the iovec and save it off.\n                self.ioVector[i] = IOVector(\n                    iov_base: bufferPointer.baseAddress! + (i * messageSize),\n                    iov_len: numericCast(messageSize)\n                )\n\n                let controlBytes: UnsafeMutableRawBufferPointer\n                if parseControlMessages {\n                    // This will be used in buildMessages below but should not be used beyond return of this function.\n                    controlBytes = self.controlMessageStorage[i]\n                } else {\n                    controlBytes = UnsafeMutableRawBufferPointer(start: nil, count: 0)\n                }\n\n                // Next we set up the msghdr structure. This points into the other vectors.\n                var msgHdr = msghdr()\n                msgHdr.msg_name = .init(self.sockaddrVector.baseAddress! + i)\n                msgHdr.msg_namelen = socklen_t(MemoryLayout<sockaddr_storage>.size)\n                msgHdr.msg_iov = self.ioVector.baseAddress! + i\n                msgHdr.msg_iovlen = 1  // This is weird, but each message gets only one array. Duh\n                msgHdr.control_ptr = controlBytes\n                msgHdr.msg_flags = 0\n                self.messageVector[i] = MMsgHdr(msg_hdr: msgHdr, msg_len: 0)\n\n                // Note that we don't set up the sockaddr vector: that's because it needs no initialization,\n                // it's written into by the kernel.\n            }\n\n            // We've set up our pointers, it's time to get going. We now issue the call.\n            return try socket.recvmmsg(msgs: self.messageVector)\n        }\n\n        switch result {\n        case .wouldBlock(let messagesProcessed):\n            assert(messagesProcessed == 0)\n            return .none\n        case .processed(let messagesProcessed):\n            buffer.moveWriterIndex(to: messageSize * messagesProcessed)\n            return try self.buildMessages(\n                messageCount: messagesProcessed,\n                sliceSize: messageSize,\n                buffer: &buffer,\n                parseControlMessages: parseControlMessages\n            )\n        }\n    }\n\n    /// Destroys this vector read manager, rendering it impossible to re-use. Use of the vector read manager after this is called is not possible.\n    mutating func deallocate() {\n        self.messageVector.deinitializeAndDeallocate()\n        self.ioVector.deinitializeAndDeallocate()\n        self.sockaddrVector.deinitializeAndDeallocate()\n        self.controlMessageStorage.deallocate()\n    }\n\n    private func buildMessages(\n        messageCount: Int,\n        sliceSize: Int,\n        buffer: inout ByteBuffer,\n        parseControlMessages: Bool\n    ) throws -> ReadResult {\n        var sliceOffset = buffer.readerIndex\n        var totalReadSize = 0\n\n        var results = [AddressedEnvelope<ByteBuffer>]()\n        results.reserveCapacity(messageCount)\n\n        for i in 0..<messageCount {\n            // We force-unwrap here because we should not have been able to write past the end of the buffer.\n            var slice = buffer.getSlice(at: sliceOffset, length: sliceSize)!\n            sliceOffset += sliceSize\n\n            // Now we move the writer index backwards to where the end of the read was. Note that 0 is not an\n            // error for datagrams, zero-length datagrams are permitted.\n            let readBytes = Int(self.messageVector[i].msg_len)\n            slice.moveWriterIndex(to: readBytes)\n            totalReadSize += readBytes\n\n            // Next we extract the remote peer address.\n            #if os(Windows)\n            precondition(self.messageVector[i].msg_hdr.namelen != 0, \"Unexpected zero length peer name\")\n            #else\n            precondition(self.messageVector[i].msg_hdr.msg_namelen != 0, \"Unexpected zero length peer name\")\n            #endif\n            let address: SocketAddress = try self.sockaddrVector[i].convert()\n\n            // Extract congestion information if requested.\n            let metadata: AddressedEnvelope<ByteBuffer>.Metadata?\n            if parseControlMessages {\n                let controlMessagesReceived =\n                    UnsafeControlMessageCollection(messageHeader: self.messageVector[i].msg_hdr)\n                metadata = .init(from: controlMessagesReceived)\n            } else {\n                metadata = nil\n            }\n\n            // Now we've finally constructed a useful AddressedEnvelope. We can store it in the results array temporarily.\n            results.append(AddressedEnvelope(remoteAddress: address, data: slice, metadata: metadata))\n        }\n\n        // Ok, all built. Now we can return these values to the caller.\n        return .some(reads: results, totalSize: totalReadSize)\n    }\n}\n\nextension DatagramVectorReadManager {\n    /// Allocates and initializes a new DatagramVectorReadManager.\n    ///\n    /// - Parameters:\n    ///   - messageCount: The number of vector reads to support initially.\n    static func allocate(messageCount: Int) -> DatagramVectorReadManager {\n        let messageVector = UnsafeMutableBufferPointer.allocateAndInitialize(\n            repeating: MMsgHdr(msg_hdr: msghdr(), msg_len: 0),\n            count: messageCount\n        )\n        let ioVector = UnsafeMutableBufferPointer.allocateAndInitialize(repeating: IOVector(), count: messageCount)\n        let sockaddrVector = UnsafeMutableBufferPointer.allocateAndInitialize(\n            repeating: sockaddr_storage(),\n            count: messageCount\n        )\n        let controlMessageStorage = UnsafeControlMessageStorage.allocate(msghdrCount: messageCount)\n\n        return DatagramVectorReadManager(\n            messageVector: messageVector,\n            ioVector: ioVector,\n            sockaddrVector: sockaddrVector,\n            controlMessageStorage: controlMessageStorage\n        )\n    }\n}\n\nextension Optional where Wrapped == DatagramVectorReadManager {\n    /// Updates the message count of the wrapped `DatagramVectorReadManager` to the new value.\n    ///\n    /// If the new value is 0 or negative, will destroy the contained vector read manager and set\n    /// self to `nil`.\n    mutating func updateMessageCount(_ newCount: Int) {\n        if newCount > 0 {\n            if self != nil {\n                self!.messageCount = newCount\n            } else {\n                self = DatagramVectorReadManager.allocate(messageCount: newCount)\n            }\n        } else {\n            if self != nil {\n                self!.deallocate()\n            }\n            self = nil\n        }\n    }\n}\n\nextension UnsafeMutableBufferPointer {\n    /// Safely creates an UnsafeMutableBufferPointer that can be used by the rest of the code. It ensures that\n    /// the memory has been bound, allocated, and initialized, such that other Swift code can use it safely without\n    /// worrying.\n    fileprivate static func allocateAndInitialize(\n        repeating element: Element,\n        count: Int\n    ) -> UnsafeMutableBufferPointer<Element> {\n        let newPointer = UnsafeMutableBufferPointer.allocate(capacity: count)\n        newPointer.initialize(repeating: element)\n        return newPointer\n    }\n\n    /// This safely destroys an UnsafeMutableBufferPointer by deinitializing and deallocating\n    /// the underlying memory. This ensures that if the pointer contains non-trivial Swift\n    /// types that no accidental memory leaks will occur, as can happen if UnsafeMutableBufferPointer.deallocate()\n    /// is used.\n    fileprivate func deinitializeAndDeallocate() {\n        guard let basePointer = self.baseAddress else {\n            // If there's no base address, who cares?\n            return\n        }\n\n        // This is the safe way to do things: the moment that deinitialize\n        // is called, we deallocate.\n        let rawPointer = basePointer.deinitialize(count: self.count)\n        rawPointer.deallocate()\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Docs.docc/GSO-GRO-Linux.md",
    "content": "# Per-Message GSO and GRO on Linux\n\nUse Generic Segmentation Offload (GSO) and Generic Receive Offload (GRO) on a per-message basis for fine-grained control over UDP datagram segmentation and aggregation.\n\n## Overview\n\nGeneric Segmentation Offload (GSO) and Generic Receive Offload (GRO) are Linux kernel features that enable efficient handling of UDP datagrams by offloading segmentation and aggregation work to the kernel or network interface card (NIC).\n\nSwiftNIO provides per-message APIs for both features, allowing dynamic control over segmentation and aggregation on a datagram-by-datagram basis. This offers more flexibility than channel-wide configuration, which requires static segment sizes known ahead of time.\n\n### What is Generic Segmentation Offload (GSO)?\n\nGSO allows you to send a single large buffer (a \"superbuffer\") that the kernel automatically splits into multiple UDP datagrams of a specified segment size. Instead of your application creating many small datagrams, you write one superbuffer and let the kernel handle the segmentation efficiently.\n\n**Benefits:**\n- Reduced application overhead by avoiding manual buffer segmentation\n- Lower CPU usage as the kernel or NIC performs the segmentation\n- Improved throughput for high-volume UDP applications\n\n### What is Generic Receive Offload (GRO)?\n\nGRO is the reverse of GSO: the kernel aggregates multiple received UDP datagrams into a single larger buffer (again, a \"superbuffer\") before delivering it to your application. When enabled with per-message metadata, you receive information about the original segment size used for aggregation.\n\n**Benefits:**\n- Fewer read syscalls and event loop iterations\n- Reduced per-packet processing overhead\n- Better performance for applications receiving many small datagrams\n\n## Per-Message GSO\n\nThe per-message GSO API allows you to specify segmentation parameters for each datagram write, rather than configuring a static segment size for the entire channel.\n\n### Enabling Per-Message GSO\n\nTo use per-message GSO, set the `segmentSize` field in `AddressedEnvelope.Metadata` when writing datagrams:\n\n```swift\nimport NIOCore\nimport NIOPosix\n\n// Create a large buffer to send (10 segments of 1000 bytes each)\nlet segmentSize = 1000\nlet segmentCount = 10\nvar largeBuffer = channel.allocator.buffer(capacity: segmentSize * segmentCount)\nlargeBuffer.writeRepeatingByte(1, count: segmentSize * segmentCount)\n\n// Write with per-message GSO metadata\nlet envelope = AddressedEnvelope(\n    remoteAddress: destinationAddress,\n    data: largeBuffer,\n    metadata: .init(\n        ecnState: .transportNotCapable,\n        packetInfo: nil,\n        segmentSize: segmentSize  // Enable GSO with 1000-byte segments\n    )\n)\n\ntry await channel.writeAndFlush(envelope)\n```\n\nThe kernel will automatically split `largeBuffer` into 10 separate UDP datagrams of 1000 bytes each.\n\n### Mixing GSO and Non-GSO Writes\n\nYou can freely mix writes with and without per-message GSO on the same channel:\n\n```swift\n// Write with GSO\nlet gsoEnvelope = AddressedEnvelope(\n    remoteAddress: destinationAddress,\n    data: largeBuffer,\n    metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: 1000)\n)\n\n// Write without GSO (normal datagram)\nlet normalEnvelope = AddressedEnvelope(\n    remoteAddress: destinationAddress,\n    data: smallBuffer\n)\n\nlet write1 = channel.write(gsoEnvelope)\nlet write2 = channel.write(normalEnvelope)\nchannel.flush()\n```\n\n## Per-Message GRO\n\nThe per-message GRO API provides segment size information for each received aggregated datagram through the same `AddressedEnvelope.Metadata.segmentSize` field used for GSO.\n\n### Enabling Per-Message GRO\n\nTo enable per-message GRO segment size reporting, you must:\n\n1. Enable channel-level GRO using `ChannelOptions.datagramReceiveOffload`\n2. Enable per-message segment size reporting using `ChannelOptions.datagramReceiveSegmentSize`\n3. Configure an appropriate receive buffer allocator to accommodate aggregated datagrams\n\n```swift\nimport NIOCore\nimport NIOPosix\n\n// Enable GRO on the channel\ntry await channel.setOption(.datagramReceiveOffload, value: true)\n\n// Enable per-message segment size reporting\ntry await channel.setOption(.datagramReceiveSegmentSize, value: true)\n\n// Configure a larger receive buffer to accommodate aggregated datagrams\nlet largeBufferAllocator = FixedSizeRecvByteBufferAllocator(capacity: 65536)\ntry await channel.setOption(.recvAllocator, value: largeBufferAllocator)\n```\n\n### Reading Segment Size from Received Datagrams\n\nWhen you receive an aggregated datagram, the `segmentSize` field in the metadata contains the original segment size:\n\n```swift\n// In your channel handler\nfunc channelRead(context: ChannelHandlerContext, data: NIOAny) {\n    let envelope = self.unwrapInboundIn(data)\n\n    // Check if this is an aggregated datagram\n    if let segmentSize = envelope.metadata?.segmentSize {\n        print(\"Received aggregated datagram:\")\n        print(\"  Total size: \\(envelope.data.readableBytes) bytes\")\n        print(\"  Original segment size: \\(segmentSize) bytes\")\n        print(\"  Approximate segment count: \\(envelope.data.readableBytes / segmentSize)\")\n    } else {\n        print(\"Received normal datagram: \\(envelope.data.readableBytes) bytes\")\n    }\n}\n```\n\n### Buffer Allocator Considerations\n\nWhen using GRO, ensure your receive buffer allocator provides buffers large enough to hold aggregated datagrams. The default datagram channel allocator uses 2048-byte fixed buffers, which may be too small:\n\n```swift\n// Instead of the default 2048-byte buffers, use larger buffers\nlet allocator = FixedSizeRecvByteBufferAllocator(capacity: 65536)  // 64KB buffers\ntry await channel.setOption(.recvAllocator, value: allocator)\n```\n\nIf the receive buffer is too small, the kernel will not be able to aggregate as many datagrams, reducing the effectiveness of GRO.\n\n## Platform Requirements and Limitations\n\n### Linux-Only Feature\n\nPer-message GSO and GRO are only supported on Linux. Attempting to use these features on other platforms will result in errors:\n\n- **GSO**: Writing an envelope with `segmentSize` set will fail the write promise with `ChannelError.operationUnsupported`\n- **GRO**: Setting `ChannelOptions.datagramReceiveSegmentSize` will fail with `ChannelError.operationUnsupported`\n\n### Kernel Version Requirements\n\n- **GSO**: Requires Linux kernel 4.18 or newer\n- **GRO**: Requires Linux kernel 5.10 or newer\n\n### Runtime Support Detection\n\nCheck for GSO and GRO support at runtime using the `System` APIs:\n\n```swift\nimport NIOPosix\n\nif System.supportsUDPSegmentationOffload {\n    print(\"GSO is supported on this platform\")\n    // Use per-message GSO\n} else {\n    print(\"GSO is not supported, falling back to normal writes\")\n}\n\nif System.supportsUDPReceiveOffload {\n    print(\"GRO is supported on this platform\")\n    // Enable per-message GRO\n} else {\n    print(\"GRO is not supported\")\n}\n```\n\n### Error Handling\n\nGenerally speaking, error handling for GSO and GRO is very similar to the error handling without them. An important note is that a single promise cannot handle individualised errors for the datagrams within the superbuffer. The kernel delivers only one return code for a given send or receive, which affects multiple datagrams within the superbuffer. However, it may not affect _all_ datagrams within the superbuffer,\nas the writes can be split. The result is that if the _final_ superbuffer write completes successfully the\npromise will be succeeded, even if errors occurred earlier.\n\nIn the event that you do not follow the steps above and attempt to use GSO on platforms that do not support it, the promise will fail with `.operationUnsupported` and no writes will be attempted.\n"
  },
  {
    "path": "Sources/NIOPosix/Docs.docc/index.md",
    "content": "# ``NIOPosix``\n\nPlatform-specific implementations of SwiftNIO abstractions for POSIX systems.\n\n## Overview\n\n``NIOPosix`` provides concrete implementations of the core SwiftNIO abstractions defined in ``NIOCore`` for POSIX-compliant operating systems including Linux, macOS, and other Unix-like platforms.\n\nThis module contains platform-specific channel implementations, event loops, and networking features that leverage operating system capabilities for high-performance networking.\n\n## Topics\n\n### Articles\n\n- <doc:GSO-GRO-Linux>\n"
  },
  {
    "path": "Sources/NIOPosix/Errors+Any.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n// 'any Error' is unconditionally boxed, avoid allocating per use by statically boxing them.\nextension ChannelError {\n    static let _alreadyClosed: any Error = ChannelError.alreadyClosed\n    static let _badInterfaceAddressFamily: any Error = ChannelError.badInterfaceAddressFamily\n    static let _badMulticastGroupAddressFamily: any Error = ChannelError.badMulticastGroupAddressFamily\n    static let _connectPending: any Error = ChannelError.connectPending\n    static let _eof: any Error = ChannelError.eof\n    static let _inappropriateOperationForState: any Error = ChannelError.inappropriateOperationForState\n    static let _inputClosed: any Error = ChannelError.inputClosed\n    static let _ioOnClosedChannel: any Error = ChannelError.ioOnClosedChannel\n    static let _operationUnsupported: any Error = ChannelError.operationUnsupported\n    static let _outputClosed: any Error = ChannelError.outputClosed\n    static let _unknownLocalAddress: any Error = ChannelError.unknownLocalAddress\n    static let _writeHostUnreachable: any Error = ChannelError.writeHostUnreachable\n    static let _writeMessageTooLarge: any Error = ChannelError.writeMessageTooLarge\n}\n\nextension EventLoopError {\n    static let _shutdown: any Error = EventLoopError.shutdown\n    static let _unsupportedOperation: any Error = EventLoopError.unsupportedOperation\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/FileDescriptor.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if !os(Windows)\nimport NIOCore\n\nextension FileDescriptor {\n    internal static func setNonBlocking(fileDescriptor: CInt) throws {\n        let flags = try Posix.fcntl(descriptor: fileDescriptor, command: F_GETFL, value: 0)\n        do {\n            let ret = try Posix.fcntl(descriptor: fileDescriptor, command: F_SETFL, value: flags | O_NONBLOCK)\n            assert(ret == 0, \"unexpectedly, fcntl(\\(fileDescriptor), F_SETFL, \\(flags) | O_NONBLOCK) returned \\(ret)\")\n        } catch let error as IOError {\n            if error.errnoCode == EINVAL {\n                // Darwin seems to sometimes do this despite the docs claiming it can't happen\n                throw NIOFcntlFailedError()\n            }\n            throw error\n        }\n    }\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/GetaddrinfoResolver.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\n/// A DNS resolver built on top of the libc `getaddrinfo` function.\n///\n/// This is the lowest-common-denominator resolver available to NIO. It's not really a very good\n/// solution because the `getaddrinfo` call blocks during the DNS resolution, meaning that this resolver\n/// will block a thread for as long as it takes to perform the getaddrinfo call. To prevent it from blocking `EventLoop`\n/// threads, it will offload the blocking `getaddrinfo` calls to a `DispatchQueue`.\n/// One advantage from leveraging `getaddrinfo` is the automatic conformance to RFC 6724, which removes some of the work\n/// needed to implement it.\n///\n/// This resolver is a single-use object: it can only be used to perform a single host resolution.\n\n#if os(Linux) || os(FreeBSD) || os(Android)\nimport CNIOLinux\n#endif\n\n#if os(Windows)\nimport let WinSDK.AF_INET\nimport let WinSDK.AF_INET6\n\nimport func WinSDK.FreeAddrInfoW\nimport func WinSDK.GetAddrInfoW\nimport func WinSDK.gai_strerrorA\n\nimport struct WinSDK.ADDRESS_FAMILY\nimport struct WinSDK.ADDRINFOW\nimport struct WinSDK.SOCKADDR_IN\nimport struct WinSDK.SOCKADDR_IN6\n#endif\n\n// A thread-specific variable where we store the offload queue if we're on an `SelectableEventLoop`.\nlet offloadQueueTSV = ThreadSpecificVariable<DispatchQueue>()\n\ninternal final class GetaddrinfoResolver: Resolver, Sendable {\n    private let loop: EventLoop\n    private let v4Future: EventLoopPromise<[SocketAddress]>\n    private let v6Future: EventLoopPromise<[SocketAddress]>\n    private let aiSocktype: NIOBSDSocket.SocketType\n    private let aiProtocol: NIOBSDSocket.OptionLevel\n\n    /// Create a new resolver.\n    ///\n    /// - Parameters:\n    ///   - loop: The `EventLoop` whose thread this resolver will block.\n    ///   - aiSocktype: The sock type to use as hint when calling getaddrinfo.\n    ///   - aiProtocol: the protocol to use as hint when calling getaddrinfo.\n    init(\n        loop: EventLoop,\n        aiSocktype: NIOBSDSocket.SocketType,\n        aiProtocol: NIOBSDSocket.OptionLevel\n    ) {\n        self.loop = loop\n        self.v4Future = loop.makePromise()\n        self.v6Future = loop.makePromise()\n        self.aiSocktype = aiSocktype\n        self.aiProtocol = aiProtocol\n    }\n\n    /// Initiate a DNS A query for a given host.\n    ///\n    /// Due to the nature of `getaddrinfo`, we only actually call the function once, in the AAAA query.\n    /// That means this just returns the future for the A results, which in practice will always have been\n    /// satisfied by the time this function is called.\n    ///\n    /// - Parameters:\n    ///   - host: The hostname to do an A lookup on.\n    ///   - port: The port we'll be connecting to.\n    /// - Returns: An `EventLoopFuture` that fires with the result of the lookup.\n    func initiateAQuery(host: String, port: Int) -> EventLoopFuture<[SocketAddress]> {\n        v4Future.futureResult\n    }\n\n    /// Initiate a DNS AAAA query for a given host.\n    ///\n    /// Due to the nature of `getaddrinfo`, we only actually call the function once, in this function.\n    ///\n    /// - Parameters:\n    ///   - host: The hostname to do an AAAA lookup on.\n    ///   - port: The port we'll be connecting to.\n    /// - Returns: An `EventLoopFuture` that fires with the result of the lookup.\n    func initiateAAAAQuery(host: String, port: Int) -> EventLoopFuture<[SocketAddress]> {\n        self.offloadQueue().async {\n            self.resolveBlocking(host: host, port: port)\n        }\n        return v6Future.futureResult\n    }\n\n    private func offloadQueue() -> DispatchQueue {\n        if let offloadQueue = offloadQueueTSV.currentValue {\n            return offloadQueue\n        } else {\n            if MultiThreadedEventLoopGroup.currentEventLoop != nil {\n                // Okay, we're on an SelectableEL thread. Let's stuff our queue into the thread local.\n                let offloadQueue = DispatchQueue(label: \"io.swiftnio.GetaddrinfoResolver.offloadQueue\")\n                offloadQueueTSV.currentValue = offloadQueue\n                return offloadQueue\n            } else {\n                return DispatchQueue.global()\n            }\n        }\n    }\n\n    /// Cancel all outstanding DNS queries.\n    ///\n    /// This method is called whenever queries that have not completed no longer have their\n    /// results needed. The resolver should, if possible, abort any outstanding queries and\n    /// clean up their state.\n    ///\n    /// In the getaddrinfo case this is a no-op, as the resolver blocks.\n    func cancelQueries() {}\n\n    /// Perform the DNS queries and record the result.\n    ///\n    /// - Parameters:\n    ///   - host: The hostname to do the DNS queries on.\n    ///   - port: The port we'll be connecting to.\n    private func resolveBlocking(host: String, port: Int) {\n        #if os(Windows)\n        host.withCString(encodedAs: UTF16.self) { wszHost in\n            String(port).withCString(encodedAs: UTF16.self) { wszPort in\n                var pResult: UnsafeMutablePointer<ADDRINFOW>?\n\n                var aiHints: ADDRINFOW = ADDRINFOW()\n                aiHints.ai_socktype = self.aiSocktype.rawValue\n                aiHints.ai_protocol = self.aiProtocol.rawValue\n\n                let iResult = GetAddrInfoW(wszHost, wszPort, &aiHints, &pResult)\n                guard iResult == 0 else {\n                    self.fail(SocketAddressError.unknown(host: host, port: port))\n                    return\n                }\n\n                if let pResult = pResult {\n                    self.parseAndPublishResults(pResult, host: host)\n                    FreeAddrInfoW(pResult)\n                } else {\n                    self.fail(SocketAddressError.unsupported)\n                }\n            }\n        }\n        #else\n        var info: UnsafeMutablePointer<addrinfo>?\n\n        var hint = addrinfo()\n        hint.ai_socktype = self.aiSocktype.rawValue\n        hint.ai_protocol = self.aiProtocol.rawValue\n        guard getaddrinfo(host, String(port), &hint, &info) == 0 else {\n            self.fail(SocketAddressError.unknown(host: host, port: port))\n            return\n        }\n\n        if let info = info {\n            self.parseAndPublishResults(info, host: host)\n            freeaddrinfo(info)\n        } else {\n            // this is odd, getaddrinfo returned NULL\n            self.fail(SocketAddressError.unsupported)\n        }\n        #endif\n    }\n\n    /// Parses the DNS results from the `addrinfo` linked list.\n    ///\n    /// - Parameters:\n    ///   - info: The pointer to the first of the `addrinfo` structures in the list.\n    ///   - host: The hostname we resolved.\n    #if os(Windows)\n    internal typealias CAddrInfo = ADDRINFOW\n    #else\n    internal typealias CAddrInfo = addrinfo\n    #endif\n\n    private func parseAndPublishResults(_ info: UnsafeMutablePointer<CAddrInfo>, host: String) {\n        var v4Results: [SocketAddress] = []\n        var v6Results: [SocketAddress] = []\n\n        var info: UnsafeMutablePointer<CAddrInfo> = info\n        while true {\n            let addressBytes = UnsafeRawPointer(info.pointee.ai_addr)\n            switch NIOBSDSocket.AddressFamily(rawValue: info.pointee.ai_family) {\n            case .inet:\n                // Force-unwrap must be safe, or libc did the wrong thing.\n                v4Results.append(.init(addressBytes!.load(as: sockaddr_in.self), host: host))\n            case .inet6:\n                // Force-unwrap must be safe, or libc did the wrong thing.\n                v6Results.append(.init(addressBytes!.load(as: sockaddr_in6.self), host: host))\n            default:\n                self.fail(SocketAddressError.unsupported)\n                return\n            }\n\n            guard let nextInfo = info.pointee.ai_next else {\n                break\n            }\n\n            info = nextInfo\n        }\n\n        // Ensure that both futures are succeeded in the same tick\n        // to avoid racing and potentially leaking a promise\n        self.loop.execute { [v4Results, v6Results] in\n            self.v6Future.succeed(v6Results)\n            self.v4Future.succeed(v4Results)\n        }\n    }\n\n    /// Record an error and fail the lookup process.\n    ///\n    /// - Parameters:\n    ///   - error: The error encountered during lookup.\n    private func fail(_ error: Error) {\n        // Ensure that both futures are succeeded in the same tick\n        // to avoid racing and potentially leaking a promise\n        self.loop.execute {\n            self.v6Future.fail(error)\n            self.v4Future.fail(error)\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/HappyEyeballs.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n// This module implements Happy Eyeballs 2 (RFC 8305). A few notes should be made about the design.\n//\n// The natural implementation of RFC 8305 is to use an explicit FSM, and this module does so. However,\n// it doesn't use the natural Swift idiom for an FSM of using an enum with mutating methods. The reason\n// for this is that the RFC 8305 FSM here needs to trigger a number of concurrent asynchronous operations,\n// each of which will register callbacks that attempt to mutate `self`. This gets tricky fast, because enums\n// are value types, while all of these callbacks need to trigger state transitions on the same underlying\n// state machine.\n//\n// For this reason, we fall back to the less Swifty but more clear approach of embedding the FSM in a class.\n// We naturally still use an enum to hold our state, but the FSM is now inside a class, which makes the shared\n// state nature of this FSM a bit clearer.\n\nextension Array where Element == EventLoopFuture<Channel> {\n    fileprivate mutating func remove(element: Element) {\n        guard let channelIndex = self.firstIndex(where: { $0 === element }) else {\n            return\n        }\n\n        remove(at: channelIndex)\n    }\n}\n\n/// An error that occurred during connection to a given target.\npublic struct SingleConnectionFailure: Sendable {\n    /// The target we were trying to connect to when we encountered the error.\n    public let target: SocketAddress\n\n    /// The error we encountered.\n    public let error: Error\n}\n\n/// A representation of all the errors that happened during an attempt to connect\n/// to a given host and port.\npublic struct NIOConnectionError: Error {\n    /// The hostname SwiftNIO was trying to connect to.\n    public let host: String\n\n    /// The port SwiftNIO was trying to connect to.\n    public let port: Int\n\n    /// The error we encountered doing the DNS A lookup, if any.\n    public fileprivate(set) var dnsAError: Error? = nil\n\n    /// The error we encountered doing the DNS AAAA lookup, if any.\n    public fileprivate(set) var dnsAAAAError: Error? = nil\n\n    /// The errors we encountered during the connection attempts.\n    public fileprivate(set) var connectionErrors: [SingleConnectionFailure] = []\n\n    fileprivate init(host: String, port: Int) {\n        self.host = host\n        self.port = port\n    }\n}\n\nextension NIOConnectionError: CustomStringConvertible {\n    public var description: String {\n        if let dnsError = (self.dnsAError ?? self.dnsAAAAError) {\n            return \"DNS error: \\(dnsError)\"\n        }\n\n        if !self.connectionErrors.isEmpty {\n            let descriptions = self.connectionErrors.map {\n                String(describing: $0)\n            }\n\n            return \"Connection errors: \\(descriptions.joined(separator: \", \"))\"\n        }\n\n        return \"NIOConnectionError: unknown\"\n    }\n}\n\n/// A simple iterator that manages iterating over the possible targets.\n///\n/// This iterator knows how to merge together the A and AAAA records in a sensible way:\n/// specifically, it keeps track of what the last address family it emitted was, and emits the\n/// address of the opposite family next.\nprivate struct TargetIterator: IteratorProtocol {\n    typealias Element = SocketAddress\n\n    private enum AddressFamily {\n        case v4\n        case v6\n    }\n\n    private var previousAddressFamily: AddressFamily = .v4\n    private var aQueryResults: [SocketAddress] = []\n    private var aaaaQueryResults: [SocketAddress] = []\n\n    mutating func aResultsAvailable(_ results: [SocketAddress]) {\n        aQueryResults.append(contentsOf: results)\n    }\n\n    mutating func aaaaResultsAvailable(_ results: [SocketAddress]) {\n        aaaaQueryResults.append(contentsOf: results)\n    }\n\n    mutating func next() -> Element? {\n        switch previousAddressFamily {\n        case .v4:\n            return popAAAA() ?? popA()\n        case .v6:\n            return popA() ?? popAAAA()\n        }\n    }\n\n    private mutating func popA() -> SocketAddress? {\n        if aQueryResults.count > 0 {\n            previousAddressFamily = .v4\n            return aQueryResults.removeFirst()\n        }\n\n        return nil\n    }\n\n    private mutating func popAAAA() -> SocketAddress? {\n        if aaaaQueryResults.count > 0 {\n            previousAddressFamily = .v6\n            return aaaaQueryResults.removeFirst()\n        }\n\n        return nil\n    }\n}\n\n/// Given a DNS resolver and an event loop, attempts to establish a connection to\n/// the target host over both IPv4 and IPv6.\n///\n/// This type provides the code that implements RFC 8305: Happy Eyeballs 2. This\n/// is a connection establishment strategy that attempts to efficiently and quickly\n/// establish connections to a host that has multiple IP addresses available to it,\n/// potentially over two different IP protocol versions (4 and 6).\n///\n/// This type should be created when a connection attempt is made and will remain\n/// active until a connection is established. It is responsible for actually creating\n/// connections and managing timeouts.\n///\n/// This type's public API is thread-safe: the constructor and `resolveAndConnect` can\n/// be called from any thread. `resolveAndConnect` will dispatch itself to the event\n/// loop to force serialization.\n///\n/// The `ChannelBuilderResult` generic type can used to tunnel an arbitrary type\n/// from the `channelBuilderCallback` to the `resolve` methods return value.\ninternal struct HappyEyeballsConnector<ChannelBuilderResult: Sendable>: Sendable {\n    /// The DNS resolver provided by the user.\n    fileprivate let resolver: Resolver & Sendable\n\n    /// The event loop this connector will run on.\n    fileprivate let loop: EventLoop\n\n    /// The host name we're connecting to.\n    fileprivate let host: String\n\n    /// The port we're connecting to.\n    fileprivate let port: Int\n\n    /// A callback, provided by the user, that is used to build a channel.\n    ///\n    /// This callback is expected to build *and register* a channel with the event loop that\n    /// was used with this resolver. It is free to set up the channel asynchronously, but note\n    /// that the time taken to set the channel up will be counted against the connection delay,\n    /// meaning that long channel setup times may cause more connections to be outstanding\n    /// than intended.\n    ///\n    /// The channel builder callback takes an event loop and a protocol family as arguments.\n    fileprivate let channelBuilderCallback:\n        @Sendable (EventLoop, NIOBSDSocket.ProtocolFamily) -> EventLoopFuture<(Channel, ChannelBuilderResult)>\n\n    /// The amount of time to wait for an AAAA response to come in after a A response is\n    /// received. By default this is 50ms.\n    fileprivate let resolutionDelay: TimeAmount\n\n    /// The amount of time to wait for a connection to succeed before beginning a new connection\n    /// attempt. By default this is 250ms.\n    fileprivate let connectionDelay: TimeAmount\n\n    /// The amount of time to allow for the overall connection process before timing it out.\n    fileprivate let connectTimeout: TimeAmount\n\n    /// The promise that will hold the final connected channel.\n    fileprivate let resolutionPromise: EventLoopPromise<(Channel, ChannelBuilderResult)>\n\n    @inlinable\n    init(\n        resolver: Resolver & Sendable,\n        loop: EventLoop,\n        host: String,\n        port: Int,\n        connectTimeout: TimeAmount,\n        resolutionDelay: TimeAmount = .milliseconds(50),\n        connectionDelay: TimeAmount = .milliseconds(250),\n        channelBuilderCallback:\n            @escaping @Sendable (EventLoop, NIOBSDSocket.ProtocolFamily) -> EventLoopFuture<\n                (Channel, ChannelBuilderResult)\n            >\n    ) {\n        self.resolver = resolver\n        self.loop = loop\n        self.host = host\n        self.port = port\n        self.connectTimeout = connectTimeout\n        self.channelBuilderCallback = channelBuilderCallback\n\n        self.resolutionPromise = self.loop.makePromise()\n\n        precondition(\n            resolutionDelay.nanoseconds > 0,\n            \"Resolution delay must be greater than zero, got \\(resolutionDelay).\"\n        )\n        self.resolutionDelay = resolutionDelay\n\n        precondition(\n            connectionDelay >= .milliseconds(100) && connectionDelay <= .milliseconds(2000),\n            \"Connection delay must be between 100 and 2000 ms, got \\(connectionDelay)\"\n        )\n        self.connectionDelay = connectionDelay\n    }\n\n    @inlinable\n    init(\n        resolver: Resolver & Sendable,\n        loop: EventLoop,\n        host: String,\n        port: Int,\n        connectTimeout: TimeAmount,\n        resolutionDelay: TimeAmount = .milliseconds(50),\n        connectionDelay: TimeAmount = .milliseconds(250),\n        channelBuilderCallback: @escaping @Sendable (EventLoop, NIOBSDSocket.ProtocolFamily) -> EventLoopFuture<Channel>\n    ) where ChannelBuilderResult == Void {\n        self.init(\n            resolver: resolver,\n            loop: loop,\n            host: host,\n            port: port,\n            connectTimeout: connectTimeout,\n            resolutionDelay: resolutionDelay,\n            connectionDelay: connectionDelay\n        ) { loop, protocolFamily in\n            channelBuilderCallback(loop, protocolFamily).map { ($0, ()) }\n        }\n    }\n\n    /// Initiate a DNS resolution attempt using Happy Eyeballs 2.\n    ///\n    /// returns: An `EventLoopFuture` that fires with a connected `Channel`.\n    @inlinable\n    func resolveAndConnect() -> EventLoopFuture<(Channel, ChannelBuilderResult)> {\n        // We dispatch ourselves onto the event loop, rather than do all the rest of our processing from outside it.\n        self.loop.execute {\n            let runner = HappyEyeballsConnectorRunner(connector: self)\n            runner.resolveAndConnect()\n        }\n        return self.resolutionPromise.futureResult\n    }\n\n    /// Initiate a DNS resolution attempt using Happy Eyeballs 2.\n    ///\n    /// returns: An `EventLoopFuture` that fires with a connected `Channel`.\n    @inlinable\n    func resolveAndConnect() -> EventLoopFuture<Channel> where ChannelBuilderResult == Void {\n        self.resolveAndConnect().map { $0.0 }\n    }\n}\n\nprivate final class HappyEyeballsConnectorRunner<ChannelBuilderResult: Sendable> {\n    /// An enum for keeping track of connection state.\n    private enum ConnectionState {\n        /// Initial state. No work outstanding.\n        case idle\n\n        /// All name queries are currently outstanding.\n        case resolving\n\n        /// The A query has resolved, but the AAAA query is outstanding and the\n        /// resolution delay has not yet elapsed.\n        case aResolvedWaiting\n\n        /// The A query has resolved and the resolution delay has elapsed. We can\n        /// begin connecting immediately, but should not give up if we run out of\n        /// targets until the AAAA result returns.\n        case aResolvedConnecting\n\n        /// The AAAA query has resolved. We can begin connecting immediately, but\n        /// should not give up if we run out of targets until the AAAA result returns.\n        case aaaaResolved\n\n        /// All DNS results are in. We can make connection attempts until we run out\n        /// of targets.\n        case allResolved\n\n        /// The connection attempt is complete.\n        case complete\n    }\n\n    /// An enum of inputs for the connector state machine.\n    private enum ConnectorInput {\n        /// Begin DNS resolution.\n        case resolve\n\n        /// The A record lookup completed.\n        case resolverACompleted\n\n        /// The AAAA record lookup completed.\n        case resolverAAAACompleted\n\n        /// The delay between the A result and the AAAA result has elapsed.\n        case resolutionDelayElapsed\n\n        /// The delay between starting one connection and the next has elapsed.\n        case connectDelayElapsed\n\n        /// The overall connect timeout has elapsed.\n        case connectTimeoutElapsed\n\n        /// A connection attempt has succeeded.\n        case connectSuccess\n\n        /// A connection attempt has failed.\n        case connectFailed\n\n        /// There are no connect targets remaining: all have been connected to and\n        /// failed.\n        case noTargetsRemaining\n    }\n\n    /// The thread-safe state across resolutions.\n    private let connector: HappyEyeballsConnector<ChannelBuilderResult>\n\n    /// A reference to the task that will execute after the resolution delay expires, if\n    /// one is scheduled. This is held to ensure that we can cancel this task if the AAAA\n    /// response comes in before the resolution delay expires.\n    private var resolutionTask: Optional<Scheduled<Void>>\n\n    /// A reference to the task that will execute after the connection delay expires, if one\n    /// is scheduled. This is held to ensure that we can cancel this task if a connection\n    /// succeeds before the connection delay expires.\n    private var connectionTask: Optional<Scheduled<Void>>\n\n    /// A reference to the task that will time us out.\n    private var timeoutTask: Optional<Scheduled<Void>>\n\n    /// Our state machine state.\n    private var state: ConnectionState\n\n    /// Our iterator of resolved targets. This keeps track of what targets are left to have\n    /// connection attempts made to them, and emits them in the appropriate order as needed.\n    private var targets: TargetIterator = TargetIterator()\n\n    /// An array of futures of channels that are currently attempting to connect.\n    ///\n    /// This is kept to ensure that we can clean up after ourselves once a connection succeeds,\n    /// and throw away all pending connection attempts that are no longer needed.\n    private var pendingConnections: [EventLoopFuture<(Channel, ChannelBuilderResult)>] = []\n\n    /// The number of DNS resolutions that have returned.\n    ///\n    /// This is used to keep track of whether we need to cancel the outstanding resolutions\n    /// during cleanup.\n    private var dnsResolutions: Int = 0\n\n    /// An object that holds any errors we encountered.\n    private var error: NIOConnectionError\n\n    @inlinable\n    init(\n        connector: HappyEyeballsConnector<ChannelBuilderResult>\n    ) {\n        self.connector = connector\n        self.resolutionTask = nil\n        self.connectionTask = nil\n        self.timeoutTask = nil\n\n        self.state = .idle\n        self.error = NIOConnectionError(host: self.connector.host, port: self.connector.port)\n    }\n\n    /// Initiate a DNS resolution attempt using Happy Eyeballs 2.\n    @inlinable\n    func resolveAndConnect() {\n        self.timeoutTask = self.connector.loop.assumeIsolated().scheduleTask(in: self.connector.connectTimeout) {\n            self.processInput(.connectTimeoutElapsed)\n        }\n        self.processInput(.resolve)\n    }\n\n    /// Spin the state machine.\n    ///\n    /// - Parameters:\n    ///   - input: The input to the state machine.\n    private func processInput(_ input: ConnectorInput) {\n        switch (state, input) {\n        // Only one valid transition from idle: to start resolving.\n        case (.idle, .resolve):\n            state = .resolving\n            beginDNSResolution()\n\n        // In the resolving state, we can exit three ways: either the A query returns,\n        // the AAAA does, or the overall connect timeout fires.\n        case (.resolving, .resolverACompleted):\n            state = .aResolvedWaiting\n            beginResolutionDelay()\n        case (.resolving, .resolverAAAACompleted):\n            state = .aaaaResolved\n            beginConnecting()\n        case (.resolving, .connectTimeoutElapsed):\n            state = .complete\n            timedOut()\n\n        // In the aResolvedWaiting state, we can exit three ways: the AAAA query returns,\n        // the resolution delay elapses, or the overall connect timeout fires.\n        case (.aResolvedWaiting, .resolverAAAACompleted):\n            state = .allResolved\n            beginConnecting()\n        case (.aResolvedWaiting, .resolutionDelayElapsed):\n            state = .aResolvedConnecting\n            beginConnecting()\n        case (.aResolvedWaiting, .connectTimeoutElapsed):\n            state = .complete\n            timedOut()\n\n        // In the aResolvedConnecting state, a number of inputs are valid: the AAAA result can\n        // return, the connectionDelay can elapse, the overall connection timeout can fire,\n        // a connection can succeed, a connection can fail, and we can run out of targets.\n        case (.aResolvedConnecting, .resolverAAAACompleted):\n            state = .allResolved\n            connectToNewTargets()\n        case (.aResolvedConnecting, .connectDelayElapsed):\n            connectionDelayElapsed()\n        case (.aResolvedConnecting, .connectTimeoutElapsed):\n            state = .complete\n            timedOut()\n        case (.aResolvedConnecting, .connectSuccess):\n            state = .complete\n            connectSuccess()\n        case (.aResolvedConnecting, .connectFailed):\n            connectFailed()\n        case (.aResolvedConnecting, .noTargetsRemaining):\n            // We are still waiting for the AAAA query, so we\n            // do nothing.\n            break\n\n        // In the aaaaResolved state, a number of inputs are valid: the A result can return,\n        // the connectionDelay can elapse, the overall connection timeout can fire, a connection\n        // can succeed, a connection can fail, and we can run out of targets.\n        case (.aaaaResolved, .resolverACompleted):\n            state = .allResolved\n            connectToNewTargets()\n        case (.aaaaResolved, .connectDelayElapsed):\n            connectionDelayElapsed()\n        case (.aaaaResolved, .connectTimeoutElapsed):\n            state = .complete\n            timedOut()\n        case (.aaaaResolved, .connectSuccess):\n            state = .complete\n            connectSuccess()\n        case (.aaaaResolved, .connectFailed):\n            connectFailed()\n        case (.aaaaResolved, .noTargetsRemaining):\n            // We are still waiting for the A query, so we\n            // do nothing.\n            break\n\n        // In the allResolved state, a number of inputs are valid: the connectionDelay can elapse,\n        // the overall connection timeout can fire, a connection can succeed, a connection can fail,\n        // and possibly we can run out of targets.\n        case (.allResolved, .connectDelayElapsed):\n            connectionDelayElapsed()\n        case (.allResolved, .connectTimeoutElapsed):\n            state = .complete\n            timedOut()\n        case (.allResolved, .connectSuccess):\n            state = .complete\n            connectSuccess()\n        case (.allResolved, .connectFailed):\n            connectFailed()\n        case (.allResolved, .noTargetsRemaining):\n            state = .complete\n            failed()\n\n        // Once we've completed, it's not impossible that we'll get state machine events for\n        // some amounts of work. For example, we could get late DNS results and late connection\n        // notifications, and can also get late scheduled task callbacks. We want to just quietly\n        // ignore these, as our transition into the complete state should have already sent\n        // cleanup messages to all of these things.\n        //\n        // We can also get the resolutionDelayElapsed after allResolved, as it's possible that\n        // callback was already dequeued in the same tick as the cancellation. That's also fine:\n        // the resolution delay isn't interesting.\n        case (.allResolved, .resolutionDelayElapsed),\n            (.complete, .resolverACompleted),\n            (.complete, .resolverAAAACompleted),\n            (.complete, .connectSuccess),\n            (.complete, .connectFailed),\n            (.complete, .connectDelayElapsed),\n            (.complete, .connectTimeoutElapsed),\n            (.complete, .resolutionDelayElapsed):\n            break\n        default:\n            fatalError(\"Invalid FSM transition attempt: state \\(state), input \\(input)\")\n        }\n    }\n\n    /// Fire off a pair of DNS queries.\n    private func beginDNSResolution() {\n        // Per RFC 8305 Section 3, we need to send A and AAAA queries.\n        // The two queries SHOULD be made as soon after one another as possible,\n        // with the AAAA query made first and immediately followed by the A\n        // query.\n        //\n        // We hop back to `self.loop` because there's no guarantee the resolver runs\n        // on our event loop. That hop then makes it safe for us to assumeIsolatedUnsafeUnchecked.\n        self.connector.loop.assertInEventLoop()\n        let aaaaLookup = self.connector.resolver.initiateAAAAQuery(\n            host: self.connector.host,\n            port: self.connector.port\n        ).hop(to: self.connector.loop).assumeIsolatedUnsafeUnchecked()\n        self.whenAAAALookupComplete(future: aaaaLookup)\n\n        let aLookup = self.connector.resolver.initiateAQuery(\n            host: self.connector.host,\n            port: self.connector.port\n        ).hop(to: self.connector.loop).assumeIsolatedUnsafeUnchecked()\n        self.whenALookupComplete(future: aLookup)\n    }\n\n    /// Called when the A query has completed before the AAAA query.\n    ///\n    /// Happy Eyeballs 2 prefers to connect over IPv6 if it's possible to do so. This means that\n    /// if the A lookup completes first we want to wait a small amount of time before we begin our\n    /// connection attempts, in the hope that the AAAA lookup will complete.\n    ///\n    /// This method sets off a scheduled task for the resolution delay.\n    private func beginResolutionDelay() {\n        resolutionTask = self.connector.loop.assumeIsolated().scheduleTask(\n            in: self.connector.resolutionDelay,\n            resolutionDelayComplete\n        )\n    }\n\n    /// Called when we're ready to start connecting to targets.\n    ///\n    /// This function sets off the first connection attempt, and also sets the connect delay task.\n    private func beginConnecting() {\n        precondition(connectionTask == nil, \"beginConnecting called while connection attempts outstanding\")\n        guard let target = targets.next() else {\n            if self.pendingConnections.isEmpty {\n                processInput(.noTargetsRemaining)\n            }\n            return\n        }\n\n        connectionTask = self.connector.loop.assumeIsolated().scheduleTask(\n            in: self.connector.connectionDelay\n        ) {\n            self.processInput(.connectDelayElapsed)\n        }\n        connectToTarget(target)\n    }\n\n    /// Called when the state machine wants us to connect to new targets, but we may already\n    /// be connecting.\n    ///\n    /// This method takes into account the possibility that we may still be connecting to\n    /// other targets.\n    private func connectToNewTargets() {\n        guard connectionTask == nil else {\n            // Already connecting, no need to do anything here.\n            return\n        }\n\n        // We're not in the middle of connecting, so we can start connecting!\n        beginConnecting()\n    }\n\n    /// Called when the connection delay timer has elapsed.\n    ///\n    /// When the connection delay elapses we are going to initiate another connection\n    /// attempt.\n    private func connectionDelayElapsed() {\n        connectionTask = nil\n        beginConnecting()\n    }\n\n    /// Called when an outstanding connection attempt fails.\n    ///\n    /// This method checks that we don't have any connection attempts outstanding. If\n    /// we discover we don't, it automatically triggers the next connection attempt.\n    private func connectFailed() {\n        if self.pendingConnections.isEmpty {\n            self.connectionTask?.cancel()\n            self.connectionTask = nil\n            beginConnecting()\n        }\n    }\n\n    /// Called when an outstanding connection attempt succeeds.\n    ///\n    /// Cleans up internal state.\n    private func connectSuccess() {\n        cleanUp()\n    }\n\n    /// Called when the overall connection timeout fires.\n    ///\n    /// Cleans up internal state and fails the connection promise.\n    private func timedOut() {\n        cleanUp()\n        self.connector.resolutionPromise.fail(\n            ChannelError.connectTimeout(self.connector.connectTimeout)\n        )\n    }\n\n    /// Called when we've attempted to connect to all our resolved targets,\n    /// and were unable to connect to any of them.\n    ///\n    /// Asserts that there is nothing left on the internal state, and then fails the connection\n    /// promise.\n    private func failed() {\n        precondition(pendingConnections.isEmpty, \"failed with pending connections\")\n        cleanUp()\n        self.connector.resolutionPromise.fail(self.error)\n    }\n\n    /// Called to connect to a given target.\n    ///\n    /// - Parameters:\n    ///   - target: The address to connect to.\n    private func connectToTarget(_ target: SocketAddress) {\n        let channelFuture = self.connector.channelBuilderCallback(self.connector.loop, target.protocol)\n        let isolatedChannelFuture = channelFuture.hop(to: self.connector.loop).assumeIsolated()\n        pendingConnections.append(channelFuture)\n\n        isolatedChannelFuture.whenSuccess { (channel, result) in\n            // If we are in the complete state then we want to abandon this channel. Otherwise, begin\n            // connecting.\n            if case .complete = self.state {\n                self.pendingConnections.removeAll { $0 === channelFuture }\n                channel.close(promise: nil)\n            } else {\n                channel.connect(to: target).assumeIsolated().map {\n                    // The channel has connected. If we are in the complete state we want to abandon this channel.\n                    // Otherwise, fire the channel connected event. Either way we don't want the channel future to\n                    // be in our list of pending connections, so we don't either double close or close the connection\n                    // we want to use.\n                    self.pendingConnections.removeAll { $0 === channelFuture }\n\n                    if case .complete = self.state {\n                        channel.close(promise: nil)\n                    } else {\n                        self.processInput(.connectSuccess)\n                        self.connector.resolutionPromise.succeed((channel, result))\n                    }\n                }.whenFailure { err in\n                    // The connection attempt failed. If we're in the complete state then there's nothing\n                    // to do. Otherwise, notify the state machine of the failure.\n                    if case .complete = self.state {\n                        assert(\n                            self.pendingConnections.firstIndex { $0 === channelFuture } == nil,\n                            \"failed but was still in pending connections\"\n                        )\n                    } else {\n                        self.error.connectionErrors.append(SingleConnectionFailure(target: target, error: err))\n                        self.pendingConnections.removeAll { $0 === channelFuture }\n                        self.processInput(.connectFailed)\n                    }\n                }\n            }\n        }\n        isolatedChannelFuture.whenFailure { error in\n            self.error.connectionErrors.append(SingleConnectionFailure(target: target, error: error))\n            self.pendingConnections.removeAll { $0 === channelFuture }\n            self.processInput(.connectFailed)\n        }\n    }\n\n    // Cleans up all internal state, ensuring that there are no reference cycles and allowing\n    // everything to eventually be deallocated.\n    private func cleanUp() {\n        assert(self.state == .complete, \"Clean up in invalid state \\(self.state)\")\n\n        if dnsResolutions < 2 {\n            self.connector.resolver.cancelQueries()\n        }\n\n        if let resolutionTask = self.resolutionTask {\n            resolutionTask.cancel()\n            self.resolutionTask = nil\n        }\n\n        if let connectionTask = self.connectionTask {\n            connectionTask.cancel()\n            self.connectionTask = nil\n        }\n\n        if let timeoutTask = self.timeoutTask {\n            timeoutTask.cancel()\n            self.timeoutTask = nil\n        }\n\n        let connections = self.pendingConnections\n        self.pendingConnections = []\n        for connection in connections {\n            connection.whenSuccess { (channel, _) in channel.close(promise: nil) }\n        }\n    }\n\n    /// A future callback that fires when a DNS A lookup completes.\n    private func whenALookupComplete(future: EventLoopFuture<[SocketAddress]>.Isolated) {\n        future.map { results in\n            self.targets.aResultsAvailable(results)\n        }.recover { err in\n            self.error.dnsAError = err\n        }.whenComplete { (_: Result<Void, Error>) in\n            self.dnsResolutions += 1\n            self.processInput(.resolverACompleted)\n        }\n    }\n\n    /// A future callback that fires when a DNS AAAA lookup completes.\n    private func whenAAAALookupComplete(future: EventLoopFuture<[SocketAddress]>.Isolated) {\n        future.map { results in\n            self.targets.aaaaResultsAvailable(results)\n        }.recover { err in\n            self.error.dnsAAAAError = err\n        }.whenComplete { (_: Result<Void, Error>) in\n            // It's possible that we were waiting to time out here, so if we were we should\n            // cancel that.\n            self.resolutionTask?.cancel()\n            self.resolutionTask = nil\n\n            self.dnsResolutions += 1\n\n            self.processInput(.resolverAAAACompleted)\n        }\n    }\n\n    /// A future callback that fires when the resolution delay completes.\n    private func resolutionDelayComplete() {\n        resolutionTask = nil\n        processInput(.resolutionDelayElapsed)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/IO.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nextension IOResult where T: FixedWidthInteger {\n    var result: T {\n        switch self {\n        case .processed(let value):\n            return value\n        case .wouldBlock(_):\n            fatalError(\"cannot unwrap IOResult\")\n        }\n    }\n}\n\n/// An result for an IO operation that was done on a non-blocking resource.\n@usableFromInline\nenum IOResult<T: Equatable>: Equatable {\n\n    /// Signals that the IO operation could not be completed as otherwise we would need to block.\n    case wouldBlock(T)\n\n    /// Signals that the IO operation was completed.\n    case processed(T)\n}\n\nextension IOResult: Sendable where T: Sendable {}\n\nextension IOResult {\n    func map<NewT>(_ body: (T) -> NewT) -> IOResult<NewT> {\n        switch self {\n        case .processed(let t):\n            return .processed(body(t))\n        case .wouldBlock(let t):\n            return .wouldBlock(body(t))\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/IntegerBitPacking.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n@usableFromInline\nenum _IntegerBitPacking: Sendable {}\n\nextension _IntegerBitPacking {\n    @inlinable\n    static func packUU<\n        Left: FixedWidthInteger & UnsignedInteger,\n        Right: FixedWidthInteger & UnsignedInteger,\n        Result: FixedWidthInteger & UnsignedInteger\n    >(\n        _ left: Left,\n        _ right: Right,\n        type: Result.Type = Result.self\n    ) -> Result {\n        assert(MemoryLayout<Left>.size + MemoryLayout<Right>.size <= MemoryLayout<Result>.size)\n\n        let resultLeft = Result(left)\n        let resultRight = Result(right)\n        let result = (resultLeft << Right.bitWidth) | resultRight\n        assert(result.nonzeroBitCount == left.nonzeroBitCount + right.nonzeroBitCount)\n        return result\n    }\n\n    @inlinable\n    static func unpackUU<\n        Input: FixedWidthInteger & UnsignedInteger,\n        Left: FixedWidthInteger & UnsignedInteger,\n        Right: FixedWidthInteger & UnsignedInteger\n    >(\n        _ input: Input,\n        leftType: Left.Type = Left.self,\n        rightType: Right.Type = Right.self\n    ) -> (Left, Right) {\n        assert(MemoryLayout<Left>.size + MemoryLayout<Right>.size <= MemoryLayout<Input>.size)\n\n        let leftMask = Input(Left.max)\n        let rightMask = Input(Right.max)\n        let right = input & rightMask\n        let left = (input >> Right.bitWidth) & leftMask\n\n        assert(input.nonzeroBitCount == left.nonzeroBitCount + right.nonzeroBitCount)\n        return (Left(left), Right(right))\n    }\n}\n\n@usableFromInline\nenum IntegerBitPacking: Sendable {}\n\nextension IntegerBitPacking {\n    @inlinable\n    static func packUInt32UInt16UInt8(_ left: UInt32, _ middle: UInt16, _ right: UInt8) -> UInt64 {\n        _IntegerBitPacking.packUU(\n            _IntegerBitPacking.packUU(right, middle, type: UInt32.self),\n            left\n        )\n    }\n\n    @inlinable\n    static func unpackUInt32UInt16UInt8(_ value: UInt64) -> (UInt32, UInt16, UInt8) {\n        let leftRight = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self)\n        let left = _IntegerBitPacking.unpackUU(leftRight.0, leftType: UInt8.self, rightType: UInt16.self)\n        return (leftRight.1, left.1, left.0)\n    }\n\n    @inlinable\n    static func packUInt8UInt8(_ left: UInt8, _ right: UInt8) -> UInt16 {\n        _IntegerBitPacking.packUU(left, right)\n    }\n\n    @inlinable\n    static func unpackUInt8UInt8(_ value: UInt16) -> (UInt8, UInt8) {\n        _IntegerBitPacking.unpackUU(value)\n    }\n\n    @inlinable\n    static func packUInt16UInt8(_ left: UInt16, _ right: UInt8) -> UInt32 {\n        _IntegerBitPacking.packUU(left, right)\n    }\n\n    @inlinable\n    static func unpackUInt16UInt8(_ value: UInt32) -> (UInt16, UInt8) {\n        _IntegerBitPacking.unpackUU(value)\n    }\n\n    @inlinable\n    static func packUInt32CInt(_ left: UInt32, _ right: CInt) -> UInt64 {\n        _IntegerBitPacking.packUU(left, UInt32(truncatingIfNeeded: right))\n    }\n\n    @inlinable\n    static func unpackUInt32CInt(_ value: UInt64) -> (UInt32, CInt) {\n        let unpacked = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self)\n        return (unpacked.0, CInt(truncatingIfNeeded: unpacked.1))\n    }\n\n    @inlinable\n    static func packUInt32UInt32(_ left: UInt32, _ right: UInt32) -> UInt64 {\n        _IntegerBitPacking.packUU(left, right)\n    }\n\n    @inlinable\n    static func unpackUInt32UInt32(_ value: UInt64) -> (UInt32, UInt32) {\n        let unpacked = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self)\n        return (unpacked.0, unpacked.1)\n    }\n\n    @inlinable\n    static func packUInt16UInt16(_ left: UInt16, _ right: UInt16) -> UInt32 {\n        _IntegerBitPacking.packUU(left, right)\n    }\n\n    @inlinable\n    static func unpackUInt16UInt16(_ value: UInt32) -> (UInt16, UInt16) {\n        let unpacked = _IntegerBitPacking.unpackUU(value, leftType: UInt16.self, rightType: UInt16.self)\n        return (unpacked.0, unpacked.1)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/IntegerTypes.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n// MARK: _UInt24\n\n/// A 24-bit unsigned integer value type.\n@usableFromInline\nstruct _UInt24: Sendable {\n    @usableFromInline var _backing: (UInt16, UInt8)\n\n    @inlinable\n    init(_ value: UInt32) {\n        assert(value & 0xff_00_00_00 == 0, \"value \\(value) too large for _UInt24\")\n        self._backing = IntegerBitPacking.unpackUInt16UInt8(value)\n    }\n\n    @inlinable\n    static var bitWidth: Int {\n        24\n    }\n\n    @inlinable\n    static var max: _UInt24 {\n        .init((UInt32(1) << 24) - 1)\n    }\n\n    @inlinable\n    static var min: _UInt24 {\n        .init(0)\n    }\n}\n\nextension UInt32 {\n    @inlinable\n    init(_ value: _UInt24) {\n        self = IntegerBitPacking.packUInt16UInt8(value._backing.0, value._backing.1)\n    }\n}\n\nextension Int {\n    @inlinable\n    init(_ value: _UInt24) {\n        self = Int(UInt32(value))\n    }\n}\n\nextension _UInt24: Equatable {\n    @inlinable\n    public static func == (lhs: _UInt24, rhs: _UInt24) -> Bool {\n        lhs._backing == rhs._backing\n    }\n}\n\nextension _UInt24: CustomStringConvertible {\n    @usableFromInline\n    var description: String {\n        UInt32(self).description\n    }\n}\n\n// MARK: _UInt56\n\n/// A 56-bit unsigned integer value type.\nstruct _UInt56: Sendable {\n    @usableFromInline var _backing: (UInt32, UInt16, UInt8)\n\n    @inlinable init(_ value: UInt64) {\n        self._backing = IntegerBitPacking.unpackUInt32UInt16UInt8(value)\n    }\n\n    @inlinable\n    static var bitWidth: Int {\n        56\n    }\n\n    @inlinable\n    static var _initializeUInt64: UInt64 {\n        (1 << 56) - 1\n    }\n    @inlinable\n    static var max: _UInt56 {\n        .init(_initializeUInt64)\n    }\n    @inlinable\n    static var min: _UInt56 {\n        .init(0)\n    }\n}\n\nextension _UInt56 {\n    init(_ value: Int) {\n        self.init(UInt64(value))\n    }\n}\n\nextension UInt64 {\n    init(_ value: _UInt56) {\n        self = IntegerBitPacking.packUInt32UInt16UInt8(\n            value._backing.0,\n            value._backing.1,\n            value._backing.2\n        )\n    }\n}\n\nextension Int {\n    init(_ value: _UInt56) {\n        self = Int(UInt64(value))\n    }\n}\n\nextension _UInt56: Equatable {\n    @inlinable\n    public static func == (lhs: _UInt56, rhs: _UInt56) -> Bool {\n        lhs._backing == rhs._backing\n    }\n}\n\nextension _UInt56: CustomStringConvertible {\n    var description: String {\n        UInt64(self).description\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Linux.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n// This is a companion to System.swift that provides only Linux specials: either things that exist\n// only on Linux, or things that have Linux-specific extensions.\n\n#if os(Linux) || os(Android)\nimport CNIOLinux\n\n@usableFromInline\ninternal enum TimerFd {\n    internal static let TFD_CLOEXEC = CNIOLinux.TFD_CLOEXEC\n    internal static let TFD_NONBLOCK = CNIOLinux.TFD_NONBLOCK\n\n    @inline(never)\n    @usableFromInline\n    internal static func timerfd_settime(\n        fd: CInt,\n        flags: CInt,\n        newValue: UnsafePointer<itimerspec>,\n        oldValue: UnsafeMutablePointer<itimerspec>?\n    ) throws {\n        _ = try syscall(blocking: false) {\n            CNIOLinux.timerfd_settime(fd, flags, newValue, oldValue)\n        }\n    }\n\n    @inline(never)\n    @usableFromInline\n    internal static func timerfd_create(clockId: CInt, flags: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            CNIOLinux.timerfd_create(clockId, flags)\n        }.result\n    }\n}\n\n@usableFromInline\ninternal enum EventFd {\n    @usableFromInline\n    internal static let EFD_CLOEXEC = CNIOLinux.EFD_CLOEXEC\n    @usableFromInline\n    internal static let EFD_NONBLOCK = CNIOLinux.EFD_NONBLOCK\n    @usableFromInline\n    internal typealias eventfd_t = CNIOLinux.eventfd_t\n\n    @inline(never)\n    internal static func eventfd_write(fd: CInt, value: UInt64) throws -> CInt {\n        try syscall(blocking: false) {\n            CNIOLinux.eventfd_write(fd, value)\n        }.result\n    }\n\n    @inline(never)\n    @usableFromInline\n    internal static func eventfd_read(fd: CInt, value: UnsafeMutablePointer<UInt64>) throws -> CInt {\n        try syscall(blocking: false) {\n            CNIOLinux.eventfd_read(fd, value)\n        }.result\n    }\n\n    @inline(never)\n    internal static func eventfd(initval: CUnsignedInt, flags: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            // Note: Please do _not_ remove the `numericCast`, this is to allow compilation in Ubuntu 14.04 and\n            // other Linux distros which ship a glibc from before this commit:\n            // https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=69eb9a183c19e8739065e430758e4d3a2c5e4f1a\n            // which changes the first argument from `CInt` to `CUnsignedInt` (from Sat, 20 Sep 2014).\n            CNIOLinux.eventfd(numericCast(initval), flags)\n        }.result\n    }\n}\n\n@usableFromInline\ninternal enum Epoll {\n    @usableFromInline\n    internal typealias epoll_event = CNIOLinux.epoll_event\n\n    @usableFromInline\n    internal static let EPOLL_CTL_ADD: CInt = numericCast(CNIOLinux.EPOLL_CTL_ADD)\n    @usableFromInline\n    internal static let EPOLL_CTL_MOD: CInt = numericCast(CNIOLinux.EPOLL_CTL_MOD)\n    @usableFromInline\n    internal static let EPOLL_CTL_DEL: CInt = numericCast(CNIOLinux.EPOLL_CTL_DEL)\n\n    #if canImport(Android) || canImport(Musl)\n    @usableFromInline\n    internal static let EPOLLIN: CUnsignedInt = numericCast(CNIOLinux.EPOLLIN)\n    @usableFromInline\n    internal static let EPOLLOUT: CUnsignedInt = numericCast(CNIOLinux.EPOLLOUT)\n    @usableFromInline\n    internal static let EPOLLERR: CUnsignedInt = numericCast(CNIOLinux.EPOLLERR)\n    @usableFromInline\n    internal static let EPOLLRDHUP: CUnsignedInt = numericCast(CNIOLinux.EPOLLRDHUP)\n    @usableFromInline\n    internal static let EPOLLHUP: CUnsignedInt = numericCast(CNIOLinux.EPOLLHUP)\n    #if canImport(Android)\n    @usableFromInline\n    internal static let EPOLLET: CUnsignedInt = 2_147_483_648  // C macro not imported by ClangImporter\n    #else\n    @usableFromInline\n    internal static let EPOLLET: CUnsignedInt = numericCast(CNIOLinux.EPOLLET)\n    #endif\n    #elseif os(Android)\n    @usableFromInline\n    internal static let EPOLLIN: CUnsignedInt = 1  //numericCast(CNIOLinux.EPOLLIN)\n    @usableFromInline\n    internal static let EPOLLOUT: CUnsignedInt = 4  //numericCast(CNIOLinux.EPOLLOUT)\n    @usableFromInline\n    internal static let EPOLLERR: CUnsignedInt = 8  // numericCast(CNIOLinux.EPOLLERR)\n    @usableFromInline\n    internal static let EPOLLRDHUP: CUnsignedInt = 8192  //numericCast(CNIOLinux.EPOLLRDHUP)\n    @usableFromInline\n    internal static let EPOLLHUP: CUnsignedInt = 16  //numericCast(CNIOLinux.EPOLLHUP)\n    @usableFromInline\n    internal static let EPOLLET: CUnsignedInt = 2_147_483_648  //numericCast(CNIOLinux.EPOLLET)\n    #else\n    @usableFromInline\n    internal static let EPOLLIN: CUnsignedInt = numericCast(CNIOLinux.EPOLLIN.rawValue)\n    @usableFromInline\n    internal static let EPOLLOUT: CUnsignedInt = numericCast(CNIOLinux.EPOLLOUT.rawValue)\n    @usableFromInline\n    internal static let EPOLLERR: CUnsignedInt = numericCast(CNIOLinux.EPOLLERR.rawValue)\n    @usableFromInline\n    internal static let EPOLLRDHUP: CUnsignedInt = numericCast(CNIOLinux.EPOLLRDHUP.rawValue)\n    @usableFromInline\n    internal static let EPOLLHUP: CUnsignedInt = numericCast(CNIOLinux.EPOLLHUP.rawValue)\n    @usableFromInline\n    internal static let EPOLLET: CUnsignedInt = numericCast(CNIOLinux.EPOLLET.rawValue)\n    #endif\n\n    @usableFromInline\n    internal static let ENOENT: CUnsignedInt = numericCast(CNIOLinux.ENOENT)\n\n    @inline(never)\n    internal static func epoll_create(size: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            CNIOLinux.epoll_create(size)\n        }.result\n    }\n\n    @inline(never)\n    @discardableResult\n    internal static func epoll_ctl(\n        epfd: CInt,\n        op: CInt,\n        fd: CInt,\n        event: UnsafeMutablePointer<epoll_event>\n    ) throws -> CInt {\n        try syscall(blocking: false) {\n            CNIOLinux.epoll_ctl(epfd, op, fd, event)\n        }.result\n    }\n\n    @inline(never)\n    @usableFromInline\n    internal static func epoll_wait(\n        epfd: CInt,\n        events: UnsafeMutablePointer<epoll_event>,\n        maxevents: CInt,\n        timeout: CInt\n    ) throws -> CInt {\n        try syscall(blocking: false) {\n            CNIOLinux.epoll_wait(epfd, events, maxevents, timeout)\n        }.result\n    }\n}\n\ninternal enum Linux {\n    #if os(Android)\n    static let SOCK_CLOEXEC = Android.SOCK_CLOEXEC\n    static let SOCK_NONBLOCK = Android.SOCK_NONBLOCK\n    #elseif canImport(Musl)\n    static let SOCK_CLOEXEC = Musl.SOCK_CLOEXEC\n    static let SOCK_NONBLOCK = Musl.SOCK_NONBLOCK\n    #else\n    static let SOCK_CLOEXEC = CInt(bitPattern: Glibc.SOCK_CLOEXEC.rawValue)\n    static let SOCK_NONBLOCK = CInt(bitPattern: Glibc.SOCK_NONBLOCK.rawValue)\n    #endif\n    @inline(never)\n    internal static func accept4(\n        descriptor: CInt,\n        addr: UnsafeMutablePointer<sockaddr>?,\n        len: UnsafeMutablePointer<socklen_t>?,\n        flags: CInt\n    ) throws -> CInt? {\n        guard\n            case let .processed(fd) = try syscall(\n                blocking: true,\n                {\n                    CNIOLinux.CNIOLinux_accept4(descriptor, addr, len, flags)\n                }\n            )\n        else {\n            return nil\n        }\n        return fd\n    }\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/LinuxCPUSet.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if os(Linux) || os(Android)\nimport CNIOLinux\n\n/// A set that contains CPU ids to use.\nstruct LinuxCPUSet {\n    /// The ids of all the cpus.\n    let cpuIds: Set<Int>\n\n    /// Create a new instance\n    ///\n    /// - arguments:\n    ///   - cpuIds: The `Set` of CPU ids. It must be non-empty and can not contain invalid ids.\n    init(cpuIds: Set<Int>) {\n        precondition(!cpuIds.isEmpty)\n        self.cpuIds = cpuIds\n    }\n\n    /// Create a new instance\n    ///\n    /// - arguments:\n    ///   - cpuId: The CPU id.\n    init(_ cpuId: Int) {\n        let ids: Set<Int> = [cpuId]\n        self.init(cpuIds: ids)\n    }\n}\n\nextension LinuxCPUSet: Equatable {}\n\n/// Linux specific extension to `NIOThread`.\nextension NIOThread {\n    /// Specify the thread-affinity of the current thread.\n    static var currentAffinity: LinuxCPUSet {\n        get {\n            var cpuset = cpu_set_t()\n\n            // Ensure the cpuset is empty (and so nothing is selected yet).\n            CNIOLinux_CPU_ZERO(&cpuset)\n\n            let res = CNIOLinux_pthread_getaffinity_np(pthread_self(), MemoryLayout.size(ofValue: cpuset), &cpuset)\n\n            precondition(res == 0, \"pthread_getaffinity_np failed: \\(res)\")\n\n            let set = Set(\n                (CInt(0)..<CNIOLinux_CPU_SETSIZE()).lazy.filter { CNIOLinux_CPU_ISSET($0, &cpuset) != 0 }.map {\n                    Int($0)\n                }\n            )\n            return LinuxCPUSet(cpuIds: set)\n        }\n        set(cpuSet) {\n            var cpuset = cpu_set_t()\n\n            // Ensure the cpuset is empty (and so nothing is selected yet).\n            CNIOLinux_CPU_ZERO(&cpuset)\n\n            // Mark the CPU we want to run on.\n            for cpuID in cpuSet.cpuIds {\n                CNIOLinux_CPU_SET(CInt(cpuID), &cpuset)\n            }\n            let res = CNIOLinux_pthread_setaffinity_np(pthread_self(), MemoryLayout.size(ofValue: cpuset), &cpuset)\n            precondition(res == 0, \"pthread_setaffinity_np failed: \\(res)\")\n        }\n    }\n}\n\nextension MultiThreadedEventLoopGroup {\n\n    /// Create a new `MultiThreadedEventLoopGroup` that create as many `NIOThread`s as `pinnedCPUIDs`. Each `NIOThread` will be pinned to the CPU with the id.\n    ///\n    /// Generally you should avoid using this API unless you have a concrete reason to need to pin threads to specific IDs.\n    ///\n    /// - arguments:\n    ///   - pinnedCPUIDs: The CPU ids to apply to the `NIOThread`s.\n    public convenience init(pinnedCPUIDs: [Int]) {\n        let initializers: [ThreadInitializer] = pinnedCPUIDs.map { id in\n            // This will also take care of validation of the provided id.\n            let set = LinuxCPUSet(id)\n            return { t in\n                precondition(t.isCurrentSlow)\n                NIOThread.currentAffinity = set\n            }\n        }\n        self.init(threadInitializers: initializers, metricsDelegate: nil)\n    }\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/LinuxUring.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if SWIFTNIO_USE_IO_URING\n#if os(Linux)\n\nimport CNIOLinux\nimport NIOCore\n\n@usableFromInline\nenum CQEEventType: UInt8 {\n    case poll = 1\n    case pollModify, pollDelete  // start with 1 to not get zero bit patterns for stdin\n}\n\ninternal enum URingError: Error {\n    case loadFailure\n    case uringSetupFailure\n    case uringWaitCqeFailure\n}\n\nextension TimeAmount {\n    func kernelTimespec() -> __kernel_timespec {\n        var ts = __kernel_timespec()\n        ts.tv_sec = self.nanoseconds / 1_000_000_000\n        ts.tv_nsec = self.nanoseconds % 1_000_000_000\n        return ts\n    }\n}\n\n// URingUserData supports (un)packing into an `UInt64` as io_uring has a user_data 64-bit payload which is set in the SQE\n// and returned in the CQE. We're using 56 of those 64 bits, 32 for the file descriptor, 16 for a \"registration ID\" and 8\n// for the type of event issued (poll/modify/delete).\n@usableFromInline struct URingUserData {\n    @usableFromInline var fileDescriptor: CInt\n    // SelectorRegistrationID truncated, only have room for bottom 16 bits (could be expanded to 24 if required)\n    @usableFromInline var registrationID: UInt16\n    @usableFromInline var eventType: CQEEventType\n    @usableFromInline var padding: Int8  // reserved for future use\n\n    @inlinable init(registrationID: SelectorRegistrationID, fileDescriptor: CInt, eventType: CQEEventType) {\n        assert(MemoryLayout<UInt64>.size == MemoryLayout<URingUserData>.size)\n        self.registrationID = UInt16(truncatingIfNeeded: registrationID.rawValue)\n        self.fileDescriptor = fileDescriptor\n        self.eventType = eventType\n        self.padding = 0\n    }\n\n    @inlinable init(rawValue: UInt64) {\n        let unpacked = IntegerBitPacking.unpackUInt32UInt16UInt8(rawValue)\n        self = .init(\n            registrationID: SelectorRegistrationID(rawValue: UInt32(unpacked.1)),\n            fileDescriptor: CInt(unpacked.0),\n            eventType: CQEEventType(rawValue: unpacked.2)!\n        )\n    }\n}\n\nextension UInt64 {\n    init(_ uringUserData: URingUserData) {\n        let fd = uringUserData.fileDescriptor\n        let eventType = uringUserData.eventType.rawValue\n        assert(fd >= 0, \"\\(fd) is not a valid file descriptor\")\n        assert(eventType >= 0, \"\\(eventType) is not a valid eventType\")\n\n        self = IntegerBitPacking.packUInt32UInt16UInt8(\n            UInt32(truncatingIfNeeded: fd),\n            uringUserData.registrationID,\n            eventType\n        )\n    }\n}\n\n// These are the events returned up to the selector\ninternal struct URingEvent {\n    var fd: CInt\n    var pollMask: UInt32\n    var registrationID: UInt16  // we just have the truncated lower 16 bits of the registrationID\n    var pollCancelled: Bool\n    init() {\n        self.fd = -1\n        self.pollMask = 0\n        self.registrationID = 0\n        self.pollCancelled = false\n    }\n}\n\n// This is the key we use for merging events in our internal hashtable\nstruct FDEventKey: Hashable {\n    var fileDescriptor: CInt\n    var registrationID: UInt16  // we just have the truncated lower 16 bits of the registrationID\n\n    init(_ f: CInt, _ s: UInt16) {\n        self.fileDescriptor = f\n        self.registrationID = s\n    }\n}\n\nfinal internal class URing {\n    internal static let POLLIN: CUnsignedInt = numericCast(CNIOLinux.POLLIN)\n    internal static let POLLOUT: CUnsignedInt = numericCast(CNIOLinux.POLLOUT)\n    internal static let POLLERR: CUnsignedInt = numericCast(CNIOLinux.POLLERR)\n    internal static let POLLRDHUP: CUnsignedInt = CNIOLinux_POLLRDHUP()  // numericCast(CNIOLinux.POLLRDHUP)\n    internal static let POLLHUP: CUnsignedInt = numericCast(CNIOLinux.POLLHUP)\n    // Poll cancelled, need to reregister for singleshot polls\n    internal static let POLLCANCEL: CUnsignedInt = 0xF000_0000\n\n    private var ring = io_uring()\n    private let ringEntries: CUnsignedInt = 8192\n    private let cqeMaxCount: UInt32 = 8192  // this is the max chunk of CQE we take.\n\n    var cqes: UnsafeMutablePointer<UnsafeMutablePointer<io_uring_cqe>?>\n    var fdEvents = [FDEventKey: UInt32]()  // fd, sequence_identifier : merged event_poll_return\n    var emptyCqe = io_uring_cqe()\n\n    var fd: CInt {\n        ring.ring_fd\n    }\n\n    static var io_uring_use_multishot_poll: Bool {\n        #if SWIFTNIO_IO_URING_MULTISHOT\n        return true\n        #else\n        return false\n        #endif\n    }\n\n    func _dumpCqes(_ header: String, count: Int = 1) {\n        #if SWIFTNIO_IO_URING_DEBUG_DUMP_CQE\n        func _debugPrintCQE(_ s: String) {\n            print(\"Q [\\(NIOThread.current)] \" + s)\n        }\n\n        if count < 0 {\n            return\n        }\n\n        _debugPrintCQE(header + \" CQE:s [\\(cqes)] - ring flags are [\\(ring.flags)]\")\n        for i in 0..<count {\n            let c = cqes[i]!.pointee\n\n            let bitPattern = UInt(bitPattern: io_uring_cqe_get_data(cqes[i]))\n            let uringUserData = URingUserData(rawValue: UInt64(bitPattern))\n\n            _debugPrintCQE(\n                \"\\(i) = fd[\\(uringUserData.fileDescriptor)] eventType[\\(String(describing:uringUserData.eventType))] registrationID[\\(uringUserData.registrationID)] res [\\(c.res)] flags [\\(c.flags)]\"\n            )\n        }\n        #endif\n    }\n\n    init() {\n        cqes = UnsafeMutablePointer<UnsafeMutablePointer<io_uring_cqe>?>.allocate(capacity: Int(cqeMaxCount))\n        cqes.initialize(repeating: &emptyCqe, count: Int(cqeMaxCount))\n    }\n\n    deinit {\n        cqes.deallocate()\n    }\n\n    internal func io_uring_queue_init() throws {\n        if CNIOLinux.io_uring_queue_init(ringEntries, &ring, 0) != 0 {\n            throw URingError.uringSetupFailure\n        }\n\n        _debugPrint(\"io_uring_queue_init \\(self.ring.ring_fd)\")\n    }\n\n    internal func io_uring_queue_exit() {\n        _debugPrint(\"io_uring_queue_exit \\(self.ring.ring_fd)\")\n        CNIOLinux.io_uring_queue_exit(&ring)\n    }\n\n    // Adopting some retry code from queue.c from liburing with slight\n    // modifications - we never want to have to handle retries of\n    // SQE allocation in all places it could possibly occur.\n    // If the SQ ring is full, we may need to submit IO first\n    func withSQE<R>(_ body: (UnsafeMutablePointer<io_uring_sqe>?) throws -> R) rethrows -> R {\n        // io_uring_submit can fail here due to backpressure from kernel for not reaping CQE:s.\n        //\n        // I think we should consider handling that as a fatalError, as fundamentally the ring size is too small\n        // compared to the amount of events the user tries to push through in a single eventloop tick.\n        //\n        // This is mostly a problem for synthetic tests that e.g. do a huge amount of registration modifications.\n        //\n        // This is a slight design issue with SwiftNIO in general that should be discussed.\n        //\n        while true {\n            if let sqe = CNIOLinux.io_uring_get_sqe(&ring) {\n                return try body(sqe)\n            }\n            self.io_uring_flush()\n        }\n    }\n\n    // Ok, this was a bummer - turns out that flushing multiple SQE:s\n    // can fail midflight and this will actually happen for real when e.g. a socket\n    // has gone down and we are re-registering polls this means we will silently lose any\n    // entries after the failed fd. Ouch. Proper approach is to use io_uring_sq_ready() in a loop.\n    // See: https://github.com/axboe/liburing/issues/309\n    internal func io_uring_flush() {  // When using SQPOLL this is basically a NOP\n        var waitingSubmissions: UInt32 = 0\n        var submissionCount = 0\n        var retval: CInt\n\n        waitingSubmissions = CNIOLinux.io_uring_sq_ready(&ring)\n\n        loop: while waitingSubmissions > 0 {\n            retval = CNIOLinux.io_uring_submit(&ring)\n            submissionCount += 1\n\n            switch retval {\n            // We can get -EAGAIN if the CQE queue is full and we get back pressure from\n            // the kernel to start processing CQE:s. If we break here with unsubmitted\n            // SQE:s, they will stay pending on the user-level side and be flushed\n            // to the kernel after we had the opportunity to reap more CQE:s\n            // In practice it will be at the end of whenReady the next\n            // time around. Given the async nature, this is fine, we will not\n            // lose any submissions. We could possibly still get stuck\n            // trying to get new SQE if the actual SQE queue is full, but\n            // that would be due to user error in usage IMHO and we should fatalError there.\n            case -EAGAIN, -EBUSY:\n                _debugPrint(\n                    \"io_uring_flush io_uring_submit -EBUSY/-EAGAIN waitingSubmissions[\\(waitingSubmissions)] submissionCount[\\(submissionCount)]. Breaking out and resubmitting later (whenReady() end).\"\n                )\n                break loop\n            // -ENOMEM when there is not enough memory to do internal allocations on the kernel side.\n            // Right nog we just loop with a sleep trying to buy time, but could also possibly fatalError here.\n            // See: https://github.com/axboe/liburing/issues/309\n            case -ENOMEM:\n                usleep(10_000)  // let's not busy loop to give the kernel some time to recover if possible\n                _debugPrint(\"io_uring_flush io_uring_submit -ENOMEM \\(submissionCount)\")\n            case 0:\n                _debugPrint(\n                    \"io_uring_flush io_uring_submit submitted 0, so far needed submissionCount[\\(submissionCount)] waitingSubmissions[\\(waitingSubmissions)] submitted [\\(retval)] SQE:s this iteration\"\n                )\n                break\n            case 1...:\n                _debugPrint(\n                    \"io_uring_flush io_uring_submit needed [\\(submissionCount)] submission(s), submitted [\\(retval)] SQE:s out of [\\(waitingSubmissions)] possible\"\n                )\n                break\n            default:  // other errors\n                fatalError(\"Unexpected error [\\(retval)] from io_uring_submit \")\n            }\n\n            waitingSubmissions = CNIOLinux.io_uring_sq_ready(&ring)\n        }\n    }\n\n    // we stuff event type into the upper byte, the next 3 bytes gives us the sequence number (16M before wrap) and final 4 bytes are fd.\n    internal func io_uring_prep_poll_add(\n        fileDescriptor: CInt,\n        pollMask: UInt32,\n        registrationID: SelectorRegistrationID,\n        submitNow: Bool = true,\n        multishot: Bool = true\n    ) {\n        let bitPattern = UInt64(\n            URingUserData(registrationID: registrationID, fileDescriptor: fileDescriptor, eventType: CQEEventType.poll)\n        )\n        let bitpatternAsPointer = UnsafeMutableRawPointer.init(bitPattern: UInt(bitPattern))\n\n        _debugPrint(\n            \"io_uring_prep_poll_add fileDescriptor[\\(fileDescriptor)] pollMask[\\(pollMask)] bitpatternAsPointer[\\(String(describing:bitpatternAsPointer))] submitNow[\\(submitNow)] multishot[\\(multishot)]\"\n        )\n\n        self.withSQE { sqe in\n            CNIOLinux.io_uring_prep_poll_add(sqe, fileDescriptor, pollMask)\n            // must be done after prep_poll_add, otherwise zeroed out.\n            CNIOLinux.io_uring_sqe_set_data(sqe, bitpatternAsPointer)\n\n            if multishot {\n                // turn on multishots, set through environment variable\n                sqe!.pointee.len |= IORING_POLL_ADD_MULTI\n            }\n        }\n\n        if submitNow {\n            self.io_uring_flush()\n        }\n    }\n\n    internal func io_uring_prep_poll_remove(\n        fileDescriptor: CInt,\n        pollMask: UInt32,\n        registrationID: SelectorRegistrationID,\n        submitNow: Bool = true,\n        link: Bool = false\n    ) {\n        let bitPattern = UInt64(\n            URingUserData(\n                registrationID: registrationID,\n                fileDescriptor: fileDescriptor,\n                eventType: CQEEventType.poll\n            )\n        )\n        let userbitPattern = UInt64(\n            URingUserData(\n                registrationID: registrationID,\n                fileDescriptor: fileDescriptor,\n                eventType: CQEEventType.pollDelete\n            )\n        )\n\n        _debugPrint(\n            \"io_uring_prep_poll_remove fileDescriptor[\\(fileDescriptor)] pollMask[\\(pollMask)] bitpatternAsPointer[\\(String(describing: bitPattern))] userBitpatternAsPointer[\\(String(describing: userbitPattern))] submitNow[\\(submitNow)] link[\\(link)]\"\n        )\n\n        self.withSQE { sqe in\n            CNIOLinux.io_uring_prep_poll_remove(sqe, .init(userData: bitPattern))\n            // must be done after prep_poll_add, otherwise zeroed out.\n            CNIOLinux.io_uring_sqe_set_data(sqe, .init(userData: userbitPattern))\n\n            if link {\n                CNIOLinux_io_uring_set_link_flag(sqe)\n            }\n        }\n\n        if submitNow {\n            self.io_uring_flush()\n        }\n    }\n\n    // the update/multishot polls are\n    internal func io_uring_poll_update(\n        fileDescriptor: CInt,\n        newPollmask: UInt32,\n        oldPollmask: UInt32,\n        registrationID: SelectorRegistrationID,\n        submitNow: Bool = true,\n        multishot: Bool = true\n    ) {\n\n        let bitpattern = UInt64(\n            URingUserData(\n                registrationID: registrationID,\n                fileDescriptor: fileDescriptor,\n                eventType: CQEEventType.poll\n            )\n        )\n        let userbitPattern = UInt64(\n            URingUserData(\n                registrationID: registrationID,\n                fileDescriptor: fileDescriptor,\n                eventType: CQEEventType.pollModify\n            )\n        )\n\n        _debugPrint(\n            \"io_uring_poll_update fileDescriptor[\\(fileDescriptor)] oldPollmask[\\(oldPollmask)] newPollmask[\\(newPollmask)]  userBitpatternAsPointer[\\(String(describing: userbitPattern))]\"\n        )\n\n        self.withSQE { sqe in\n            // \"Documentation\" for multishot polls and updates here:\n            // https://git.kernel.dk/cgit/linux-block/commit/?h=poll-multiple&id=33021a19e324fb747c2038416753e63fd7cd9266\n            var flags = IORING_POLL_UPDATE_EVENTS | IORING_POLL_UPDATE_USER_DATA\n            if multishot {\n                flags |= IORING_POLL_ADD_MULTI  // ask for multiple updates\n            }\n\n            CNIOLinux.io_uring_prep_poll_update(\n                sqe,\n                .init(userData: bitpattern),\n                .init(userData: bitpattern),\n                newPollmask,\n                flags\n            )\n            CNIOLinux.io_uring_sqe_set_data(sqe, .init(userData: userbitPattern))\n        }\n\n        if submitNow {\n            self.io_uring_flush()\n        }\n    }\n\n    internal func _debugPrint(_ s: @autoclosure () -> String) {\n        #if SWIFTNIO_IO_URING_DEBUG_URING\n        print(\"L [\\(NIOThread.current)] \" + s())\n        #endif\n    }\n\n    // We merge results into fdEvents on (fd, registrationID) for the given CQE\n    // this minimizes amount of events propagating up and allows Selector to discard\n    // events with an old sequence identifier.\n    internal func _process_cqe(events: UnsafeMutablePointer<URingEvent>, cqeIndex: Int, multishot: Bool) {\n        let bitPattern = UInt(bitPattern: io_uring_cqe_get_data(cqes[cqeIndex]))\n        let uringUserData = URingUserData(rawValue: UInt64(bitPattern))\n        let result = cqes[cqeIndex]!.pointee.res\n\n        switch uringUserData.eventType {\n        case .poll:\n            switch result {\n            case -ECANCELED:\n                var pollError: UInt32 = 0\n                assert(uringUserData.fileDescriptor >= 0, \"fd must be zero or greater\")\n                if multishot {  // -ECANCELED for streaming polls, should signal error\n                    pollError = URing.POLLERR | URing.POLLHUP\n                } else {  // this just signals that Selector just should resubmit a new fresh poll\n                    pollError = URing.POLLCANCEL\n                }\n                if let current = fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] {\n                    fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] =\n                        current | pollError\n                } else {\n                    fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] = pollError\n                }\n                break\n            // We can validly receive an EBADF as a close() can race vis-a-vis pending SQE:s\n            // with polls / pollModifications - in that case, we should just discard the result.\n            // This is similar to the assert in BaseSocketChannel and is due to the lack\n            // of implicit synchronization with regard to registration changes for io_uring\n            // - we simply can't know when the kernel will process our SQE without\n            // heavy-handed synchronization which would dump performance.\n            // Discussion here:\n            // https://github.com/apple/swift-nio/pull/1804#discussion_r621304055\n            // including clarifications from @isilence (one of the io_uring developers)\n            case -EBADF:\n                _debugPrint(\"Failed poll with -EBADF for cqeIndex[\\(cqeIndex)]\")\n                break\n            case ..<0:  // other errors\n                fatalError(\"Failed poll with unexpected error (\\(result) for cqeIndex[\\(cqeIndex)]\")\n                break\n            case 0:  // successfull chained add for singleshots, not an event\n                break\n            default:  // positive success\n                assert(uringUserData.fileDescriptor >= 0, \"fd must be zero or greater\")\n                let uresult = UInt32(result)\n\n                if let current = fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] {\n                    fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] = current | uresult\n                } else {\n                    fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] = uresult\n                }\n            }\n        case .pollModify:  // we only get this for multishot modifications\n            switch result {\n            case -ECANCELED:  // -ECANCELED for streaming polls, should signal error\n                assert(uringUserData.fileDescriptor >= 0, \"fd must be zero or greater\")\n\n                let pollError = URing.POLLERR  // URing.POLLERR // (URing.POLLHUP | URing.POLLERR)\n                if let current = fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] {\n                    fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] =\n                        current | pollError\n                } else {\n                    fdEvents[FDEventKey(uringUserData.fileDescriptor, uringUserData.registrationID)] = pollError\n                }\n                break\n            case -EALREADY:\n                _debugPrint(\"Failed pollModify with -EALREADY for cqeIndex[\\(cqeIndex)]\")\n                break\n            case -ENOENT:\n                _debugPrint(\"Failed pollModify with -ENOENT for cqeIndex [\\(cqeIndex)]\")\n                break\n            // See the description for EBADF handling above in the poll case for rationale of allowing EBADF.\n            case -EBADF:\n                _debugPrint(\"Failed pollModify with -EBADF for cqeIndex[\\(cqeIndex)]\")\n                break\n            case ..<0:  // other errors\n                fatalError(\"Failed pollModify with unexpected error (\\(result) for cqeIndex[\\(cqeIndex)]\")\n                break\n            case 0:  // successfull chained add, not an event\n                break\n            default:  // positive success\n                fatalError(\"pollModify returned > 0\")\n            }\n            break\n        case .pollDelete:\n            break\n        }\n    }\n\n    internal func io_uring_peek_batch_cqe(\n        events: UnsafeMutablePointer<URingEvent>,\n        maxevents: UInt32,\n        multishot: Bool = true\n    ) -> Int {\n        var eventCount = 0\n        var currentCqeCount = CNIOLinux.io_uring_peek_batch_cqe(&ring, cqes, cqeMaxCount)\n\n        if currentCqeCount == 0 {\n            _debugPrint(\"io_uring_peek_batch_cqe found zero events, breaking out\")\n            return 0\n        }\n\n        _debugPrint(\"io_uring_peek_batch_cqe found [\\(currentCqeCount)] events\")\n\n        self._dumpCqes(\"io_uring_peek_batch_cqe\", count: Int(currentCqeCount))\n\n        assert(currentCqeCount >= 0, \"currentCqeCount should never be negative\")\n        assert(maxevents > 0, \"maxevents should be a positive number\")\n\n        for cqeIndex in 0..<currentCqeCount {\n            self._process_cqe(events: events, cqeIndex: Int(cqeIndex), multishot: multishot)\n\n            if fdEvents.count == maxevents  // ensure we don't generate more events than maxevents\n            {\n                _debugPrint(\n                    \"io_uring_peek_batch_cqe breaking loop early, currentCqeCount [\\(currentCqeCount)] maxevents [\\(maxevents)]\"\n                )\n                currentCqeCount = maxevents  // to make sure we only cq_advance the correct amount\n                break\n            }\n        }\n\n        io_uring_cq_advance(&ring, currentCqeCount)  // bulk variant of io_uring_cqe_seen(&ring, dataPointer)\n\n        //  we just return single event per fd, sequencenumber pair\n        eventCount = 0\n        for (eventKey, pollMask) in fdEvents {\n            assert(eventCount < maxevents)\n            assert(eventKey.fileDescriptor >= 0)\n\n            events[eventCount].fd = eventKey.fileDescriptor\n            events[eventCount].pollMask = pollMask\n            events[eventCount].registrationID = eventKey.registrationID\n            if (pollMask & URing.POLLCANCEL) != 0 {\n                events[eventCount].pollMask &= ~URing.POLLCANCEL\n                events[eventCount].pollCancelled = true\n            }\n            eventCount += 1\n        }\n\n        fdEvents.removeAll(keepingCapacity: true)  // reused for next batch\n\n        _debugPrint(\"io_uring_peek_batch_cqe returning [\\(eventCount)] events, fdEvents.count [\\(fdEvents.count)]\")\n\n        return eventCount\n    }\n\n    internal func _io_uring_wait_cqe_shared(\n        events: UnsafeMutablePointer<URingEvent>,\n        error: Int32,\n        multishot: Bool\n    ) throws -> Int {\n        var eventCount = 0\n\n        switch error {\n        case 0:\n            break\n        case -CNIOLinux.EINTR:\n            _debugPrint(\"_io_uring_wait_cqe_shared got CNIOLinux.EINTR\")\n            return eventCount\n        case -CNIOLinux.ETIME:\n            _debugPrint(\"_io_uring_wait_cqe_shared timed out with -CNIOLinux.ETIME\")\n            CNIOLinux.io_uring_cqe_seen(&ring, cqes[0])\n            return eventCount\n        default:\n            _debugPrint(\"URingError.uringWaitCqeFailure \\(error)\")\n            throw URingError.uringWaitCqeFailure\n        }\n\n        self._dumpCqes(\"_io_uring_wait_cqe_shared\")\n\n        self._process_cqe(events: events, cqeIndex: 0, multishot: multishot)\n\n        CNIOLinux.io_uring_cqe_seen(&ring, cqes[0])\n\n        if let firstEvent = fdEvents.first {\n            events[0].fd = firstEvent.key.fileDescriptor\n            events[0].pollMask = firstEvent.value\n            events[0].registrationID = firstEvent.key.registrationID\n            eventCount = 1\n        } else {\n            _debugPrint(\"_io_uring_wait_cqe_shared if let firstEvent = fdEvents.first failed\")\n        }\n\n        fdEvents.removeAll(keepingCapacity: true)  // reused for next batch\n\n        return eventCount\n    }\n\n    internal func io_uring_wait_cqe(\n        events: UnsafeMutablePointer<URingEvent>,\n        maxevents: UInt32,\n        multishot: Bool = true\n    ) throws -> Int {\n        _debugPrint(\"io_uring_wait_cqe\")\n\n        let error = CNIOLinux.io_uring_wait_cqe(&ring, cqes)\n\n        return try self._io_uring_wait_cqe_shared(events: events, error: error, multishot: multishot)\n    }\n\n    internal func io_uring_wait_cqe_timeout(\n        events: UnsafeMutablePointer<URingEvent>,\n        maxevents: UInt32,\n        timeout: TimeAmount,\n        multishot: Bool = true\n    ) throws -> Int {\n        var ts = timeout.kernelTimespec()\n\n        _debugPrint(\"io_uring_wait_cqe_timeout.ETIME milliseconds \\(ts)\")\n\n        let error = CNIOLinux.io_uring_wait_cqe_timeout(&ring, cqes, &ts)\n\n        return try self._io_uring_wait_cqe_shared(events: events, error: error, multishot: multishot)\n    }\n}\n\n// MARK: Conversion helpers\n// Newer versions of liburing changed one of the method arguments from UnsafeMutableRawPointer\n// to UInt64 in order to allow 32-bit systems to work properly. We therefore need a way to\n// transform a UInt64 into either of these types. These two initializers help us do that in\n// a way that supports both the old and new format in source.\nextension UInt64 {\n    init(userData: UInt64) {\n        self = userData\n    }\n}\n\nextension Optional where Wrapped == UnsafeMutableRawPointer {\n    init(userData: UInt64) {\n        // This will crash on 32-bit systems: that's fine, our liburing support\n        // never worked on 32-bit for older libraries anyway.\n        self = .init(bitPattern: UInt(userData))\n    }\n}\n\n#endif\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/MultiThreadedEventLoopGroup.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport CNIOPosix\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\n@usableFromInline\nstruct NIORegistration: Registration {\n    enum ChannelType {\n        case serverSocketChannel(ServerSocketChannel)\n        case socketChannel(SocketChannel)\n        case datagramChannel(DatagramChannel)\n        case pipeChannel(PipeChannel, PipeChannel.Direction)\n    }\n\n    var channel: ChannelType\n\n    /// The `SelectorEventSet` in which this `NIORegistration` is interested in.\n    @usableFromInline\n    var interested: SelectorEventSet\n\n    /// The registration ID for this `NIORegistration` used by the `Selector`.\n    @usableFromInline\n    var registrationID: SelectorRegistrationID\n}\n\n@available(*, unavailable)\nextension NIORegistration: Sendable {}\n\n/// Called per `NIOThread` that is created for an EventLoop to do custom initialization of the `NIOThread` before the actual `EventLoop` is run on it.\ntypealias ThreadInitializer = (NIOThread) -> Void\n\n/// An `EventLoopGroup` which will create multiple `EventLoop`s, each tied to its own `NIOThread`.\n///\n/// The effect of initializing a `MultiThreadedEventLoopGroup` is to spawn `numberOfThreads` fresh threads which will\n/// all run their own `EventLoop`. Those threads will not be shut down until `shutdownGracefully` or\n/// `syncShutdownGracefully` is called.\n///\n/// - warning: Unit tests often spawn one `MultiThreadedEventLoopGroup` per unit test to force isolation between the\n///            tests. In those cases it's important to shut the `MultiThreadedEventLoopGroup` down at the end of the\n///            test. A good place to start a `MultiThreadedEventLoopGroup` is the `setUp` method of your `XCTestCase`\n///            subclass, a good place to shut it down is the `tearDown` method.\npublic final class MultiThreadedEventLoopGroup: EventLoopGroup {\n    typealias _ShutdownGracefullyCallback = @Sendable (Error?) -> Void\n\n    private enum RunState {\n        case running\n        case closing([(DispatchQueue, _ShutdownGracefullyCallback)])\n        case closed(Error?)\n    }\n\n    internal enum _CanBeShutDown {\n        case yes\n        case no\n        case notByUser\n    }\n\n    private let myGroupID: Int\n    private let index = ManagedAtomic<Int>(0)\n    private var eventLoops: [SelectableEventLoop]\n    private let shutdownLock: NIOLock = NIOLock()\n    private let threadNamePrefix: String\n    private var runState: RunState = .running\n    private let canBeShutDown: _CanBeShutDown\n\n    private static func storeLoopThreadLocalReference(to loop: SelectableEventLoop) {\n        let existingRef = c_nio_posix_get_el_ptr()\n        precondition(\n            existingRef == nil,\n            \"weird, current SEL reference \\(String(describing: existingRef)), expected nil\"\n        )\n\n        let newRef = Unmanaged.passRetained(loop).toOpaque()\n        c_nio_posix_set_el_ptr(newRef)\n    }\n\n    private static func clearLoopThreadLocalReference() {\n        let existingRef = c_nio_posix_get_el_ptr()\n        precondition(existingRef != nil, \"weird, current SEL reference is unexpectedly nil\")\n\n        Unmanaged<SelectableEventLoop>.fromOpaque(existingRef!).release()\n        c_nio_posix_set_el_ptr(nil)\n    }\n\n    private static func runTheLoop(\n        thread: NIOThread,\n        uniqueID: SelectableEventLoopUniqueID,\n        parentGroup: MultiThreadedEventLoopGroup?,  // nil iff thread take-over\n        canEventLoopBeShutdownIndividually: Bool,\n        selectorFactory: @escaping (NIOThread) throws -> NIOPosix.Selector<NIORegistration>,\n        initializer: @escaping ThreadInitializer,\n        metricsDelegate: NIOEventLoopMetricsDelegate?,\n        _ callback: @escaping (SelectableEventLoop) -> Void\n    ) {\n        assert(thread.isCurrentSlow)\n        uniqueID.attachToCurrentThread()\n        defer {\n            uniqueID.detachFromCurrentThread()\n        }\n        initializer(thread)\n\n        do {\n            let loop = SelectableEventLoop(\n                thread: thread,\n                uniqueID: uniqueID,\n                parentGroup: parentGroup,\n                selector: try selectorFactory(thread),\n                canBeShutdownIndividually: canEventLoopBeShutdownIndividually,\n                metricsDelegate: metricsDelegate\n            )\n            Self.storeLoopThreadLocalReference(to: loop)\n            defer {\n                Self.clearLoopThreadLocalReference()\n            }\n            callback(loop)\n            try loop.run()\n        } catch {\n            // We fatalError here because the only reasons this can be hit is if the underlying kqueue/epoll give us\n            // errors that we cannot handle which is an unrecoverable error for us.\n            fatalError(\"Unexpected error while running SelectableEventLoop: \\(error).\")\n        }\n    }\n\n    private static func setupThreadAndEventLoop(\n        name: String,\n        uniqueID: SelectableEventLoopUniqueID,\n        parentGroup: MultiThreadedEventLoopGroup,\n        selectorFactory: @escaping (NIOThread) throws -> NIOPosix.Selector<NIORegistration>,\n        initializer: @escaping ThreadInitializer,\n        metricsDelegate: NIOEventLoopMetricsDelegate?\n    ) -> SelectableEventLoop {\n        let lock = ConditionLock(value: 0)\n\n        // synchronised by `lock`\n        var _loop: SelectableEventLoop! = nil\n\n        NIOThread.spawnAndRun(name: name) { t in\n            MultiThreadedEventLoopGroup.runTheLoop(\n                thread: t,\n                uniqueID: uniqueID,\n                parentGroup: parentGroup,\n                canEventLoopBeShutdownIndividually: false,  // part of MTELG\n                selectorFactory: selectorFactory,\n                initializer: initializer,\n                metricsDelegate: metricsDelegate\n            ) { l in\n                lock.lock(whenValue: 0)\n                _loop = l\n                lock.unlock(withValue: 1)\n            }\n        }\n        lock.lock(whenValue: 1)\n        defer { lock.unlock() }\n        return _loop!\n    }\n\n    /// Creates a `MultiThreadedEventLoopGroup` instance which uses `numberOfThreads`.\n    ///\n    /// - Note: Don't forget to call `shutdownGracefully` or `syncShutdownGracefully` when you no longer need this\n    ///         `EventLoopGroup`. If you forget to shut the `EventLoopGroup` down you will leak `numberOfThreads`\n    ///         (kernel) threads which are costly resources. This is especially important in unit tests where one\n    ///         `MultiThreadedEventLoopGroup` is started per test case.\n    ///\n    /// - arguments:\n    ///   - numberOfThreads: The number of `Threads` to use.\n    public convenience init(numberOfThreads: Int) {\n        self.init(\n            numberOfThreads: numberOfThreads,\n            canBeShutDown: .yes,\n            metricsDelegate: nil,\n            selectorFactory: NIOPosix.Selector<NIORegistration>.init\n        )\n    }\n\n    /// Creates a `MultiThreadedEventLoopGroup` instance which uses `numberOfThreads`.\n    ///\n    /// - Note: Don't forget to call `shutdownGracefully` or `syncShutdownGracefully` when you no longer need this\n    ///         `EventLoopGroup`. If you forget to shut the `EventLoopGroup` down you will leak `numberOfThreads`\n    ///         (kernel) threads which are costly resources. This is especially important in unit tests where one\n    ///         `MultiThreadedEventLoopGroup` is started per test case.\n    ///\n    /// - Parameters:\n    ///    - numberOfThreads: The number of `Threads` to use.\n    ///    - metricsDelegate: Delegate for collecting information from this eventloop\n    public convenience init(numberOfThreads: Int, metricsDelegate: NIOEventLoopMetricsDelegate) {\n        self.init(\n            numberOfThreads: numberOfThreads,\n            canBeShutDown: .yes,\n            metricsDelegate: metricsDelegate,\n            selectorFactory: NIOPosix.Selector<NIORegistration>.init\n        )\n    }\n\n    /// Create a ``MultiThreadedEventLoopGroup`` that cannot be shut down and must not be `deinit`ed.\n    ///\n    /// This is only useful for global singletons.\n    public static func _makePerpetualGroup(\n        threadNamePrefix: String,\n        numberOfThreads: Int\n    ) -> MultiThreadedEventLoopGroup {\n        self.init(\n            numberOfThreads: numberOfThreads,\n            canBeShutDown: .no,\n            threadNamePrefix: threadNamePrefix,\n            metricsDelegate: nil,\n            selectorFactory: NIOPosix.Selector<NIORegistration>.init\n        )\n    }\n\n    internal convenience init(\n        numberOfThreads: Int,\n        metricsDelegate: NIOEventLoopMetricsDelegate?,\n        selectorFactory: @escaping (NIOThread) throws -> NIOPosix.Selector<NIORegistration>\n    ) {\n        precondition(numberOfThreads > 0, \"numberOfThreads must be positive\")\n        let initializers: [ThreadInitializer] = Array(repeating: { _ in }, count: numberOfThreads)\n        self.init(\n            threadInitializers: initializers,\n            canBeShutDown: .yes,\n            metricsDelegate: metricsDelegate,\n            selectorFactory: selectorFactory\n        )\n    }\n\n    internal convenience init(\n        numberOfThreads: Int,\n        canBeShutDown: _CanBeShutDown,\n        threadNamePrefix: String,\n        metricsDelegate: NIOEventLoopMetricsDelegate?,\n        selectorFactory: @escaping (NIOThread) throws -> NIOPosix.Selector<NIORegistration>\n    ) {\n        precondition(numberOfThreads > 0, \"numberOfThreads must be positive\")\n        let initializers: [ThreadInitializer] = Array(repeating: { _ in }, count: numberOfThreads)\n        self.init(\n            threadInitializers: initializers,\n            canBeShutDown: canBeShutDown,\n            threadNamePrefix: threadNamePrefix,\n            metricsDelegate: metricsDelegate,\n            selectorFactory: selectorFactory\n        )\n    }\n\n    internal convenience init(\n        numberOfThreads: Int,\n        canBeShutDown: _CanBeShutDown,\n        metricsDelegate: NIOEventLoopMetricsDelegate?,\n        selectorFactory: @escaping (NIOThread) throws -> NIOPosix.Selector<NIORegistration>\n    ) {\n        precondition(numberOfThreads > 0, \"numberOfThreads must be positive\")\n        let initializers: [ThreadInitializer] = Array(repeating: { _ in }, count: numberOfThreads)\n        self.init(\n            threadInitializers: initializers,\n            canBeShutDown: canBeShutDown,\n            metricsDelegate: metricsDelegate,\n            selectorFactory: selectorFactory\n        )\n    }\n\n    internal convenience init(\n        threadInitializers: [ThreadInitializer],\n        metricsDelegate: NIOEventLoopMetricsDelegate?,\n        selectorFactory: @escaping (NIOThread) throws -> NIOPosix.Selector<NIORegistration> = NIOPosix.Selector<\n            NIORegistration\n        >\n        .init\n    ) {\n        self.init(\n            threadInitializers: threadInitializers,\n            canBeShutDown: .yes,\n            metricsDelegate: metricsDelegate,\n            selectorFactory: selectorFactory\n        )\n    }\n\n    /// Creates a `MultiThreadedEventLoopGroup` instance which uses the given `ThreadInitializer`s. One `NIOThread` per `ThreadInitializer` is created and used.\n    ///\n    /// - arguments:\n    ///   - threadInitializers: The `ThreadInitializer`s to use.\n    internal init(\n        threadInitializers: [ThreadInitializer],\n        canBeShutDown: _CanBeShutDown,\n        threadNamePrefix: String = \"NIO-ELT-\",\n        metricsDelegate: NIOEventLoopMetricsDelegate?,\n        selectorFactory: @escaping (NIOThread) throws -> Selector<NIORegistration> = Selector<NIORegistration>\n            .init\n    ) {\n        self.threadNamePrefix = threadNamePrefix\n        let firstLoopID = SelectableEventLoopUniqueID.makeNextGroup()\n        self.myGroupID = firstLoopID.groupID\n        self.canBeShutDown = canBeShutDown\n        self.eventLoops = []  // Just so we're fully initialised and can vend `self` to the `SelectableEventLoop`.\n        var loopUniqueID = firstLoopID\n        self.eventLoops = threadInitializers.map { initializer in\n            // Maximum name length on linux is 16 by default.\n            let ev = MultiThreadedEventLoopGroup.setupThreadAndEventLoop(\n                name: \"\\(threadNamePrefix)\\(loopUniqueID.groupID)-#\\(loopUniqueID.loopID)\",\n                uniqueID: loopUniqueID,\n                parentGroup: self,\n                selectorFactory: selectorFactory,\n                initializer: initializer,\n                metricsDelegate: metricsDelegate\n            )\n            loopUniqueID.nextLoop()\n            return ev\n        }\n    }\n\n    deinit {\n        assert(\n            self.canBeShutDown != .no,\n            \"Perpetual MTELG shut down, you must ensure that perpetual MTELGs don't deinit\"\n        )\n    }\n\n    /// Returns the `EventLoop` for the calling thread.\n    ///\n    /// - Returns: The current `EventLoop` for the calling thread or `nil` if none is assigned to the thread.\n    public static var currentEventLoop: EventLoop? {\n        self.currentSelectableEventLoop\n    }\n\n    internal static var currentSelectableEventLoop: SelectableEventLoop? {\n        guard let ref = c_nio_posix_get_el_ptr() else {\n            return nil\n        }\n\n        return Unmanaged<SelectableEventLoop>.fromOpaque(ref).takeUnretainedValue()\n    }\n\n    /// Returns an `EventLoopIterator` over the `EventLoop`s in this `MultiThreadedEventLoopGroup`.\n    ///\n    /// - Returns: `EventLoopIterator`\n    public func makeIterator() -> EventLoopIterator {\n        EventLoopIterator(self.eventLoops)\n    }\n\n    /// Returns the next `EventLoop` from this `MultiThreadedEventLoopGroup`.\n    ///\n    /// `MultiThreadedEventLoopGroup` uses _round robin_ across all its `EventLoop`s to select the next one.\n    ///\n    /// - Returns: The next `EventLoop` to use.\n    public func next() -> EventLoop {\n        self.nextSEL()\n    }\n\n    internal func nextSEL() -> SelectableEventLoop {\n        eventLoops[abs(index.loadThenWrappingIncrement(ordering: .relaxed) % eventLoops.count)]\n    }\n\n    /// Returns the current `EventLoop` if we are on an `EventLoop` of this `MultiThreadedEventLoopGroup` instance.\n    ///\n    /// - Returns: The `EventLoop`.\n    public func any() -> EventLoop {\n        self.anySEL()\n    }\n\n    internal func anySEL() -> SelectableEventLoop {\n        if let loop = Self.currentSelectableEventLoop,\n            // We are on `loop`'s thread, so we may ask for the its parent group.\n            loop.parentGroupCallableFromThisEventLoopOnly() === self\n        {\n            // Nice, we can return this.\n            loop.assertInEventLoop()\n            return loop\n        } else {\n            // Oh well, let's just vend the next one then.\n            return self.nextSEL()\n        }\n    }\n\n    /// Shut this `MultiThreadedEventLoopGroup` down which causes the `EventLoop`s and their associated threads to be\n    /// shut down and release their resources.\n    ///\n    /// Even though calling `shutdownGracefully` more than once should be avoided, it is safe to do so and execution\n    /// of the `handler` is guaranteed.\n    ///\n    /// - Parameters:\n    ///    - queue: The `DispatchQueue` to run `handler` on when the shutdown operation completes.\n    ///    - handler: The handler which is called after the shutdown operation completes. The parameter will be `nil`\n    ///               on success and contain the `Error` otherwise.\n    @preconcurrency\n    public func shutdownGracefully(queue: DispatchQueue, _ handler: @escaping @Sendable (Error?) -> Void) {\n        self._shutdownGracefully(queue: queue, handler)\n    }\n\n    internal func _shutdownGracefully(\n        queue: DispatchQueue,\n        allowShuttingDownOverride: Bool = false,\n        _ handler: @escaping _ShutdownGracefullyCallback\n    ) {\n        switch self.canBeShutDown {\n        case .yes:\n            ()  // ok\n        case .no:\n            queue.async {\n                handler(EventLoopError._unsupportedOperation)\n            }\n            return\n        case .notByUser:\n            guard allowShuttingDownOverride else {\n                queue.async {\n                    handler(EventLoopError._unsupportedOperation)\n                }\n                return\n            }\n        }\n\n        // This method cannot perform its final cleanup using EventLoopFutures, because it requires that all\n        // our event loops still be alive, and they may not be. Instead, we use Dispatch to manage\n        // our shutdown signaling, and then do our cleanup once the DispatchQueue is empty.\n        let g = DispatchGroup()\n        let q = DispatchQueue(label: \"nio.shutdownGracefullyQueue\", target: queue)\n        let wasRunning: Bool = self.shutdownLock.withLock {\n            // We need to check the current `runState` and react accordingly.\n            switch self.runState {\n            case .running:\n                // If we are still running, we set the `runState` to `closing`,\n                // so that potential future invocations know, that the shutdown\n                // has already been initiaited.\n                self.runState = .closing([])\n                return true\n            case .closing(var callbacks):\n                // If we are currently closing, we need to register the `handler`\n                // for invocation after the shutdown is completed.\n                callbacks.append((q, handler))\n                self.runState = .closing(callbacks)\n                return false\n            case .closed(let error):\n                // If we are already closed, we can directly dispatch the `handler`\n                q.async {\n                    handler(error)\n                }\n                return false\n            }\n        }\n\n        // If the `runState` was not `running` when `shutdownGracefully` was called,\n        // the shutdown has already been initiated and we have to return here.\n        guard wasRunning else {\n            return\n        }\n\n        let result: NIOLockedValueBox<Result<Void, Error>> = NIOLockedValueBox(.success(()))\n\n        for loop in self.eventLoops {\n            g.enter()\n            loop.initiateClose(queue: q) { closeResult in\n                switch closeResult {\n                case .success:\n                    ()\n                case .failure(let error):\n                    result.withLockedValue {\n                        $0 = .failure(error)\n                    }\n                }\n                g.leave()\n            }\n        }\n\n        g.notify(queue: q) {\n            for loop in self.eventLoops {\n                loop.syncFinaliseClose(joinThread: true)\n            }\n            let (overallError, queueCallbackPairs): (Error?, [(DispatchQueue, _ShutdownGracefullyCallback)]) = self\n                .shutdownLock.withLock {\n                    switch self.runState {\n                    case .closed, .running:\n                        preconditionFailure(\n                            \"MultiThreadedEventLoopGroup in illegal state when closing: \\(self.runState)\"\n                        )\n                    case .closing(let callbacks):\n                        let overallError: Error? = result.withLockedValue {\n                            switch $0 {\n                            case .success:\n                                return nil\n                            case .failure(let error):\n                                return error\n                            }\n                        }\n                        self.runState = .closed(overallError)\n                        return (overallError, callbacks)\n                    }\n                }\n\n            queue.async {\n                handler(overallError)\n            }\n            for queueCallbackPair in queueCallbackPairs {\n                queueCallbackPair.0.async {\n                    queueCallbackPair.1(overallError)\n                }\n            }\n        }\n    }\n\n    /// Convert the calling thread into an `EventLoop`.\n    ///\n    /// This function will not return until the `EventLoop` has stopped. You can initiate stopping the `EventLoop` by\n    /// calling `eventLoop.shutdownGracefully` which will eventually make this function return.\n    ///\n    /// - Parameters:\n    ///   - callback: Called _on_ the `EventLoop` that the calling thread was converted to, providing you the\n    ///                 `EventLoop` reference. Just like usually on the `EventLoop`, do not block in `callback`.\n    public static func withCurrentThreadAsEventLoop(_ callback: @escaping (EventLoop) -> Void) {\n        NIOThread.withCurrentThread { callingThread in\n            MultiThreadedEventLoopGroup.runTheLoop(\n                thread: callingThread,\n                uniqueID: .makeNextGroup(),\n                parentGroup: nil,\n                canEventLoopBeShutdownIndividually: true,\n                selectorFactory: NIOPosix.Selector<NIORegistration>.init,\n                initializer: { _ in },\n                metricsDelegate: nil,\n                { loop in\n                    loop.assertInEventLoop()\n                    callback(loop)\n                }\n            )\n        }\n    }\n\n    public func _preconditionSafeToSyncShutdown(file: StaticString, line: UInt) {\n        if let eventLoop = MultiThreadedEventLoopGroup.currentEventLoop {\n            preconditionFailure(\n                \"\"\"\n                BUG DETECTED: syncShutdownGracefully() must not be called when on an EventLoop.\n                Calling syncShutdownGracefully() on any EventLoop can lead to deadlocks.\n                Current eventLoop: \\(eventLoop)\n                \"\"\",\n                file: file,\n                line: line\n            )\n        }\n    }\n}\n\nextension MultiThreadedEventLoopGroup: @unchecked Sendable {}\n\nextension MultiThreadedEventLoopGroup: CustomStringConvertible {\n    public var description: String {\n        \"MultiThreadedEventLoopGroup { threadPattern = \\(self.threadNamePrefix)\\(self.myGroupID)-#* }\"\n    }\n}\n\n@usableFromInline\nstruct ErasedUnownedJob: Sendable {\n    @usableFromInline\n    let erasedJob: any Sendable\n\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    init(job: UnownedJob) {\n        self.erasedJob = job\n    }\n\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    @inlinable\n    var unownedJob: UnownedJob {\n        // This force-cast is safe since we only store an UnownedJob\n        self.erasedJob as! UnownedJob\n    }\n}\n\n@usableFromInline\ninternal struct ScheduledTask {\n    @usableFromInline\n    enum Kind {\n        case task(task: () -> Void, failFn: (Error) -> Void)\n        case callback(any NIOScheduledCallbackHandler)\n    }\n\n    @usableFromInline\n    let kind: Kind\n\n    /// The id of the scheduled task.\n    ///\n    /// - Important: This id has two purposes. First, it is used to give this struct an identity so that we can implement ``Equatable``\n    ///     Second, it is used to give the tasks an order which we use to execute them.\n    ///     This means, the ids need to be unique for a given ``SelectableEventLoop`` and they need to be in ascending order.\n    @usableFromInline\n    let id: UInt64\n\n    @usableFromInline\n    internal let readyTime: NIODeadline\n\n    @usableFromInline\n    init(id: UInt64, _ task: @escaping () -> Void, _ failFn: @escaping (Error) -> Void, _ time: NIODeadline) {\n        self.id = id\n        self.readyTime = time\n        self.kind = .task(task: task, failFn: failFn)\n    }\n\n    @usableFromInline\n    init(id: UInt64, _ handler: any NIOScheduledCallbackHandler, _ time: NIODeadline) {\n        self.id = id\n        self.readyTime = time\n        self.kind = .callback(handler)\n    }\n}\n\nextension ScheduledTask: CustomStringConvertible {\n    @usableFromInline\n    var description: String {\n        \"ScheduledTask(readyTime: \\(self.readyTime))\"\n    }\n}\n\nextension ScheduledTask: Comparable {\n    @usableFromInline\n    static func < (lhs: ScheduledTask, rhs: ScheduledTask) -> Bool {\n        if lhs.readyTime == rhs.readyTime {\n            return lhs.id < rhs.id\n        } else {\n            return lhs.readyTime < rhs.readyTime\n        }\n    }\n\n    @usableFromInline\n    static func == (lhs: ScheduledTask, rhs: ScheduledTask) -> Bool {\n        lhs.id == rhs.id\n    }\n}\n\n@available(*, unavailable)\nextension ScheduledTask: Sendable {}\n\n@available(*, unavailable)\nextension ScheduledTask.Kind: Sendable {}\n\nextension NIODeadline {\n    @inlinable\n    func readyIn(_ target: NIODeadline) -> TimeAmount {\n        if self < target {\n            return .nanoseconds(0)\n        }\n        return self - target\n    }\n}\n\nextension MultiThreadedEventLoopGroup {\n    /// Start & automatically shut down a new ``MultiThreadedEventLoopGroup``.\n    ///\n    /// This method allows to start & automatically dispose of a ``MultiThreadedEventLoopGroup`` following the principle of Structured Concurrency.\n    /// The ``MultiThreadedEventLoopGroup`` is guaranteed to be shut down upon return, whether `body` throws or not.\n    ///\n    /// - Note: Outside of top-level code (typically in your main function) or tests, you should generally not use this function to create a new\n    ///         ``MultiThreadedEventLoopGroup`` because creating & destroying threads is expensive. Instead, share an existing one.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public static func withEventLoopGroup<Result>(\n        numberOfThreads: Int,\n        metricsDelegate: (any NIOEventLoopMetricsDelegate)? = nil,\n        isolation actor: isolated (any Actor)? = #isolation,\n        _ body: (MultiThreadedEventLoopGroup) async throws -> Result\n    ) async throws -> Result {\n        let group = MultiThreadedEventLoopGroup(\n            numberOfThreads: numberOfThreads,\n            canBeShutDown: .notByUser,  // We want to prevent direct user shutdowns.\n            metricsDelegate: metricsDelegate,\n            selectorFactory: NIOPosix.Selector<NIORegistration>.init\n        )\n        return try await asyncDo {\n            try await body(group)\n        } finally: { _ in\n            let q = DispatchQueue(label: \"MTELG.shutdown\")\n            let _: () = try await withCheckedThrowingContinuation { (cont) -> Void in\n                group._shutdownGracefully(queue: q, allowShuttingDownOverride: true) { error in\n                    if let error {\n                        cont.resume(throwing: error)\n                    } else {\n                        cont.resume()\n                    }\n                }\n            }\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/NIOPosixSendableMetatype.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if compiler(>=6.2)\npublic typealias _NIOPosixSendableMetatype = SendableMetatype\n#else\npublic typealias _NIOPosixSendableMetatype = Any\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/NIOThreadPool.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport DequeModule\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n#if canImport(Dispatch)\nimport Dispatch\n#endif\n\n/// Errors that may be thrown when executing work on a `NIOThreadPool`\npublic enum NIOThreadPoolError: Sendable {\n\n    /// The `NIOThreadPool` was not active.\n    public struct ThreadPoolInactive: Error {\n        public init() {}\n    }\n\n    /// The `NIOThreadPool` operation is unsupported (e.g. shutdown of a perpetual pool).\n    public struct UnsupportedOperation: Error {\n        public init() {}\n    }\n}\n\n/// A thread pool that should be used if some (kernel thread) blocking work\n/// needs to be performed for which no non-blocking API exists.\n///\n/// When using NIO it is crucial not to block any of the `EventLoop`s as that\n/// leads to slow downs or stalls of arbitrary other work. Unfortunately though\n/// there are tasks that applications need to achieve for which no non-blocking\n/// APIs exist. In those cases `NIOThreadPool` can be used but should be\n/// treated as a last resort.\n///\n/// - Note: The prime example for missing non-blocking APIs is file IO on UNIX.\n///   The OS does not provide a usable and truly non-blocking API but with\n///   `NonBlockingFileIO` NIO provides a high-level API for file IO that should\n///   be preferred to running blocking file IO system calls directly on\n///   `NIOThreadPool`. Under the covers `NonBlockingFileIO` will use\n///   `NIOThreadPool` on all currently supported platforms though.\npublic final class NIOThreadPool {\n\n    /// The state of the `WorkItem`.\n    public enum WorkItemState: Sendable {\n        /// The `WorkItem` is active now and in process by the `NIOThreadPool`.\n        case active\n        /// The `WorkItem` was cancelled and will not be processed by the `NIOThreadPool`.\n        case cancelled\n    }\n\n    /// The work that should be done by the `NIOThreadPool`.\n    public typealias WorkItem = @Sendable (WorkItemState) -> Void\n\n    @usableFromInline\n    struct IdentifiableWorkItem: Sendable {\n        @usableFromInline\n        var workItem: WorkItem\n\n        @usableFromInline\n        var id: Int?\n    }\n\n    @usableFromInline\n    internal enum State: Sendable {\n        /// The `NIOThreadPool` is already stopped.\n        case stopped\n        /// The `NIOThreadPool` is shutting down, the array has one boolean entry for each thread indicating if it has shut down already.\n        case shuttingDown([Bool])\n        /// The `NIOThreadPool` is up and running, the `Deque` containing the yet unprocessed `IdentifiableWorkItem`s.\n        case running(Deque<IdentifiableWorkItem>)\n        /// Temporary state used when mutating the .running(items). Used to avoid CoW copies.\n        /// It should never be \"leaked\" outside of the lock block.\n        case modifying\n    }\n\n    @usableFromInline\n    internal let _workAvailable: NIOThreadPoolWorkAvailable\n    private var threads: [NIOThread]? = nil  // protected by `_workAvailable`\n    @usableFromInline\n    internal var _state: State = .stopped\n\n    // WorkItems don't have a handle so they can't be cancelled directly. Instead an ID is assigned\n    // to each cancellable work item and the IDs of each work item to cancel is stored in this set.\n    // The set is checked when dequeuing work items prior to running them, the presence of an ID\n    // indicates it should be cancelled. This approach makes cancellation cheap, but slow, as the\n    // task isn't cancelled until it's dequeued.\n    //\n    // Possible alternatives:\n    // - Removing items from the work queue on cancellation. This is linear and runs the risk of\n    //   being expensive if a task tree with many enqueued work items is cancelled.\n    // - Storing an atomic 'is cancelled' flag with each work item. This adds an allocation per\n    //   work item.\n    //\n    // If a future version of this thread pool has work items which do have a handle this set should\n    // be removed.\n    //\n    // Note: protected by 'lock'.\n    @usableFromInline\n    internal var _cancelledWorkIDs: Set<Int> = []\n    private let nextWorkID = ManagedAtomic(0)\n\n    public let numberOfThreads: Int\n    private let canBeStopped: Bool\n\n    /// Gracefully shutdown this `NIOThreadPool`. All tasks will be run before shutdown will take place.\n    ///\n    /// - Parameters:\n    ///   - queue: The `DispatchQueue` used to executed the callback\n    ///   - callback: The function to be executed once the shutdown is complete.\n    @preconcurrency\n    public func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable (Error?) -> Void) {\n        self._shutdownGracefully(queue: queue, callback)\n    }\n\n    private func _shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable (Error?) -> Void) {\n        guard self.canBeStopped else {\n            queue.async {\n                callback(NIOThreadPoolError.UnsupportedOperation())\n            }\n            return\n        }\n\n        let threadsToJoin = self._workAvailable.withLockSettingWorkAvailable {\n            switch self._state {\n            case .running(let items):\n                self._state = .modifying\n                queue.async {\n                    for item in items {\n                        item.workItem(.cancelled)\n                    }\n                }\n                self._state = .shuttingDown(Array(repeating: true, count: self.numberOfThreads))\n\n                let threads = self.threads!\n                self.threads = nil\n\n                // Wake all threads so they can see .shuttingDown and exit.\n                return (workAvailable: self.numberOfThreads, signal: .broadcastAll, result: threads)\n\n            case .shuttingDown, .stopped:\n                // Don't modify workAvailable - threads may still be waking up to see .shuttingDown\n                return (workAvailable: nil, signal: .none, result: [])\n\n            case .modifying:\n                fatalError(\".modifying state misuse\")\n            }\n        }\n\n        DispatchQueue(label: \"io.swiftnio.NIOThreadPool.shutdownGracefully\").async {\n            for thread in threadsToJoin {\n                thread.join()\n            }\n            queue.async {\n                callback(nil)\n            }\n        }\n    }\n\n    /// Submit a `WorkItem` to process.\n    ///\n    /// - Note: This is a low-level method, in most cases the `runIfActive` method should be used.\n    ///\n    /// - Parameters:\n    ///   - body: The `WorkItem` to process by the `NIOThreadPool`.\n    @preconcurrency\n    public func submit(_ body: @escaping WorkItem) {\n        self._submit(id: nil, body)\n    }\n\n    private func _submit(id: Int?, _ body: @escaping WorkItem) {\n        let submitted = self._workAvailable.withLock {\n            let submitted: Bool\n\n            switch self._state {\n            case .running(var items):\n                self._state = .modifying\n                items.append(.init(workItem: body, id: id))\n                self._state = .running(items)\n                submitted = true\n\n            case .shuttingDown, .stopped:\n                submitted = false\n\n            case .modifying:\n                fatalError(\".modifying state misuse\")\n            }\n\n            return (workDelta: submitted ? 1 : 0, signal: submitted ? .signalOne : .none, result: submitted)\n        }\n\n        // if item couldn't be added run it immediately indicating that it couldn't be run\n        if !submitted {\n            body(.cancelled)\n        }\n    }\n\n    /// Initialize a `NIOThreadPool` thread pool with `numberOfThreads` threads.\n    ///\n    /// - Parameters:\n    ///   - numberOfThreads: The number of threads to use for the thread pool.\n    public convenience init(numberOfThreads: Int) {\n        self.init(numberOfThreads: numberOfThreads, canBeStopped: true)\n    }\n\n    /// Create a ``NIOThreadPool`` that is already started, cannot be shut down and must not be `deinit`ed.\n    ///\n    /// This is only useful for global singletons.\n    public static func _makePerpetualStartedPool(numberOfThreads: Int, threadNamePrefix: String) -> NIOThreadPool {\n        let pool = self.init(numberOfThreads: numberOfThreads, canBeStopped: false)\n        pool._start(threadNamePrefix: threadNamePrefix)\n        return pool\n    }\n\n    private init(numberOfThreads: Int, canBeStopped: Bool) {\n        self.numberOfThreads = numberOfThreads\n        self.canBeStopped = canBeStopped\n        self._workAvailable = NIOThreadPoolWorkAvailable()\n    }\n\n    // Do not rename or remove this function.\n    //\n    // When doing on-/off-CPU analysis, for example with continuous profiling, it's\n    // important to recognise certain functions that are purely there to wait.\n    //\n    // This function is one of those and giving it a consistent name makes it much easier to remove from the profiles\n    // when only interested in on-CPU work.\n    @inlinable\n    internal func _blockingWaitForWork(identifier: Int) -> (item: WorkItem, state: WorkItemState)? {\n        self._workAvailable.withLockWaitingForWork {\n            let result: (WorkItem, WorkItemState)?\n\n            switch self._state {\n            case .running(var items):\n                self._state = .modifying\n                let itemAndID = items.removeFirst()\n\n                let state: WorkItemState\n                if let id = itemAndID.id, !self._cancelledWorkIDs.isEmpty {\n                    state = self._cancelledWorkIDs.remove(id) == nil ? .active : .cancelled\n                } else {\n                    state = .active\n                }\n\n                self._state = .running(items)\n\n                result = (itemAndID.workItem, state)\n\n            case .shuttingDown(var aliveStates):\n                self._state = .modifying\n                assert(aliveStates[identifier])\n                aliveStates[identifier] = false\n                self._state = .shuttingDown(aliveStates)\n\n                result = nil\n\n            case .stopped:\n                // Unreachable: 'stopped' is the initial state which is left when starting the\n                // thread pool, and before any thread calls this function.\n                fatalError(\"Invalid state\")\n\n            case .modifying:\n                fatalError(\".modifying state misuse\")\n            }\n\n            return (workDelta: -1, signal: .none, result: result)\n        }\n    }\n\n    private func process(identifier: Int) {\n        repeat {\n            let itemAndState = self._blockingWaitForWork(identifier: identifier)\n\n            if let (item, state) = itemAndState {\n                // if there was a work item popped, run it\n                item(state)\n            } else {\n                break  // Otherwise, we're done\n            }\n        } while true\n    }\n\n    /// Start the `NIOThreadPool` if not already started.\n    public func start() {\n        self._start(threadNamePrefix: \"TP-#\")\n    }\n\n    public func _start(threadNamePrefix: String) {\n        let alreadyRunning = self._workAvailable.withLock {\n            switch self._state {\n            case .running:\n                // Already running, this has no effect on whether there is more work for the\n                // threads to run.\n                return (workDelta: 0, signal: .none, result: true)\n\n            case .shuttingDown:\n                // This should never happen\n                fatalError(\"start() called while in shuttingDown\")\n\n            case .stopped:\n                self._state = .running(Deque(minimumCapacity: 16))\n                assert(self.threads == nil)\n                self.threads = []\n                self.threads!.reserveCapacity(self.numberOfThreads)\n                return (workDelta: 0, signal: .none, result: false)\n\n            case .modifying:\n                fatalError(\".modifying state misuse\")\n            }\n        }\n\n        if alreadyRunning {\n            return\n        }\n\n        // We use this condition lock as a tricky kind of semaphore.\n        // This is done to sidestep the thread performance checker warning\n        // that would otherwise be emitted.\n        let readyThreads = ConditionLock(value: 0)\n        for id in 0..<self.numberOfThreads {\n            // We should keep thread names under 16 characters because Linux doesn't allow more.\n            NIOThread.spawnAndRun(name: \"\\(threadNamePrefix)\\(id)\") { thread in\n                readyThreads.withLock {\n                    let threadCount = self._workAvailable.withLock {\n                        self.threads!.append(thread)\n                        let threadCount = self.threads!.count\n                        return (workDelta: 0, signal: .none, result: threadCount)\n                    }\n\n                    return (unlockWith: threadCount, result: ())\n                }\n\n                self.process(identifier: id)\n                return ()\n            }\n        }\n\n        readyThreads.lock(whenValue: self.numberOfThreads)\n        readyThreads.unlock()\n\n        func threadCount() -> Int {\n            self._workAvailable.withLock {\n                (workDelta: 0, signal: .none, result: self.threads?.count ?? -1)\n            }\n        }\n        assert(threadCount() == self.numberOfThreads)\n    }\n\n    deinit {\n        assert(\n            self.canBeStopped,\n            \"Perpetual NIOThreadPool has been deinited, you must make sure that perpetual pools don't deinit\"\n        )\n        switch self._state {\n        case .stopped, .shuttingDown:\n            ()\n        default:\n            assertionFailure(\"wrong state \\(self._state)\")\n        }\n    }\n}\n\nextension NIOThreadPool: @unchecked Sendable {}\n\nextension NIOThreadPool {\n\n    /// Runs the submitted closure if the thread pool is still active, otherwise fails the promise.\n    /// The closure will be run on the thread pool so can do blocking work.\n    ///\n    /// - Parameters:\n    ///   - eventLoop: The `EventLoop` the returned `EventLoopFuture` will fire on.\n    ///   - body: The closure which performs some blocking work to be done on the thread pool.\n    /// - Returns: The `EventLoopFuture` of `promise` fulfilled with the result (or error) of the passed closure.\n    @preconcurrency\n    public func runIfActive<T: Sendable>(\n        eventLoop: EventLoop,\n        _ body: @escaping @Sendable () throws -> T\n    ) -> EventLoopFuture<T> {\n        self._runIfActive(eventLoop: eventLoop, body)\n    }\n\n    private func _runIfActive<T: Sendable>(\n        eventLoop: EventLoop,\n        _ body: @escaping @Sendable () throws -> T\n    ) -> EventLoopFuture<T> {\n        let promise = eventLoop.makePromise(of: T.self)\n        self.submit { shouldRun in\n            guard case shouldRun = NIOThreadPool.WorkItemState.active else {\n                promise.fail(NIOThreadPoolError.ThreadPoolInactive())\n                return\n            }\n            do {\n                try promise.succeed(body())\n            } catch {\n                promise.fail(error)\n            }\n        }\n        return promise.futureResult\n    }\n\n    /// Runs the submitted closure if the thread pool is still active, otherwise throw an error.\n    /// The closure will be run on the thread pool, such that we can do blocking work.\n    ///\n    /// - Parameters:\n    ///   - body: The closure which performs some blocking work to be done on the thread pool.\n    /// - Returns: Result of the passed closure.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func runIfActive<T: Sendable>(_ body: @escaping @Sendable () throws -> T) async throws -> T {\n        let workID = self.nextWorkID.loadThenWrappingIncrement(ordering: .relaxed)\n\n        return try await withTaskCancellationHandler {\n            try await withCheckedThrowingContinuation { (cont: CheckedContinuation<T, Error>) in\n                self._submit(id: workID) { shouldRun in\n                    switch shouldRun {\n                    case .active:\n                        let result = Result(catching: body)\n                        cont.resume(with: result)\n                    case .cancelled:\n                        cont.resume(throwing: CancellationError())\n                    }\n                }\n            }\n        } onCancel: {\n            self._workAvailable.withLock {\n                self._cancelledWorkIDs.insert(workID)\n                return (workDelta: 0, signal: .none, result: ())\n            }\n        }\n    }\n}\n\nextension NIOThreadPool {\n    @preconcurrency\n    public func shutdownGracefully(_ callback: @escaping @Sendable (Error?) -> Void) {\n        self.shutdownGracefully(queue: .global(), callback)\n    }\n\n    /// Shuts down the thread pool gracefully.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    @inlinable\n    public func shutdownGracefully() async throws {\n        try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in\n            self.shutdownGracefully { error in\n                if let error = error {\n                    cont.resume(throwing: error)\n                } else {\n                    cont.resume()\n                }\n            }\n        }\n    }\n\n    @available(*, noasync, message: \"this can end up blocking the calling thread\", renamed: \"shutdownGracefully()\")\n    public func syncShutdownGracefully() throws {\n        try self._syncShutdownGracefully()\n    }\n\n    private func _syncShutdownGracefully() throws {\n        let errorStorageLock = NIOLockedValueBox<Swift.Error?>(nil)\n        let continuation = ConditionLock(value: 0)\n        self.shutdownGracefully { error in\n            if let error = error {\n                errorStorageLock.withLockedValue {\n                    $0 = error\n                }\n            }\n            continuation.lock(whenValue: 0)\n            continuation.unlock(withValue: 1)\n        }\n        continuation.lock(whenValue: 1)\n        continuation.unlock()\n        try errorStorageLock.withLockedValue {\n            if let error = $0 {\n                throw error\n            }\n        }\n    }\n}\n\nextension ConditionLock {\n    @inlinable\n    func _lock(when value: T?) {\n        if let value = value {\n            self.lock(whenValue: value)\n        } else {\n            self.lock()\n        }\n    }\n\n    @inlinable\n    func _unlock(with value: T?) {\n        if let value = value {\n            self.unlock(withValue: value)\n        } else {\n            self.unlock()\n        }\n    }\n\n    @inlinable\n    func withLock<Result>(when value: T? = nil, _ body: () -> (unlockWith: T?, result: Result)) -> Result {\n        self._lock(when: value)\n        let (unlockValue, result) = body()\n        self._unlock(with: unlockValue)\n        return result\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/NonBlockingFileIO.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport CNIOLinux\nimport CNIOOpenBSD\nimport CNIOWindows\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n/// ``NonBlockingFileIO`` is a helper that allows you to read files without blocking the calling thread.\n///\n/// - warning: The `NonBlockingFileIO` API is deprecated, do not use going forward. It's not marked as `deprecated` yet such\n///            that users don't get the deprecation warnings affecting their APIs everywhere. For file I/O, please use\n///            the `NIOFileSystem` API.\n///\n/// It is worth noting that `kqueue`, `epoll` or `poll` returning claiming a file is readable does not mean that the\n/// data is already available in the kernel's memory. In other words, a `read` from a file can still block even if\n/// reported as readable. This behaviour is also documented behaviour:\n///\n///  - [`poll`](http://pubs.opengroup.org/onlinepubs/009695399/functions/poll.html): \"Regular files shall always poll TRUE for reading and writing.\"\n///  - [`epoll`](http://man7.org/linux/man-pages/man7/epoll.7.html): \"epoll is simply a faster poll(2), and can be used wherever the latter is used since it shares the same semantics.\"\n///  - [`kqueue`](https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2): \"Returns when the file pointer is not at the end of file.\"\n///\n/// ``NonBlockingFileIO`` helps to work around this issue by maintaining its own thread pool that is used to read the data\n/// from the files into memory. It will then hand the (in-memory) data back which makes it available without the possibility\n/// of blocking.\npublic struct NonBlockingFileIO: Sendable {\n    /// The default and recommended size for ``NonBlockingFileIO``'s thread pool.\n    @inlinable\n    public static var defaultThreadPoolSize: Int { 2 }\n\n    /// The default and recommended chunk size.\n    @inlinable\n    public static var defaultChunkSize: Int { 128 * 1024 }\n\n    /// ``NonBlockingFileIO`` errors.\n    public enum Error: Swift.Error {\n        /// ``NonBlockingFileIO`` is meant to be used with file descriptors that are set to the default (blocking) mode.\n        /// It doesn't make sense to use it with a file descriptor where `O_NONBLOCK` is set therefore this error is\n        /// raised when that was requested.\n        case descriptorSetToNonBlocking\n    }\n\n    private let threadPool: NIOThreadPool\n\n    /// Initialize a ``NonBlockingFileIO`` which uses the `NIOThreadPool`.\n    ///\n    /// - Parameters:\n    ///   - threadPool: The `NIOThreadPool` that will be used for all the IO.\n    public init(threadPool: NIOThreadPool) {\n        self.threadPool = threadPool\n    }\n\n    /// Read a `FileRegion` in chunks of `chunkSize` bytes on ``NonBlockingFileIO``'s private thread\n    /// pool which is separate from any `EventLoop` thread.\n    ///\n    /// `chunkHandler` will be called on `eventLoop` for every chunk that was read. Assuming `fileRegion.readableBytes` is greater than\n    /// zero and there are enough bytes available `chunkHandler` will be called `1 + |_ fileRegion.readableBytes / chunkSize _|`\n    /// times, delivering `chunkSize` bytes each time. If less than `fileRegion.readableBytes` bytes can be read from the file,\n    /// `chunkHandler` will be called less often with the last invocation possibly being of less than `chunkSize` bytes.\n    ///\n    /// The allocation and reading of a subsequent chunk will only be attempted when `chunkHandler` succeeds.\n    ///\n    /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the\n    /// same `FileRegion` in multiple threads.\n    ///\n    /// - Parameters:\n    ///   - fileRegion: The file region to read.\n    ///   - chunkSize: The size of the individual chunks to deliver.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the chunks.\n    ///   - eventLoop: The `EventLoop` to call `chunkHandler` on.\n    ///   - chunkHandler: Called for every chunk read. The next chunk will be read upon successful completion of the returned `EventLoopFuture`. If the returned `EventLoopFuture` fails, the overall operation is aborted.\n    /// - Returns: An `EventLoopFuture` which is the result of the overall operation. If either the reading of `fileHandle` or `chunkHandler` fails, the `EventLoopFuture` will fail too. If the reading of `fileHandle` as well as `chunkHandler` always succeeded, the `EventLoopFuture` will succeed too.\n    @preconcurrency\n    public func readChunked(\n        fileRegion: FileRegion,\n        chunkSize: Int = NonBlockingFileIO.defaultChunkSize,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop,\n        chunkHandler: @escaping @Sendable (ByteBuffer) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Void> {\n        let readableBytes = fileRegion.readableBytes\n        return self.readChunked(\n            fileHandle: fileRegion.fileHandle,\n            fromOffset: Int64(fileRegion.readerIndex),\n            byteCount: readableBytes,\n            chunkSize: chunkSize,\n            allocator: allocator,\n            eventLoop: eventLoop,\n            chunkHandler: chunkHandler\n        )\n    }\n\n    /// Read `byteCount` bytes in chunks of `chunkSize` bytes from `fileHandle` in ``NonBlockingFileIO``'s private thread\n    /// pool which is separate from any `EventLoop` thread.\n    ///\n    /// `chunkHandler` will be called on `eventLoop` for every chunk that was read. Assuming `byteCount` is greater than\n    /// zero and there are enough bytes available `chunkHandler` will be called `1 + |_ byteCount / chunkSize _|`\n    /// times, delivering `chunkSize` bytes each time. If less than `byteCount` bytes can be read from `descriptor`,\n    /// `chunkHandler` will be called less often with the last invocation possibly being of less than `chunkSize` bytes.\n    ///\n    /// The allocation and reading of a subsequent chunk will only be attempted when `chunkHandler` succeeds.\n    ///\n    /// - Note: `readChunked(fileRegion:chunkSize:allocator:eventLoop:chunkHandler:)` should be preferred as it uses\n    ///         `FileRegion` object instead of raw `NIOFileHandle`s. In case you do want to use raw `NIOFileHandle`s,\n    ///         please consider using `readChunked(fileHandle:fromOffset:chunkSize:allocator:eventLoop:chunkHandler:)`\n    ///         because it doesn't use the file descriptor's seek pointer (which may be shared with other file\n    ///         descriptors and even across processes.)\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read from.\n    ///   - byteCount: The number of bytes to read from `fileHandle`.\n    ///   - chunkSize: The size of the individual chunks to deliver.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the chunks.\n    ///   - eventLoop: The `EventLoop` to call `chunkHandler` on.\n    ///   - chunkHandler: Called for every chunk read. The next chunk will be read upon successful completion of the returned `EventLoopFuture`. If the returned `EventLoopFuture` fails, the overall operation is aborted.\n    /// - Returns: An `EventLoopFuture` which is the result of the overall operation. If either the reading of `fileHandle` or `chunkHandler` fails, the `EventLoopFuture` will fail too. If the reading of `fileHandle` as well as `chunkHandler` always succeeded, the `EventLoopFuture` will succeed too.\n    @preconcurrency\n    public func readChunked(\n        fileHandle: NIOFileHandle,\n        byteCount: Int,\n        chunkSize: Int = NonBlockingFileIO.defaultChunkSize,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop,\n        chunkHandler: @escaping @Sendable (ByteBuffer) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Void> {\n        self.readChunked0(\n            fileHandle: fileHandle,\n            fromOffset: nil,\n            byteCount: byteCount,\n            chunkSize: chunkSize,\n            allocator: allocator,\n            eventLoop: eventLoop,\n            chunkHandler: chunkHandler\n        )\n    }\n\n    /// Read `byteCount` bytes from offset `fileOffset` in chunks of `chunkSize` bytes from `fileHandle` in ``NonBlockingFileIO``'s private thread\n    /// pool which is separate from any `EventLoop` thread.\n    ///\n    /// `chunkHandler` will be called on `eventLoop` for every chunk that was read. Assuming `byteCount` is greater than\n    /// zero and there are enough bytes available `chunkHandler` will be called `1 + |_ byteCount / chunkSize _|`\n    /// times, delivering `chunkSize` bytes each time. If less than `byteCount` bytes can be read from `descriptor`,\n    /// `chunkHandler` will be called less often with the last invocation possibly being of less than `chunkSize` bytes.\n    ///\n    /// The allocation and reading of a subsequent chunk will only be attempted when `chunkHandler` succeeds.\n    ///\n    /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the\n    /// same `NIOFileHandle` in multiple threads.\n    ///\n    /// - Note: `readChunked(fileRegion:chunkSize:allocator:eventLoop:chunkHandler:)` should be preferred as it uses\n    ///         `FileRegion` object instead of raw `NIOFileHandle`s.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read from.\n    ///   - fileOffset: The offset into the file at which the read should begin.\n    ///   - byteCount: The number of bytes to read from `fileHandle`.\n    ///   - chunkSize: The size of the individual chunks to deliver.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the chunks.\n    ///   - eventLoop: The `EventLoop` to call `chunkHandler` on.\n    ///   - chunkHandler: Called for every chunk read. The next chunk will be read upon successful completion of the returned `EventLoopFuture`. If the returned `EventLoopFuture` fails, the overall operation is aborted.\n    /// - Returns: An `EventLoopFuture` which is the result of the overall operation. If either the reading of `fileHandle` or `chunkHandler` fails, the `EventLoopFuture` will fail too. If the reading of `fileHandle` as well as `chunkHandler` always succeeded, the `EventLoopFuture` will succeed too.\n    @preconcurrency\n    public func readChunked(\n        fileHandle: NIOFileHandle,\n        fromOffset fileOffset: Int64,\n        byteCount: Int,\n        chunkSize: Int = NonBlockingFileIO.defaultChunkSize,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop,\n        chunkHandler: @escaping @Sendable (ByteBuffer) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Void> {\n        self.readChunked0(\n            fileHandle: fileHandle,\n            fromOffset: fileOffset,\n            byteCount: byteCount,\n            chunkSize: chunkSize,\n            allocator: allocator,\n            eventLoop: eventLoop,\n            chunkHandler: chunkHandler\n        )\n    }\n\n    private typealias ReadChunkHandler = @Sendable (ByteBuffer) -> EventLoopFuture<Void>\n\n    private func readChunked0(\n        fileHandle: NIOFileHandle,\n        fromOffset: Int64?,\n        byteCount: Int,\n        chunkSize: Int,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop,\n        chunkHandler: @escaping ReadChunkHandler\n    ) -> EventLoopFuture<Void> {\n        precondition(chunkSize > 0, \"chunkSize must be > 0 (is \\(chunkSize))\")\n        let remainingReads = 1 + (byteCount / chunkSize)\n        let lastReadSize = byteCount % chunkSize\n\n        let promise = eventLoop.makePromise(of: Void.self)\n\n        @Sendable\n        func _read(remainingReads: Int, bytesReadSoFar: Int64) {\n            if remainingReads > 1 || (remainingReads == 1 && lastReadSize > 0) {\n                let readSize = remainingReads > 1 ? chunkSize : lastReadSize\n                assert(readSize > 0)\n                let readFuture = self.read0(\n                    fileHandle: fileHandle,\n                    fromOffset: fromOffset.map { $0 + bytesReadSoFar },\n                    byteCount: readSize,\n                    allocator: allocator,\n                    eventLoop: eventLoop\n                )\n                readFuture.whenComplete { (result) in\n                    switch result {\n                    case .success(let buffer):\n                        guard buffer.readableBytes > 0 else {\n                            // EOF, call `chunkHandler` one more time.\n                            let handlerFuture = chunkHandler(buffer)\n                            handlerFuture.cascade(to: promise)\n                            return\n                        }\n                        let bytesRead = Int64(buffer.readableBytes)\n                        chunkHandler(buffer).hop(to: eventLoop).whenComplete { result in\n                            switch result {\n                            case .success(_):\n                                eventLoop.assertInEventLoop()\n                                _read(\n                                    remainingReads: remainingReads - 1,\n                                    bytesReadSoFar: bytesReadSoFar + bytesRead\n                                )\n                            case .failure(let error):\n                                promise.fail(error)\n                            }\n                        }\n                    case .failure(let error):\n                        promise.fail(error)\n                    }\n                }\n            } else {\n                promise.succeed(())\n            }\n        }\n        _read(remainingReads: remainingReads, bytesReadSoFar: 0)\n\n        return promise.futureResult\n    }\n\n    /// Read a `FileRegion` in ``NonBlockingFileIO``'s private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// The returned `ByteBuffer` will not have less than `fileRegion.readableBytes` unless we hit end-of-file in which\n    /// case the `ByteBuffer` will contain the bytes available to read.\n    ///\n    /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the\n    /// same `FileRegion` in multiple threads.\n    ///\n    /// - Note: Only use this function for small enough `FileRegion`s as it will need to allocate enough memory to hold `fileRegion.readableBytes` bytes.\n    /// - Note: In most cases you should prefer one of the `readChunked` functions.\n    ///\n    /// - Parameters:\n    ///   - fileRegion: The file region to read.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the returned `ByteBuffer`.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which delivers a `ByteBuffer` if the read was successful or a failure on error.\n    public func read(\n        fileRegion: FileRegion,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<ByteBuffer> {\n        let readableBytes = fileRegion.readableBytes\n        return self.read(\n            fileHandle: fileRegion.fileHandle,\n            fromOffset: Int64(fileRegion.readerIndex),\n            byteCount: readableBytes,\n            allocator: allocator,\n            eventLoop: eventLoop\n        )\n    }\n\n    /// Read `byteCount` bytes from `fileHandle` in ``NonBlockingFileIO``'s private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// The returned `ByteBuffer` will not have less than `byteCount` bytes unless we hit end-of-file in which\n    /// case the `ByteBuffer` will contain the bytes available to read.\n    ///\n    /// - Note: Only use this function for small enough `byteCount`s as it will need to allocate enough memory to hold `byteCount` bytes.\n    /// - Note: ``read(fileRegion:allocator:eventLoop:)`` should be preferred as it uses `FileRegion` object instead of\n    ///         raw `NIOFileHandle`s. In case you do want to use raw `NIOFileHandle`s,\n    ///         please consider using ``read(fileHandle:fromOffset:byteCount:allocator:eventLoop:)``\n    ///         because it doesn't use the file descriptor's seek pointer (which may be shared with other file\n    ///         descriptors and even across processes.)\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read.\n    ///   - byteCount: The number of bytes to read from `fileHandle`.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the returned `ByteBuffer`.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which delivers a `ByteBuffer` if the read was successful or a failure on error.\n    public func read(\n        fileHandle: NIOFileHandle,\n        byteCount: Int,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<ByteBuffer> {\n        self.read0(\n            fileHandle: fileHandle,\n            fromOffset: nil,\n            byteCount: byteCount,\n            allocator: allocator,\n            eventLoop: eventLoop\n        )\n    }\n\n    /// Read `byteCount` bytes starting at `fileOffset` from `fileHandle` in ``NonBlockingFileIO``'s private thread pool\n    /// which is separate from any `EventLoop` thread.\n    ///\n    /// The returned `ByteBuffer` will not have less than `byteCount` bytes unless we hit end-of-file in which\n    /// case the `ByteBuffer` will contain the bytes available to read.\n    ///\n    /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the\n    /// same `fileHandle` in multiple threads.\n    ///\n    /// - Note: Only use this function for small enough `byteCount`s as it will need to allocate enough memory to hold `byteCount` bytes.\n    /// - Note: ``read(fileRegion:allocator:eventLoop:)`` should be preferred as it uses `FileRegion` object instead of raw `NIOFileHandle`s.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read.\n    ///   - fileOffset: The offset to read from.\n    ///   - byteCount: The number of bytes to read from `fileHandle`.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the returned `ByteBuffer`.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which delivers a `ByteBuffer` if the read was successful or a failure on error.\n    public func read(\n        fileHandle: NIOFileHandle,\n        fromOffset fileOffset: Int64,\n        byteCount: Int,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<ByteBuffer> {\n        self.read0(\n            fileHandle: fileHandle,\n            fromOffset: fileOffset,\n            byteCount: byteCount,\n            allocator: allocator,\n            eventLoop: eventLoop\n        )\n    }\n\n    private func read0(\n        fileHandle: NIOFileHandle,\n        fromOffset: Int64?,  // > 2 GB offset is reasonable on 32-bit systems\n        byteCount rawByteCount: Int,\n        allocator: ByteBufferAllocator,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<ByteBuffer> {\n        guard rawByteCount > 0 else {\n            return eventLoop.makeSucceededFuture(allocator.buffer(capacity: 0))\n        }\n        let byteCount = rawByteCount < Int32.max ? rawByteCount : size_t(Int32.max)\n\n        return self.threadPool.runIfActive(eventLoop: eventLoop) { () -> ByteBuffer in\n            try self.readSync(\n                fileHandle: fileHandle,\n                fromOffset: fromOffset,\n                byteCount: byteCount,\n                allocator: allocator\n            )\n        }\n    }\n\n    private func readSync(\n        fileHandle: NIOFileHandle,\n        fromOffset: Int64?,  // > 2 GB offset is reasonable on 32-bit systems\n        byteCount: Int,\n        allocator: ByteBufferAllocator\n    ) throws -> ByteBuffer {\n        var bytesRead = 0\n        var buf = allocator.buffer(capacity: byteCount)\n\n        while bytesRead < byteCount {\n            let n = try buf.writeWithUnsafeMutableBytes(minimumWritableBytes: byteCount - bytesRead) { ptr -> Int in\n                let res = try fileHandle.withUnsafeFileDescriptor { descriptor -> IOResult<ssize_t> in\n                    if let offset = fromOffset {\n                        #if !os(Windows)\n                        return try Posix.pread(\n                            descriptor: descriptor,\n                            pointer: ptr.baseAddress!,\n                            size: byteCount - bytesRead,\n                            offset: off_t(offset) + off_t(bytesRead)\n                        )\n                        #else\n                        return try Windows.pread(\n                            descriptor: descriptor,\n                            pointer: ptr.baseAddress!,\n                            size: byteCount - bytesRead,\n                            offset: off_t(offset) + off_t(bytesRead)\n                        )\n                        #endif\n                    }\n\n                    return try Posix.read(\n                        descriptor: descriptor,\n                        pointer: ptr.baseAddress!,\n                        size: byteCount - bytesRead\n                    )\n                }\n                switch res {\n                case .processed(let n):\n                    assert(n >= 0, \"read claims to have read a negative number of bytes \\(n)\")\n                    return numericCast(n)  // ssize_t is Int64 on Windows and Int everywhere else.\n                case .wouldBlock:\n                    throw Error.descriptorSetToNonBlocking\n                }\n            }\n            if n == 0 {\n                // EOF\n                break\n            } else {\n                bytesRead += n\n            }\n        }\n        return buf\n    }\n\n    /// Changes the file size of `fileHandle` to `size`.\n    ///\n    /// If `size` is smaller than the current file size, the remaining bytes will be truncated and are lost. If `size`\n    /// is larger than the current file size, the gap will be filled with zero bytes.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to write to.\n    ///   - size: The new file size in bytes to write.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the write was successful or fails on error.\n    public func changeFileSize(\n        fileHandle: NIOFileHandle,\n        size: Int64,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<()> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try fileHandle.withUnsafeFileDescriptor { descriptor -> Void in\n                try Posix.ftruncate(descriptor: descriptor, size: off_t(size))\n            }\n        }\n    }\n\n    /// Returns the length of the file in bytes associated with `fileHandle`.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read from.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which is fulfilled with the length of the file in bytes if the write was successful or fails on error.\n    public func readFileSize(\n        fileHandle: NIOFileHandle,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<Int64> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try fileHandle.withUnsafeFileDescriptor { descriptor in\n                let curr = try Posix.lseek(descriptor: descriptor, offset: 0, whence: SEEK_CUR)\n                let eof = try Posix.lseek(descriptor: descriptor, offset: 0, whence: SEEK_END)\n                try Posix.lseek(descriptor: descriptor, offset: curr, whence: SEEK_SET)\n                return Int64(eof)\n            }\n        }\n    }\n\n    /// Write `buffer` to `fileHandle` in ``NonBlockingFileIO``'s private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to write to.\n    ///   - buffer: The `ByteBuffer` to write.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the write was successful or fails on error.\n    public func write(\n        fileHandle: NIOFileHandle,\n        buffer: ByteBuffer,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<()> {\n        self.write0(fileHandle: fileHandle, toOffset: nil, buffer: buffer, eventLoop: eventLoop)\n    }\n\n    /// Write `buffer` starting from `toOffset` to `fileHandle` in ``NonBlockingFileIO``'s private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to write to.\n    ///   - toOffset: The file offset to write to.\n    ///   - buffer: The `ByteBuffer` to write.\n    ///   - eventLoop: The `EventLoop` to create the returned `EventLoopFuture` from.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the write was successful or fails on error.\n    public func write(\n        fileHandle: NIOFileHandle,\n        toOffset: Int64,\n        buffer: ByteBuffer,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<()> {\n        self.write0(fileHandle: fileHandle, toOffset: toOffset, buffer: buffer, eventLoop: eventLoop)\n    }\n\n    private func write0(\n        fileHandle: NIOFileHandle,\n        toOffset: Int64?,\n        buffer: ByteBuffer,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<()> {\n        let byteCount = buffer.readableBytes\n\n        guard byteCount > 0 else {\n            return eventLoop.makeSucceededFuture(())\n        }\n\n        return self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try self.writeSync(fileHandle: fileHandle, byteCount: byteCount, toOffset: toOffset, buffer: buffer)\n        }\n    }\n\n    private func writeSync(\n        fileHandle: NIOFileHandle,\n        byteCount: Int,\n        toOffset: Int64?,\n        buffer: ByteBuffer\n    ) throws {\n        var buf = buffer\n\n        var offsetAccumulator: Int = 0\n        repeat {\n            let n = try buf.readWithUnsafeReadableBytes { ptr in\n                precondition(ptr.count == byteCount - offsetAccumulator)\n                let res: IOResult<ssize_t> = try fileHandle.withUnsafeFileDescriptor { descriptor in\n                    if let toOffset = toOffset {\n                        #if os(Windows)\n                        return try Windows.pwrite(\n                            descriptor: descriptor,\n                            pointer: ptr.baseAddress!,\n                            size: byteCount - offsetAccumulator,\n                            offset: off_t(toOffset + Int64(offsetAccumulator))\n                        )\n                        #else\n                        return try Posix.pwrite(\n                            descriptor: descriptor,\n                            pointer: ptr.baseAddress!,\n                            size: byteCount - offsetAccumulator,\n                            offset: off_t(toOffset + Int64(offsetAccumulator))\n                        )\n                        #endif\n                    } else {\n                        let result = try Posix.write(\n                            descriptor: descriptor,\n                            pointer: ptr.baseAddress!,\n                            size: byteCount - offsetAccumulator\n                        )\n                        #if os(Windows)\n                        return result.map { ssize_t($0) }\n                        #else\n                        return result\n                        #endif\n                    }\n                }\n                switch res {\n                case .processed(let n):\n                    assert(n >= 0, \"write claims to have written a negative number of bytes \\(n)\")\n                    return numericCast(n)\n                case .wouldBlock:\n                    throw Error.descriptorSetToNonBlocking\n                }\n            }\n            offsetAccumulator += n\n        } while offsetAccumulator < byteCount\n    }\n\n    /// Open the file at `path` for reading on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// This function will return (a future) of the `NIOFileHandle` associated with the file opened and a `FileRegion`\n    /// comprising of the whole file. The caller must close the returned `NIOFileHandle` when it's no longer needed.\n    ///\n    /// - Note: The reason this returns the `NIOFileHandle` and the `FileRegion` is that both the opening of a file as well as the querying of its size are blocking.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be opened for reading.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing the `NIOFileHandle` and the `FileRegion` comprising the whole file.\n    @available(\n        *,\n        deprecated,\n        message:\n            \"Avoid using NIOFileHandle. The type is difficult to hold correctly, use NIOFileSystem as a replacement API.\"\n    )\n    public func openFile(path: String, eventLoop: EventLoop) -> EventLoopFuture<(NIOFileHandle, FileRegion)> {\n        self.openFile(_deprecatedPath: path, eventLoop: eventLoop)\n    }\n\n    /// Open the file at `path` for reading on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// This function will return (a future) of the `NIOFileHandle` associated with the file opened and a `FileRegion`\n    /// comprising of the whole file. The caller must close the returned `NIOFileHandle` when it's no longer needed.\n    ///\n    /// - Note: The reason this returns the `NIOFileHandle` and the `FileRegion` is that both the opening of a file as well as the querying of its size are blocking.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be opened for reading.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing the `NIOFileHandle` and the `FileRegion` comprising the whole file.\n    public func openFile(\n        _deprecatedPath path: String,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<(NIOFileHandle, FileRegion)> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            let fh = try NIOFileHandle(_deprecatedPath: path)\n            do {\n                let fr = try FileRegion(fileHandle: fh)\n                return (fh, fr)\n            } catch {\n                _ = try? fh.close()\n                throw error\n            }\n        }\n    }\n\n    /// Open the file at `path` with specified access mode and POSIX flags on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// This function will return (a future) of the `NIOFileHandle` associated with the file opened.\n    /// The caller must close the returned `NIOFileHandle` when it's no longer needed.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be opened for writing.\n    ///   - mode: File access mode.\n    ///   - flags: Additional POSIX flags.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing the `NIOFileHandle`.\n    @available(\n        *,\n        deprecated,\n        message:\n            \"Avoid using NonBlockingFileIO. The type is difficult to hold correctly, use NIOFileSystem as a replacement API.\"\n    )\n    public func openFile(\n        path: String,\n        mode: NIOFileHandle.Mode,\n        flags: NIOFileHandle.Flags = .default,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<NIOFileHandle> {\n        self.openFile(_deprecatedPath: path, mode: mode, flags: flags, eventLoop: eventLoop)\n    }\n\n    /// Open the file at `path` with specified access mode and POSIX flags on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// This function will return (a future) of the `NIOFileHandle` associated with the file opened.\n    /// The caller must close the returned `NIOFileHandle` when it's no longer needed.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be opened for writing.\n    ///   - mode: File access mode.\n    ///   - flags: Additional POSIX flags.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing the `NIOFileHandle`.\n    public func openFile(\n        _deprecatedPath path: String,\n        mode: NIOFileHandle.Mode,\n        flags: NIOFileHandle.Flags = .default,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<NIOFileHandle> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try NIOFileHandle(_deprecatedPath: path, mode: mode, flags: flags)\n        }\n    }\n\n    #if !os(Windows)\n    /// Returns information about a file at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Note: If `path` is a symlink, information about the link, not the file it points to.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to get information about.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing file information.\n    public func lstat(path: String, eventLoop: EventLoop) -> EventLoopFuture<stat> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            var s = stat()\n            try Posix.lstat(pathname: path, outStat: &s)\n            return s\n        }\n    }\n\n    /// Creates a symbolic link to a  `destination` file  at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the link.\n    ///   - destination: Target path where this link will point to.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the rename was successful or fails on error.\n    public func symlink(path: String, to destination: String, eventLoop: EventLoop) -> EventLoopFuture<Void> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try Posix.symlink(pathname: path, destination: destination)\n        }\n    }\n\n    /// Returns target of the symbolic link at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the link to read.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing link target.\n    public func readlink(path: String, eventLoop: EventLoop) -> EventLoopFuture<String> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            let maxLength = Int(PATH_MAX)\n            let pointer = UnsafeMutableBufferPointer<CChar>.allocate(capacity: maxLength)\n            defer {\n                pointer.deallocate()\n            }\n            let length = try Posix.readlink(pathname: path, outPath: pointer.baseAddress!, outPathSize: maxLength)\n            return String(decoding: UnsafeRawBufferPointer(pointer).prefix(length), as: UTF8.self)\n        }\n    }\n\n    /// Removes symbolic link at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the link to remove.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the rename was successful or fails on error.\n    public func unlink(path: String, eventLoop: EventLoop) -> EventLoopFuture<Void> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try Posix.unlink(pathname: path)\n        }\n    }\n\n    private func createDirectory0(_ path: String, mode: NIOPOSIXFileMode) throws {\n        let pathView = path.utf8\n        if pathView.isEmpty {\n            return\n        }\n\n        // Fail fast if not a directory or file exists\n        do {\n            var s = stat()\n            try Posix.stat(pathname: path, outStat: &s)\n            if (S_IFMT & s.st_mode) == S_IFDIR {\n                return\n            }\n            throw IOError(errnoCode: ENOTDIR, reason: \"Not a directory\")\n        } catch let error as IOError where error.errnoCode == ENOENT {\n            // if directory does not exist we can proceed with creating it\n        }\n\n        // Slow path, check that all intermediate directories exist recursively\n\n        // Trim any trailing path separators\n        var index = pathView.index(before: pathView.endIndex)\n        let pathSeparator = UInt8(ascii: \"/\")\n        while index != pathView.startIndex && pathView[index] == pathSeparator {\n            index = pathView.index(before: index)\n        }\n\n        // Find first non-trailing path separator if it exists\n        while index != pathView.startIndex && pathView[index] != pathSeparator {\n            index = pathView.index(before: index)\n        }\n\n        // If non-trailing path separator is found, create parent directory\n        if index > pathView.startIndex {\n            try self.createDirectory0(String(Substring(pathView.prefix(upTo: index))), mode: mode)\n        }\n\n        do {\n            try Posix.mkdir(pathname: path, mode: mode)\n        } catch {\n            // If user tries to create a path like `/some/path/.` it may fail, as path will be created\n            // by the recursive call. Checks if directory exists and re-throw the error if it does not\n            do {\n                var s = stat()\n                try Posix.lstat(pathname: path, outStat: &s)\n                if (S_IFMT & s.st_mode) == S_IFDIR {\n                    return\n                }\n            } catch {\n                // fallthrough\n            }\n            throw error\n        }\n    }\n\n    /// Creates directory at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to be created.\n    ///   - createIntermediates: Whether intermediate directories should be created.\n    ///   - mode: POSIX file mode.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the rename was successful or fails on error.\n    public func createDirectory(\n        path: String,\n        withIntermediateDirectories createIntermediates: Bool = false,\n        mode: NIOPOSIXFileMode,\n        eventLoop: EventLoop\n    ) -> EventLoopFuture<Void> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            if createIntermediates {\n                #if canImport(Darwin)\n                try Posix.mkpath_np(pathname: path, mode: mode)\n                #else\n                try self.createDirectory0(path, mode: mode)\n                #endif\n            } else {\n                try Posix.mkdir(pathname: path, mode: mode)\n            }\n        }\n    }\n\n    /// List contents of the directory at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to list the content of.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` containing the directory entries.\n    public func listDirectory(path: String, eventLoop: EventLoop) -> EventLoopFuture<[NIODirectoryEntry]> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            let dir = try Posix.opendir(pathname: path)\n            var entries: [NIODirectoryEntry] = []\n            do {\n                while let entry = try Posix.readdir(dir: dir) {\n                    let name = withUnsafeBytes(of: entry.pointee.d_name) { pointer -> String in\n                        let ptr = pointer.baseAddress!.assumingMemoryBound(to: CChar.self)\n                        return String(cString: ptr)\n                    }\n                    #if os(OpenBSD)\n                    let ino = entry.pointee.d_fileno\n                    #else\n                    let ino = entry.pointee.d_ino\n                    #endif\n                    entries.append(\n                        NIODirectoryEntry(ino: UInt64(ino), type: entry.pointee.d_type, name: name)\n                    )\n                }\n                try? Posix.closedir(dir: dir)\n            } catch {\n                try? Posix.closedir(dir: dir)\n                throw error\n            }\n            return entries\n        }\n    }\n\n    /// Renames the file at `path` to `newName` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be renamed.\n    ///   - newName: New file name.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the rename was successful or fails on error.\n    public func rename(path: String, newName: String, eventLoop: EventLoop) -> EventLoopFuture<Void> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try Posix.rename(pathname: path, newName: newName)\n        }\n    }\n\n    /// Removes the file at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be removed.\n    ///   - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.\n    /// - Returns: An `EventLoopFuture` which is fulfilled if the remove was successful or fails on error.\n    public func remove(path: String, eventLoop: EventLoop) -> EventLoopFuture<Void> {\n        self.threadPool.runIfActive(eventLoop: eventLoop) {\n            try Posix.remove(pathname: path)\n        }\n    }\n    #endif\n}\n\n#if !os(Windows)\n/// A `NIODirectoryEntry` represents a single directory entry.\npublic struct NIODirectoryEntry: Hashable, Sendable {\n    // File number of entry\n    public var ino: UInt64\n    // File type\n    public var type: UInt8\n    // File name\n    public var name: String\n\n    public init(ino: UInt64, type: UInt8, name: String) {\n        self.ino = ino\n        self.type = type\n        self.name = name\n    }\n}\n#endif\n\nextension NonBlockingFileIO {\n    /// Read a `FileRegion` in ``NonBlockingFileIO``'s private thread pool.\n    ///\n    /// The returned `ByteBuffer` will not have less than the minimum of `fileRegion.readableBytes` and `UInt32.max` unless we hit\n    /// end-of-file in which case the `ByteBuffer` will contain the bytes available to read.\n    ///\n    /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the\n    /// same `FileRegion` in multiple threads.\n    ///\n    /// - Note: Only use this function for small enough `FileRegion`s as it will need to allocate enough memory to hold `fileRegion.readableBytes` bytes.\n    /// - Note: In most cases you should prefer one of the `readChunked` functions.\n    ///\n    /// - Parameters:\n    ///   - fileRegion: The file region to read.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the returned `ByteBuffer`.\n    /// - Returns: ByteBuffer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func read(fileRegion: FileRegion, allocator: ByteBufferAllocator) async throws -> ByteBuffer {\n        let readableBytes = fileRegion.readableBytes\n        return try await self.read(\n            fileHandle: fileRegion.fileHandle,\n            fromOffset: Int64(fileRegion.readerIndex),\n            byteCount: readableBytes,\n            allocator: allocator\n        )\n    }\n\n    /// Read `byteCount` bytes from `fileHandle` in ``NonBlockingFileIO``'s private thread pool.\n    ///\n    /// The returned `ByteBuffer` will not have less than `byteCount` bytes unless we hit end-of-file in which\n    /// case the `ByteBuffer` will contain the bytes available to read.\n    ///\n    /// - Note: Only use this function for small enough `byteCount`s as it will need to allocate enough memory to hold `byteCount` bytes.\n    /// - Note: ``read(fileRegion:allocator:eventLoop:)`` should be preferred as it uses `FileRegion` object instead of\n    ///         raw `NIOFileHandle`s. In case you do want to use raw `NIOFileHandle`s,\n    ///         please consider using ``read(fileHandle:fromOffset:byteCount:allocator:eventLoop:)``\n    ///         because it doesn't use the file descriptor's seek pointer (which may be shared with other file\n    ///         descriptors and even across processes.)\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read.\n    ///   - byteCount: The number of bytes to read from `fileHandle`.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the returned `ByteBuffer`.\n    /// - Returns: ByteBuffer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func read(\n        fileHandle: NIOFileHandle,\n        byteCount: Int,\n        allocator: ByteBufferAllocator\n    ) async throws -> ByteBuffer {\n        try await self.read0(\n            fileHandle: fileHandle,\n            fromOffset: nil,\n            byteCount: byteCount,\n            allocator: allocator\n        )\n    }\n\n    /// Read `byteCount` bytes starting at `fileOffset` from `fileHandle` in ``NonBlockingFileIO``'s private thread pool\n    ///.\n    ///\n    /// The returned `ByteBuffer` will not have less than `byteCount` bytes unless we hit end-of-file in which\n    /// case the `ByteBuffer` will contain the bytes available to read.\n    ///\n    /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the\n    /// same `fileHandle` in multiple threads.\n    ///\n    /// - Note: Only use this function for small enough `byteCount`s as it will need to allocate enough memory to hold `byteCount` bytes.\n    /// - Note: ``read(fileRegion:allocator:eventLoop:)`` should be preferred as it uses `FileRegion` object instead of raw `NIOFileHandle`s.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read.\n    ///   - fileOffset: The offset to read from.\n    ///   - byteCount: The number of bytes to read from `fileHandle`.\n    ///   - allocator: A `ByteBufferAllocator` used to allocate space for the returned `ByteBuffer`.\n    /// - Returns: ByteBuffer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func read(\n        fileHandle: NIOFileHandle,\n        fromOffset fileOffset: Int64,\n        byteCount: Int,\n        allocator: ByteBufferAllocator\n    ) async throws -> ByteBuffer {\n        try await self.read0(\n            fileHandle: fileHandle,\n            fromOffset: fileOffset,\n            byteCount: byteCount,\n            allocator: allocator\n        )\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func read0(\n        fileHandle: NIOFileHandle,\n        fromOffset: Int64?,  // > 2 GB offset is reasonable on 32-bit systems\n        byteCount rawByteCount: Int,\n        allocator: ByteBufferAllocator\n    ) async throws -> ByteBuffer {\n        guard rawByteCount > 0 else {\n            return allocator.buffer(capacity: 0)\n        }\n        let byteCount = rawByteCount < Int32.max ? rawByteCount : size_t(Int32.max)\n\n        return try await self.threadPool.runIfActive { () -> ByteBuffer in\n            try self.readSync(\n                fileHandle: fileHandle,\n                fromOffset: fromOffset,\n                byteCount: byteCount,\n                allocator: allocator\n            )\n        }\n    }\n\n    /// Changes the file size of `fileHandle` to `size`.\n    ///\n    /// If `size` is smaller than the current file size, the remaining bytes will be truncated and are lost. If `size`\n    /// is larger than the current file size, the gap will be filled with zero bytes.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to write to.\n    ///   - size: The new file size in bytes to write.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func changeFileSize(\n        fileHandle: NIOFileHandle,\n        size: Int64\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try fileHandle.withUnsafeFileDescriptor { descriptor -> Void in\n                try Posix.ftruncate(descriptor: descriptor, size: off_t(size))\n            }\n        }\n    }\n\n    /// Returns the length of the file associated with `fileHandle`.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to read from.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func readFileSize(fileHandle: NIOFileHandle) async throws -> Int64 {\n        try await self.threadPool.runIfActive {\n            try fileHandle.withUnsafeFileDescriptor { descriptor in\n                let curr = try Posix.lseek(descriptor: descriptor, offset: 0, whence: SEEK_CUR)\n                let eof = try Posix.lseek(descriptor: descriptor, offset: 0, whence: SEEK_END)\n                try Posix.lseek(descriptor: descriptor, offset: curr, whence: SEEK_SET)\n                return Int64(eof)\n            }\n        }\n    }\n\n    /// Write `buffer` to `fileHandle` in ``NonBlockingFileIO``'s private thread pool.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to write to.\n    ///   - buffer: The `ByteBuffer` to write.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func write(\n        fileHandle: NIOFileHandle,\n        buffer: ByteBuffer\n    ) async throws {\n        try await self.write0(fileHandle: fileHandle, toOffset: nil, buffer: buffer)\n    }\n\n    /// Write `buffer` starting from `toOffset` to `fileHandle` in ``NonBlockingFileIO``'s private thread pool.\n    ///\n    /// - Parameters:\n    ///   - fileHandle: The `NIOFileHandle` to write to.\n    ///   - toOffset: The file offset to write to.\n    ///   - buffer: The `ByteBuffer` to write.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func write(\n        fileHandle: NIOFileHandle,\n        toOffset: Int64,\n        buffer: ByteBuffer\n    ) async throws {\n        try await self.write0(fileHandle: fileHandle, toOffset: toOffset, buffer: buffer)\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func write0(\n        fileHandle: NIOFileHandle,\n        toOffset: Int64?,\n        buffer: ByteBuffer\n    ) async throws {\n        let byteCount = buffer.readableBytes\n\n        guard byteCount > 0 else {\n            return\n        }\n\n        return try await self.threadPool.runIfActive {\n            try self.writeSync(fileHandle: fileHandle, byteCount: byteCount, toOffset: toOffset, buffer: buffer)\n        }\n    }\n\n    /// Open file at `path` and query its size on a private thread pool, run an operation given\n    /// the resulting file region and then close the file handle.\n    ///\n    /// The will return the result of the operation.\n    ///\n    /// - Note: This function opens a file and queries it size which are both blocking operations\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be opened for reading.\n    ///   - body: operation to run with file handle and region\n    /// - Returns: return value of operation\n    @available(\n        *,\n        deprecated,\n        message:\n            \"Avoid using NonBlockingFileIO. The API is difficult to hold correctly, use NIOFileSystem as a replacement API.\"\n    )\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withFileRegion<Result>(\n        path: String,\n        _ body: (_ fileRegion: FileRegion) async throws -> Result\n    ) async throws -> Result {\n        try await self.withFileRegion(_deprecatedPath: path, body)\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withFileRegion<Result>(\n        _deprecatedPath path: String,\n        _ body: (_ fileRegion: FileRegion) async throws -> Result\n    ) async throws -> Result {\n        let fileRegion = try await self.threadPool.runIfActive {\n            let fh = try NIOFileHandle(_deprecatedPath: path)\n            do {\n                return try FileRegion(fileHandle: fh)\n            } catch {\n                _ = try? fh.close()\n                throw error\n            }\n        }\n        let result: Result\n        do {\n            result = try await body(fileRegion)\n        } catch {\n            try fileRegion.fileHandle.close()\n            throw error\n        }\n        try fileRegion.fileHandle.close()\n        return result\n    }\n\n    /// Open file at `path` on a private thread pool, run an operation given the file handle and then close the file handle.\n    ///\n    /// This function will return the result of the operation.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be opened for writing.\n    ///   - mode: File access mode.\n    ///   - flags: Additional POSIX flags.\n    ///   - body: operation to run with the file handle\n    /// - Returns: return value of operation\n    @available(\n        *,\n        deprecated,\n        message:\n            \"Avoid using NonBlockingFileIO. The API is difficult to hold correctly, use NIOFileSystem as a replacement API.\"\n    )\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withFileHandle<Result>(\n        path: String,\n        mode: NIOFileHandle.Mode,\n        flags: NIOFileHandle.Flags = .default,\n        _ body: (NIOFileHandle) async throws -> Result\n    ) async throws -> Result {\n        try await self.withFileHandle(_deprecatedPath: path, mode: mode, flags: flags, body)\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withFileHandle<Result>(\n        _deprecatedPath path: String,\n        mode: NIOFileHandle.Mode,\n        flags: NIOFileHandle.Flags = .default,\n        _ body: (NIOFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let fileHandle = try await self.threadPool.runIfActive {\n            try NIOFileHandle(_deprecatedPath: path, mode: mode, flags: flags)\n        }\n        let result: Result\n        do {\n            result = try await body(fileHandle)\n        } catch {\n            try fileHandle.close()\n            throw error\n        }\n        try fileHandle.close()\n        return result\n    }\n\n    #if !os(Windows)\n\n    /// Returns information about a file at `path` on a private thread pool.\n    ///\n    /// - Note: If `path` is a symlink, information about the link, not the file it points to.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to get information about.\n    /// - Returns: file information.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func lstat(path: String) async throws -> stat {\n        try await self.threadPool.runIfActive {\n            var s = stat()\n            try Posix.lstat(pathname: path, outStat: &s)\n            return s\n        }\n    }\n\n    /// Creates a symbolic link to a  `destination` file  at `path` on a private thread pool.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the link.\n    ///   - destination: Target path where this link will point to.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func symlink(path: String, to destination: String) async throws {\n        try await self.threadPool.runIfActive {\n            try Posix.symlink(pathname: path, destination: destination)\n        }\n    }\n\n    /// Returns target of the symbolic link at `path` on a private thread pool.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the link to read.\n    /// - Returns: link target.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func readlink(path: String) async throws -> String {\n        try await self.threadPool.runIfActive {\n            let maxLength = Int(PATH_MAX)\n            let pointer = UnsafeMutableBufferPointer<CChar>.allocate(capacity: maxLength)\n            defer {\n                pointer.deallocate()\n            }\n            let length = try Posix.readlink(pathname: path, outPath: pointer.baseAddress!, outPathSize: maxLength)\n            return String(decoding: UnsafeRawBufferPointer(pointer).prefix(length), as: UTF8.self)\n        }\n    }\n\n    /// Removes symbolic link at `path` on a private thread pool which is separate from any `EventLoop` thread.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the link to remove.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func unlink(path: String) async throws {\n        try await self.threadPool.runIfActive {\n            try Posix.unlink(pathname: path)\n        }\n    }\n\n    /// Creates directory at `path` on a private thread pool.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to be created.\n    ///   - createIntermediates: Whether intermediate directories should be created.\n    ///   - mode: POSIX file mode.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func createDirectory(\n        path: String,\n        withIntermediateDirectories createIntermediates: Bool = false,\n        mode: NIOPOSIXFileMode\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            if createIntermediates {\n                #if canImport(Darwin)\n                try Posix.mkpath_np(pathname: path, mode: mode)\n                #else\n                try self.createDirectory0(path, mode: mode)\n                #endif\n            } else {\n                try Posix.mkdir(pathname: path, mode: mode)\n            }\n        }\n    }\n\n    /// List contents of the directory at `path` on a private thread pool.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to list the content of.\n    /// - Returns: The directory entries.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func listDirectory(path: String) async throws -> [NIODirectoryEntry] {\n        try await self.threadPool.runIfActive {\n            let dir = try Posix.opendir(pathname: path)\n            var entries: [NIODirectoryEntry] = []\n            do {\n                while let entry = try Posix.readdir(dir: dir) {\n                    let name = withUnsafeBytes(of: entry.pointee.d_name) { pointer -> String in\n                        let ptr = pointer.baseAddress!.assumingMemoryBound(to: CChar.self)\n                        return String(cString: ptr)\n                    }\n                    #if os(OpenBSD)\n                    let ino = entry.pointee.d_fileno\n                    #else\n                    let ino = entry.pointee.d_ino\n                    #endif\n                    entries.append(\n                        NIODirectoryEntry(ino: UInt64(ino), type: entry.pointee.d_type, name: name)\n                    )\n                }\n                try? Posix.closedir(dir: dir)\n            } catch {\n                try? Posix.closedir(dir: dir)\n                throw error\n            }\n            return entries\n        }\n    }\n\n    /// Renames the file at `path` to `newName` on a private thread pool.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be renamed.\n    ///   - newName: New file name.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func rename(path: String, newName: String) async throws {\n        try await self.threadPool.runIfActive {\n            try Posix.rename(pathname: path, newName: newName)\n        }\n    }\n\n    /// Removes the file at `path` on a private thread pool.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to be removed.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func remove(path: String) async throws {\n        try await self.threadPool.runIfActive {\n            try Posix.remove(pathname: path)\n        }\n    }\n    #endif\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PendingDatagramWritesManager.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport CNIODarwin\nimport CNIOLinux\nimport CNIOOpenBSD\nimport CNIOWindows\nimport NIOCore\n\n#if canImport(WinSDK)\nimport struct WinSDK.socklen_t\n#endif\n\nprivate struct PendingDatagramWrite {\n    var data: ByteBuffer\n    var promise: Optional<EventLoopPromise<Void>>\n    let address: SocketAddress?\n    var metadata: AddressedEnvelope<ByteBuffer>.Metadata?\n\n    /// A helper function that copies the underlying sockaddr structure into temporary storage,\n    /// and then returns the length.\n    ///\n    /// This copying is an annoyance, but one way or another this copy will have to happen as\n    /// we do not want to expose the backing socket address to libc in case it mutates it. Because\n    /// we are using a box to store the underlying sockaddr, if libc ever did mess with that data\n    /// it will screw any other values pointing to that box. That would be a pretty bad scene. And\n    /// in most cases we're not copying large values here: only for UDS does this become a problem.\n    func copySocketAddress(_ target: UnsafeMutablePointer<sockaddr_storage>) -> socklen_t {\n        let erased = UnsafeMutableRawPointer(target)\n\n        switch self.address {\n        case .none:\n            preconditionFailure(\"copySocketAddress called on write that has no address\")\n        case .v4(let innerAddress):\n            erased.storeBytes(of: innerAddress.address, as: sockaddr_in.self)\n            return socklen_t(MemoryLayout.size(ofValue: innerAddress.address))\n        case .v6(let innerAddress):\n            erased.storeBytes(of: innerAddress.address, as: sockaddr_in6.self)\n            return socklen_t(MemoryLayout.size(ofValue: innerAddress.address))\n        case .unixDomainSocket:\n            fatalError(\"UDS with datagrams is currently not supported\")\n        }\n    }\n}\n\nextension Error {\n    /// Returns whether the error is \"recoverable\" from the perspective of datagram sending.\n    ///\n    /// - Returns: `true` if the error is recoverable, `false` otherwise.\n    fileprivate var isRecoverable: Bool {\n        switch self {\n        case let e as IOError where e.errnoCode == EMSGSIZE,\n            let e as IOError where e.errnoCode == EHOSTUNREACH:\n            return true\n        default:\n            return false\n        }\n    }\n}\n\n/// Does the setup required to trigger a `sendmmsg`.\nprivate func doPendingDatagramWriteVectorOperation(\n    pending: PendingDatagramWritesState,\n    bufferPool: Pool<PooledBuffer>,\n    msgs: UnsafeMutableBufferPointer<MMsgHdr>,\n    addresses: UnsafeMutableBufferPointer<sockaddr_storage>,\n    controlMessageStorage: UnsafeControlMessageStorage,\n    _ body: (UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>\n) throws -> IOResult<Int> {\n    assert(msgs.count >= Socket.writevLimitIOVectors, \"Insufficiently sized buffer for a maximal sendmmsg\")\n    assert(\n        controlMessageStorage.count >= Socket.writevLimitIOVectors,\n        \"Insufficiently sized control message storage for a maximal sendmmsg\"\n    )\n\n    // the numbers of storage refs that we need to decrease later.\n    var c = 0\n    var toWrite: Int = 0\n\n    let buffer = bufferPool.get()\n    defer { bufferPool.put(buffer) }\n\n    return try buffer.withUnsafePointers { iovecs, storageRefs in\n        for p in pending.flushedWrites {\n            // Must not write more than Int32.max in one go.\n            // TODO(cory): I can't see this limit documented in a man page anywhere, but it seems\n            // plausible given that a similar limit exists for TCP. For now we assume it's present\n            // in UDP until I can do some research to validate the existence of this limit.\n            guard Socket.writevLimitBytes - toWrite >= p.data.readableBytes else {\n                if c == 0 {\n                    // The first buffer is larger than the writev limit. Let's throw, and fall back to linear processing.\n                    throw IOError(errnoCode: EMSGSIZE, reason: \"synthetic error for overlarge write\")\n                } else {\n                    break\n                }\n            }\n\n            // Must not write more than writevLimitIOVectors in one go\n            guard c < Socket.writevLimitIOVectors else {\n                break\n            }\n\n            let toWriteForThisBuffer = p.data.readableBytes\n            toWrite += numericCast(toWriteForThisBuffer)\n\n            p.data.withUnsafeReadableBytesWithStorageManagement { ptr, storageRef in\n                storageRefs[c] = storageRef.retain()\n\n                /// From man page of `sendmsg(2)`:\n                ///\n                /// > The `msg_name` field is used on an unconnected socket to specify\n                /// > the target address for a datagram.  It points to a buffer\n                /// > containing the address; the `msg_namelen` field should be set to\n                /// > the size of the address.  For a connected socket, these fields\n                /// > should be specified as `NULL` and 0, respectively.\n                let address: UnsafeMutablePointer<sockaddr_storage>?\n                let addressLen: socklen_t\n                let protocolFamily: NIOBSDSocket.ProtocolFamily\n                if let envelopeAddress = p.address {\n                    precondition(pending.remoteAddress == nil, \"Pending write with address on connected socket.\")\n                    address = addresses.baseAddress! + c\n                    addressLen = p.copySocketAddress(address!)\n                    protocolFamily = envelopeAddress.protocol\n                } else {\n                    guard let connectedRemoteAddress = pending.remoteAddress else {\n                        preconditionFailure(\"Pending write without address on unconnected socket.\")\n                    }\n                    address = nil\n                    addressLen = 0\n                    protocolFamily = connectedRemoteAddress.protocol\n                }\n\n                iovecs[c] = IOVector(\n                    iov_base: UnsafeMutableRawPointer(mutating: ptr.baseAddress!),\n                    iov_len: numericCast(toWriteForThisBuffer)\n                )\n\n                var controlBytes = UnsafeOutboundControlBytes(controlBytes: controlMessageStorage[c])\n                controlBytes.appendExplicitCongestionState(metadata: p.metadata, protocolFamily: protocolFamily)\n                controlBytes.appendUDPSegmentSize(metadata: p.metadata)\n                let controlMessageBytePointer = controlBytes.validControlBytes\n\n                var msg = msghdr()\n                msg.msg_name = .init(address)\n                msg.msg_namelen = addressLen\n                msg.msg_iov = iovecs.baseAddress! + c\n                msg.msg_iovlen = 1\n                msg.control_ptr = controlMessageBytePointer\n                msg.msg_flags = 0\n                msgs[c] = MMsgHdr(msg_hdr: msg, msg_len: 0)\n            }\n            c += 1\n        }\n        defer {\n            for i in 0..<c {\n                storageRefs[i].release()\n            }\n        }\n        return try body(UnsafeMutableBufferPointer(start: msgs.baseAddress!, count: c))\n    }\n}\n\n/// This holds the states of the currently pending datagram writes. The core is a `MarkedCircularBuffer` which holds all the\n/// writes and a mark up until the point the data is flushed. This struct has several behavioural differences from the\n/// `PendingStreamWritesState`, most notably that it handles partial writes differently.\n///\n/// The most important operations on this object are:\n///  - `append` to add a `ByteBuffer` to the list of pending writes.\n///  - `markFlushCheckpoint` which sets a flush mark on the current position of the `MarkedCircularBuffer`. All the items before the checkpoint will be written eventually.\n///  - `didWrite` when a number of bytes have been written.\n///  - `failAll` if for some reason all outstanding writes need to be discarded and the corresponding `EventLoopPromise` needs to be failed.\nprivate struct PendingDatagramWritesState {\n    fileprivate typealias DatagramWritePromiseFiller = (EventLoopPromise<Void>, Error?)\n\n    private var pendingWrites = MarkedCircularBuffer<PendingDatagramWrite>(initialCapacity: 16)\n    private var chunks: Int = 0\n    public private(set) var bytes: Int64 = 0\n    private(set) var remoteAddress: SocketAddress? = nil\n\n    public var nextWrite: PendingDatagramWrite? {\n        self.pendingWrites.first\n    }\n\n    /// Subtract `bytes` from the number of outstanding bytes to write.\n    private mutating func subtractOutstanding(bytes: Int) {\n        assert(self.bytes >= bytes, \"allegedly written more bytes (\\(bytes)) than outstanding (\\(self.bytes))\")\n        self.bytes -= numericCast(bytes)\n    }\n\n    /// Indicates that the first outstanding write was written.\n    ///\n    /// - Returns: The promise that the caller must fire, along with an error to fire it with if it needs one.\n    private mutating func wroteFirst(error: Error? = nil) -> DatagramWritePromiseFiller? {\n        let first = self.pendingWrites.removeFirst()\n        self.chunks -= 1\n        self.subtractOutstanding(bytes: first.data.readableBytes)\n        if let promise = first.promise {\n            return (promise, error)\n        }\n        return nil\n    }\n\n    /// Initialise a new, empty `PendingWritesState`.\n    public init() {}\n\n    /// Check if there are no outstanding writes.\n    public var isEmpty: Bool {\n        if self.pendingWrites.isEmpty {\n            assert(self.chunks == 0)\n            assert(self.bytes == 0)\n            assert(!self.pendingWrites.hasMark)\n            return true\n        } else {\n            assert(self.chunks > 0 && self.bytes >= 0)\n            return false\n        }\n    }\n\n    /// Add a new write and optionally the corresponding promise to the list of outstanding writes.\n    public mutating func append(_ chunk: PendingDatagramWrite) {\n        self.pendingWrites.append(chunk)\n        self.chunks += 1\n        self.bytes += numericCast(chunk.data.readableBytes)\n    }\n\n    /// Mark the flush checkpoint.\n    ///\n    /// All writes before this checkpoint will eventually be written to the socket.\n    public mutating func markFlushCheckpoint() {\n        self.pendingWrites.mark()\n    }\n\n    mutating func markConnected(to remoteAddress: SocketAddress) {\n        self.remoteAddress = remoteAddress\n    }\n\n    /// Indicate that a write has happened, this may be a write of multiple outstanding writes (using for example `sendmmsg`).\n    ///\n    /// - warning: The closure will simply fulfill all the promises in order. If one of those promises does for example close the `Channel` we might see subsequent writes fail out of order. Example: Imagine the user issues three writes: `A`, `B` and `C`. Imagine that `A` and `B` both get successfully written in one write operation but the user closes the `Channel` in `A`'s callback. Then overall the promises will be fulfilled in this order: 1) `A`: success 2) `C`: error 3) `B`: success. Note how `B` and `C` get fulfilled out of order.\n    ///\n    /// - Parameters:\n    ///   - data: The result of the write operation: namely, for each datagram we attempted to write, the number of bytes we wrote.\n    ///   - messages: The vector messages written, if any.\n    /// - Returns: A promise and the error that should be sent to it, if any, and a `WriteResult` which indicates if we could write everything or not.\n    public mutating func didWrite(\n        _ data: IOResult<Int>,\n        messages: UnsafeMutableBufferPointer<MMsgHdr>?\n    ) -> (DatagramWritePromiseFiller?, OneWriteOperationResult) {\n        switch data {\n        case .processed(let written):\n            if let messages = messages {\n                return didVectorWrite(written: written, messages: messages)\n            } else {\n                return didScalarWrite(written: written)\n            }\n        case .wouldBlock:\n            return (nil, .wouldBlock)\n        }\n    }\n\n    public mutating func recoverableError(_ error: Error) -> (DatagramWritePromiseFiller?, OneWriteOperationResult) {\n        // When we've hit an error we treat it like fully writing the first datagram. We aren't going to try to\n        // send it again.\n        let promiseFiller = self.wroteFirst(error: error)\n        let result: OneWriteOperationResult = self.pendingWrites.hasMark ? .writtenPartially : .writtenCompletely\n\n        return (promiseFiller, result)\n    }\n\n    /// Indicates that a vector write succeeded.\n    ///\n    /// - Parameters:\n    ///   - written: The number of messages successfully written.\n    ///   - messages: The list of message objects.\n    /// - Returns: A closure that the caller _needs_ to run which will fulfill the promises of the writes, and a `WriteResult` that indicates if we could write\n    ///     everything or not.\n    private mutating func didVectorWrite(\n        written: Int,\n        messages: UnsafeMutableBufferPointer<MMsgHdr>\n    ) -> (DatagramWritePromiseFiller?, OneWriteOperationResult) {\n        // This was a vector write. We wrote `written` number of messages.\n        let writes = messages[messages.startIndex...messages.index(messages.startIndex, offsetBy: written - 1)]\n        var promiseFiller: DatagramWritePromiseFiller?\n\n        for write in writes {\n            let written = write.msg_len\n            let thisWriteFiller = didScalarWrite(written: Int(written)).0\n            assert(thisWriteFiller?.1 == nil, \"didVectorWrite called with errors on single writes!\")\n\n            switch (promiseFiller, thisWriteFiller) {\n            case (.some(let all), .some(let this)):\n                all.0.futureResult.cascade(to: this.0)\n            case (.none, .some(let this)):\n                promiseFiller = this\n            case (.some, .none),\n                (.none, .none):\n                break\n            }\n        }\n\n        // If we no longer have a mark, we wrote everything.\n        let result: OneWriteOperationResult = self.pendingWrites.hasMark ? .writtenPartially : .writtenCompletely\n        return (promiseFiller, result)\n    }\n\n    /// Indicates that a scalar write succeeded.\n    ///\n    /// - Parameters:\n    ///   - written: The number of bytes successfully written.\n    /// - Returns: All the promises that must be fired, and a `WriteResult` that indicates if we could write\n    ///     everything or not.\n    private mutating func didScalarWrite(written: Int) -> (DatagramWritePromiseFiller?, OneWriteOperationResult) {\n        precondition(\n            written <= self.pendingWrites.first!.data.readableBytes,\n            \"Appeared to write more bytes (\\(written)) than the datagram contained (\\(self.pendingWrites.first!.data.readableBytes))\"\n        )\n        let writeFiller = self.wroteFirst()\n        // If we no longer have a mark, we wrote everything.\n        let result: OneWriteOperationResult = self.pendingWrites.hasMark ? .writtenPartially : .writtenCompletely\n        return (writeFiller, result)\n    }\n\n    /// Is there a pending flush?\n    public var isFlushPending: Bool {\n        self.pendingWrites.hasMark\n    }\n\n    /// Fail all the outstanding writes.\n    ///\n    /// - warning: See the warning for `didWrite`.\n    ///\n    /// - Returns: Nothing\n    public mutating func failAll(error: Error) {\n        var promises: [EventLoopPromise<Void>] = []\n        promises.reserveCapacity(self.pendingWrites.count)\n\n        while !self.pendingWrites.isEmpty {\n            let w = self.pendingWrites.removeFirst()\n            self.chunks -= 1\n            self.bytes -= numericCast(w.data.readableBytes)\n            w.promise.map { promises.append($0) }\n        }\n\n        for promise in promises {\n            promise.fail(error)\n        }\n    }\n\n    /// Returns the best mechanism to write pending data at the current point in time.\n    var currentBestWriteMechanism: WriteMechanism {\n        switch self.pendingWrites.markedElementIndex {\n        case .some(let e) where self.pendingWrites.distance(from: self.pendingWrites.startIndex, to: e) > 0:\n            return .vectorBufferWrite\n        case .some(let e):\n            // The compiler can't prove this, but it must be so.\n            assert(self.pendingWrites.distance(from: e, to: self.pendingWrites.startIndex) == 0)\n            return .scalarBufferWrite\n        default:\n            return .nothingToBeWritten\n        }\n    }\n}\n\n// This extension contains a lazy sequence that makes other parts of the code work better.\nextension PendingDatagramWritesState {\n    struct FlushedDatagramWriteSequence: Sequence, IteratorProtocol {\n        private let pendingWrites: PendingDatagramWritesState\n        private var index: CircularBuffer<PendingDatagramWrite>.Index\n        private let markedIndex: CircularBuffer<PendingDatagramWrite>.Index?\n\n        init(_ pendingWrites: PendingDatagramWritesState) {\n            self.pendingWrites = pendingWrites\n            self.index = pendingWrites.pendingWrites.startIndex\n            self.markedIndex = pendingWrites.pendingWrites.markedElementIndex\n        }\n\n        mutating func next() -> PendingDatagramWrite? {\n            while let markedIndex = self.markedIndex,\n                self.pendingWrites.pendingWrites.distance(\n                    from: self.index,\n                    to: markedIndex\n                ) >= 0\n            {\n                let element = self.pendingWrites.pendingWrites[index]\n                index = self.pendingWrites.pendingWrites.index(after: index)\n                return element\n            }\n\n            return nil\n        }\n    }\n\n    var flushedWrites: FlushedDatagramWriteSequence {\n        FlushedDatagramWriteSequence(self)\n    }\n}\n\n/// This class manages the writing of pending writes to datagram sockets. The state is held in a `PendingWritesState`\n/// value. The most important purpose of this object is to call `sendto` or `sendmmsg` depending on the writes held and\n/// the availability of the functions.\nfinal class PendingDatagramWritesManager: PendingWritesManager {\n\n    private let bufferPool: Pool<PooledBuffer>\n    private let msgBufferPool: Pool<PooledMsgBuffer>\n\n    private var state = PendingDatagramWritesState()\n\n    internal var waterMark: ChannelOptions.Types.WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark(\n        low: 32 * 1024,\n        high: 64 * 1024\n    )\n    internal let channelWritabilityFlag = ManagedAtomic<Bool>(true)\n    internal var publishedWritability = true\n    internal var writeSpinCount: UInt = 16\n    private(set) var isOpen = true\n    var outboundCloseState: CloseState {\n        if self.isOpen {\n            .open\n        } else {\n            .closed\n        }\n    }\n\n    /// Initialize with a pre-allocated array of message headers and storage references. We pass in these pre-allocated\n    /// objects to save allocations. They can be safely be re-used for all `Channel`s on a given `EventLoop` as an\n    /// `EventLoop` always runs on one and the same thread. That means that there can't be any writes of more than\n    /// one `Channel` on the same `EventLoop` at the same time.\n    ///\n    /// - Parameters:\n    ///   - bufferPool: a pool of buffers to be used for IOVector and storage references\n    ///   - msgBufferPool: a pool of buffers to be usded for `MMsgHdr`, `sockaddr_storage` and cmsghdr elements\n    init(bufferPool: Pool<PooledBuffer>, msgBufferPool: Pool<PooledMsgBuffer>) {\n        self.bufferPool = bufferPool\n        self.msgBufferPool = msgBufferPool\n    }\n\n    /// Mark the flush checkpoint.\n    func markFlushCheckpoint() {\n        self.state.markFlushCheckpoint()\n    }\n\n    /// Mark that the socket is connected.\n    func markConnected(to remoteAddress: SocketAddress) {\n        self.state.markConnected(to: remoteAddress)\n    }\n\n    /// Is there a flush pending?\n    var isFlushPending: Bool {\n        self.state.isFlushPending\n    }\n\n    /// Are there any outstanding writes currently?\n    var isEmpty: Bool {\n        self.state.isEmpty\n    }\n\n    var bufferedBytes: Int64 {\n        self.state.bytes\n    }\n\n    private func add(_ pendingWrite: PendingDatagramWrite) -> Bool {\n        assert(self.isOpen)\n        self.state.append(pendingWrite)\n\n        if self.state.bytes > waterMark.high\n            && channelWritabilityFlag.compareExchange(expected: true, desired: false, ordering: .relaxed).exchanged\n        {\n            // Returns false to signal the Channel became non-writable and we need to notify the user.\n            self.publishedWritability = false\n            return false\n        }\n        return true\n    }\n\n    /// Add a pending write, with an `AddressedEnvelope`, usually on an unconnected socket.\n    ///\n    /// - Parameters:\n    ///   - envelope: The `AddressedEnvelope<ByteBuffer>` to write.\n    ///   - promise: Optionally an `EventLoopPromise` that will get the write operation's result\n    /// - Returns: If the `Channel` is still writable after adding the write of `data`.\n    ///\n    /// - warning: If the socket is connected, then the `envelope.remoteAddress` _must_ match the\n    /// address of the connected peer, otherwise this function will throw a fatal error.\n    func add(envelope: AddressedEnvelope<ByteBuffer>, promise: EventLoopPromise<Void>?) -> Bool {\n        if let remoteAddress = self.state.remoteAddress {\n            precondition(\n                envelope.remoteAddress == remoteAddress,\n                \"\"\"\n                Remote address of AddressedEnvelope does not match remote address of connected socket.\n                \"\"\"\n            )\n            return self.add(\n                PendingDatagramWrite(\n                    data: envelope.data,\n                    promise: promise,\n                    address: nil,\n                    metadata: envelope.metadata\n                )\n            )\n        } else {\n            return self.add(\n                PendingDatagramWrite(\n                    data: envelope.data,\n                    promise: promise,\n                    address: envelope.remoteAddress,\n                    metadata: envelope.metadata\n                )\n            )\n        }\n    }\n\n    /// Add a pending write, without an `AddressedEnvelope`, on a connected socket.\n    ///\n    /// - Parameters:\n    ///   - data: The `ByteBuffer` to write.\n    ///   - promise: Optionally an `EventLoopPromise` that will get the write operation's result\n    /// - Returns: If the `Channel` is still writable after adding the write of `data`.\n    func add(data: ByteBuffer, promise: EventLoopPromise<Void>?) -> Bool {\n        self.add(\n            PendingDatagramWrite(\n                data: data,\n                promise: promise,\n                address: nil,\n                metadata: nil\n            )\n        )\n    }\n\n    /// Returns the best mechanism to write pending data at the current point in time.\n    var currentBestWriteMechanism: WriteMechanism {\n        self.state.currentBestWriteMechanism\n    }\n\n    /// Triggers the appropriate write operation. This is a fancy way of saying trigger either `sendto` or `sendmmsg`.\n    /// On platforms that do not support a gathering write operation,\n    ///\n    /// - Parameters:\n    ///   - scalarWriteOperation: An operation that writes a single, contiguous array of bytes (usually `sendmsg`).\n    ///   - vectorWriteOperation: An operation that writes multiple contiguous arrays of bytes (usually `sendmmsg`).\n    /// - Returns: The `WriteResult` and whether the `Channel` is now writable.\n    func triggerAppropriateWriteOperations(\n        scalarWriteOperation: (\n            UnsafeRawBufferPointer, UnsafePointer<sockaddr>?, socklen_t, AddressedEnvelope<ByteBuffer>.Metadata?\n        ) throws -> IOResult<Int>,\n        vectorWriteOperation: (UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>\n    ) throws -> OverallWriteResult {\n        try self.triggerWriteOperations { writeMechanism in\n            switch writeMechanism {\n            case .scalarBufferWrite:\n                return try triggerScalarBufferWrite(scalarWriteOperation: { try scalarWriteOperation($0, $1, $2, $3) })\n            case .vectorBufferWrite:\n                do {\n                    return try triggerVectorBufferWrite(vectorWriteOperation: { try vectorWriteOperation($0) })\n                } catch {\n                    // If the error we just hit is recoverable, we fall back to single write mode to\n                    // isolate exactly which write triggered the problem.\n                    guard error.isRecoverable else {\n                        throw error\n                    }\n\n                    return try triggerScalarBufferWrite(scalarWriteOperation: {\n                        try scalarWriteOperation($0, $1, $2, $3)\n                    })\n                }\n            case .scalarFileWrite:\n                preconditionFailure(\"PendingDatagramWritesManager was handed a file write\")\n            case .nothingToBeWritten:\n                assertionFailure(\"called \\(#function) with nothing available to be written\")\n                return OneWriteOperationResult.writtenCompletely\n            }\n        }\n    }\n\n    /// To be called after a write operation (usually selected and run by `triggerAppropriateWriteOperation`) has\n    /// completed.\n    ///\n    /// - Parameters:\n    ///   - data: The result of the write operation.\n    private func didWrite(\n        _ data: IOResult<Int>,\n        messages: UnsafeMutableBufferPointer<MMsgHdr>?\n    ) -> OneWriteOperationResult {\n        let (promise, result) = self.state.didWrite(data, messages: messages)\n\n        if self.state.bytes < waterMark.low {\n            channelWritabilityFlag.store(true, ordering: .relaxed)\n        }\n\n        self.fulfillPromise(promise)\n        return result\n    }\n\n    /// Called after a scalar write operation has hit an error. Attempts to map some tolerable datagram errors to\n    /// useful errors and fail the individual write, rather than fail the entire connection. If the error cannot\n    /// be tolerated by a datagram application, will rethrow the error.\n    ///\n    /// - Parameters:\n    ///   - error: The error we hit.\n    /// - Returns: A `WriteResult` indicating whether the writes should continue.\n    /// - Throws: Any error that cannot be ignored by a datagram write.\n    private func handleError(_ error: Error) throws -> OneWriteOperationResult {\n        switch error {\n        case let e as IOError where e.errnoCode == EMSGSIZE:\n            let (promise, result) = self.state.recoverableError(ChannelError._writeMessageTooLarge)\n            self.fulfillPromise(promise)\n            return result\n        case let e as IOError where e.errnoCode == EHOSTUNREACH:\n            let (promise, result) = self.state.recoverableError(ChannelError._writeHostUnreachable)\n            self.fulfillPromise(promise)\n            return result\n        default:\n            throw error\n        }\n    }\n\n    /// Trigger a write of a single object where an object can either be a contiguous array of bytes or a region of a file.\n    ///\n    /// - Parameters:\n    ///   - scalarWriteOperation: An operation that writes a single, contiguous array of bytes (usually `sendto`).\n    private func triggerScalarBufferWrite(\n        scalarWriteOperation: (\n            UnsafeRawBufferPointer, UnsafePointer<sockaddr>?, socklen_t, AddressedEnvelope<ByteBuffer>.Metadata?\n        ) throws -> IOResult<Int>\n    ) rethrows -> OneWriteOperationResult {\n        assert(\n            self.state.isFlushPending && self.isOpen && !self.state.isEmpty,\n            \"illegal state for scalar datagram write operation: flushPending: \\(self.state.isFlushPending), isOpen: \\(self.isOpen), empty: \\(self.state.isEmpty)\"\n        )\n        let pending = self.state.nextWrite!\n        do {\n            let writeResult: IOResult<Int>\n\n            if let address = pending.address {\n                assert(self.state.remoteAddress == nil, \"Pending write with address on connected socket.\")\n                writeResult = try address.withSockAddr { (addrPtr, addrSize) in\n                    try pending.data.withUnsafeReadableBytes {\n                        try scalarWriteOperation($0, addrPtr, socklen_t(addrSize), pending.metadata)\n                    }\n                }\n            } else {\n                /// From man page of `sendmsg(2)`:\n                ///\n                /// > The `msg_name` field is used on an unconnected socket to specify\n                /// > the target address for a datagram.  It points to a buffer\n                /// > containing the address; the `msg_namelen` field should be set to\n                /// > the size of the address.  For a connected socket, these fields\n                /// > should be specified as `NULL` and 0, respectively.\n                assert(self.state.remoteAddress != nil, \"Pending write without address on unconnected socket.\")\n                writeResult = try pending.data.withUnsafeReadableBytes {\n                    try scalarWriteOperation($0, nil, 0, pending.metadata)\n                }\n            }\n            return self.didWrite(writeResult, messages: nil)\n        } catch {\n            return try self.handleError(error)\n        }\n    }\n\n    /// Trigger a vector write operation. In other words: Write multiple contiguous arrays of bytes.\n    ///\n    /// - Parameters:\n    ///   - vectorWriteOperation: The vector write operation to use. Usually `sendmmsg`.\n    private func triggerVectorBufferWrite(\n        vectorWriteOperation: (UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>\n    ) throws -> OneWriteOperationResult {\n        assert(\n            self.state.isFlushPending && self.isOpen && !self.state.isEmpty,\n            \"illegal state for vector datagram write operation: flushPending: \\(self.state.isFlushPending), isOpen: \\(self.isOpen), empty: \\(self.state.isEmpty)\"\n        )\n\n        let msgBuffer = self.msgBufferPool.get()\n        defer { self.msgBufferPool.put(msgBuffer) }\n\n        return try msgBuffer.withUnsafePointers { msgs, addresses, controlMessageStorage in\n            self.didWrite(\n                try doPendingDatagramWriteVectorOperation(\n                    pending: self.state,\n                    bufferPool: self.bufferPool,\n                    msgs: msgs,\n                    addresses: addresses,\n                    controlMessageStorage: controlMessageStorage,\n                    { try vectorWriteOperation($0) }\n                ),\n                messages: msgs\n            )\n        }\n    }\n\n    private func fulfillPromise(_ promise: PendingDatagramWritesState.DatagramWritePromiseFiller?) {\n        if let promise = promise, let error = promise.1 {\n            promise.0.fail(error)\n        } else if let promise = promise {\n            promise.0.succeed(())\n        }\n    }\n\n    /// Fail all the outstanding writes. This is useful if for example the `Channel` is closed.\n    func failAll(error: Error, close: Bool) {\n        if close {\n            assert(self.isOpen)\n            self.isOpen = false\n        }\n\n        self.state.failAll(error: error)\n\n        assert(self.state.isEmpty)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PendingWritesManager.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport CNIOLinux\nimport CNIOOpenBSD\nimport NIOCore\n\nprivate struct PendingStreamWrite {\n    var data: IOData\n    var promise: Optional<EventLoopPromise<Void>>\n}\n\n/// Write result is `.couldNotWriteEverything` but we have no more writes to perform.\npublic struct NIOReportedIncompleteWritesWhenNoMoreToPerform: Error {}\n\n/// Close result is `.open`.\npublic struct NIOReportedOpenAfterClose: Error {}\n\n/// There are buffered writes after it should have been cleared, `.readyForClose` or `.closed` state\npublic struct NIOReportedPendingWritesInInvalidState: Error {}\n\n/// Does the setup required to issue a writev.\n///\n/// - Parameters:\n///    - pending: The currently pending writes.\n///    - bufferPool: Pool of buffers to use for iovecs and storageRefs\n///    - body: The function that actually does the vector write (usually `writev`).\n/// - Returns: A tuple of the number of items attempted to write and the result of the write operation.\nprivate func doPendingWriteVectorOperation(\n    pending: PendingStreamWritesState,\n    bufferPool: Pool<PooledBuffer>,\n    _ body: (UnsafeBufferPointer<IOVector>) throws -> IOResult<Int>\n) throws -> (itemCount: Int, writeResult: IOResult<Int>) {\n    let buffer = bufferPool.get()\n    defer { bufferPool.put(buffer) }\n\n    return try buffer.withUnsafePointers { iovecs, storageRefs in\n        // Clamp the number of writes we're willing to issue to the limit for writev.\n        var count = min(iovecs.count, storageRefs.count)\n        count = min(pending.flushedChunks, count)\n\n        // the numbers of storage refs that we need to decrease later.\n        var numberOfUsedStorageSlots = 0\n        var toWrite: Int = 0\n\n        loop: for i in 0..<count {\n            let p = pending[i]\n            switch p.data {\n            case .byteBuffer(let buffer):\n                // Must not write more than Int32.max in one go.\n                guard (numberOfUsedStorageSlots == 0) || (Socket.writevLimitBytes - toWrite >= buffer.readableBytes)\n                else {\n                    break loop\n                }\n                let toWriteForThisBuffer = min(Socket.writevLimitBytes, buffer.readableBytes)\n                toWrite += numericCast(toWriteForThisBuffer)\n\n                buffer.withUnsafeReadableBytesWithStorageManagement { ptr, storageRef in\n                    storageRefs[i] = storageRef.retain()\n                    iovecs[i] = IOVector(\n                        iov_base: UnsafeMutableRawPointer(mutating: ptr.baseAddress!),\n                        iov_len: numericCast(toWriteForThisBuffer)\n                    )\n                }\n                numberOfUsedStorageSlots += 1\n            case .fileRegion:\n                assert(numberOfUsedStorageSlots != 0, \"first item in doPendingWriteVectorOperation was a FileRegion\")\n                // We found a FileRegion so stop collecting\n                break loop\n            }\n        }\n        defer {\n            for i in 0..<numberOfUsedStorageSlots {\n                storageRefs[i].release()\n            }\n        }\n        let result = try body(UnsafeBufferPointer(start: iovecs.baseAddress!, count: numberOfUsedStorageSlots))\n        // if we hit a limit, we really wanted to write more than we have so the caller should retry us\n        return (numberOfUsedStorageSlots, result)\n    }\n}\n\n/// The result of a single write operation, usually `write`, `sendfile` or `writev`.\ninternal enum OneWriteOperationResult {\n    /// Wrote everything asked.\n    case writtenCompletely\n\n    /// Wrote some portion of what was asked.\n    case writtenPartially\n\n    /// Could not write as doing that would have blocked.\n    case wouldBlock\n}\n\n/// The result of trying to write all the outstanding flushed data. That naturally includes all `ByteBuffer`s and\n/// `FileRegions` and the individual writes have potentially been retried (see `WriteSpinOption`).\ninternal struct OverallWriteResult {\n    enum WriteOutcome: Equatable {\n        /// Wrote all the data that was flushed. When receiving this result, we can unsubscribe from 'writable' notification.\n        case writtenCompletely(WrittenCompletelyResult)\n\n        /// Could not write everything. Before attempting further writes the eventing system should send a 'writable' notification.\n        case couldNotWriteEverything\n\n        /// The resulting status of a `PendingWritesManager` after a completely-written write\n        ///\n        /// This type is subtly different to `CloseState` so that it only surfaces the close promise when the caller\n        /// is expected to fulfill it\n        internal enum WrittenCompletelyResult: Equatable {\n            case open\n            case readyForClose(EventLoopPromise<Void>?)\n            case closed(EventLoopPromise<Void>?)\n\n            init(_ closeState: CloseState) {\n                switch closeState {\n                case .open:\n                    self = .open\n                case .pending(let closePromise), .readyForClose(let closePromise):\n                    self = .readyForClose(closePromise)\n                case .closed:\n                    self = .closed(nil)\n                }\n            }\n        }\n    }\n\n    internal var writeResult: WriteOutcome\n    internal var writabilityChange: Bool\n}\n\n/// This holds the states of the currently pending stream writes. The core is a `MarkedCircularBuffer` which holds all the\n/// writes and a mark up until the point the data is flushed.\n///\n/// The most important operations on this object are:\n///  - `append` to add an `IOData` to the list of pending writes.\n///  - `markFlushCheckpoint` which sets a flush mark on the current position of the `MarkedCircularBuffer`. All the items before the checkpoint will be written eventually.\n///  - `didWrite` when a number of bytes have been written.\n///  - `failAll` if for some reason all outstanding writes need to be discarded and the corresponding `EventLoopPromise` needs to be failed.\nprivate struct PendingStreamWritesState {\n    private var pendingWrites = MarkedCircularBuffer<PendingStreamWrite>(initialCapacity: 16)\n    public private(set) var bytes: Int64 = 0\n\n    public var flushedChunks: Int {\n        self.pendingWrites.markedElementIndex.map {\n            self.pendingWrites.distance(from: self.pendingWrites.startIndex, to: $0) + 1\n        } ?? 0\n    }\n\n    /// Subtract `bytes` from the number of outstanding bytes to write.\n    private mutating func subtractOutstanding(bytes: Int) {\n        assert(self.bytes >= bytes, \"allegedly written more bytes (\\(bytes)) than outstanding (\\(self.bytes))\")\n        self.bytes -= numericCast(bytes)\n    }\n\n    /// Indicates that the first outstanding write was written in its entirety.\n    ///\n    /// - Returns: The `EventLoopPromise` of the write or `nil` if none was provided. The promise needs to be fulfilled by the caller.\n    ///\n    private mutating func fullyWrittenFirst() -> EventLoopPromise<Void>? {\n        let first = self.pendingWrites.removeFirst()\n        self.subtractOutstanding(bytes: first.data.readableBytes)\n        return first.promise\n    }\n\n    /// Indicates that the first outstanding object has been partially written.\n    ///\n    /// - Parameters:\n    ///   - bytes: How many bytes of the item were written.\n    private mutating func partiallyWrittenFirst(bytes: Int) {\n        self.pendingWrites[self.pendingWrites.startIndex].data.moveReaderIndex(forwardBy: bytes)\n        self.subtractOutstanding(bytes: bytes)\n    }\n\n    /// Initialize a new, empty `PendingWritesState`.\n    public init() {}\n\n    /// Check if there are no outstanding writes.\n    public var isEmpty: Bool {\n        if self.pendingWrites.isEmpty {\n            assert(self.bytes == 0)\n            assert(!self.pendingWrites.hasMark)\n            return true\n        } else {\n            assert(self.bytes >= 0)\n            return false\n        }\n    }\n\n    /// Add a new write and optionally the corresponding promise to the list of outstanding writes.\n    public mutating func append(_ chunk: PendingStreamWrite) {\n        self.pendingWrites.append(chunk)\n        switch chunk.data {\n        case .byteBuffer(let buffer):\n            self.bytes += numericCast(buffer.readableBytes)\n        case .fileRegion(let fileRegion):\n            self.bytes += numericCast(fileRegion.readableBytes)\n        }\n    }\n\n    /// Get the outstanding write at `index`.\n    public subscript(index: Int) -> PendingStreamWrite {\n        self.pendingWrites[self.pendingWrites.index(self.pendingWrites.startIndex, offsetBy: index)]\n    }\n\n    /// Mark the flush checkpoint.\n    ///\n    /// All writes before this checkpoint will eventually be written to the socket.\n    public mutating func markFlushCheckpoint() {\n        self.pendingWrites.mark()\n    }\n\n    /// Indicate that a write has happened, this may be a write of multiple outstanding writes (using for example `writev`).\n    ///\n    /// - warning: The promises will be returned in order. If one of those promises does for example close the `Channel` we might see subsequent writes fail out of order. Example: Imagine the user issues three writes: `A`, `B` and `C`. Imagine that `A` and `B` both get successfully written in one write operation but the user closes the `Channel` in `A`'s callback. Then overall the promises will be fulfilled in this order: 1) `A`: success 2) `C`: error 3) `B`: success. Note how `B` and `C` get fulfilled out of order.\n    ///\n    /// - Parameters:\n    ///   - writeResult: The result of the write operation.\n    /// - Returns: A tuple of a promise and a `OneWriteResult`. The promise is the first promise that needs to be notified of the write result.\n    ///            This promise will cascade the result to all other promises that need notifying. If no promises need to be notified, will be `nil`.\n    ///            The write result will indicate whether we were able to write everything or not.\n    public mutating func didWrite(\n        itemCount: Int,\n        result writeResult: IOResult<Int>\n    ) -> (EventLoopPromise<Void>?, OneWriteOperationResult) {\n        switch writeResult {\n        case .wouldBlock(0):\n            return (nil, .wouldBlock)\n        case .processed(let written), .wouldBlock(let written):\n            var promise0: EventLoopPromise<Void>?\n            assert(written >= 0, \"allegedly written a negative amount of bytes: \\(written)\")\n            var unaccountedWrites = written\n            for _ in 0..<itemCount {\n                let headItemReadableBytes = self.pendingWrites.first!.data.readableBytes\n                if unaccountedWrites >= headItemReadableBytes {\n                    unaccountedWrites -= headItemReadableBytes\n                    // we wrote at least the whole head item, so drop it and succeed the promise\n                    if let promise = self.fullyWrittenFirst() {\n                        if let p = promise0 {\n                            p.futureResult.cascade(to: promise)\n                        } else {\n                            promise0 = promise\n                        }\n                    }\n                } else {\n                    // we could only write a part of the head item, so don't drop it but remember what we wrote\n                    self.partiallyWrittenFirst(bytes: unaccountedWrites)\n\n                    // may try again depending on the writeSpinCount\n                    return (promise0, .writtenPartially)\n                }\n            }\n            assert(\n                unaccountedWrites == 0,\n                \"after doing all the accounting for the byte written, \\(unaccountedWrites) bytes of unaccounted writes remain.\"\n            )\n            return (promise0, .writtenCompletely)\n        }\n    }\n\n    /// Is there a pending flush?\n    public var isFlushPending: Bool {\n        self.pendingWrites.hasMark\n    }\n\n    /// Remove all pending writes and return a `EventLoopPromise` which will cascade notifications to all.\n    ///\n    /// - warning: See the warning for `didWrite`.\n    ///\n    /// - Returns: promise that needs to be failed, or `nil` if there were no pending writes.\n    public mutating func removeAll() -> EventLoopPromise<Void>? {\n        var promise0: EventLoopPromise<Void>?\n\n        while !self.pendingWrites.isEmpty {\n            if let p = self.fullyWrittenFirst() {\n                if let promise = promise0 {\n                    promise.futureResult.cascade(to: p)\n                } else {\n                    promise0 = p\n                }\n            }\n        }\n        return promise0\n    }\n\n    /// Returns the best mechanism to write pending data at the current point in time.\n    var currentBestWriteMechanism: WriteMechanism {\n        switch self.flushedChunks {\n        case 0:\n            return .nothingToBeWritten\n        case 1:\n            switch self.pendingWrites.first!.data {\n            case .byteBuffer:\n                return .scalarBufferWrite\n            case .fileRegion:\n                return .scalarFileWrite\n            }\n        default:\n            let startIndex = self.pendingWrites.startIndex\n            switch (\n                self.pendingWrites[startIndex].data,\n                self.pendingWrites[self.pendingWrites.index(after: startIndex)].data\n            ) {\n            case (.byteBuffer, .byteBuffer):\n                return .vectorBufferWrite\n            case (.byteBuffer, .fileRegion):\n                return .scalarBufferWrite\n            case (.fileRegion, _):\n                return .scalarFileWrite\n            }\n        }\n    }\n}\n\n/// This class manages the writing of pending writes to stream sockets. The state is held in a `PendingWritesState`\n/// value. The most important purpose of this object is to call `write`, `writev` or `sendfile` depending on the\n/// currently pending writes.\nfinal class PendingStreamWritesManager: PendingWritesManager {\n    private var state = PendingStreamWritesState()\n    private let bufferPool: Pool<PooledBuffer>\n\n    internal var waterMark: ChannelOptions.Types.WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark(\n        low: 32 * 1024,\n        high: 64 * 1024\n    )\n    internal let channelWritabilityFlag = ManagedAtomic(true)\n    internal var publishedWritability = true\n\n    internal var writeSpinCount: UInt = 16\n\n    private(set) var isOpen = true\n\n    private(set) var outboundCloseState: CloseState = .open\n\n    /// Mark the flush checkpoint.\n    func markFlushCheckpoint() {\n        self.state.markFlushCheckpoint()\n    }\n\n    /// Is there a flush pending?\n    var isFlushPending: Bool {\n        self.state.isFlushPending\n    }\n\n    /// Are there any outstanding writes currently?\n    var isEmpty: Bool {\n        self.state.isEmpty\n    }\n\n    var bufferedBytes: Int64 {\n        self.state.bytes\n    }\n\n    /// Add a pending write alongside its promise.\n    ///\n    /// - Parameters:\n    ///   - data: The `IOData` to write.\n    ///   - promise: Optionally an `EventLoopPromise` that will get the write operation's result\n    /// - result: If the `Channel` is still writable after adding the write of `data`.\n    func add(data: IOData, promise: EventLoopPromise<Void>?) -> Bool {\n        assert(self.isOpen)\n        self.state.append(PendingStreamWrite(data: data, promise: promise))\n\n        if self.state.bytes > waterMark.high\n            && channelWritabilityFlag.compareExchange(expected: true, desired: false, ordering: .relaxed).exchanged\n        {\n            // Returns false to signal the Channel became non-writable and we need to notify the user.\n            self.publishedWritability = false\n            return false\n        }\n        return true\n    }\n\n    /// Returns the best mechanism to write pending data at the current point in time.\n    var currentBestWriteMechanism: WriteMechanism {\n        self.state.currentBestWriteMechanism\n    }\n\n    /// Triggers the appropriate write operation. This is a fancy way of saying trigger either `write`, `writev` or\n    /// `sendfile`.\n    ///\n    /// - Parameters:\n    ///   - scalarBufferWriteOperation: An operation that writes a single, contiguous array of bytes (usually `write`).\n    ///   - vectorBufferWriteOperation: An operation that writes multiple contiguous arrays of bytes (usually `writev`).\n    ///   - scalarFileWriteOperation: An operation that writes a region of a file descriptor (usually `sendfile`).\n    /// - Returns: The `OneWriteOperationResult` and whether the `Channel` is now writable.\n    func triggerAppropriateWriteOperations(\n        scalarBufferWriteOperation: (UnsafeRawBufferPointer) throws -> IOResult<Int>,\n        vectorBufferWriteOperation: (UnsafeBufferPointer<IOVector>) throws -> IOResult<Int>,\n        scalarFileWriteOperation: (CInt, Int, Int) throws -> IOResult<Int>\n    ) throws -> OverallWriteResult {\n        try self.triggerWriteOperations { writeMechanism in\n            switch writeMechanism {\n            case .scalarBufferWrite:\n                return try triggerScalarBufferWrite({ try scalarBufferWriteOperation($0) })\n            case .vectorBufferWrite:\n                return try triggerVectorBufferWrite({ try vectorBufferWriteOperation($0) })\n            case .scalarFileWrite:\n                return try triggerScalarFileWrite({ try scalarFileWriteOperation($0, $1, $2) })\n            case .nothingToBeWritten:\n                assertionFailure(\"called \\(#function) with nothing available to be written\")\n                return .writtenCompletely\n            }\n        }\n    }\n\n    /// To be called after a write operation (usually selected and run by `triggerAppropriateWriteOperation`) has\n    /// completed.\n    ///\n    /// - Parameters:\n    ///   - itemCount: The number of items we tried to write.\n    ///   - result: The result of the write operation.\n    private func didWrite(itemCount: Int, result: IOResult<Int>) -> OneWriteOperationResult {\n        let (promise, result) = self.state.didWrite(itemCount: itemCount, result: result)\n\n        if self.state.bytes < waterMark.low {\n            channelWritabilityFlag.store(true, ordering: .relaxed)\n        }\n\n        promise?.succeed(())\n        return result\n    }\n\n    /// Trigger a write of a single `ByteBuffer` (usually using `write(2)`).\n    ///\n    /// - Parameters:\n    ///   - operation: An operation that writes a single, contiguous array of bytes (usually `write`).\n    private func triggerScalarBufferWrite(\n        _ operation: (UnsafeRawBufferPointer) throws -> IOResult<Int>\n    ) throws -> OneWriteOperationResult {\n        assert(\n            self.state.isFlushPending && !self.state.isEmpty && self.isOpen,\n            \"single write called in illegal state: flush pending: \\(self.state.isFlushPending), empty: \\(self.state.isEmpty), isOpen: \\(self.isOpen)\"\n        )\n\n        switch self.state[0].data {\n        case .byteBuffer(let buffer):\n            return self.didWrite(itemCount: 1, result: try buffer.withUnsafeReadableBytes({ try operation($0) }))\n        case .fileRegion:\n            preconditionFailure(\"called \\(#function) but first item to write was a FileRegion\")\n        }\n    }\n\n    /// Trigger a write of a single `FileRegion` (usually using `sendfile(2)`).\n    ///\n    /// - Parameters:\n    ///   - operation: An operation that writes a region of a file descriptor.\n    private func triggerScalarFileWrite(\n        _ operation: (CInt, Int, Int) throws -> IOResult<Int>\n    ) throws -> OneWriteOperationResult {\n        assert(\n            self.state.isFlushPending && !self.state.isEmpty && self.isOpen,\n            \"single write called in illegal state: flush pending: \\(self.state.isFlushPending), empty: \\(self.state.isEmpty), isOpen: \\(self.isOpen)\"\n        )\n\n        switch self.state[0].data {\n        case .fileRegion(let file):\n            let readerIndex = file.readerIndex\n            let endIndex = file.endIndex\n            let writeResult = try file.fileHandle.withUnsafeFileDescriptor { fd in\n                try operation(fd, readerIndex, endIndex)\n            }\n            return self.didWrite(itemCount: 1, result: writeResult)\n        case .byteBuffer:\n            preconditionFailure(\"called \\(#function) but first item to write was a ByteBuffer\")\n        }\n    }\n\n    /// Trigger a vector write operation. In other words: Write multiple contiguous arrays of bytes.\n    ///\n    /// - Parameters:\n    ///   - operation: The vector write operation to use. Usually `writev`.\n    private func triggerVectorBufferWrite(\n        _ operation: (UnsafeBufferPointer<IOVector>) throws -> IOResult<Int>\n    ) throws -> OneWriteOperationResult {\n        assert(\n            self.state.isFlushPending && !self.state.isEmpty && self.isOpen,\n            \"vector write called in illegal state: flush pending: \\(self.state.isFlushPending), empty: \\(self.state.isEmpty), isOpen: \\(self.isOpen)\"\n        )\n        let result = try doPendingWriteVectorOperation(\n            pending: self.state,\n            bufferPool: bufferPool,\n            { try operation($0) }\n        )\n        return self.didWrite(itemCount: result.itemCount, result: result.writeResult)\n    }\n\n    /// Fail all the outstanding writes.\n    func failAll(error: Error) -> EventLoopPromise<Void>? {\n        let promise: EventLoopPromise<Void>?\n        self.isOpen = false\n        switch self.outboundCloseState {\n        case .open, .closed:\n            self.outboundCloseState = .closed\n            promise = nil\n        case .pending(let closePromise), .readyForClose(let closePromise):\n            self.outboundCloseState = .closed\n            promise = closePromise\n        }\n\n        self.state.removeAll()?.fail(error)\n\n        assert(self.state.isEmpty)\n        return promise\n    }\n\n    // The result of calling `closeOutbound`\n    enum CloseOutboundResult {\n        case pending\n        case readyForClose(EventLoopPromise<Void>?)\n        case closed(EventLoopPromise<Void>?)\n        case errored(Error, EventLoopPromise<Void>?)\n\n        init(_ closeState: CloseState, _ isEmpty: Bool, _ promise: EventLoopPromise<Void>?) {\n            switch closeState {\n            case .open:\n                assertionFailure(\n                    \"We are in .open state after being asked to close. This should never happen.\"\n                )\n                self = .errored(NIOReportedOpenAfterClose(), promise)\n            case .pending:\n                // `promise` has already been taken care of in the pending state for later completion\n                self = .pending\n            case .readyForClose(let closePromise):\n                if isEmpty {\n                    self = .readyForClose(closePromise)\n                } else {\n                    assertionFailure(\n                        \"We are in .readyForClose state but we still have pending writes. This should never happen.\"\n                    )\n                    // `promise` has already been cascaded off `closePromise`\n                    self = .errored(NIOReportedPendingWritesInInvalidState(), closePromise)\n                }\n            case .closed:\n                if isEmpty {\n                    self = .closed(promise)\n                } else {\n                    assertionFailure(\n                        \"We are in .closed state but we still have pending writes. This should never happen.\"\n                    )\n                    self = .errored(NIOReportedPendingWritesInInvalidState(), promise)\n                }\n            }\n        }\n    }\n\n    /// Signal the intention to close. Takes a promise which will be returned for completing when pending writes are dealt with\n    ///\n    /// - Parameters:\n    ///   - promise: Optionally an `EventLoopPromise` which is stored and is returned to be completed by the caller once\n    ///              all outstanding writes have been dealt with or an error condition is encountered.\n    func closeOutbound(_ promise: EventLoopPromise<Void>?) -> CloseOutboundResult {\n        // Update our internal state\n        switch self.outboundCloseState {\n        case .open:\n            if self.isEmpty {\n                self.outboundCloseState = .readyForClose(promise)\n            } else {\n                self.outboundCloseState = .pending(promise)\n            }\n        case .readyForClose(var closePromise):\n            closePromise.setOrCascade(to: promise)\n            self.outboundCloseState = .readyForClose(closePromise)\n        case .pending(var closePromise):\n            closePromise.setOrCascade(to: promise)\n            if self.isEmpty {\n                self.outboundCloseState = .readyForClose(closePromise)\n            } else {\n                self.outboundCloseState = .pending(closePromise)\n            }\n        case .closed:\n            ()\n        }\n\n        // Decide on the result\n        let result = CloseOutboundResult(self.outboundCloseState, self.isEmpty, promise)\n        switch result {\n        case .pending, .readyForClose:\n            ()\n        case .closed, .errored:\n            self.isOpen = false\n        }\n\n        return result\n    }\n\n    /// Initialize with a pre-allocated array of IO vectors and storage references. We pass in these pre-allocated\n    /// objects to save allocations. They can be safely be re-used for all `Channel`s on a given `EventLoop` as an\n    /// `EventLoop` always runs on one and the same thread. That means that there can't be any writes of more than\n    /// one `Channel` on the same `EventLoop` at the same time.\n    ///\n    /// - Parameters:\n    ///   - bufferPool: Pool of buffers to be used for iovecs and storage references\n    init(bufferPool: Pool<PooledBuffer>) {\n        self.bufferPool = bufferPool\n    }\n}\n\ninternal enum WriteMechanism {\n    case scalarBufferWrite\n    case vectorBufferWrite\n    case scalarFileWrite\n    case nothingToBeWritten\n}\n\ninternal protocol PendingWritesManager: AnyObject {\n    var isOpen: Bool { get }\n    var isEmpty: Bool { get }\n    var outboundCloseState: CloseState { get }\n    var isFlushPending: Bool { get }\n    var writeSpinCount: UInt { get }\n    var currentBestWriteMechanism: WriteMechanism { get }\n    var channelWritabilityFlag: ManagedAtomic<Bool> { get }\n\n    /// Represents the writability state the last time we published a writability change to the `Channel`.\n    /// This is used in `triggerWriteOperations` to determine whether we need to trigger a writability\n    /// change.\n    var publishedWritability: Bool { get set }\n}\n\n/// Describes the state that a `PendingWritesManager` closure state machine will step through when instructed to close\ninternal enum CloseState {\n    /// The manager will accept new writes\n    case open\n    /// The manager has been asked to close but cannot because its write buffer is not empty\n    case pending(EventLoopPromise<Void>?)\n    /// The manager has been asked to close and is ready to be closed because its write buffer is empty\n    case readyForClose(EventLoopPromise<Void>?)\n    /// The manager is closed\n    case closed\n}\n\nextension PendingWritesManager {\n    // This is called from `Channel` API so must be thread-safe.\n    var isWritable: Bool {\n        self.channelWritabilityFlag.load(ordering: .relaxed)\n    }\n\n    internal func triggerWriteOperations(\n        triggerOneWriteOperation: (WriteMechanism) throws -> OneWriteOperationResult\n    ) throws -> OverallWriteResult {\n        var result = OverallWriteResult(writeResult: .couldNotWriteEverything, writabilityChange: false)\n\n        writeSpinLoop: for _ in 0...self.writeSpinCount {\n            var oneResult: OneWriteOperationResult\n            repeat {\n                guard self.isOpen && self.isFlushPending else {\n                    result.writeResult = .writtenCompletely(.init(self.outboundCloseState))\n                    break writeSpinLoop\n                }\n\n                oneResult = try triggerOneWriteOperation(self.currentBestWriteMechanism)\n                if oneResult == .wouldBlock {\n                    break writeSpinLoop\n                }\n            } while oneResult == .writtenCompletely\n        }\n\n        // Please note that the re-entrancy protection in `flushNow` expects this code to try to write _all_ the data\n        // that is flushed. If we receive a `flush` whilst processing a previous `flush`, we won't do anything because\n        // we expect this loop to attempt to attempt all writes, even ones that arrive after this method begins to run.\n        //\n        // In other words, don't return `.writtenCompletely` unless you've written everything the PendingWritesManager\n        // knows to be flushed.\n        //\n        // Also, it is very important to not do any outcalls to user code outside of the loop until the `flushNow`\n        // re-entrancy protection is off again.\n\n        if !self.publishedWritability {\n            // When we last published a writability change the `Channel` wasn't writable, signal back to the caller\n            // whether we should emit a writability change.\n            result.writabilityChange = self.isWritable\n            self.publishedWritability = result.writabilityChange\n        }\n        return result\n    }\n}\n\nextension PendingStreamWritesManager: CustomStringConvertible {\n    var description: String {\n        \"PendingStreamWritesManager { isFlushPending: \\(self.isFlushPending), \"\n            + \"writabilityFlag: \\(self.channelWritabilityFlag.load(ordering: .relaxed))), state: \\(self.state) }\"\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PipeChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\nfinal class PipeChannel: BaseStreamSocketChannel<PipePair>, @unchecked Sendable {\n    private let pipePair: PipePair\n\n    internal enum Direction {\n        case input\n        case output\n    }\n\n    init(\n        eventLoop: SelectableEventLoop,\n        input: SelectablePipeHandle?,\n        output: SelectablePipeHandle?\n    ) throws {\n        self.pipePair = try PipePair(input: input, output: output)\n        try super.init(\n            socket: self.pipePair,\n            parent: nil,\n            eventLoop: eventLoop,\n            recvAllocator: AdaptiveRecvByteBufferAllocator()\n        )\n    }\n\n    func registrationForInput(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration {\n        NIORegistration(\n            channel: .pipeChannel(self, .input),\n            interested: interested,\n            registrationID: registrationID\n        )\n    }\n\n    func registrationForOutput(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration\n    {\n        NIORegistration(\n            channel: .pipeChannel(self, .output),\n            interested: interested,\n            registrationID: registrationID\n        )\n    }\n\n    override func connectSocket(to address: SocketAddress) throws -> Bool {\n        throw ChannelError._operationUnsupported\n    }\n\n    override func connectSocket(to address: VsockAddress) throws -> Bool {\n        throw ChannelError._operationUnsupported\n    }\n\n    override func finishConnectSocket() throws {\n        throw ChannelError._inappropriateOperationForState\n    }\n\n    override func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        if let inputSPH = self.pipePair.input {\n            try selector.register(\n                selectable: inputSPH,\n                interested: interested.intersection([.read, .reset, .error]),\n                makeRegistration: self.registrationForInput\n            )\n        }\n\n        if let outputSPH = self.pipePair.output {\n            try selector.register(\n                selectable: outputSPH,\n                interested: interested.intersection([.write, .reset, .error]),\n                makeRegistration: self.registrationForOutput\n            )\n        }\n    }\n\n    override func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws {\n        if let inputSPH = self.pipePair.input, (mode == .all || mode == .input) && inputSPH.isOpen {\n            try selector.deregister(selectable: inputSPH)\n        }\n        if let outputSPH = self.pipePair.output, (mode == .all || mode == .output) && outputSPH.isOpen {\n            try selector.deregister(selectable: outputSPH)\n        }\n    }\n\n    override func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        if let inputSPH = self.pipePair.input, inputSPH.isOpen {\n            try selector.reregister(\n                selectable: inputSPH,\n                interested: interested.intersection([.read, .reset, .error])\n            )\n        }\n        if let outputSPH = self.pipePair.output, outputSPH.isOpen {\n            try selector.reregister(\n                selectable: outputSPH,\n                interested: interested.intersection([.write, .reset, .error])\n            )\n        }\n    }\n\n    override func readEOF() {\n        super.readEOF()\n        guard let inputSPH = self.pipePair.input, inputSPH.isOpen else {\n            return\n        }\n        try! self.selectableEventLoop.deregister(channel: self, mode: .input)\n        try! inputSPH.close()\n    }\n\n    override func writeEOF() {\n        guard let outputSPH = self.pipePair.output, outputSPH.isOpen else {\n            return\n        }\n        try! self.selectableEventLoop.deregister(channel: self, mode: .output)\n        try! outputSPH.close()\n\n        // Only close the entire channel if the input is already closed.\n        // If input is still open, we can continue half-duplex operation.\n        var inputIsClosed = true\n        if let inputSPH = self.pipePair.input {\n            inputIsClosed = !inputSPH.isOpen\n        }\n        if inputIsClosed {\n            let error = IOError(errnoCode: EPIPE, reason: \"Broken pipe\")\n            self.close0(error: error, mode: .all, promise: nil)\n        }\n    }\n\n    override func shutdownSocket(mode: CloseMode) throws {\n        switch mode {\n        case .input:\n            try! self.selectableEventLoop.deregister(channel: self, mode: .input)\n        case .output:\n            try! self.selectableEventLoop.deregister(channel: self, mode: .output)\n        case .all:\n            break\n        }\n        try super.shutdownSocket(mode: mode)\n    }\n}\n\nextension PipeChannel: CustomStringConvertible {\n    var description: String {\n        \"PipeChannel { \\(self.socketDescription), active = \\(self.isActive), localAddress = \\(self.localAddress.debugDescription), remoteAddress = \\(self.remoteAddress.debugDescription) }\"\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PipePair.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if canImport(WinSDK)\nimport struct WinSDK.socklen_t\n#endif\n\nfinal class SelectablePipeHandle {\n    var fileDescriptor: NIOBSDSocket.Handle\n\n    var isOpen: Bool {\n        self.fileDescriptor >= 0\n    }\n\n    init(takingOwnershipOfDescriptor fd: NIOBSDSocket.Handle) {\n        precondition(fd >= 0)\n        self.fileDescriptor = fd\n    }\n\n    func close() throws {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        let fd = try self.takeDescriptorOwnership()\n        try Posix.close(descriptor: fd)\n        #endif\n    }\n\n    func takeDescriptorOwnership() throws -> NIOBSDSocket.Handle {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        guard self.isOpen else {\n            throw IOError(errnoCode: EBADF, reason: \"SelectablePipeHandle already closed [in close]\")\n        }\n        defer {\n            self.fileDescriptor = -1\n        }\n        return self.fileDescriptor\n        #endif\n    }\n\n    deinit {\n        assert(!self.isOpen, \"leaking \\(self)\")\n    }\n}\n\nextension SelectablePipeHandle: Selectable {\n    func withUnsafeHandle<T>(_ body: (NIOBSDSocket.Handle) throws -> T) throws -> T {\n        guard self.isOpen else {\n            throw IOError(errnoCode: EBADF, reason: \"SelectablePipeHandle already closed [in wUH]\")\n        }\n        return try body(self.fileDescriptor)\n    }\n}\n\nextension SelectablePipeHandle: CustomStringConvertible {\n    public var description: String {\n        \"SelectableFileHandle(isOpen: \\(self.isOpen), fd: \\(self.fileDescriptor))\"\n    }\n}\n\nfinal class PipePair: SocketProtocol {\n    typealias SelectableType = SelectablePipeHandle\n\n    let input: SelectablePipeHandle?\n    let output: SelectablePipeHandle?\n\n    init(input: SelectablePipeHandle?, output: SelectablePipeHandle?) throws {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        self.input = input\n        self.output = output\n        try self.ignoreSIGPIPE()\n        for fh in [input, output].compactMap({ $0 }) {\n            try fh.withUnsafeHandle { fd in\n                try NIOFileHandle.setNonBlocking(fileDescriptor: fd)\n            }\n        }\n        #endif\n    }\n\n    func ignoreSIGPIPE() throws {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        for fileHandle in [self.input, self.output].compactMap({ $0 }) {\n            try fileHandle.withUnsafeHandle {\n                try PipePair.ignoreSIGPIPE(descriptor: $0)\n            }\n        }\n        #endif\n    }\n\n    var description: String {\n        \"PipePair { in=\\(String(describing: self.input)), out=\\(String(describing: self.output)) }\"\n    }\n\n    func connect(to address: SocketAddress) throws -> Bool {\n        throw ChannelError._operationUnsupported\n    }\n\n    func finishConnect() throws {\n        throw ChannelError._operationUnsupported\n    }\n\n    func write(pointer: UnsafeRawBufferPointer) throws -> IOResult<Int> {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        guard let outputSPH = self.output else {\n            fatalError(\"Internal inconsistency inside NIO: outputSPH closed on write. Please file a bug\")\n        }\n        return try outputSPH.withUnsafeHandle {\n            try Posix.write(descriptor: $0, pointer: pointer.baseAddress!, size: pointer.count)\n        }\n        #endif\n    }\n\n    func writev(iovecs: UnsafeBufferPointer<IOVector>) throws -> IOResult<Int> {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        guard let outputSPH = self.output else {\n            fatalError(\"Internal inconsistency inside NIO: outputSPH closed on writev. Please file a bug\")\n        }\n        return try outputSPH.withUnsafeHandle {\n            try Posix.writev(descriptor: $0, iovecs: iovecs)\n        }\n        #endif\n    }\n\n    func read(pointer: UnsafeMutableRawBufferPointer) throws -> IOResult<Int> {\n        #if os(Windows)\n        fatalError(missingPipeSupportWindows)\n        #else\n        guard let inputSPH = self.input else {\n            fatalError(\"Internal inconsistency inside NIO: inputSPH closed on read. Please file a bug\")\n        }\n        return try inputSPH.withUnsafeHandle {\n            try Posix.read(descriptor: $0, pointer: pointer.baseAddress!, size: pointer.count)\n        }\n        #endif\n    }\n\n    func recvmsg(\n        pointer: UnsafeMutableRawBufferPointer,\n        storage: inout sockaddr_storage,\n        storageLen: inout socklen_t,\n        controlBytes: inout UnsafeReceivedControlBytes\n    ) throws -> IOResult<Int> {\n        throw ChannelError._operationUnsupported\n    }\n\n    func sendmsg(\n        pointer: UnsafeRawBufferPointer,\n        destinationPtr: UnsafePointer<sockaddr>?,\n        destinationSize: socklen_t,\n        controlBytes: UnsafeMutableRawBufferPointer\n    ) throws -> IOResult<Int> {\n        throw ChannelError._operationUnsupported\n    }\n\n    func sendFile(fd: CInt, offset: Int, count: Int) throws -> IOResult<Int> {\n        throw ChannelError._operationUnsupported\n    }\n\n    func recvmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int> {\n        throw ChannelError._operationUnsupported\n    }\n\n    func sendmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int> {\n        throw ChannelError._operationUnsupported\n    }\n\n    func shutdown(how: Shutdown) throws {\n        switch how {\n        case .RD:\n            try self.input?.close()\n        case .WR:\n            try self.output?.close()\n        case .RDWR:\n            try self.close()\n        }\n    }\n\n    var isOpen: Bool {\n        self.input?.isOpen ?? false || self.output?.isOpen ?? false\n    }\n\n    func close() throws {\n        guard self.isOpen else {\n            throw ChannelError._alreadyClosed\n        }\n        let r1 = Result {\n            if let inputFD = self.input, inputFD.isOpen {\n                try inputFD.close()\n            }\n        }\n        let r2 = Result {\n            if let outputFD = self.output, outputFD.isOpen {\n                try outputFD.close()\n            }\n        }\n        try r1.get()\n        try r2.get()\n    }\n\n    func bind(to address: SocketAddress) throws {\n        throw ChannelError._operationUnsupported\n    }\n\n    func localAddress() throws -> SocketAddress {\n        throw ChannelError._operationUnsupported\n    }\n\n    func remoteAddress() throws -> SocketAddress {\n        throw ChannelError._operationUnsupported\n    }\n\n    func setOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option, value: T) throws {\n        throw ChannelError._operationUnsupported\n    }\n\n    func getOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) throws -> T {\n        throw ChannelError._operationUnsupported\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Pool.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nprotocol PoolElement {\n    init()\n    func evictedFromPool()\n}\n\nclass Pool<Element: PoolElement> {\n    private let maxSize: Int\n    private var elements: [Element]\n\n    init(maxSize: Int) {\n        self.maxSize = maxSize\n        self.elements = [Element]()\n    }\n\n    deinit {\n        for e in elements {\n            e.evictedFromPool()\n        }\n    }\n\n    func get() -> Element {\n        if elements.isEmpty {\n            return Element()\n        } else {\n            return elements.removeLast()\n        }\n    }\n\n    func put(_ e: Element) {\n        if elements.count == maxSize {\n            e.evictedFromPool()\n        } else {\n            elements.append(e)\n        }\n    }\n}\n\n/// A ``PooledBuffer`` is used to track an allocation of memory required\n/// by a `Channel` or `EventLoopGroup`.\n///\n/// ``PooledBuffer`` is a reference type with inline storage. It is intended to\n/// be bound to a single thread, and ensures that the allocation it stores does not\n/// get freed before the buffer is out of use.\nstruct PooledBuffer: PoolElement {\n    private static let sentinelValue = MemorySentinel(0xdead_beef)\n\n    private let storage: BackingStorage\n\n    init() {\n        self.storage = .create(iovectorCount: Socket.writevLimitIOVectors)\n        self.configureSentinel()\n    }\n\n    func evictedFromPool() {\n        self.validateSentinel()\n    }\n\n    func withUnsafePointers<ReturnValue>(\n        _ body: (UnsafeMutableBufferPointer<IOVector>, UnsafeMutableBufferPointer<Unmanaged<AnyObject>>) throws ->\n            ReturnValue\n    ) rethrows -> ReturnValue {\n        defer {\n            self.validateSentinel()\n        }\n        return try self.storage.withUnsafeMutableTypedPointers { iovecPointer, ownerPointer, _ in\n            try body(iovecPointer, ownerPointer)\n        }\n    }\n\n    /// Yields buffer pointers containing this ``PooledBuffer``'s readable bytes. You may hold a pointer to those bytes\n    /// even after the closure has returned iff you model the lifetime of those bytes correctly using the `Unmanaged`\n    /// instance. If you don't require the pointer after the closure returns, use ``withUnsafePointers``.\n    ///\n    /// If you escape the pointer from the closure, you _must_ call `storageManagement.retain()` to get ownership to\n    /// the bytes and you also must call `storageManagement.release()` if you no longer require those bytes. Calls to\n    /// `retain` and `release` must be balanced.\n    ///\n    /// - Parameters:\n    ///   - body: The closure that will accept the yielded pointers and the `storageManagement`.\n    /// - Returns: The value returned by `body`.\n    func withUnsafePointersWithStorageManagement<ReturnValue>(\n        _ body: (\n            UnsafeMutableBufferPointer<IOVector>, UnsafeMutableBufferPointer<Unmanaged<AnyObject>>, Unmanaged<AnyObject>\n        ) throws -> ReturnValue\n    ) rethrows -> ReturnValue {\n        let storageRef: Unmanaged<AnyObject> = Unmanaged.passUnretained(self.storage)\n        return try self.storage.withUnsafeMutableTypedPointers { iovecPointer, ownerPointer, _ in\n            try body(iovecPointer, ownerPointer, storageRef)\n        }\n    }\n\n    private func configureSentinel() {\n        self.storage.withUnsafeMutableTypedPointers { _, _, sentinelPointer in\n            sentinelPointer.pointee = Self.sentinelValue\n        }\n    }\n\n    private func validateSentinel() {\n        self.storage.withUnsafeMutableTypedPointers { _, _, sentinelPointer in\n            precondition(sentinelPointer.pointee == Self.sentinelValue, \"Detected memory handling error!\")\n        }\n    }\n}\n\nextension PooledBuffer {\n    fileprivate typealias MemorySentinel = UInt32\n\n    fileprivate struct PooledBufferHead {\n        let iovectorCount: Int\n\n        let spaceForIOVectors: Int\n\n        let spaceForBufferOwners: Int\n\n        init(iovectorCount: Int) {\n            var spaceForIOVectors = MemoryLayout<IOVector>.stride * iovectorCount\n            spaceForIOVectors.roundUpToAlignment(for: Unmanaged<AnyObject>.self)\n\n            var spaceForBufferOwners = MemoryLayout<Unmanaged<AnyObject>>.stride * iovectorCount\n            spaceForBufferOwners.roundUpToAlignment(for: MemorySentinel.self)\n\n            self.iovectorCount = iovectorCount\n            self.spaceForIOVectors = spaceForIOVectors\n            self.spaceForBufferOwners = spaceForBufferOwners\n        }\n\n        var totalByteCount: Int {\n            self.spaceForIOVectors + self.spaceForBufferOwners + MemoryLayout<MemorySentinel>.size\n        }\n\n        var iovectorOffset: Int {\n            0\n        }\n\n        var bufferOwnersOffset: Int {\n            self.spaceForIOVectors\n        }\n\n        var memorySentinelOffset: Int {\n            self.spaceForIOVectors + self.spaceForBufferOwners\n        }\n    }\n\n    fileprivate final class BackingStorage: ManagedBuffer<PooledBufferHead, UInt8> {\n        static func create(iovectorCount: Int) -> Self {\n            let head = PooledBufferHead(iovectorCount: iovectorCount)\n\n            let baseStorage = Self.create(minimumCapacity: head.totalByteCount) { _ in\n                head\n            }\n\n            // Here we set up our memory bindings.\n\n            // Intentionally using a force cast here to avoid a miss compiliation in 5.10.\n            // This is as fast as an unsafeDownCast since ManagedBuffer is inlined and the optimizer\n            // can eliminate the upcast/downcast pair\n            let storage = baseStorage as! Self\n            storage.withUnsafeMutablePointers { headPointer, tailPointer in\n                UnsafeRawPointer(tailPointer + headPointer.pointee.iovectorOffset).bindMemory(\n                    to: IOVector.self,\n                    capacity: iovectorCount\n                )\n                UnsafeRawPointer(tailPointer + headPointer.pointee.bufferOwnersOffset).bindMemory(\n                    to: Unmanaged<AnyObject>.self,\n                    capacity: iovectorCount\n                )\n                UnsafeRawPointer(tailPointer + headPointer.pointee.memorySentinelOffset).bindMemory(\n                    to: MemorySentinel.self,\n                    capacity: 1\n                )\n            }\n\n            return storage\n        }\n\n        func withUnsafeMutableTypedPointers<ReturnType>(\n            _ body: (\n                UnsafeMutableBufferPointer<IOVector>, UnsafeMutableBufferPointer<Unmanaged<AnyObject>>,\n                UnsafeMutablePointer<MemorySentinel>\n            ) throws -> ReturnType\n        ) rethrows -> ReturnType {\n            try self.withUnsafeMutablePointers { headPointer, tailPointer in\n                let iovecPointer = UnsafeMutableRawPointer(tailPointer + headPointer.pointee.iovectorOffset)\n                    .assumingMemoryBound(to: IOVector.self)\n                let ownersPointer = UnsafeMutableRawPointer(tailPointer + headPointer.pointee.bufferOwnersOffset)\n                    .assumingMemoryBound(to: Unmanaged<AnyObject>.self)\n                let sentinelPointer = UnsafeMutableRawPointer(tailPointer + headPointer.pointee.memorySentinelOffset)\n                    .assumingMemoryBound(to: MemorySentinel.self)\n\n                let iovecBufferPointer = UnsafeMutableBufferPointer(\n                    start: iovecPointer,\n                    count: headPointer.pointee.iovectorCount\n                )\n                let ownersBufferPointer = UnsafeMutableBufferPointer(\n                    start: ownersPointer,\n                    count: headPointer.pointee.iovectorCount\n                )\n                return try body(iovecBufferPointer, ownersBufferPointer, sentinelPointer)\n            }\n        }\n    }\n}\n\nextension Int {\n    fileprivate mutating func roundUpToAlignment<Type>(for: Type.Type) {\n        // Alignment is always positive, we can use unchecked subtraction here.\n        let alignmentGuide = MemoryLayout<Type>.alignment &- 1\n\n        // But we can't use unchecked addition.\n        self = (self + alignmentGuide) & (~alignmentGuide)\n    }\n}\n\nstruct PooledMsgBuffer: PoolElement {\n\n    private typealias MemorySentinel = UInt32\n    private static let sentinelValue = MemorySentinel(0xdead_beef)\n\n    private struct PooledMsgBufferHead {\n        let count: Int\n        let spaceForMsgHdrs: Int\n        let spaceForAddresses: Int\n        let spaceForControlData: Int\n\n        init(count: Int) {\n            var spaceForMsgHdrs = MemoryLayout<MMsgHdr>.stride * count\n            spaceForMsgHdrs.roundUpToAlignment(for: sockaddr_storage.self)\n\n            var spaceForAddress = MemoryLayout<sockaddr_storage>.stride * count\n            spaceForAddress.roundUpToAlignment(for: MemorySentinel.self)\n\n            var spaceForControlData = (UnsafeControlMessageStorage.bytesPerMessage * count)\n            spaceForControlData.roundUpToAlignment(for: cmsghdr.self)\n\n            self.count = count\n            self.spaceForMsgHdrs = spaceForMsgHdrs\n            self.spaceForAddresses = spaceForAddress\n            self.spaceForControlData = spaceForControlData\n        }\n\n        var totalByteCount: Int {\n            self.spaceForMsgHdrs + self.spaceForAddresses + self.spaceForControlData + MemoryLayout<MemorySentinel>.size\n        }\n\n        var msgHdrsOffset: Int {\n            0\n        }\n\n        var addressesOffset: Int {\n            self.spaceForMsgHdrs\n        }\n\n        var controlDataOffset: Int {\n            self.spaceForMsgHdrs + self.spaceForAddresses\n        }\n\n        var memorySentinelOffset: Int {\n            self.spaceForMsgHdrs + self.spaceForAddresses + self.spaceForControlData\n        }\n    }\n\n    private class BackingStorage: ManagedBuffer<PooledMsgBufferHead, UInt8> {\n        static func create(count: Int) -> Self {\n            let head = PooledMsgBufferHead(count: count)\n\n            let baseStorage = Self.create(minimumCapacity: head.totalByteCount) { _ in\n                head\n            }\n\n            // Intentionally using a force cast here to avoid a miss compiliation in 5.10.\n            // This is as fast as an unsafeDownCast since ManagedBuffer is inlined and the optimizer\n            // can eliminate the upcast/downcast pair\n            let storage = baseStorage as! Self\n            storage.withUnsafeMutablePointers { headPointer, tailPointer in\n                UnsafeRawPointer(tailPointer + headPointer.pointee.msgHdrsOffset).bindMemory(\n                    to: MMsgHdr.self,\n                    capacity: count\n                )\n                UnsafeRawPointer(tailPointer + headPointer.pointee.addressesOffset).bindMemory(\n                    to: sockaddr_storage.self,\n                    capacity: count\n                )\n                // space for control message data not needed to be bound\n                UnsafeRawPointer(tailPointer + headPointer.pointee.memorySentinelOffset).bindMemory(\n                    to: MemorySentinel.self,\n                    capacity: 1\n                )\n            }\n\n            return storage\n        }\n\n        func withUnsafeMutableTypedPointers<ReturnType>(\n            _ body: (\n                UnsafeMutableBufferPointer<MMsgHdr>, UnsafeMutableBufferPointer<sockaddr_storage>,\n                UnsafeControlMessageStorage, UnsafeMutablePointer<MemorySentinel>\n            ) throws -> ReturnType\n        ) rethrows -> ReturnType {\n            try self.withUnsafeMutablePointers { headPointer, tailPointer in\n                let msgHdrsPointer = UnsafeMutableRawPointer(tailPointer + headPointer.pointee.msgHdrsOffset)\n                    .assumingMemoryBound(to: MMsgHdr.self)\n                let addressesPointer = UnsafeMutableRawPointer(tailPointer + headPointer.pointee.addressesOffset)\n                    .assumingMemoryBound(to: sockaddr_storage.self)\n                let controlDataPointer = UnsafeMutableRawBufferPointer(\n                    start: tailPointer + headPointer.pointee.controlDataOffset,\n                    count: headPointer.pointee.spaceForControlData\n                )\n                let sentinelPointer = UnsafeMutableRawPointer(tailPointer + headPointer.pointee.memorySentinelOffset)\n                    .assumingMemoryBound(to: MemorySentinel.self)\n\n                let msgHdrsBufferPointer = UnsafeMutableBufferPointer(\n                    start: msgHdrsPointer,\n                    count: headPointer.pointee.count\n                )\n                let addressesBufferPointer = UnsafeMutableBufferPointer(\n                    start: addressesPointer,\n                    count: headPointer.pointee.count\n                )\n                let controlMessageStorage = UnsafeControlMessageStorage.makeNotOwning(\n                    bytesPerMessage: UnsafeControlMessageStorage.bytesPerMessage,\n                    buffer: controlDataPointer\n                )\n                return try body(msgHdrsBufferPointer, addressesBufferPointer, controlMessageStorage, sentinelPointer)\n            }\n        }\n    }\n\n    private func validateSentinel() {\n        self.storage.withUnsafeMutableTypedPointers { _, _, _, sentinelPointer in\n            precondition(sentinelPointer.pointee == Self.sentinelValue, \"Detected memory handling error!\")\n        }\n    }\n\n    private var storage: BackingStorage\n\n    init() {\n        self.storage = .create(count: Socket.writevLimitIOVectors)\n        self.storage.withUnsafeMutableTypedPointers { _, _, _, sentinelPointer in\n            sentinelPointer.pointee = Self.sentinelValue\n        }\n    }\n\n    func evictedFromPool() {\n        self.validateSentinel()\n    }\n\n    func withUnsafePointers<ReturnValue>(\n        _ body: (\n            UnsafeMutableBufferPointer<MMsgHdr>, UnsafeMutableBufferPointer<sockaddr_storage>,\n            UnsafeControlMessageStorage\n        ) throws -> ReturnValue\n    ) rethrows -> ReturnValue {\n        defer {\n            self.validateSentinel()\n        }\n        return try self.storage.withUnsafeMutableTypedPointers { msgs, addresses, controlMessageStorage, _ in\n            try body(msgs, addresses, controlMessageStorage)\n        }\n    }\n\n    func withUnsafePointersWithStorageManagement<ReturnValue>(\n        _ body: (\n            UnsafeMutableBufferPointer<MMsgHdr>, UnsafeMutableBufferPointer<sockaddr_storage>,\n            UnsafeControlMessageStorage, Unmanaged<AnyObject>\n        ) throws -> ReturnValue\n    ) rethrows -> ReturnValue {\n        let storageRef: Unmanaged<AnyObject> = Unmanaged.passUnretained(self.storage)\n        return try self.storage.withUnsafeMutableTypedPointers { msgs, addresses, controlMessageStorage, _ in\n            try body(msgs, addresses, controlMessageStorage, storageRef)\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PosixSingletons+ConcurrencyTakeOver.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport NIOCore\n\nprivate protocol SilenceWarning {\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    func enqueue(_ job: UnownedJob)\n}\n@available(macOS 14, *)\nextension SelectableEventLoop: SilenceWarning {}\n\nprivate let _haveWeTakenOverTheConcurrencyPool = ManagedAtomic(false)\nextension NIOSingletons {\n    /// Install ``MultiThreadedEventLoopGroup/singleton`` as Swift Concurrency's global executor.\n    ///\n    /// This allows to use Swift Concurrency and retain high-performance I/O alleviating the otherwise necessary thread switches between\n    /// Swift Concurrency's own global pool and a place (like an `EventLoop`) that allows to perform I/O\n    ///\n    /// This method uses an atomic compare and exchange to install the hook (and makes sure it's not already set). This unilateral atomic memory\n    /// operation doesn't guarantee anything because another piece of code could have done the same without using atomic operations. But we\n    /// do our best.\n    ///\n    /// - Returns: If ``MultiThreadedEventLoopGroup/singleton`` was successfully installed as Swift Concurrency's global executor or not.\n    ///\n    /// - warning: You may only call this method from the main thread.\n    /// - warning: You may only call this method once.\n    /// - warning: This method is currently not supported on Windows and will return false.\n    @discardableResult\n    public static func unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor() -> Bool {\n        #if os(Windows)\n        return false\n        #else\n        // Guard between the minimum and maximum supported version for the hook\n        #if compiler(<6.4)\n        guard #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) else {\n            return false\n        }\n\n        typealias ConcurrencyEnqueueGlobalHook =\n            @convention(thin) (\n                UnownedJob, @convention(thin) (UnownedJob) -> Void\n            ) -> Void\n\n        guard\n            _haveWeTakenOverTheConcurrencyPool.compareExchange(\n                expected: false,\n                desired: true,\n                ordering: .relaxed\n            ).exchanged\n        else {\n            fatalError(\"Must be called only once\")\n        }\n\n        #if canImport(Darwin)\n        guard pthread_main_np() == 1 else {\n            fatalError(\"Must be called from the main thread\")\n        }\n        #endif\n\n        // Unsafe 1: We pretend that the hook's type is actually fully equivalent to `ConcurrencyEnqueueGlobalHook`\n        //   @convention(thin) (UnownedJob, @convention(thin) (UnownedJob) -> Void) -> Void\n        // which isn't formally guaranteed.\n        let concurrencyEnqueueGlobalHookPtr = dlsym(\n            dlopen(nil, RTLD_NOW),\n            \"swift_task_enqueueGlobal_hook\"\n        )?.assumingMemoryBound(to: UnsafeRawPointer?.AtomicRep.self)\n        guard let concurrencyEnqueueGlobalHookPtr = concurrencyEnqueueGlobalHookPtr else {\n            return false\n        }\n\n        // We will use an atomic operation to swap the pointers aiming to protect against other code that attempts\n        // to swap the pointer. This isn't guaranteed to work as we can't be sure that the other code will actually\n        // use atomic compares and exchanges to. Nevertheless, we're doing our best.\n        let concurrencyEnqueueGlobalHookAtomic = UnsafeAtomic<UnsafeRawPointer?>(at: concurrencyEnqueueGlobalHookPtr)\n        // note: We don't need to destroy this atomic as we're borrowing the storage from `dlsym`.\n\n        return withUnsafeTemporaryAllocation(\n            of: ConcurrencyEnqueueGlobalHook.self,\n            capacity: 1\n        ) { enqueueOnNIOPtr -> Bool in\n            // Unsafe 2: We mandate that we're actually getting _the_ function pointer to the closure below which\n            // isn't formally guaranteed by Swift.\n            enqueueOnNIOPtr.baseAddress!.initialize(to: { job, _ in\n                // This formally picks a random EventLoop from the singleton group. However, `EventLoopGroup.any()`\n                // attempts to be sticky. So if we're already in an `EventLoop` that's part of the singleton\n                // `EventLoopGroup`, we'll get that one and be very fast (avoid a thread switch).\n                let targetEL = MultiThreadedEventLoopGroup.singleton.anySEL()\n\n                (targetEL as any SilenceWarning).enqueue(job)\n            })\n\n            // Unsafe 3: We mandate that the function pointer can be reinterpreted as `UnsafeRawPointer` which isn't\n            // formally guaranteed by Swift\n            return enqueueOnNIOPtr.baseAddress!.withMemoryRebound(\n                to: UnsafeRawPointer.self,\n                capacity: 1\n            ) { enqueueOnNIOPtr in\n                // Unsafe 4: We just pretend that we're the only ones in the world pulling this trick (or at least\n                // that the others also use a `compareExchange`)...\n                guard\n                    concurrencyEnqueueGlobalHookAtomic.compareExchange(\n                        expected: nil,\n                        desired: enqueueOnNIOPtr.pointee,\n                        ordering: .relaxed\n                    ).exchanged\n                else {\n                    return false\n                }\n\n                // nice, everything worked.\n                return true\n            }\n        }\n        #else\n        return false\n        #endif\n        #endif  // windows unimplemented\n    }\n}\n\n// Workaround for https://github.com/apple/swift-nio/issues/2893\nextension Optional\nwhere\n    Wrapped: AtomicOptionalWrappable,\n    Wrapped.AtomicRepresentation.Value == Wrapped\n{\n    typealias AtomicRep = Wrapped.AtomicOptionalRepresentation\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PosixSingletons.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\nextension NIOSingletons {\n    /// A globally shared, lazily initialized ``MultiThreadedEventLoopGroup``  that uses `epoll`/`kqueue` as the\n    /// selector mechanism.\n    ///\n    /// The number of threads is determined by `NIOSingletons/groupLoopCountSuggestion`.\n    public static var posixEventLoopGroup: MultiThreadedEventLoopGroup {\n        singletonMTELG\n    }\n\n    /// A globally shared, lazily initialized ``NIOThreadPool`` that can be used for blocking I/O and other blocking operations.\n    ///\n    /// The number of threads is determined by `NIOSingletons/blockingPoolThreadCountSuggestion`.\n    public static var posixBlockingThreadPool: NIOThreadPool {\n        globalPosixBlockingPool\n    }\n}\n\nextension MultiThreadedEventLoopGroup {\n    /// A globally shared, singleton ``MultiThreadedEventLoopGroup``.\n    ///\n    /// SwiftNIO allows and encourages the precise management of all operating system resources such as threads and file descriptors.\n    /// Certain resources (such as the main `EventLoopGroup`) however are usually globally shared across the program. This means\n    /// that many programs have to carry around an `EventLoopGroup` despite the fact they don't require the ability to fully return\n    /// all the operating resources which would imply shutting down the `EventLoopGroup`. This type is the global handle for singleton\n    /// resources that applications (and some libraries) can use to obtain never-shut-down singleton resources.\n    ///\n    /// Programs and libraries that do not use these singletons will not incur extra resource usage, these resources are lazily initialized on\n    /// first use.\n    ///\n    /// The loop count of this group is determined by `NIOSingletons/groupLoopCountSuggestion`.\n    ///\n    /// - Note: Users who do not want any code to spawn global singleton resources may set\n    ///         `NIOSingletons/singletonsEnabledSuggestion` to `false` which will lead to a forced crash\n    ///         if any code attempts to use the global singletons.\n    ///\n    public static var singleton: MultiThreadedEventLoopGroup {\n        NIOSingletons.posixEventLoopGroup\n    }\n}\n\n// swift-format-ignore: DontRepeatTypeInStaticProperties\nextension EventLoopGroup where Self == MultiThreadedEventLoopGroup {\n    /// A globally shared, singleton ``MultiThreadedEventLoopGroup``.\n    ///\n    /// This provides the same object as ``MultiThreadedEventLoopGroup/singleton``.\n    public static var singletonMultiThreadedEventLoopGroup: Self {\n        MultiThreadedEventLoopGroup.singleton\n    }\n}\n\nextension NIOThreadPool {\n    /// A globally shared, singleton ``NIOThreadPool``.\n    ///\n    /// SwiftNIO allows and encourages the precise management of all operating system resources such as threads and file descriptors.\n    /// Certain resources (such as the main ``NIOThreadPool``) however are usually globally shared across the program. This means\n    /// that many programs have to carry around an ``NIOThreadPool`` despite the fact they don't require the ability to fully return\n    /// all the operating resources which would imply shutting down the ``NIOThreadPool``. This type is the global handle for singleton\n    /// resources that applications (and some libraries) can use to obtain never-shut-down singleton resources.\n    ///\n    /// Programs and libraries that do not use these singletons will not incur extra resource usage, these resources are lazily initialized on\n    /// first use.\n    ///\n    /// The thread count of this pool is determined by `NIOSingletons/suggestedBlockingPoolThreadCount`.\n    ///\n    /// - Note: Users who do not want any code to spawn global singleton resources may set\n    ///         `NIOSingletons/singletonsEnabledSuggestion` to `false` which will lead to a forced crash\n    ///         if any code attempts to use the global singletons.\n    public static var singleton: NIOThreadPool {\n        NIOSingletons.posixBlockingThreadPool\n    }\n}\n\nprivate let singletonMTELG: MultiThreadedEventLoopGroup = {\n    guard NIOSingletons.singletonsEnabledSuggestion else {\n        fatalError(\n            \"\"\"\n            Cannot create global singleton MultiThreadedEventLoopGroup because the global singletons have been \\\n            disabled by setting  `NIOSingletons.singletonsEnabledSuggestion = false`\n            \"\"\"\n        )\n    }\n    let threadCount = NIOSingletons.groupLoopCountSuggestion\n    let group = MultiThreadedEventLoopGroup._makePerpetualGroup(\n        threadNamePrefix: \"NIO-SGLTN-\",\n        numberOfThreads: threadCount\n    )\n    _ = Unmanaged.passUnretained(group).retain()  // Never gonna give you up,\n    return group\n}()\n\nprivate let globalPosixBlockingPool: NIOThreadPool = {\n    guard NIOSingletons.singletonsEnabledSuggestion else {\n        fatalError(\n            \"\"\"\n            Cannot create global singleton NIOThreadPool because the global singletons have been \\\n            disabled by setting `NIOSingletons.singletonsEnabledSuggestion = false`\n            \"\"\"\n        )\n    }\n    let pool = NIOThreadPool._makePerpetualStartedPool(\n        numberOfThreads: NIOSingletons.blockingPoolThreadCountSuggestion,\n        threadNamePrefix: \"SGLTN-TP-#\"\n    )\n    _ = Unmanaged.passRetained(pool)  // never gonna let you down.\n    return pool\n}()\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyTracking</key>\n\t<false/>\n\t<key>NSPrivacyAccessedAPITypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>0A2A.1</string>\n\t\t\t</array>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>\n\t\t</dict>\n\t</array>\n\t<key>NSPrivacyCollectedDataTypes</key>\n\t<array/>\n\t<key>NSPrivacyTrackingDomains</key>\n\t<array/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Sources/NIOPosix/RawSocketBootstrap.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n/// A `RawSocketBootstrap` is an easy way to interact with IP based protocols other then TCP and UDP.\n///\n/// Example:\n///\n/// ```swift\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///     defer {\n///         try! group.syncShutdownGracefully()\n///     }\n///     let bootstrap = RawSocketBootstrap(group: group)\n///         .channelInitializer { channel in\n///             channel.pipeline.addHandler(MyChannelHandler())\n///         }\n///     let channel = try! bootstrap.bind(host: \"127.0.0.1\", ipProtocol: .icmp).wait()\n///     /* the Channel is now ready to send/receive IP packets */\n///\n///     try channel.closeFuture.wait()  // Wait until the channel un-binds.\n/// ```\n///\n/// The `Channel` will operate on `AddressedEnvelope<ByteBuffer>` as inbound and outbound messages.\npublic final class NIORawSocketBootstrap {\n\n    private let group: EventLoopGroup\n    private var channelInitializer: Optional<ChannelInitializerCallback>\n    @usableFromInline\n    internal var _channelOptions: ChannelOptions.Storage\n\n    /// Create a `RawSocketBootstrap` on the `EventLoopGroup` `group`.\n    ///\n    /// The `EventLoopGroup` `group` must be compatible, otherwise the program will crash. `RawSocketBootstrap` is\n    /// compatible only with `MultiThreadedEventLoopGroup` as well as the `EventLoop`s returned by\n    /// `MultiThreadedEventLoopGroup.next`. See `init(validatingGroup:)` for a fallible initializer for\n    /// situations where it's impossible to tell ahead of time if the `EventLoopGroup` is compatible or not.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public convenience init(group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            preconditionFailure(\n                \"RawSocketBootstrap is only compatible with MultiThreadedEventLoopGroup and \"\n                    + \"SelectableEventLoop. You tried constructing one with \\(group) which is incompatible.\"\n            )\n        }\n        self.init(validatingGroup: group)!\n    }\n\n    /// Create a `RawSocketBootstrap` on the `EventLoopGroup` `group`, validating that `group` is compatible.\n    ///\n    /// - Parameters:\n    ///   - group: The `EventLoopGroup` to use.\n    public init?(validatingGroup group: EventLoopGroup) {\n        guard NIOOnSocketsBootstraps.isCompatible(group: group) else {\n            return nil\n        }\n        self._channelOptions = ChannelOptions.Storage()\n        self.group = group\n        self.channelInitializer = nil\n    }\n\n    /// Initialize the bound `Channel` with `initializer`. The most common task in initializer is to add\n    /// `ChannelHandler`s to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - handler: A closure that initializes the provided `Channel`.\n    public func channelInitializer(_ handler: @escaping @Sendable (Channel) -> EventLoopFuture<Void>) -> Self {\n        self.channelInitializer = handler\n        return self\n    }\n\n    /// Specifies a `ChannelOption` to be applied to the `Channel`.\n    ///\n    /// - Parameters:\n    ///   - option: The option to be applied.\n    ///   - value: The value for the option.\n    @inlinable\n    public func channelOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> Self {\n        self._channelOptions.append(key: option, value: value)\n        return self\n    }\n\n    /// Bind the `Channel` to `host`.\n    /// All packets or errors matching the `ipProtocol` specified are passed to the resulting `Channel`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - ipProtocol: The IP protocol used in the IP protocol/nextHeader field.\n    public func bind(host: String, ipProtocol: NIOIPProtocol) -> EventLoopFuture<Channel> {\n        bind0(ipProtocol: ipProtocol) {\n            try SocketAddress.makeAddressResolvingHost(host, port: 0)\n        }\n    }\n\n    private func bind0(\n        ipProtocol: NIOIPProtocol,\n        _ makeSocketAddress: () throws -> SocketAddress\n    ) -> EventLoopFuture<Channel> {\n        let address: SocketAddress\n        do {\n            address = try makeSocketAddress()\n        } catch {\n            return group.next().makeFailedFuture(error)\n        }\n        precondition(address.port == nil || address.port == 0, \"port must be 0 or not set\")\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: .init(ipProtocol),\n                socketType: .raw\n            )\n        }\n        return withNewChannel(makeChannel: makeChannel) { (eventLoop, channel) in\n            channel.register().flatMap {\n                channel.bind(to: address)\n            }\n        }\n    }\n\n    /// Connect the `Channel` to `host`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - ipProtocol: The IP protocol used in the IP protocol/nextHeader field.\n    public func connect(host: String, ipProtocol: NIOIPProtocol) -> EventLoopFuture<Channel> {\n        connect0(ipProtocol: ipProtocol) {\n            try SocketAddress.makeAddressResolvingHost(host, port: 0)\n        }\n    }\n\n    private func connect0(\n        ipProtocol: NIOIPProtocol,\n        _ makeSocketAddress: () throws -> SocketAddress\n    ) -> EventLoopFuture<Channel> {\n        let address: SocketAddress\n        do {\n            address = try makeSocketAddress()\n        } catch {\n            return group.next().makeFailedFuture(error)\n        }\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: .init(ipProtocol),\n                socketType: .raw\n            )\n        }\n        return withNewChannel(makeChannel: makeChannel) { (eventLoop, channel) in\n            channel.register().flatMap {\n                channel.connect(to: address)\n            }\n        }\n    }\n\n    private func withNewChannel(\n        makeChannel: (_ eventLoop: SelectableEventLoop) throws -> DatagramChannel,\n        _ bringup: @escaping @Sendable (EventLoop, DatagramChannel) -> EventLoopFuture<Void>\n    ) -> EventLoopFuture<Channel> {\n        let eventLoop = self.group.next()\n        let channelInitializer = self.channelInitializer ?? { @Sendable _ in eventLoop.makeSucceededFuture(()) }\n        let channelOptions = self._channelOptions\n\n        let channel: DatagramChannel\n        do {\n            channel = try makeChannel(eventLoop as! SelectableEventLoop)\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        @Sendable\n        func setupChannel() -> EventLoopFuture<Channel> {\n            eventLoop.assertInEventLoop()\n            return channelOptions.applyAllChannelOptions(to: channel).flatMap {\n                channelInitializer(channel)\n            }.flatMap {\n                eventLoop.assertInEventLoop()\n                return bringup(eventLoop, channel)\n            }.map {\n                channel\n            }.flatMapError { error in\n                eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n    }\n}\n\n// MARK: Async connect/bind methods\n\nextension NIORawSocketBootstrap {\n    /// Bind the `Channel` to `host`.\n    /// All packets or errors matching the `ipProtocol` specified are passed to the resulting `Channel`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - ipProtocol: The IP protocol used in the IP protocol/nextHeader field.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `bind`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output: Sendable>(\n        host: String,\n        ipProtocol: NIOIPProtocol,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.bind0(\n            host: host,\n            ipProtocol: ipProtocol,\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { $1.makeSucceededFuture($0) }\n        )\n    }\n\n    /// Connect the `Channel` to `host`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - ipProtocol: The IP protocol used in the IP protocol/nextHeader field.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output: Sendable>(\n        host: String,\n        ipProtocol: NIOIPProtocol,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Output>\n    ) async throws -> Output {\n        try await self.connect0(\n            host: host,\n            ipProtocol: ipProtocol,\n            channelInitializer: channelInitializer,\n            postRegisterTransformation: { $1.makeSucceededFuture($0) }\n        )\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func connect0<ChannelInitializerResult: Sendable, PostRegistrationTransformationResult: Sendable>(\n        host: String,\n        ipProtocol: NIOIPProtocol,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) async throws -> PostRegistrationTransformationResult {\n        let address = try SocketAddress.makeAddressResolvingHost(host, port: 0)\n\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: .init(ipProtocol),\n                socketType: .raw\n            )\n        }\n\n        return try await self.makeConfiguredChannel(\n            makeChannel: makeChannel(_:),\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                channel.register().flatMap {\n                    channel.connect(to: address)\n                }\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func bind0<ChannelInitializerResult: Sendable, PostRegistrationTransformationResult: Sendable>(\n        host: String,\n        ipProtocol: NIOIPProtocol,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) async throws -> PostRegistrationTransformationResult {\n        let address = try SocketAddress.makeAddressResolvingHost(host, port: 0)\n\n        precondition(address.port == nil || address.port == 0, \"port must be 0 or not set\")\n        func makeChannel(_ eventLoop: SelectableEventLoop) throws -> DatagramChannel {\n            try DatagramChannel(\n                eventLoop: eventLoop,\n                protocolFamily: address.protocol,\n                protocolSubtype: .init(ipProtocol),\n                socketType: .raw\n            )\n        }\n\n        return try await self.makeConfiguredChannel(\n            makeChannel: makeChannel(_:),\n            channelInitializer: channelInitializer,\n            registration: { channel in\n                channel.register().flatMap {\n                    channel.bind(to: address)\n                }\n            },\n            postRegisterTransformation: postRegisterTransformation\n        ).get()\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    private func makeConfiguredChannel<\n        ChannelInitializerResult: Sendable,\n        PostRegistrationTransformationResult: Sendable\n    >(\n        makeChannel: (_ eventLoop: SelectableEventLoop) throws -> DatagramChannel,\n        channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<ChannelInitializerResult>,\n        registration: @escaping @Sendable (Channel) -> EventLoopFuture<Void>,\n        postRegisterTransformation:\n            @escaping @Sendable (ChannelInitializerResult, EventLoop) -> EventLoopFuture<\n                PostRegistrationTransformationResult\n            >\n    ) -> EventLoopFuture<PostRegistrationTransformationResult> {\n        let eventLoop = self.group.next()\n        let bootstrapInitializer = self.channelInitializer ?? { @Sendable _ in eventLoop.makeSucceededFuture(()) }\n        let channelInitializer = { @Sendable (channel: Channel) -> EventLoopFuture<ChannelInitializerResult> in\n            bootstrapInitializer(channel).flatMap { channelInitializer(channel) }\n        }\n        let channelOptions = self._channelOptions\n\n        let channel: DatagramChannel\n        do {\n            channel = try makeChannel(eventLoop as! SelectableEventLoop)\n        } catch {\n            return eventLoop.makeFailedFuture(error)\n        }\n\n        @Sendable\n        func setupChannel() -> EventLoopFuture<PostRegistrationTransformationResult> {\n            eventLoop.assertInEventLoop()\n            return channelOptions.applyAllChannelOptions(to: channel).flatMap {\n                channelInitializer(channel)\n            }.flatMap { (result: ChannelInitializerResult) in\n                eventLoop.assertInEventLoop()\n                return registration(channel).map {\n                    result\n                }\n            }.flatMap { (result: ChannelInitializerResult) -> EventLoopFuture<PostRegistrationTransformationResult> in\n                postRegisterTransformation(result, eventLoop)\n            }.flatMapError { error in\n                eventLoop.assertInEventLoop()\n                channel.close0(error: error, mode: .all, promise: nil)\n                return channel.eventLoop.makeFailedFuture(error)\n            }\n        }\n\n        if eventLoop.inEventLoop {\n            return setupChannel()\n        } else {\n            return eventLoop.flatSubmit {\n                setupChannel()\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIORawSocketBootstrap: Sendable {}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Resolver.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n/// A protocol that covers an object that does DNS lookups.\n///\n/// In general the rules for the resolver are relatively broad: there are no specific requirements on how\n/// it operates. However, the rest of the code assumes that it obeys RFC 6724, particularly section 6 on\n/// ordering returned addresses. That is, the IPv6 and IPv4 responses should be ordered by the destination\n/// address ordering rules from that RFC. This specification is widely implemented by getaddrinfo\n/// implementations, so any implementation based on getaddrinfo will work just fine. In the future, a custom\n/// resolver will need also to implement these sorting rules.\npublic protocol Resolver {\n    /// Initiate a DNS A query for a given host.\n    ///\n    /// - Parameters:\n    ///   - host: The hostname to do an A lookup on.\n    ///   - port: The port we'll be connecting to.\n    /// - Returns: An `EventLoopFuture` that fires with the result of the lookup.\n    func initiateAQuery(host: String, port: Int) -> EventLoopFuture<[SocketAddress]>\n\n    /// Initiate a DNS AAAA query for a given host.\n    ///\n    /// - Parameters:\n    ///   - host: The hostname to do an AAAA lookup on.\n    ///   - port: The port we'll be connecting to.\n    /// - Returns: An `EventLoopFuture` that fires with the result of the lookup.\n    func initiateAAAAQuery(host: String, port: Int) -> EventLoopFuture<[SocketAddress]>\n\n    /// Cancel all outstanding DNS queries.\n    ///\n    /// This method is called whenever queries that have not completed no longer have their\n    /// results needed. The resolver should, if possible, abort any outstanding queries and\n    /// clean up their state.\n    ///\n    /// This method is not guaranteed to terminate the outstanding queries.\n    func cancelQueries()\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Selectable.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n/// Represents a selectable resource which can be registered to a `Selector` to\n/// be notified once there are some events ready for it.\n///\n/// - warning:\n///     `Selectable`s are not thread-safe, only to be used on the appropriate\n///     `EventLoop`.\nprotocol Selectable {\n    func withUnsafeHandle<T>(_: (NIOBSDSocket.Handle) throws -> T) throws -> T\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectableChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n/// A `SelectableChannel` is a `Channel` that can be used with a `Selector` which notifies a user when certain events\n/// are possible. On UNIX a `Selector` is usually an abstraction of `select`, `poll`, `epoll` or `kqueue`.\n///\n/// - warning: `SelectableChannel` methods and properties are _not_ thread-safe (unless they also belong to `Channel`).\ninternal protocol SelectableChannel: Channel {\n    /// The type of the `Selectable`. A `Selectable` is usually wrapping a file descriptor that can be registered in a\n    /// `Selector`.\n    associatedtype SelectableType: Selectable\n\n    var isOpen: Bool { get }\n\n    /// The event(s) of interest.\n    var interestedEvent: SelectorEventSet { get }\n\n    /// Called when the `SelectableChannel` is ready to be written.\n    func writable()\n\n    /// Called when the `SelectableChannel` is ready to be read.\n    func readable()\n\n    /// Called when the read side of the `SelectableChannel` hit EOF.\n    func readEOF()\n\n    /// Called when the write side of the `SelectableChannel` hit EOF.\n    func writeEOF()\n\n    /// Called when the `SelectableChannel` was reset (ie. is now unusable)\n    func reset()\n\n    /// Called when the `SelectableChannel` had an error reported on the selector.\n    func error() -> ErrorResult\n\n    func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws\n\n    func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws\n\n    func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws\n}\n\ninternal enum ErrorResult {\n    case fatal\n    case nonFatal\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectableEventLoop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport Atomics\nimport CNIOPosix\nimport DequeModule\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport _NIODataStructures\n\nprivate func printError(_ string: StaticString) {\n    string.withUTF8Buffer { buf in\n        var buf = buf\n        while buf.count > 0 {\n            // 2 is stderr\n            let rc = write(2, buf.baseAddress, buf.count)\n            if rc < 0 {\n                let err = errno\n                if err == EINTR { continue }\n                fatalError(\"Unexpected error writing: \\(err)\")\n            }\n            buf = .init(rebasing: buf.dropFirst(Int(rc)))\n        }\n    }\n}\n\n/// Execute the given closure and ensure we release all auto pools if needed.\n@inlinable\ninternal func withAutoReleasePool<T>(_ execute: () throws -> T) rethrows -> T {\n    #if canImport(Darwin)\n    return try autoreleasepool {\n        try execute()\n    }\n    #else\n    return try execute()\n    #endif\n}\n\n/// Information about an EventLoop tick\npublic struct NIOEventLoopTickInfo: Sendable, Hashable {\n    /// The eventloop which ticked\n    public var eventLoopID: ObjectIdentifier\n    /// The number of tasks which were executed in this tick\n    public var numberOfTasks: Int\n    /// The time the event loop slept since the last tick\n    public var sleepTime: TimeAmount\n    /// The time at which the tick began\n    public var startTime: NIODeadline\n    /// The time at which the tick finished\n    public var endTime: NIODeadline\n\n    internal init(\n        eventLoopID: ObjectIdentifier,\n        numberOfTasks: Int,\n        sleepTime: TimeAmount,\n        startTime: NIODeadline,\n        endTime: NIODeadline\n    ) {\n        self.eventLoopID = eventLoopID\n        self.numberOfTasks = numberOfTasks\n        self.sleepTime = sleepTime\n        self.startTime = startTime\n        self.endTime = endTime\n    }\n}\n\n/// Implement this delegate to receive information about the EventLoop, such as each tick\npublic protocol NIOEventLoopMetricsDelegate: Sendable {\n    /// Called after a tick has run\n    /// This function is called after every tick - avoid long-running tasks here\n    /// - Warning: This function is called after every event loop tick and on the event loop thread. Any non-trivial work in this function will block the event loop and cause latency increases and performance degradation.\n    /// - Parameter info: Information about the tick, such as how many tasks were executed\n    func processedTick(info: NIOEventLoopTickInfo)\n}\n\n/// `EventLoop` implementation that uses a `Selector` to get notified once there is more I/O or tasks to process.\n/// The whole processing of I/O and tasks is done by a `NIOThread` that is tied to the `SelectableEventLoop`. This `NIOThread`\n/// is guaranteed to never change!\n@usableFromInline\ninternal final class SelectableEventLoop: EventLoop, @unchecked Sendable {\n\n    static let strictModeEnabled: Bool = {\n        #if os(Windows)\n        let env = Windows.getenv(\"SWIFTNIO_STRICT\")\n        #else\n        let env = getenv(\"SWIFTNIO_STRICT\").flatMap { String(cString: $0) }\n        #endif\n        switch env?.lowercased() {\n        case \"true\", \"y\", \"yes\", \"on\", \"1\":\n            return true\n        default:\n            return false\n        }\n    }()\n\n    /// The different state in the lifecycle of an `EventLoop` seen from _outside_ the `EventLoop`.\n    private enum ExternalState {\n        /// `EventLoop` is open and so can process more work.\n        case open\n        /// `EventLoop` is currently in the process of closing.\n        case closing\n        /// `EventLoop` is closed.\n        case closed\n        /// `EventLoop` is closed and is currently trying to reclaim resources (such as the EventLoop thread).\n        case reclaimingResources\n        /// `EventLoop` is closed and all the resources (such as the EventLoop thread) have been reclaimed.\n        case resourcesReclaimed\n    }\n\n    /// The different state in the lifecycle of an `EventLoop` seen from _inside_ the `EventLoop`.\n    private enum InternalState {\n        case runningAndAcceptingNewRegistrations\n        case runningButNotAcceptingNewRegistrations\n        case noLongerRunning\n        case exitingThread\n    }\n\n    @usableFromInline\n    internal let _selector: NIOPosix.Selector<NIORegistration>\n    private let thread: NIOThread\n    @usableFromInline\n    // _pendingTaskPop is set to `true` if the event loop is about to pop tasks off the task queue.\n    // This may only be read/written while holding the _tasksLock.\n    internal var _pendingTaskPop = false\n    @usableFromInline\n    internal let scheduledTaskCounter = ManagedAtomic<UInt64>(0)\n    @usableFromInline\n    internal var _scheduledTasks = PriorityQueue<ScheduledTask>()\n    @usableFromInline\n    internal var _immediateTasks = Deque<UnderlyingTask>()\n    @usableFromInline\n    internal let _uniqueID: SelectableEventLoopUniqueID\n\n    // We only need the ScheduledTask's task closure. However, an `Array<() -> Void>` allocates\n    // for every appended closure. https://bugs.swift.org/browse/SR-15872\n    private var tasksCopy = ContiguousArray<UnderlyingTask>()\n    private static var tasksCopyBatchSize: Int {\n        4096\n    }\n\n    @usableFromInline\n    internal var _succeededVoidFuture: EventLoopFuture<Void>? = nil {\n        didSet {\n            self.assertInEventLoop()\n        }\n    }\n\n    private let canBeShutdownIndividually: Bool\n    @usableFromInline\n    internal let _tasksLock = NIOLock()\n    private let _externalStateLock = NIOLock()\n    private var externalStateLock: NIOLock {\n        // The assert is here to check that we never try to read the external state on the EventLoop unless we're\n        // shutting down.\n        assert(\n            !self.inEventLoop || self.internalState != .runningAndAcceptingNewRegistrations,\n            \"lifecycle lock taken whilst up and running and in EventLoop\"\n        )\n        return self._externalStateLock\n    }\n    // protected by the EventLoop thread\n    private var internalState: InternalState = .runningAndAcceptingNewRegistrations\n    // protected by externalStateLock\n    private var externalState: ExternalState = .open\n\n    let bufferPool: Pool<PooledBuffer>\n    let msgBufferPool: Pool<PooledMsgBuffer>\n\n    // The `_parentGroup` will always be set unless this is a thread takeover or we shut down.\n    @usableFromInline\n    internal var _parentGroup: Optional<MultiThreadedEventLoopGroup>\n\n    /// Creates a new `SelectableEventLoop` instance that is tied to the given `pthread_t`.\n\n    private let promiseCreationStoreLock = NIOLock()\n    private var _promiseCreationStore: [_NIOEventLoopFutureIdentifier: (file: StaticString, line: UInt)] = [:]\n\n    private var metricsDelegateState: MetricsDelegateState?\n\n    @usableFromInline\n    internal func _promiseCreated(futureIdentifier: _NIOEventLoopFutureIdentifier, file: StaticString, line: UInt) {\n        precondition(_isDebugAssertConfiguration())\n        self.promiseCreationStoreLock.withLock {\n            self._promiseCreationStore[futureIdentifier] = (file: file, line: line)\n        }\n    }\n\n    @usableFromInline\n    internal func _promiseCompleted(\n        futureIdentifier: _NIOEventLoopFutureIdentifier\n    ) -> (file: StaticString, line: UInt)? {\n        precondition(_isDebugAssertConfiguration())\n        return self.promiseCreationStoreLock.withLock {\n            self._promiseCreationStore.removeValue(forKey: futureIdentifier)\n        }\n    }\n\n    @usableFromInline\n    internal func _preconditionSafeToWait(file: StaticString, line: UInt) {\n        let explainer: () -> String = {\n            \"\"\"\n            BUG DETECTED: wait() must not be called when on an EventLoop.\n            Calling wait() on any EventLoop can lead to\n            - deadlocks\n            - stalling processing of other connections (Channels) that are handled on the EventLoop that wait was called on\n\n            Further information:\n            - current eventLoop: \\(MultiThreadedEventLoopGroup.currentEventLoop.debugDescription)\n            - event loop associated to future: \\(self)\n            \"\"\"\n        }\n        precondition(!self.inEventLoop, explainer(), file: file, line: line)\n        precondition(MultiThreadedEventLoopGroup.currentEventLoop == nil, explainer(), file: file, line: line)\n    }\n\n    @usableFromInline\n    internal var _validInternalStateToScheduleTasks: Bool {\n        switch self.internalState {\n        case .exitingThread:\n            return false\n        case .runningAndAcceptingNewRegistrations, .runningButNotAcceptingNewRegistrations, .noLongerRunning:\n            return true\n        }\n    }\n\n    // access with `externalStateLock` held\n    private var validExternalStateToScheduleTasks: Bool {\n        switch self.externalState {\n        case .open, .closing:\n            return true\n        case .closed, .reclaimingResources, .resourcesReclaimed:\n            return false\n        }\n    }\n\n    internal var testsOnly_validExternalStateToScheduleTasks: Bool {\n        self.externalStateLock.withLock {\n            self.validExternalStateToScheduleTasks\n        }\n    }\n\n    internal init(\n        thread: NIOThread,\n        uniqueID: SelectableEventLoopUniqueID,\n        parentGroup: MultiThreadedEventLoopGroup?,  // nil iff thread take-over\n        selector: NIOPosix.Selector<NIORegistration>,\n        canBeShutdownIndividually: Bool,\n        metricsDelegate: NIOEventLoopMetricsDelegate?\n    ) {\n        self.metricsDelegateState = metricsDelegate.map { delegate in\n            MetricsDelegateState(metricsDelegate: delegate, lastTickEndime: .now())\n        }\n        self._uniqueID = uniqueID\n        self._parentGroup = parentGroup\n        self._selector = selector\n        self.thread = thread\n        self.bufferPool = Pool<PooledBuffer>(maxSize: 16)\n        self.msgBufferPool = Pool<PooledMsgBuffer>(maxSize: 16)\n        self.tasksCopy.reserveCapacity(Self.tasksCopyBatchSize)\n        self.canBeShutdownIndividually = canBeShutdownIndividually\n        // note: We are creating a reference cycle here that we'll break when shutting the SelectableEventLoop down.\n        // note: We have to create the promise and complete it because otherwise we'll hit a loop in `makeSucceededFuture`. This is\n        //       fairly dumb, but it's the only option we have.\n        let voidPromise = self.makePromise(of: Void.self)\n        voidPromise.succeed(())\n        self._succeededVoidFuture = voidPromise.futureResult\n        preconditionInEventLoop()\n        precondition(self._uniqueID.matchesCurrentThread)\n    }\n\n    deinit {\n        assert(\n            self.internalState == .exitingThread,\n            \"illegal internal state on deinit: \\(self.internalState)\"\n        )\n        assert(\n            self.externalState == .resourcesReclaimed,\n            \"illegal external state on shutdown: \\(self.externalState)\"\n        )\n    }\n\n    /// Is this `SelectableEventLoop` still open (ie. not shutting down or shut down)\n    internal var isOpen: Bool {\n        self.assertInEventLoop()\n        switch self.internalState {\n        case .noLongerRunning, .runningButNotAcceptingNewRegistrations, .exitingThread:\n            return false\n        case .runningAndAcceptingNewRegistrations:\n            return true\n        }\n    }\n\n    /// Register the given `SelectableChannel` with this `SelectableEventLoop`. After this point all I/O for the `SelectableChannel` will be processed by this `SelectableEventLoop` until it\n    /// is deregistered by calling `deregister`.\n    internal func register<C: SelectableChannel>(channel: C) throws {\n        self.assertInEventLoop()\n\n        // Don't allow registration when we're closed.\n        guard self.isOpen else {\n            throw EventLoopError._shutdown\n        }\n\n        try channel.register(selector: self._selector, interested: channel.interestedEvent)\n    }\n\n    /// Deregister the given `SelectableChannel` from this `SelectableEventLoop`.\n    internal func deregister<C: SelectableChannel>(channel: C, mode: CloseMode = .all) throws {\n        self.assertInEventLoop()\n        guard self.isOpen else {\n            // It's possible the EventLoop was closed before we were able to call deregister, so just return in this case as there is no harm.\n            return\n        }\n\n        try channel.deregister(selector: self._selector, mode: mode)\n    }\n\n    /// Register the given `SelectableChannel` with this `SelectableEventLoop`. This should be done whenever `channel.interestedEvents` has changed and it should be taken into account when\n    /// waiting for new I/O for the given `SelectableChannel`.\n    internal func reregister<C: SelectableChannel>(channel: C) throws {\n        self.assertInEventLoop()\n\n        try channel.reregister(selector: self._selector, interested: channel.interestedEvent)\n    }\n\n    /// - see: `EventLoop.inEventLoop`\n    @usableFromInline\n    internal var inEventLoop: Bool {\n        self._uniqueID.matchesCurrentThread\n    }\n\n    /// - see: `EventLoop.now`\n    @usableFromInline\n    internal var now: NIODeadline {\n        .now()\n    }\n\n    /// - see: `EventLoop.scheduleTask(deadline:_:)`\n    @inlinable\n    internal func scheduleTask<T>(deadline: NIODeadline, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        let promise: EventLoopPromise<T> = self.makePromise()\n        let (task, scheduled) = self._prepareToSchedule(deadline: deadline, promise: promise, task: task)\n\n        do {\n            try self._schedule0(.scheduled(task))\n        } catch {\n            promise.fail(error)\n        }\n\n        return scheduled\n    }\n\n    /// - see: `EventLoop.scheduleTask(in:_:)`\n    @inlinable\n    internal func scheduleTask<T>(in: TimeAmount, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        self.scheduleTask(deadline: .now() + `in`, task)\n    }\n\n    @inlinable\n    func _prepareToSchedule<T>(\n        deadline: NIODeadline,\n        promise: EventLoopPromise<T>,\n        task: @escaping () throws -> T\n    ) -> (ScheduledTask, Scheduled<T>) {\n        let task = ScheduledTask(\n            id: self.scheduledTaskCounter.loadThenWrappingIncrement(ordering: .relaxed),\n            {\n                do {\n                    promise.assumeIsolatedUnsafeUnchecked().succeed(try task())\n                } catch let err {\n                    promise.fail(err)\n                }\n            },\n            { error in\n                promise.fail(error)\n            },\n            deadline\n        )\n\n        let taskId = task.id\n        let scheduled = Scheduled(\n            promise: promise,\n            cancellationTask: {\n                self._tasksLock.withLock { () -> Void in\n                    self._scheduledTasks.removeFirst(where: { $0.id == taskId })\n                }\n                // We don't need to wake up the selector here, the scheduled task will never be picked up. Waking up the\n                // selector would mean that we may be able to recalculate the shutdown to a later date. The cost of not\n                // doing the recalculation is one potentially unnecessary wakeup which is exactly what we're\n                // saving here. So in the worst case, we didn't do a performance optimisation, in the best case, we saved\n                // one wakeup.\n            }\n        )\n        return (task, scheduled)\n    }\n\n    @inlinable\n    func _executeIsolatedUnsafeUnchecked(_ task: @escaping () -> Void) {\n        // nothing we can do if we fail enqueuing here.\n        try? self._scheduleIsolated0(.immediate(.function(task)))\n    }\n\n    @inlinable\n    func _submitIsolatedUnsafeUnchecked<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        let promise = self.makePromise(of: T.self)\n\n        self._executeIsolatedUnsafeUnchecked {\n            do {\n                // UnsafeUnchecked is allowed here because we know we are on the EL.\n                promise.assumeIsolatedUnsafeUnchecked().succeed(try task())\n            } catch let err {\n                promise.fail(err)\n            }\n        }\n\n        return promise.futureResult\n    }\n\n    @inlinable\n    @discardableResult\n    func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        deadline: NIODeadline,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        let promise: EventLoopPromise<T> = self.makePromise()\n        let (task, scheduled) = self._prepareToSchedule(deadline: deadline, promise: promise, task: task)\n\n        do {\n            try self._scheduleIsolated0(.scheduled(task))\n        } catch {\n            promise.fail(error)\n        }\n\n        return scheduled\n    }\n\n    @inlinable\n    @discardableResult\n    func _scheduleTaskIsolatedUnsafeUnchecked<T>(\n        in delay: TimeAmount,\n        _ task: @escaping () throws -> T\n    ) -> Scheduled<T> {\n        self._scheduleTaskIsolatedUnsafeUnchecked(deadline: .now() + delay, task)\n    }\n\n    // - see: `EventLoop.execute`\n    @inlinable\n    internal func execute(_ task: @escaping () -> Void) {\n        // nothing we can do if we fail enqueuing here.\n        try? self._schedule0(.immediate(.function(task)))\n    }\n\n    @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\n    @usableFromInline\n    func enqueue(_ job: consuming ExecutorJob) {\n        // nothing we can do if we fail enqueuing here.\n        let erasedJob = ErasedUnownedJob(job: UnownedJob(job))\n        try? self._schedule0(.immediate(.unownedJob(erasedJob)))\n    }\n\n    /// Add the `ScheduledTask` to be executed.\n    @usableFromInline\n    internal func _schedule0(_ task: LoopTask) throws {\n        if self.inEventLoop {\n            try self._scheduleIsolated0(task)\n        } else {\n            let shouldWakeSelector: Bool = self.externalStateLock.withLock {\n                guard self.validExternalStateToScheduleTasks else {\n                    if Self.strictModeEnabled {\n                        fatalError(\"Cannot schedule tasks on an EventLoop that has already shut down.\")\n                    }\n                    printError(\n                        \"\"\"\n                        ERROR: Cannot schedule tasks on an EventLoop that has already shut down. \\\n                        This will be upgraded to a forced crash in future SwiftNIO versions.\\n\n                        \"\"\"\n                    )\n                    return false\n                }\n\n                return self._tasksLock.withLock {\n                    switch task {\n                    case .scheduled(let task):\n                        self._scheduledTasks.push(task)\n                    case .immediate(let task):\n                        self._immediateTasks.append(task)\n                    }\n\n                    if self._pendingTaskPop == false {\n                        // Our job to wake the selector.\n                        self._pendingTaskPop = true\n                        return true\n                    } else {\n                        // There is already an event-loop-tick scheduled, we don't need to wake the selector.\n                        return false\n                    }\n                }\n            }\n\n            // We only need to wake up the selector if we're not in the EventLoop. If we're in the EventLoop already, we're\n            // either doing IO tasks (which happens before checking the scheduled tasks) or we're running a scheduled task\n            // already which means that we'll check at least once more if there are other scheduled tasks runnable. While we\n            // had the task lock we also checked whether the loop was _already_ going to be woken. This saves us a syscall on\n            // hot loops.\n            //\n            // In the future we'll use an MPSC queue here and that will complicate things, so we may get some spurious wakeups,\n            // but as long as we're using the big dumb lock we can make this optimization safely.\n            if shouldWakeSelector {\n                try self._wakeupSelector()\n            }\n        }\n    }\n\n    /// Add the `ScheduledTask` to be executed.\n    @usableFromInline\n    internal func _scheduleIsolated0(_ task: LoopTask) throws {\n        self.assertInEventLoop()\n        precondition(\n            self._validInternalStateToScheduleTasks,\n            \"BUG IN NIO (please report): EventLoop is shutdown, yet we're on the EventLoop.\"\n        )\n\n        self._tasksLock.withLock { () -> Void in\n            switch task {\n            case .scheduled(let task):\n                self._scheduledTasks.push(task)\n            case .immediate(let task):\n                self._immediateTasks.append(task)\n            }\n        }\n    }\n\n    /// Wake the `Selector` which means `Selector.whenReady(...)` will unblock.\n    @usableFromInline\n    internal func _wakeupSelector() throws {\n        try _selector.wakeup()\n    }\n\n    /// Handle the given `SelectorEventSet` for the `SelectableChannel`.\n    internal final func handleEvent<C: SelectableChannel>(_ ev: SelectorEventSet, channel: C) {\n        guard channel.isOpen else {\n            return\n        }\n\n        // process resets first as they'll just cause the writes to fail anyway.\n        if ev.contains(.reset) {\n            channel.reset()\n        } else {\n            if ev.contains(.error) {\n                switch channel.error() {\n                case .fatal:\n                    return\n                case .nonFatal:\n                    break\n                }\n\n                guard channel.isOpen else {\n                    return\n                }\n            }\n            if ev.contains(.writeEOF) {\n                channel.writeEOF()\n\n                guard channel.isOpen else {\n                    return\n                }\n            } else if ev.contains(.write) {\n                channel.writable()\n\n                guard channel.isOpen else {\n                    return\n                }\n            }\n\n            if ev.contains(.readEOF) {\n                channel.readEOF()\n            } else if ev.contains(.read) {\n                channel.readable()\n            }\n        }\n    }\n\n    @inlinable\n    internal func _currentSelectorStrategy(nextReadyDeadline: NIODeadline?) -> SelectorStrategy {\n        guard let deadline = nextReadyDeadline else {\n            // No tasks to handle so just block. If any tasks were added in the meantime wakeup(...) was called and so this\n            // will directly unblock.\n            return .block\n        }\n\n        let nextReady = deadline.readyIn(.now())\n        if nextReady <= .nanoseconds(0) {\n            // Something is ready to be processed just do a non-blocking select of events.\n            return .now\n        } else {\n            return .blockUntilTimeout(nextReady)\n        }\n    }\n\n    private func run(_ task: UnderlyingTask) {\n        // for macOS: in case any calls we make to Foundation put objects into an autoreleasepool\n        withAutoReleasePool {\n            switch task {\n            case .function(let function):\n                function()\n            case .unownedJob(let erasedUnownedJob):\n                if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {\n                    erasedUnownedJob.unownedJob.runSynchronously(on: self.asUnownedSerialExecutor())\n                } else {\n                    fatalError(\"Tried to run an UnownedJob without runtime support\")\n                }\n            case .callback(let handler):\n                handler.handleScheduledCallback(eventLoop: self)\n            }\n        }\n    }\n\n    private static func _popTasksLockedAssertInvariants(\n        immediateTasks: Deque<UnderlyingTask>,\n        scheduledTasks: PriorityQueue<ScheduledTask>,\n        tasksCopy: ContiguousArray<UnderlyingTask>,\n        tasksCopyBatchSize: Int,\n        now: NIODeadline,\n        nextDeadline: NIODeadline\n    ) {\n        assert(tasksCopy.count <= tasksCopyBatchSize)\n        // When we exit the loop, we would expect to\n        // * have taskCopy full, or:\n        // * to have completely drained task queues\n        //     * that means all immediateTasks, and:\n        //     * all scheduledTasks that are ready\n        assertExpression {\n            if tasksCopy.count == tasksCopyBatchSize {\n                return true\n            }\n\n            if !immediateTasks.isEmpty {\n                return false\n            }\n\n            guard let nextScheduledTask = scheduledTasks.peek() else {\n                return true\n            }\n\n            return nextScheduledTask.readyTime.readyIn(now) > .nanoseconds(0)\n        }\n\n        //  nextDeadline must be set to now if there are more immediate tasks left\n        assertExpression {\n            if immediateTasks.count == 0 {\n                return true\n            }\n\n            return nextDeadline == now\n        }\n\n        // nextDeadline should be set to != now, iff there are more\n        // scheduled tasks, and they are all scheduled for the future\n        // Moreover, nextDeadline must equal the expiry time for the\n        // \"top-most\" scheduled task\n        assertExpression {\n            if nextDeadline == now {\n                return true\n            }\n\n            guard let topMostScheduledTask = scheduledTasks.peek() else {\n                return false\n            }\n\n            return topMostScheduledTask.readyTime == nextDeadline\n        }\n    }\n\n    private static func _popTasksLocked(\n        immediateTasks: inout Deque<UnderlyingTask>,\n        scheduledTasks: inout PriorityQueue<ScheduledTask>,\n        tasksCopy: inout ContiguousArray<UnderlyingTask>,\n        tasksCopyBatchSize: Int\n    ) -> NIODeadline? {\n        // We expect empty tasksCopy, to put a new batch of tasks into\n        assert(tasksCopy.isEmpty)\n\n        var moreImmediateTasksToConsider = !immediateTasks.isEmpty\n        var moreScheduledTasksToConsider = !scheduledTasks.isEmpty\n\n        guard moreImmediateTasksToConsider || moreScheduledTasksToConsider else {\n            // Reset nextReadyDeadline to nil which means we will do a blocking select.\n            return nil\n        }\n\n        // We only fetch the time one time as this may be expensive and is generally good enough as if we miss anything we will just do a non-blocking select again anyway.\n        let now: NIODeadline = .now()\n        var nextScheduledTaskDeadline = now\n\n        while moreImmediateTasksToConsider || moreScheduledTasksToConsider {\n            // We pick one item from immediateTasks & scheduledTask per iteration of the loop.\n            // This prevents one task queue starving the other.\n            if moreImmediateTasksToConsider, tasksCopy.count < tasksCopyBatchSize, let task = immediateTasks.popFirst()\n            {\n                tasksCopy.append(task)\n            } else {\n                moreImmediateTasksToConsider = false\n            }\n\n            if moreScheduledTasksToConsider, tasksCopy.count < tasksCopyBatchSize, let task = scheduledTasks.peek() {\n                if task.readyTime.readyIn(now) <= .nanoseconds(0) {\n                    scheduledTasks.pop()\n                    switch task.kind {\n                    case .task(let task, _): tasksCopy.append(.function(task))\n                    case .callback(let handler): tasksCopy.append(.callback(handler))\n                    }\n                } else {\n                    nextScheduledTaskDeadline = task.readyTime\n                    moreScheduledTasksToConsider = false\n                }\n            } else {\n                moreScheduledTasksToConsider = false\n            }\n        }\n\n        let nextDeadline = immediateTasks.count > 0 ? now : nextScheduledTaskDeadline\n        debugOnly {\n            // The asserts are spun off to a separate functions to aid code clarity\n            // and to remove mutable access to certain structures, e.g. `immediateTasks`.\n            Self._popTasksLockedAssertInvariants(\n                immediateTasks: immediateTasks,\n                scheduledTasks: scheduledTasks,\n                tasksCopy: tasksCopy,\n                tasksCopyBatchSize: tasksCopyBatchSize,\n                now: now,\n                nextDeadline: nextDeadline\n            )\n        }\n\n        return nextDeadline\n    }\n\n    private func runOneLoopTick(selfIdentifier: ObjectIdentifier) -> NIODeadline? {\n        let tickStartInfo:\n            (\n                metricsDelegate: any NIOEventLoopMetricsDelegate,\n                tickStartTime: NIODeadline,\n                sleepTime: TimeAmount\n            )? = self.metricsDelegateState.map { metricsDelegateState in\n                let tickStartTime = NIODeadline.now()  // Potentially expensive, only if delegate set.\n                return (\n                    metricsDelegate: metricsDelegateState.metricsDelegate,\n                    tickStartTime: tickStartTime,\n                    sleepTime: tickStartTime - metricsDelegateState.lastTickEndime\n                )\n            }\n\n        var tasksProcessedInTick = 0\n        defer {\n            if let tickStartInfo = tickStartInfo {\n                let tickEndTime = NIODeadline.now()  // Potentially expensive, only if delegate set.\n                let tickInfo = NIOEventLoopTickInfo(\n                    eventLoopID: selfIdentifier,\n                    numberOfTasks: tasksProcessedInTick,\n                    sleepTime: tickStartInfo.sleepTime,\n                    startTime: tickStartInfo.tickStartTime,\n                    endTime: tickEndTime\n                )\n                tickStartInfo.metricsDelegate.processedTick(info: tickInfo)\n                self.metricsDelegateState?.lastTickEndime = tickEndTime\n            }\n        }\n        while true {\n            let nextReadyDeadline = self._tasksLock.withLock { () -> NIODeadline? in\n                let deadline = Self._popTasksLocked(\n                    immediateTasks: &self._immediateTasks,\n                    scheduledTasks: &self._scheduledTasks,\n                    tasksCopy: &self.tasksCopy,\n                    tasksCopyBatchSize: Self.tasksCopyBatchSize\n                )\n                if self.tasksCopy.isEmpty {\n                    // Rare, but it's possible to find no tasks to execute if all scheduled tasks are expiring in the future.\n                    self._pendingTaskPop = false\n                }\n                return deadline\n            }\n\n            // all pending tasks are set to occur in the future, so we can stop looping.\n            if self.tasksCopy.isEmpty {\n                return nextReadyDeadline\n            }\n\n            // Execute all the tasks that were submitted\n            let (partialTotal, totalOverflowed) = tasksProcessedInTick.addingReportingOverflow(self.tasksCopy.count)\n            if totalOverflowed {\n                tasksProcessedInTick = Int.max\n            } else {\n                tasksProcessedInTick = partialTotal\n            }\n            for task in self.tasksCopy {\n                self.run(task)\n            }\n            // Drop everything (but keep the capacity) so we can fill it again on the next iteration.\n            self.tasksCopy.removeAll(keepingCapacity: true)\n        }\n    }\n\n    // Do not rename or remove this function.\n    //\n    // When doing on-/off-CPU analysis, for example with continuous profiling, it's\n    // important to recognise certain functions that are purely there to wait.\n    //\n    // This function is one of those and giving it a consistent name makes it much easier to remove from the profiles\n    // when only interested in on-CPU work.\n    @inline(never)\n    @inlinable\n    internal func _blockingWaitForWork(\n        nextReadyDeadline: NIODeadline?,\n        _ body: (SelectorEvent<NIORegistration>) -> Void\n    ) throws {\n        try self._selector.whenReady(\n            strategy: self._currentSelectorStrategy(nextReadyDeadline: nextReadyDeadline),\n            onLoopBegin: { self._tasksLock.withLock { () -> Void in self._pendingTaskPop = true } },\n            body\n        )\n    }\n\n    /// Start processing I/O and tasks for this `SelectableEventLoop`. This method will continue running (and so block) until the `SelectableEventLoop` is closed.\n    internal func run() throws {\n        self.preconditionInEventLoop()\n\n        defer {\n            var iterations = 0\n            var drained = false\n            var scheduledTasksCopy = ContiguousArray<ScheduledTask>()\n            var immediateTasksCopy = Deque<UnderlyingTask>()\n            repeat {  // We may need to do multiple rounds of this because failing tasks may lead to more work.\n                self._tasksLock.withLock {\n                    // In this state we never want the selector to be woken again, so we pretend we're permanently running.\n                    self._pendingTaskPop = true\n\n                    // reserve the correct capacity so we don't need to realloc later on.\n                    scheduledTasksCopy.reserveCapacity(self._scheduledTasks.count)\n                    while let sched = self._scheduledTasks.pop() {\n                        scheduledTasksCopy.append(sched)\n                    }\n                    swap(&immediateTasksCopy, &self._immediateTasks)\n                }\n\n                // Run all the immediate tasks. They're all \"expired\" and don't have failFn,\n                // therefore the best course of action is to run them.\n                for task in immediateTasksCopy {\n                    self.run(task)\n                }\n                for task in scheduledTasksCopy {\n                    switch task.kind {\n                    // Fail all the scheduled tasks.\n                    case .task(_, let failFn):\n                        failFn(EventLoopError._shutdown)\n                    // Call the cancellation handler for all the scheduled callbacks.\n                    case .callback(let handler):\n                        handler.didCancelScheduledCallback(eventLoop: self)\n                    }\n                }\n\n                iterations += 1\n                drained = immediateTasksCopy.count == 0 && scheduledTasksCopy.count == 0\n                immediateTasksCopy.removeAll(keepingCapacity: true)\n                scheduledTasksCopy.removeAll(keepingCapacity: true)\n            } while !drained && iterations < 1000\n            precondition(drained, \"EventLoop \\(self) didn't quiesce after 1000 ticks.\")\n\n            assert(self.internalState == .noLongerRunning, \"illegal state: \\(self.internalState)\")\n            self.internalState = .exitingThread\n        }\n        var nextReadyDeadline: NIODeadline? = nil\n        self._tasksLock.withLock {\n            if let firstScheduledTask = self._scheduledTasks.peek() {\n                // The reason this is necessary is a very interesting race:\n                // In theory (and with `makeEventLoopFromCallingThread` even in practise), we could publish an\n                // `EventLoop` reference _before_ the EL thread has entered the `run` function.\n                // If that is the case, we need to schedule the first wakeup at the ready time for this task that was\n                // enqueued really early on, so let's do that :).\n                nextReadyDeadline = firstScheduledTask.readyTime\n            }\n            if !self._immediateTasks.isEmpty {\n                nextReadyDeadline = NIODeadline.now()\n            }\n        }\n        let selfIdentifier = ObjectIdentifier(self)\n        while self.internalState != .noLongerRunning && self.internalState != .exitingThread {\n            // Block until there are events to handle or the selector was woken up\n            // for macOS: in case any calls we make to Foundation put objects into an autoreleasepool\n            try withAutoReleasePool {\n                try self._blockingWaitForWork(nextReadyDeadline: nextReadyDeadline) { ev in\n                    switch ev.registration.channel {\n                    case .serverSocketChannel(let chan):\n                        self.handleEvent(ev.io, channel: chan)\n                    case .socketChannel(let chan):\n                        self.handleEvent(ev.io, channel: chan)\n                    case .datagramChannel(let chan):\n                        self.handleEvent(ev.io, channel: chan)\n                    case .pipeChannel(let chan, let direction):\n                        var ev = ev\n                        if ev.io.contains(.reset) || ev.io.contains(.error) {\n                            // .reset and .error needs special treatment here because we're dealing with two separate pipes instead\n                            // of one socket. So we turn .reset input .readEOF/.writeEOF.\n                            ev.io.subtract([.reset, .error])\n                            ev.io.formUnion([direction == .input ? .readEOF : .writeEOF])\n                        }\n                        self.handleEvent(ev.io, channel: chan)\n                    }\n                }\n            }\n            nextReadyDeadline = self.runOneLoopTick(selfIdentifier: selfIdentifier)\n        }\n\n        // This EventLoop was closed so also close the underlying selector.\n        try self._selector.close()\n\n        // This breaks the retain cycle created in `init`.\n        self._succeededVoidFuture = nil\n    }\n\n    internal func initiateClose(\n        queue: DispatchQueue,\n        completionHandler: @escaping @Sendable (Result<Void, Error>) -> Void\n    ) {\n        func doClose() {\n            self.assertInEventLoop()\n            self._parentGroup = nil  // break the cycle\n            // There should only ever be one call into this function so we need to be up and running, ...\n            assert(self.internalState == .runningAndAcceptingNewRegistrations)\n            self.internalState = .runningButNotAcceptingNewRegistrations\n\n            self.externalStateLock.withLock {\n                // ... but before this call happened, the lifecycle state should have been changed on some other thread.\n                assert(self.externalState == .closing)\n            }\n\n            self._selector.closeGently(eventLoop: self).whenComplete { result in\n                self.assertInEventLoop()\n                assert(self.internalState == .runningButNotAcceptingNewRegistrations)\n                self.internalState = .noLongerRunning\n                self.execute {}  // force a new event loop tick, so the event loop definitely stops looping very soon.\n                self.externalStateLock.withLock {\n                    assert(self.externalState == .closing)\n                    self.externalState = .closed\n                }\n                queue.async {\n                    completionHandler(result)\n                }\n            }\n        }\n        if self.inEventLoop {\n            queue.async {\n                self.initiateClose(queue: queue, completionHandler: completionHandler)\n            }\n        } else {\n            let goAhead = self.externalStateLock.withLock { () -> Bool in\n                if self.externalState == .open {\n                    self.externalState = .closing\n                    return true\n                } else {\n                    return false\n                }\n            }\n            guard goAhead else {\n                queue.async {\n                    completionHandler(Result.failure(EventLoopError._shutdown))\n                }\n                return\n            }\n            self.execute {\n                doClose()\n            }\n        }\n    }\n\n    internal func syncFinaliseClose(joinThread: Bool) {\n        // This may not be true in the future but today we need to join all ELs that can't be shut down individually.\n        assert(joinThread != self.canBeShutdownIndividually)\n        let goAhead = self.externalStateLock.withLock { () -> Bool in\n            switch self.externalState {\n            case .closed:\n                self.externalState = .reclaimingResources\n                return true\n            case .resourcesReclaimed, .reclaimingResources:\n                return false\n            default:\n                preconditionFailure(\"illegal lifecycle state in syncFinaliseClose: \\(self.externalState)\")\n            }\n        }\n        guard goAhead else {\n            return\n        }\n        if joinThread {\n            self.thread.join()\n        }\n        self.externalStateLock.withLock {\n            precondition(self.externalState == .reclaimingResources)\n            self.externalState = .resourcesReclaimed\n        }\n    }\n\n    @usableFromInline\n    func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable (Error?) -> Void) {\n        if self.canBeShutdownIndividually {\n            self.initiateClose(queue: queue) { result in\n                self.syncFinaliseClose(joinThread: false)  // This thread was taken over by somebody else\n                switch result {\n                case .success:\n                    callback(nil)\n                case .failure(let error):\n                    callback(error)\n                }\n            }\n        } else {\n            // This function is never called legally because the only possibly owner of an `SelectableEventLoop` is\n            // `MultiThreadedEventLoopGroup` which calls `initiateClose` followed by `syncFinaliseClose`.\n            queue.async {\n                callback(EventLoopError._unsupportedOperation)\n            }\n        }\n    }\n\n    @inlinable\n    public func makeSucceededVoidFuture() -> EventLoopFuture<Void> {\n        guard self.inEventLoop, let voidFuture = self._succeededVoidFuture else {\n            // We have to create the promise and complete it because otherwise we'll hit a loop in `makeSucceededFuture`. This is\n            // fairly dumb, but it's the only option we have. This one can only happen after the loop is shut down, or when calling from off the loop.\n            let voidPromise = self.makePromise(of: Void.self)\n            voidPromise.succeed(())\n            return voidPromise.futureResult\n        }\n        return voidFuture\n    }\n\n    @inlinable\n    internal func parentGroupCallableFromThisEventLoopOnly() -> MultiThreadedEventLoopGroup? {\n        self.assertInEventLoop()\n        return self._parentGroup\n    }\n}\n\nstruct MetricsDelegateState {\n    var metricsDelegate: any NIOEventLoopMetricsDelegate\n    var lastTickEndime: NIODeadline\n}\n\nextension SelectableEventLoop: CustomStringConvertible, CustomDebugStringConvertible {\n    @usableFromInline\n    var description: String {\n        if self.inEventLoop {\n            return \"\"\"\n                SelectableEventLoop { \\\n                selector = \\(self._selector), \\\n                thread = \\(self.thread), \\\n                state = \\(self.internalState) \\\n                }\n                \"\"\"\n        } else {\n            // We can't print the selector or the internal state here (getting the external state under the lock\n            // is a bit too dangerous in case somebody is holding that lock and then calling description).\n            return \"\"\"\n                SelectableEventLoop { \\\n                thread = \\(self.thread) \\\n                }\n                \"\"\"\n        }\n    }\n\n    @usableFromInline\n    var debugDescription: String {\n        let scheduledTasks = self._tasksLock.withLock {\n            self._scheduledTasks.description\n        }\n\n        if self.inEventLoop {\n            return \"\"\"\n                SelectableEventLoop { \\\n                selector = \\(self._selector), \\\n                scheduledTasks = \\(scheduledTasks), \\\n                thread = \\(self.thread), \\\n                state = \\(self.internalState) \\\n                }\n                \"\"\"\n        } else {\n            let externalState = self.externalStateLock.withLock {\n                self.externalState\n            }\n            return \"\"\"\n                SelectableEventLoop { \\\n                selector = \\(self._selector), \\\n                scheduledTasks = \\(scheduledTasks), \\\n                thread = \\(self.thread), \\\n                state = \\(externalState) \\\n                }\n                \"\"\"\n        }\n    }\n}\n\n// MARK: SerialExecutor conformance\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\nextension SelectableEventLoop: NIOSerialEventLoopExecutor {}\n\n@usableFromInline\nenum UnderlyingTask {\n    case function(() -> Void)\n    case unownedJob(ErasedUnownedJob)\n    case callback(any NIOScheduledCallbackHandler)\n}\n\n@available(*, unavailable)\nextension UnderlyingTask: Sendable {}\n\n@usableFromInline\ninternal enum LoopTask {\n    case scheduled(ScheduledTask)\n    case immediate(UnderlyingTask)\n}\n\n@available(*, unavailable)\nextension LoopTask: Sendable {}\n\n@inlinable\ninternal func assertExpression(_ body: () -> Bool) {\n    assert(\n        {\n            body()\n        }()\n    )\n}\n\nextension SelectableEventLoop {\n    @inlinable\n    func scheduleCallback(\n        at deadline: NIODeadline,\n        handler: some NIOScheduledCallbackHandler\n    ) throws -> NIOScheduledCallback {\n        let taskID = self.scheduledTaskCounter.loadThenWrappingIncrement(ordering: .relaxed)\n        let task = ScheduledTask(id: taskID, handler, deadline)\n        try self._schedule0(.scheduled(task))\n        return NIOScheduledCallback(self, id: taskID)\n    }\n\n    @inlinable\n    func cancelScheduledCallback(_ scheduledCallback: NIOScheduledCallback) {\n        guard let id = scheduledCallback.customCallbackID else {\n            preconditionFailure(\"No custom ID for callback\")\n        }\n        self._tasksLock.withLock {\n            guard let scheduledTask = self._scheduledTasks.removeFirst(where: { $0.id == id }) else {\n                // Must have been cancelled already.\n                return\n            }\n            guard case .callback(let handler) = scheduledTask.kind else {\n                preconditionFailure(\"Incorrect task kind for callback\")\n            }\n            handler.didCancelScheduledCallback(eventLoop: self)\n        }\n    }\n}\n\n@usableFromInline\nstruct SelectableEventLoopUniqueID: Sendable {\n    @usableFromInline\n    static let _nextGroupID = ManagedAtomic<UInt64>(1)  // DO NOT MAKE THIS 0.\n\n    @usableFromInline\n    var _loopID: UInt32\n\n    @usableFromInline\n    let _groupID: UInt32\n\n    @inlinable\n    var groupID: Int {\n        Int(self._groupID)\n    }\n\n    @inlinable\n    var loopID: Int {\n        Int(self._loopID)\n    }\n\n    @inlinable\n    init(_loopID: UInt32, groupID: UInt32) {\n        self._loopID = _loopID\n        self._groupID = groupID\n    }\n\n    static func makeNextGroup() -> Self {\n        let groupID = Self._nextGroupID.loadThenWrappingIncrement(ordering: .relaxed)\n\n        // If we're crashing just below, we created more 2^32 ELGs -- unlikely.\n        return Self(_loopID: 1, groupID: UInt32(groupID))\n    }\n\n    mutating func nextLoop() {\n        self._loopID += 1\n    }\n\n    @inlinable\n    internal var matchesCurrentThread: Bool {\n        let threadUniqueID = c_nio_posix_get_el_id()\n        return threadUniqueID == self.packedEventLoopID\n    }\n\n    @inlinable\n    internal var packedEventLoopID: UInt {\n        #if arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n        // 32 bit\n        // If we're crashing below, we created more than 2^16 (64ki) ELGs which is unsupported.\n        precondition(self._groupID < UInt32(UInt16.max), \"too many event loops created\")\n        precondition(self._loopID < UInt32(UInt16.max), \"event loop group with too many event loops created\")\n        let packedID = IntegerBitPacking.packUInt16UInt16(\n            UInt16(self._groupID),\n            UInt16(self._loopID)\n        )\n        #else\n        // 64 bit\n        let packedID = IntegerBitPacking.packUInt32UInt32(self._groupID, self._loopID)\n        #endif\n        assert(MemoryLayout<UInt>.size == MemoryLayout.size(ofValue: packedID))\n        return UInt(packedID)\n    }\n\n    internal func attachToCurrentThread() {\n        let existingPackedID = c_nio_posix_get_el_id()\n        precondition(existingPackedID == 0, \"weird, current thread ID \\(existingPackedID), expected 0\")\n\n        let packedID = self.packedEventLoopID\n        c_nio_posix_set_el_id(UInt(packedID))\n    }\n\n    internal func detachFromCurrentThread() {\n        let existingPackedID = c_nio_posix_get_el_id()\n        precondition(existingPackedID == self.packedEventLoopID)\n\n        c_nio_posix_set_el_id(0)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectorEpoll.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n#if !SWIFTNIO_USE_IO_URING\n\n#if os(Linux) || os(Android)\nimport CNIOLinux\n\n/// Represents the `epoll` filters/events we might use:\n///\n///  - `hangup` corresponds to `EPOLLHUP`\n///  - `readHangup` corresponds to `EPOLLRDHUP`\n///  - `input` corresponds to `EPOLLIN`\n///  - `output` corresponds to `EPOLLOUT`\n///  - `error` corresponds to `EPOLLERR`\nprivate struct EpollFilterSet: OptionSet, Equatable {\n    typealias RawValue = UInt8\n\n    let rawValue: RawValue\n\n    static let _none = EpollFilterSet([])\n    static let hangup = EpollFilterSet(rawValue: 1 << 0)\n    static let readHangup = EpollFilterSet(rawValue: 1 << 1)\n    static let input = EpollFilterSet(rawValue: 1 << 2)\n    static let output = EpollFilterSet(rawValue: 1 << 3)\n    static let error = EpollFilterSet(rawValue: 1 << 4)\n\n    init(rawValue: RawValue) {\n        self.rawValue = rawValue\n    }\n}\n\nextension EpollFilterSet {\n    /// Convert NIO's `SelectorEventSet` set to a `EpollFilterSet`\n    init(selectorEventSet: SelectorEventSet) {\n        var thing: EpollFilterSet = [.error, .hangup]\n        if selectorEventSet.contains(.read) {\n            thing.formUnion(.input)\n        }\n        if selectorEventSet.contains(.write) {\n            thing.formUnion(.output)\n        }\n        if selectorEventSet.contains(.readEOF) {\n            thing.formUnion(.readHangup)\n        }\n        self = thing\n    }\n}\n\nextension SelectorEventSet {\n    var epollEventSet: UInt32 {\n        assert(self != ._none)\n        // EPOLLERR | EPOLLHUP is always set unconditionally anyway but it's easier to understand if we explicitly ask.\n        var filter: UInt32 = Epoll.EPOLLERR | Epoll.EPOLLHUP\n        let epollFilters = EpollFilterSet(selectorEventSet: self)\n        if epollFilters.contains(.input) {\n            filter |= Epoll.EPOLLIN\n        }\n        if epollFilters.contains(.output) {\n            filter |= Epoll.EPOLLOUT\n        }\n        if epollFilters.contains(.readHangup) {\n            filter |= Epoll.EPOLLRDHUP\n        }\n        assert(filter & Epoll.EPOLLHUP != 0)  // both of these are reported\n        assert(filter & Epoll.EPOLLERR != 0)  // always and can't be masked.\n        return filter\n    }\n\n    @inlinable\n    internal init(epollEvent: Epoll.epoll_event) {\n        var selectorEventSet: SelectorEventSet = ._none\n        if epollEvent.events & Epoll.EPOLLIN != 0 {\n            selectorEventSet.formUnion(.read)\n        }\n        if epollEvent.events & Epoll.EPOLLOUT != 0 {\n            selectorEventSet.formUnion(.write)\n        }\n        if epollEvent.events & Epoll.EPOLLRDHUP != 0 {\n            selectorEventSet.formUnion(.readEOF)\n        }\n        if epollEvent.events & Epoll.EPOLLERR != 0 {\n            selectorEventSet.formUnion(.error)\n        }\n        if epollEvent.events & Epoll.EPOLLHUP != 0 {\n            selectorEventSet.formUnion(.reset)\n        }\n        self = selectorEventSet\n    }\n}\n\n// EPollUserData supports (un)packing into an `UInt64` because epoll has a user info field that we can attach which is\n// up to 64 bits wide. We're using all of those 64 bits, 32 for a \"registration ID\" and 32 for the file descriptor.\n@usableFromInline struct EPollUserData {\n    @usableFromInline var registrationID: SelectorRegistrationID\n    @usableFromInline var fileDescriptor: CInt\n\n    @inlinable init(registrationID: SelectorRegistrationID, fileDescriptor: CInt) {\n        assert(MemoryLayout<UInt64>.size == MemoryLayout<EPollUserData>.size)\n        self.registrationID = registrationID\n        self.fileDescriptor = fileDescriptor\n    }\n\n    @inlinable init(rawValue: UInt64) {\n        let unpacked = IntegerBitPacking.unpackUInt32CInt(rawValue)\n        self = .init(registrationID: SelectorRegistrationID(rawValue: unpacked.0), fileDescriptor: unpacked.1)\n    }\n}\n\nextension UInt64 {\n    @inlinable\n    init(_ epollUserData: EPollUserData) {\n        let fd = epollUserData.fileDescriptor\n        assert(fd >= 0, \"\\(fd) is not a valid file descriptor\")\n        self = IntegerBitPacking.packUInt32CInt(epollUserData.registrationID.rawValue, fd)\n    }\n}\n\nextension Selector: _SelectorBackendProtocol {\n    func initialiseState0() throws {\n        self.selectorFD = try Epoll.epoll_create(size: 128)\n        self.eventFD = try EventFd.eventfd(initval: 0, flags: Int32(EventFd.EFD_CLOEXEC | EventFd.EFD_NONBLOCK))\n        self.timerFD = try TimerFd.timerfd_create(\n            clockId: CLOCK_MONOTONIC,\n            flags: Int32(TimerFd.TFD_CLOEXEC | TimerFd.TFD_NONBLOCK)\n        )\n\n        self.lifecycleState = .open\n\n        var ev = Epoll.epoll_event()\n        ev.events = SelectorEventSet.read.epollEventSet\n        ev.data.u64 = UInt64(\n            EPollUserData(\n                registrationID: .initialRegistrationID,\n                fileDescriptor: self.eventFD\n            )\n        )\n\n        try Epoll.epoll_ctl(epfd: self.selectorFD, op: Epoll.EPOLL_CTL_ADD, fd: self.eventFD, event: &ev)\n\n        var timerev = Epoll.epoll_event()\n        timerev.events = Epoll.EPOLLIN | Epoll.EPOLLERR | Epoll.EPOLLRDHUP\n        timerev.data.u64 = UInt64(\n            EPollUserData(\n                registrationID: .initialRegistrationID,\n                fileDescriptor: self.timerFD\n            )\n        )\n        try Epoll.epoll_ctl(epfd: self.selectorFD, op: Epoll.EPOLL_CTL_ADD, fd: self.timerFD, event: &timerev)\n    }\n\n    func deinitAssertions0() {\n        assert(self.eventFD == -1, \"self.eventFD == \\(self.eventFD) in deinitAssertions0, forgot close?\")\n        assert(self.timerFD == -1, \"self.timerFD == \\(self.timerFD) in deinitAssertions0, forgot close?\")\n    }\n\n    func register0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        interested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        var ev = Epoll.epoll_event()\n        ev.events = interested.epollEventSet\n        ev.data.u64 = UInt64(EPollUserData(registrationID: registrationID, fileDescriptor: fileDescriptor))\n\n        try Epoll.epoll_ctl(epfd: self.selectorFD, op: Epoll.EPOLL_CTL_ADD, fd: fileDescriptor, event: &ev)\n    }\n\n    func reregister0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        oldInterested: SelectorEventSet,\n        newInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        var ev = Epoll.epoll_event()\n        ev.events = newInterested.epollEventSet\n        ev.data.u64 = UInt64(EPollUserData(registrationID: registrationID, fileDescriptor: fileDescriptor))\n\n        _ = try Epoll.epoll_ctl(epfd: self.selectorFD, op: Epoll.EPOLL_CTL_MOD, fd: fileDescriptor, event: &ev)\n    }\n\n    func deregister0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        oldInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        var ev = Epoll.epoll_event()\n        _ = try Epoll.epoll_ctl(epfd: self.selectorFD, op: Epoll.EPOLL_CTL_DEL, fd: fileDescriptor, event: &ev)\n    }\n\n    /// Apply the given `SelectorStrategy` and execute `body` once it's complete (which may produce `SelectorEvent`s to handle).\n    ///\n    /// - Parameters:\n    ///   - strategy: The `SelectorStrategy` to apply\n    ///   - body: The function to execute for each `SelectorEvent` that was produced.\n    @inlinable\n    func whenReady0(\n        strategy: SelectorStrategy,\n        onLoopBegin loopStart: () -> Void,\n        _ body: (SelectorEvent<R>) throws -> Void\n    ) throws {\n        assert(self.myThread.isCurrentSlow)\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't call whenReady for selector as it's \\(self.lifecycleState).\")\n        }\n        let ready: Int\n\n        switch strategy {\n        case .now:\n            ready = Int(\n                try Epoll.epoll_wait(\n                    epfd: self.selectorFD,\n                    events: events,\n                    maxevents: Int32(eventsCapacity),\n                    timeout: 0\n                )\n            )\n        case .blockUntilTimeout(let timeAmount):\n            // Only call timerfd_settime if we're not already scheduled one that will cover it.\n            // This guards against calling timerfd_settime if not needed as this is generally speaking\n            // expensive.\n            let next = NIODeadline.now() + timeAmount\n            if next < self.earliestTimer {\n                self.earliestTimer = next\n\n                var ts = itimerspec()\n                ts.it_value = timespec(timeAmount: timeAmount)\n                try TimerFd.timerfd_settime(fd: self.timerFD, flags: 0, newValue: &ts, oldValue: nil)\n            }\n            fallthrough\n        case .block:\n            ready = Int(\n                try Epoll.epoll_wait(\n                    epfd: self.selectorFD,\n                    events: events,\n                    maxevents: Int32(eventsCapacity),\n                    timeout: -1\n                )\n            )\n        }\n\n        loopStart()\n\n        for i in 0..<ready {\n            let ev = events[i]\n            let epollUserData = EPollUserData(rawValue: ev.data.u64)\n            let fd = epollUserData.fileDescriptor\n            let eventRegistrationID = epollUserData.registrationID\n            switch fd {\n            case self.eventFD:\n                var val = EventFd.eventfd_t()\n                // Consume event\n                _ = try EventFd.eventfd_read(fd: self.eventFD, value: &val)\n            case self.timerFD:\n                // Consume event\n                var val: UInt64 = 0\n                // We are not interested in the result\n                _ = try! Posix.read(descriptor: self.timerFD, pointer: &val, size: MemoryLayout.size(ofValue: val))\n\n                // Processed the earliest set timer so reset it.\n                self.earliestTimer = .distantFuture\n            default:\n                // If the registration is not in the Map anymore we deregistered it during the processing of whenReady(...). In this case just skip it.\n                if let registration = registrations[Int(fd)] {\n                    guard eventRegistrationID == registration.registrationID else {\n                        continue\n                    }\n\n                    var selectorEvent = SelectorEventSet(epollEvent: ev)\n                    // we can only verify the events for i == 0 as for i > 0 the user might have changed the registrations since then.\n                    assert(\n                        i != 0 || selectorEvent.isSubset(of: registration.interested),\n                        \"selectorEvent: \\(selectorEvent), registration: \\(registration)\"\n                    )\n\n                    // in any case we only want what the user is currently registered for & what we got\n                    selectorEvent = selectorEvent.intersection(registration.interested)\n\n                    guard selectorEvent != ._none else {\n                        continue\n                    }\n\n                    try body((SelectorEvent(io: selectorEvent, registration: registration)))\n                }\n            }\n        }\n        growEventArrayIfNeeded(ready: ready)\n    }\n\n    /// Close the `Selector`.\n    ///\n    /// After closing the `Selector` it's no longer possible to use it.\n    public func close0() throws {\n        self.externalSelectorFDLock.withLock {\n            // We try! all of the closes because close can only fail in the following ways:\n            // - EINTR, which we eat in Posix.close\n            // - EIO, which can only happen for on-disk files\n            // - EBADF, which can't happen here because we would crash as EBADF is marked unacceptable\n            // Therefore, we assert here that close will always succeed and if not, that's a NIO bug we need to know\n            // about.\n\n            try! Posix.close(descriptor: self.timerFD)\n            self.timerFD = -1\n\n            try! Posix.close(descriptor: self.eventFD)\n            self.eventFD = -1\n\n            try! Posix.close(descriptor: self.selectorFD)\n            self.selectorFD = -1\n        }\n    }\n\n    // attention, this may (will!) be called from outside the event loop, ie. can't access mutable shared state (such as `self.open`)\n    func wakeup0() throws {\n        assert(!self.myThread.isCurrentSlow)\n        try self.externalSelectorFDLock.withLock {\n            guard self.eventFD >= 0 else {\n                throw EventLoopError.shutdown\n            }\n            _ = try EventFd.eventfd_write(fd: self.eventFD, value: 1)\n        }\n    }\n}\n\n#endif\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectorGeneric.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n#if os(Linux)\nimport CNIOLinux\n#elseif os(Windows)\nimport WinSDK\n#endif\n\n@usableFromInline\ninternal enum SelectorLifecycleState: Sendable {\n    case open\n    case closing\n    case closed\n}\n\nextension Optional {\n    @inlinable\n    internal func withUnsafeOptionalPointer<T>(_ body: (UnsafePointer<Wrapped>?) throws -> T) rethrows -> T {\n        if var this = self {\n            return try withUnsafePointer(to: &this) { x in\n                try body(x)\n            }\n        } else {\n            return try body(nil)\n        }\n    }\n}\n\n#if !os(Windows)\nextension timespec {\n    @inlinable\n    init(timeAmount amount: TimeAmount) {\n        let nsecPerSec: Int64 = 1_000_000_000\n        let ns = amount.nanoseconds\n        let sec = ns / nsecPerSec\n        self = timespec(tv_sec: time_t(sec), tv_nsec: Int(ns - sec * nsecPerSec))\n    }\n}\n#endif\n\n/// Represents IO events NIO might be interested in. `SelectorEventSet` is used for two purposes:\n///  1. To express interest in a given event set and\n///  2. for notifications about an IO event set that has occurred.\n///\n/// For example, if you were interested in reading and writing data from/to a socket and also obviously if the socket\n/// receives a connection reset, express interest with `[.read, .write, .reset]`.\n/// If then suddenly the socket becomes both readable and writable, the eventing mechanism will tell you about that\n/// fact using `[.read, .write]`.\n@usableFromInline\nstruct SelectorEventSet: OptionSet, Equatable, Sendable {\n\n    @usableFromInline\n    typealias RawValue = UInt8\n\n    @usableFromInline\n    let rawValue: RawValue\n\n    /// It's impossible to actually register for no events, therefore `_none` should only be used to bootstrap a set\n    /// of flags or to compare against spurious wakeups.\n    @usableFromInline\n    static let _none = SelectorEventSet([])\n\n    /// Connection reset.\n    @usableFromInline\n    static let reset = SelectorEventSet(rawValue: 1 << 0)\n\n    /// EOF at the read/input end of a `Selectable`.\n    @usableFromInline\n    static let readEOF = SelectorEventSet(rawValue: 1 << 1)\n\n    /// Interest in/availability of data to be read\n    @usableFromInline\n    static let read = SelectorEventSet(rawValue: 1 << 2)\n\n    /// Interest in/availability of data to be written\n    @usableFromInline\n    static let write = SelectorEventSet(rawValue: 1 << 3)\n\n    /// EOF at the write/output end of a `Selectable`.\n    ///\n    /// - Note: This is rarely used because in many cases, there is no signal that this happened.\n    @usableFromInline\n    static let writeEOF = SelectorEventSet(rawValue: 1 << 4)\n\n    /// Error encountered.\n    @usableFromInline\n    static let error = SelectorEventSet(rawValue: 1 << 5)\n\n    @inlinable\n    init(rawValue: SelectorEventSet.RawValue) {\n        self.rawValue = rawValue\n    }\n}\n\ninternal let isEarlyEOFDeliveryWorkingOnThisOS: Bool = {\n    #if canImport(Darwin)\n    return false  // rdar://53656794 , once fixed we need to do an OS version check here.\n    #else\n    return true\n    #endif\n}()\n\n/// This protocol defines the methods that are expected to be found on\n/// `Selector`. While defined as a protocol there is no expectation that any\n/// object other than `Selector` will implement this protocol: instead, this\n/// protocol acts as a reference for what new supported selector backends\n/// must implement.\nprotocol _SelectorBackendProtocol {\n    associatedtype R: Registration\n    func initialiseState0() throws\n    func deinitAssertions0()  // allows actual implementation to run some assertions as part of the class deinit\n    func register0(\n        selectableFD: NIOBSDSocket.Handle,\n        fileDescriptor: NIOBSDSocket.Handle,\n        interested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws\n    func reregister0(\n        selectableFD: NIOBSDSocket.Handle,\n        fileDescriptor: NIOBSDSocket.Handle,\n        oldInterested: SelectorEventSet,\n        newInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws\n    func deregister0(\n        selectableFD: NIOBSDSocket.Handle,\n        fileDescriptor: NIOBSDSocket.Handle,\n        oldInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws\n\n    // attention, this may (will!) be called from outside the event loop, ie. can't access mutable shared state (such as `self.open`)\n    func wakeup0() throws\n\n    /// Apply the given `SelectorStrategy` and execute `body` once it's complete (which may produce `SelectorEvent`s to handle).\n    ///\n    /// - Parameters:\n    ///   - strategy: The `SelectorStrategy` to apply\n    ///   - body: The function to execute for each `SelectorEvent` that was produced.\n    func whenReady0(\n        strategy: SelectorStrategy,\n        onLoopBegin: () -> Void,\n        _ body: (SelectorEvent<R>) throws -> Void\n    ) throws\n    func close0() throws\n}\n\n///  A `Selector` allows a user to register different `Selectable` sources to an underlying OS selector, and for that selector to notify them once IO is ready for them to process.\n///\n/// This implementation offers an consistent API over epoll/liburing (for linux) and kqueue (for Darwin, BSD).\n/// There are specific subclasses  per API type with a shared common superclass providing overall scaffolding.\n\n// this is deliberately not thread-safe, only the wakeup() function may be called unprotectedly\n@usableFromInline\ninternal class Selector<R: Registration> {\n    @usableFromInline\n    var lifecycleState: SelectorLifecycleState\n    @usableFromInline\n    var registrations = [Int: R]()\n    @usableFromInline\n    var registrationID: SelectorRegistrationID = .initialRegistrationID\n\n    @usableFromInline\n    let myThread: NIOThread\n    // The rules for `self.selectorFD`, `self.eventFD`, and `self.timerFD`:\n    // reads: `self.externalSelectorFDLock` OR access from the EventLoop thread\n    // writes: `self.externalSelectorFDLock` AND access from the EventLoop thread\n    let externalSelectorFDLock = NIOLock()\n    @usableFromInline\n    var selectorFD: CInt = -1  // -1 == we're closed\n\n    // Here we add the stored properties that are used by the specific backends\n    #if canImport(Darwin) || os(OpenBSD)\n    @usableFromInline\n    typealias EventType = kevent\n    #elseif os(Linux) || os(Android)\n    #if !SWIFTNIO_USE_IO_URING\n    @usableFromInline\n    typealias EventType = Epoll.epoll_event\n    @usableFromInline\n    var earliestTimer: NIODeadline = .distantFuture\n    @usableFromInline\n    var eventFD: CInt = -1  // -1 == we're closed\n    @usableFromInline\n    var timerFD: CInt = -1  // -1 == we're closed\n    #else\n    @usableFromInline\n    typealias EventType = URingEvent\n    @usableFromInline\n    var eventFD: CInt = -1  // -1 == we're closed\n    @usableFromInline\n    var ring = URing()\n    @usableFromInline\n    let multishot = URing.io_uring_use_multishot_poll  // if true, we run with streaming multishot polls\n    @usableFromInline\n    let deferReregistrations = true  // if true we only flush once at reentring whenReady() - saves syscalls\n    @usableFromInline\n    var deferredReregistrationsPending = false  // true if flush needed when reentring whenReady()\n    #endif\n    #elseif os(Windows)\n    @usableFromInline\n    typealias EventType = WinSDK.pollfd\n    @usableFromInline\n    var pollFDs = [WinSDK.pollfd]()\n    #else\n    #error(\"Unsupported platform, no suitable selector backend (we need kqueue or epoll support)\")\n    #endif\n\n    @usableFromInline\n    var events: UnsafeMutablePointer<EventType>\n    @usableFromInline\n    var eventsCapacity = 64\n\n    internal func testsOnly_withUnsafeSelectorFD<T>(_ body: (CInt) throws -> T) throws -> T {\n        assert(!self.myThread.isCurrentSlow)\n        return try self.externalSelectorFDLock.withLock {\n            guard self.selectorFD != -1 else {\n                throw EventLoopError._shutdown\n            }\n            return try body(self.selectorFD)\n        }\n    }\n\n    init(thread: NIOThread) throws {\n        precondition(thread.isCurrentSlow)\n        self.myThread = thread\n        self.lifecycleState = .closed\n        self.events = Selector.allocateEventsArray(capacity: self.eventsCapacity)\n        try self.initialiseState0()\n    }\n\n    deinit {\n        self.deinitAssertions0()\n        assert(self.registrations.count == 0, \"left-over registrations: \\(self.registrations)\")\n        assert(self.lifecycleState == .closed, \"Selector \\(self.lifecycleState) (expected .closed) on deinit\")\n        assert(self.selectorFD == -1, \"self.selectorFD == \\(self.selectorFD) on Selector deinit, forgot close?\")\n        Selector.deallocateEventsArray(events: self.events, capacity: self.eventsCapacity)\n    }\n\n    @inlinable\n    internal static func allocateEventsArray(capacity: Int) -> UnsafeMutablePointer<EventType> {\n        let events: UnsafeMutablePointer<EventType> = UnsafeMutablePointer.allocate(capacity: capacity)\n        events.initialize(to: EventType())\n        return events\n    }\n\n    @inlinable\n    internal static func deallocateEventsArray(events: UnsafeMutablePointer<EventType>, capacity: Int) {\n        events.deinitialize(count: capacity)\n        events.deallocate()\n    }\n\n    @inlinable\n    func growEventArrayIfNeeded(ready: Int) {\n        assert(self.myThread.isCurrentSlow)\n        guard ready == self.eventsCapacity else {\n            return\n        }\n        Selector.deallocateEventsArray(events: self.events, capacity: self.eventsCapacity)\n\n        // double capacity\n        self.eventsCapacity = ready << 1\n        self.events = Selector.allocateEventsArray(capacity: self.eventsCapacity)\n    }\n\n    /// Register `Selectable` on the `Selector`.\n    ///\n    /// - Parameters:\n    ///   - selectable: The `Selectable` to register.\n    ///   - interested: The `SelectorEventSet` in which we are interested and want to be notified about.\n    ///   - makeRegistration: Creates the registration data for the given `SelectorEventSet`.\n    func register<S: Selectable>(\n        selectable: S,\n        interested: SelectorEventSet,\n        makeRegistration: (SelectorEventSet, SelectorRegistrationID) -> R\n    ) throws {\n        assert(self.myThread.isCurrentSlow)\n        assert(interested.contains([.reset, .error]))\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't register on selector as it's \\(self.lifecycleState).\")\n        }\n\n        try selectable.withUnsafeHandle { fd in\n            assert(registrations[Int(fd)] == nil)\n            try self.register0(\n                selectableFD: fd,\n                fileDescriptor: fd,\n                interested: interested,\n                registrationID: self.registrationID\n            )\n            let registration = makeRegistration(interested, self.registrationID.nextRegistrationID())\n            registrations[Int(fd)] = registration\n        }\n    }\n\n    /// Re-register `Selectable`, must be registered via `register` before.\n    ///\n    /// - Parameters:\n    ///   - selectable: The `Selectable` to re-register.\n    ///   - interested: The `SelectorEventSet` in which we are interested and want to be notified about.\n    func reregister<S: Selectable>(selectable: S, interested: SelectorEventSet) throws {\n        assert(self.myThread.isCurrentSlow)\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't re-register on selector as it's \\(self.lifecycleState).\")\n        }\n        assert(\n            interested.contains([.reset, .error]),\n            \"must register for at least .reset & .error but tried registering for \\(interested)\"\n        )\n        try selectable.withUnsafeHandle { fd in\n            var reg = registrations[Int(fd)]!\n            try self.reregister0(\n                selectableFD: fd,\n                fileDescriptor: fd,\n                oldInterested: reg.interested,\n                newInterested: interested,\n                registrationID: reg.registrationID\n            )\n            reg.interested = interested\n            self.registrations[Int(fd)] = reg\n        }\n    }\n\n    /// Deregister `Selectable`, must be registered via `register` before.\n    ///\n    /// After the `Selectable is deregistered no `SelectorEventSet` will be produced anymore for the `Selectable`.\n    ///\n    /// - Parameters:\n    ///   - selectable: The `Selectable` to deregister.\n    func deregister<S: Selectable>(selectable: S) throws {\n        assert(self.myThread.isCurrentSlow)\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't deregister from selector as it's \\(self.lifecycleState).\")\n        }\n\n        try selectable.withUnsafeHandle { fd in\n            guard let reg = registrations.removeValue(forKey: Int(fd)) else {\n                return\n            }\n            try self.deregister0(\n                selectableFD: fd,\n                fileDescriptor: fd,\n                oldInterested: reg.interested,\n                registrationID: reg.registrationID\n            )\n        }\n    }\n\n    /// Apply the given `SelectorStrategy` and execute `body` once it's complete (which may produce `SelectorEvent`s to handle).\n    ///\n    /// - Parameters:\n    ///   - strategy: The `SelectorStrategy` to apply\n    ///   - onLoopBegin: A function executed after the selector returns, just before the main loop begins..\n    ///   - body: The function to execute for each `SelectorEvent` that was produced.\n    @inlinable\n    func whenReady(\n        strategy: SelectorStrategy,\n        onLoopBegin loopStart: () -> Void,\n        _ body: (SelectorEvent<R>) throws -> Void\n    ) throws {\n        try self.whenReady0(strategy: strategy, onLoopBegin: loopStart, body)\n    }\n\n    /// Close the `Selector`.\n    ///\n    /// After closing the `Selector` it's no longer possible to use it.\n    public func close() throws {\n        assert(self.myThread.isCurrentSlow)\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't close selector as it's \\(self.lifecycleState).\")\n        }\n        try self.close0()\n        self.lifecycleState = .closed\n        self.registrations.removeAll()\n    }\n\n    // attention, this may (will!) be called from outside the event loop, ie. can't access mutable shared state (such as `self.open`)\n    func wakeup() throws {\n        try self.wakeup0()\n    }\n}\n\nextension Selector: CustomStringConvertible {\n    @usableFromInline\n    var description: String {\n        func makeDescription() -> String {\n            \"Selector { descriptor = \\(self.selectorFD) }\"\n        }\n\n        if self.myThread.isCurrentSlow {\n            return makeDescription()\n        } else {\n            return self.externalSelectorFDLock.withLock {\n                makeDescription()\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension Selector: Sendable {}\n\n/// An event that is triggered once the `Selector` was able to select something.\n@usableFromInline\nstruct SelectorEvent<R> {\n    public let registration: R\n    public var io: SelectorEventSet\n\n    /// Create new instance\n    ///\n    /// - Parameters:\n    ///   - io: The `SelectorEventSet` that triggered this event.\n    ///   - registration: The registration that belongs to the event.\n    @inlinable\n    init(io: SelectorEventSet, registration: R) {\n        self.io = io\n        self.registration = registration\n    }\n}\n\n@available(*, unavailable)\nextension SelectorEvent: Sendable {}\n\nextension Selector where R == NIORegistration {\n    /// Gently close the `Selector` after all registered `Channel`s are closed.\n    func closeGently(eventLoop: EventLoop) -> EventLoopFuture<Void> {\n        assert(self.myThread.isCurrentSlow)\n        guard self.lifecycleState == .open else {\n            return eventLoop.makeFailedFuture(\n                IOError(errnoCode: EBADF, reason: \"can't close selector gently as it's \\(self.lifecycleState).\")\n            )\n        }\n\n        let futures: [EventLoopFuture<Void>] = self.registrations.map {\n            (_, reg: NIORegistration) -> EventLoopFuture<Void> in\n            // The futures will only be notified (of success) once also the closeFuture of each Channel is notified.\n            // This only happens after all other actions on the Channel is complete and all events are propagated through the\n            // ChannelPipeline. We do this to minimize the risk to left over any tasks / promises that are tied to the\n            // EventLoop itself.\n            func closeChannel(_ chan: Channel) -> EventLoopFuture<Void> {\n                chan.close(promise: nil)\n                return chan.closeFuture\n            }\n\n            switch reg.channel {\n            case .serverSocketChannel(let chan):\n                return closeChannel(chan)\n            case .socketChannel(let chan):\n                return closeChannel(chan)\n            case .datagramChannel(let chan):\n                return closeChannel(chan)\n            case .pipeChannel(let chan, _):\n                return closeChannel(chan)\n            }\n        }.map { future in\n            future.flatMapErrorThrowing { error in\n                if let error = error as? ChannelError, error == .alreadyClosed {\n                    return ()\n                } else {\n                    throw error\n                }\n            }\n        }\n\n        guard futures.count > 0 else {\n            return eventLoop.makeSucceededFuture(())\n        }\n\n        return .andAllSucceed(futures, on: eventLoop)\n    }\n}\n\n/// The strategy used for the `Selector`.\n@usableFromInline\nenum SelectorStrategy: Sendable {\n    /// Block until there is some IO ready to be processed or the `Selector` is explicitly woken up.\n    case block\n\n    /// Block until there is some IO ready to be processed, the `Selector` is explicitly woken up or the given `TimeAmount` elapsed.\n    case blockUntilTimeout(TimeAmount)\n\n    /// Try to select all ready IO at this point in time without blocking at all.\n    case now\n}\n\n/// A Registration on a `Selector`, which is interested in an `SelectorEventSet`.\n/// `registrationID` is used by the event notification backends (kqueue, epoll, ...)\n/// to mark events to allow for filtering of received return values to not be delivered to a\n/// new `Registration` instance that receives the same file descriptor. Ok if it wraps.\n/// Needed for i.e. testWeDoNotDeliverEventsForPreviouslyClosedChannels to succeed.\n@usableFromInline struct SelectorRegistrationID: Hashable, Sendable {\n    @usableFromInline var _rawValue: UInt32\n\n    @inlinable var rawValue: UInt32 {\n        self._rawValue\n    }\n\n    @inlinable static var initialRegistrationID: SelectorRegistrationID {\n        SelectorRegistrationID(rawValue: .max)\n    }\n\n    @inlinable mutating func nextRegistrationID() -> SelectorRegistrationID {\n        let current = self\n        // Overflow is okay here, this is just for very short-term disambiguation\n        self._rawValue = self._rawValue &+ 1\n        return current\n    }\n\n    @inlinable init(rawValue: UInt32) {\n        self._rawValue = rawValue\n    }\n\n    @inlinable static func == (_ lhs: SelectorRegistrationID, _ rhs: SelectorRegistrationID) -> Bool {\n        lhs._rawValue == rhs._rawValue\n    }\n\n    @inlinable func hash(into hasher: inout Hasher) {\n        hasher.combine(self._rawValue)\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectorKqueue.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n#if canImport(Darwin) || os(OpenBSD)\n\n/// Represents the `kqueue` filters we might use:\n///\n///  - `except` corresponds to `EVFILT_EXCEPT`\n///  - `read` corresponds to `EVFILT_READ`\n///  - `write` corresponds to `EVFILT_WRITE`\nprivate struct KQueueEventFilterSet: OptionSet, Equatable {\n    typealias RawValue = UInt8\n\n    let rawValue: RawValue\n\n    static let _none = KQueueEventFilterSet([])\n    // skipping `1 << 0` because kqueue doesn't have a direct match for `.reset` (`EPOLLHUP` for epoll)\n    static let except = KQueueEventFilterSet(rawValue: 1 << 1)\n    static let read = KQueueEventFilterSet(rawValue: 1 << 2)\n    static let write = KQueueEventFilterSet(rawValue: 1 << 3)\n\n    init(rawValue: RawValue) {\n        self.rawValue = rawValue\n    }\n}\n\nextension KQueueEventFilterSet {\n    /// Convert NIO's `SelectorEventSet` set to a `KQueueEventFilterSet`\n    init(selectorEventSet: SelectorEventSet) {\n        var kqueueFilterSet: KQueueEventFilterSet = .init(rawValue: 0)\n        if selectorEventSet.contains(.read) {\n            kqueueFilterSet.formUnion(.read)\n        }\n\n        if selectorEventSet.contains(.write) {\n            kqueueFilterSet.formUnion(.write)\n        }\n\n        if isEarlyEOFDeliveryWorkingOnThisOS && selectorEventSet.contains(.readEOF) {\n            kqueueFilterSet.formUnion(.except)\n        }\n        self = kqueueFilterSet\n    }\n\n    /// Calculate the kqueue filter changes that are necessary to transition from `previousKQueueFilterSet` to `self`.\n    /// The `body` closure is then called with the changes necessary expressed as a number of `kevent`.\n    ///\n    /// - Parameters:\n    ///    - previousKQueueFilterSet: The previous filter set that is currently registered with kqueue.\n    ///    - fileDescriptor: The file descriptor the `kevent`s should be generated to.\n    ///    - body: The closure that will then apply the change set.\n    func calculateKQueueFilterSetChanges(\n        previousKQueueFilterSet: KQueueEventFilterSet,\n        fileDescriptor: CInt,\n        registrationID: SelectorRegistrationID,\n        _ body: (UnsafeMutableBufferPointer<kevent>) throws -> Void\n    ) rethrows {\n        // we only use three filters (EVFILT_READ, EVFILT_WRITE and EVFILT_EXCEPT) so the number of changes would be 3.\n        var kevents = KeventTriple()\n\n        // contains all the events that need a change (either need to be added or removed)\n        let differences = previousKQueueFilterSet.symmetricDifference(self)\n\n        func calculateKQueueChange(event: KQueueEventFilterSet) -> UInt16? {\n            guard differences.contains(event) else {\n                return nil\n            }\n            return UInt16(self.contains(event) ? EV_ADD : EV_DELETE)\n        }\n\n        for (event, filter) in [\n            (KQueueEventFilterSet.read, EVFILT_READ), (.write, EVFILT_WRITE), (.except, EVFILT_EXCEPT),\n        ] {\n            if let flags = calculateKQueueChange(event: event) {\n                kevents.appendEvent(\n                    fileDescriptor: fileDescriptor,\n                    filter: filter,\n                    flags: flags,\n                    registrationID: registrationID\n                )\n            }\n        }\n\n        try kevents.withUnsafeBufferPointer(body)\n    }\n}\n\nextension SelectorRegistrationID {\n    @inlinable\n    init(kqueueUData: UnsafeMutableRawPointer?) {\n        self = .init(rawValue: UInt32(truncatingIfNeeded: UInt(bitPattern: kqueueUData)))\n    }\n}\n\n// this is deliberately not thread-safe, only the wakeup() function may be called unprotectedly\nextension Selector: _SelectorBackendProtocol {\n    @inlinable\n    internal static func toKQueueTimeSpec(strategy: SelectorStrategy) -> timespec? {\n        switch strategy {\n        case .block:\n            return nil\n        case .now:\n            return timespec(tv_sec: 0, tv_nsec: 0)\n        case .blockUntilTimeout(let nanoseconds):\n            // A scheduledTask() specified with a zero or negative timeAmount, will be scheduled immediately\n            // and therefore SHOULD NOT result in a kevent being created with a negative or zero timespec.\n            precondition(nanoseconds.nanoseconds > 0, \"\\(nanoseconds) is invalid (0 < nanoseconds)\")\n\n            var ts = timespec(timeAmount: nanoseconds)\n            // Check that the timespec tv_nsec field conforms to the definition in the C11 standard (ISO/IEC 9899:2011).\n            assert((0..<1_000_000_000).contains(ts.tv_nsec), \"\\(ts) is invalid (0 <= tv_nsec < 1_000_000_000)\")\n\n            // The maximum value in seconds supported by the Darwin-kernel interval timer (kern_time.c:itimerfix())\n            // (note that - whilst unlikely - this value *could* change).\n            let sysIntervalTimerMaxSec = 100_000_000\n\n            // Clamp the timespec tv_sec value to the maximum supported by the Darwin-kernel.\n            // Whilst this schedules the event far into the future (several years) it will still be triggered provided\n            // the system stays up.\n            #if os(OpenBSD)\n            // Should double-check if this makes sense for OpenBSD, but\n            // let's just get this to compile for now.\n            ts.tv_sec = min(ts.tv_sec, time_t(sysIntervalTimerMaxSec))\n            #else\n            ts.tv_sec = min(ts.tv_sec, sysIntervalTimerMaxSec)\n            #endif\n\n            return ts\n        }\n    }\n\n    /// Apply a kqueue changeset by calling the `kevent` function with the `kevent`s supplied in `keventBuffer`.\n    private func kqueueApplyEventChangeSet(keventBuffer: UnsafeMutableBufferPointer<kevent>) throws {\n        // WARNING: This is called on `self.myThread` OR with `self.externalSelectorFDLock` held.\n        // So it MUST NOT touch anything on `self.` apart from constants and `self.selectorFD`.\n        guard keventBuffer.count > 0 else {\n            // nothing to do\n            return\n        }\n        do {\n            try KQueue.kevent(\n                kq: self.selectorFD,\n                changelist: keventBuffer.baseAddress!,\n                nchanges: CInt(keventBuffer.count),\n                eventlist: nil,\n                nevents: 0,\n                timeout: nil\n            )\n        } catch let err as IOError {\n            if err.errnoCode == EINTR {\n                // See https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2\n                // When kevent() call fails with EINTR error, all changes in the changelist have been applied.\n                return\n            }\n            throw err\n        }\n    }\n\n    private func kqueueUpdateEventNotifications(\n        selectableFD: CInt,\n        interested: SelectorEventSet,\n        oldInterested: SelectorEventSet?,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        assert(self.myThread.isCurrentSlow)\n        let oldKQueueFilters = KQueueEventFilterSet(selectorEventSet: oldInterested ?? ._none)\n        let newKQueueFilters = KQueueEventFilterSet(selectorEventSet: interested)\n        assert(interested.contains(.reset))\n        assert(oldInterested?.contains(.reset) ?? true)\n\n        try newKQueueFilters.calculateKQueueFilterSetChanges(\n            previousKQueueFilterSet: oldKQueueFilters,\n            fileDescriptor: selectableFD,\n            registrationID: registrationID,\n            kqueueApplyEventChangeSet\n        )\n    }\n\n    func initialiseState0() throws {\n\n        self.selectorFD = try KQueue.kqueue()\n        self.lifecycleState = .open\n\n        var event = kevent()\n        event.ident = 0\n        event.filter = Int16(EVFILT_USER)\n        event.fflags = UInt32(NOTE_FFNOP)\n        event.data = 0\n        event.udata = nil\n        event.flags = UInt16(EV_ADD | EV_ENABLE | EV_CLEAR)\n        try withUnsafeMutablePointer(to: &event) { ptr in\n            try kqueueApplyEventChangeSet(keventBuffer: UnsafeMutableBufferPointer(start: ptr, count: 1))\n        }\n    }\n\n    func deinitAssertions0() {\n    }\n\n    func register0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        interested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        try kqueueUpdateEventNotifications(\n            selectableFD: selectableFD,\n            interested: interested,\n            oldInterested: nil,\n            registrationID: registrationID\n        )\n    }\n\n    func reregister0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        oldInterested: SelectorEventSet,\n        newInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        try kqueueUpdateEventNotifications(\n            selectableFD: selectableFD,\n            interested: newInterested,\n            oldInterested: oldInterested,\n            registrationID: registrationID\n        )\n    }\n\n    func deregister0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        oldInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        try kqueueUpdateEventNotifications(\n            selectableFD: selectableFD,\n            interested: .reset,\n            oldInterested: oldInterested,\n            registrationID: registrationID\n        )\n    }\n\n    /// Apply the given `SelectorStrategy` and execute `body` once it's complete (which may produce `SelectorEvent`s to handle).\n    ///\n    /// - Parameters:\n    ///   - strategy: The `SelectorStrategy` to apply\n    ///   - body: The function to execute for each `SelectorEvent` that was produced.\n    @inlinable\n    func whenReady0(\n        strategy: SelectorStrategy,\n        onLoopBegin loopStart: () -> Void,\n        _ body: (SelectorEvent<R>) throws -> Void\n    ) throws {\n        assert(self.myThread.isCurrentSlow)\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't call whenReady for selector as it's \\(self.lifecycleState).\")\n        }\n\n        let timespec = Selector.toKQueueTimeSpec(strategy: strategy)\n        let ready = try timespec.withUnsafeOptionalPointer { ts in\n            Int(\n                try KQueue.kevent(\n                    kq: self.selectorFD,\n                    changelist: nil,\n                    nchanges: 0,\n                    eventlist: self.events,\n                    nevents: Int32(self.eventsCapacity),\n                    timeout: ts\n                )\n            )\n        }\n\n        loopStart()\n\n        for i in 0..<ready {\n            let ev = self.events[i]\n            let filter = Int32(ev.filter)\n            let eventRegistrationID = SelectorRegistrationID(kqueueUData: ev.udata)\n            guard Int32(ev.flags) & EV_ERROR == 0 else {\n                throw IOError(\n                    errnoCode: Int32(ev.data),\n                    reason: \"kevent returned with EV_ERROR set: \\(String(describing: ev))\"\n                )\n            }\n            guard filter != EVFILT_USER, let registration = self.registrations[Int(ev.ident)] else {\n                continue\n            }\n            guard eventRegistrationID == registration.registrationID else {\n                continue\n            }\n            var selectorEvent: SelectorEventSet = ._none\n            switch filter {\n            case EVFILT_READ:\n                selectorEvent.formUnion(.read)\n                fallthrough  // falling through here as `EVFILT_READ` also delivers `EV_EOF` (meaning `.readEOF`)\n            case EVFILT_EXCEPT:\n                if Int32(ev.flags) & EV_EOF != 0 && registration.interested.contains(.readEOF) {\n                    // we only add `.readEOF` if it happened and the user asked for it\n                    selectorEvent.formUnion(.readEOF)\n                }\n            case EVFILT_WRITE:\n                selectorEvent.formUnion(.write)\n            default:\n                // We only use EVFILT_USER, EVFILT_READ, EVFILT_EXCEPT and EVFILT_WRITE.\n                fatalError(\"unexpected filter \\(ev.filter)\")\n            }\n            if ev.fflags != 0 {\n                selectorEvent.formUnion(.reset)\n            }\n            // we can only verify the events for i == 0 as for i > 0 the user might have changed the registrations since then.\n            assert(\n                i != 0 || selectorEvent.isSubset(of: registration.interested),\n                \"selectorEvent: \\(selectorEvent), registration: \\(registration)\"\n            )\n\n            // in any case we only want what the user is currently registered for & what we got\n            selectorEvent = selectorEvent.intersection(registration.interested)\n\n            guard selectorEvent != ._none else {\n                continue\n            }\n            try body((SelectorEvent(io: selectorEvent, registration: registration)))\n        }\n\n        self.growEventArrayIfNeeded(ready: ready)\n    }\n\n    /// Close the `Selector`.\n    ///\n    /// After closing the `Selector` it's no longer possible to use it.\n    func close0() throws {\n\n        self.externalSelectorFDLock.withLock {\n            // We try! all of the closes because close can only fail in the following ways:\n            // - EINTR, which we eat in Posix.close\n            // - EIO, which can only happen for on-disk files\n            // - EBADF, which can't happen here because we would crash as EBADF is marked unacceptable\n            // Therefore, we assert here that close will always succeed and if not, that's a NIO bug we need to know\n            // about.\n            // We limit close to only be for positive FD:s though, as subclasses (e.g. uring)\n            // may already have closed some of these FD:s in their close function.\n\n            try! Posix.close(descriptor: self.selectorFD)\n            self.selectorFD = -1\n        }\n    }\n\n    // attention, this may (will!) be called from outside the event loop, ie. can't access mutable shared state (such as `self.open`)\n    func wakeup0() throws {\n        assert(!self.myThread.isCurrentSlow)\n        try self.externalSelectorFDLock.withLock {\n            guard self.selectorFD >= 0 else {\n                throw EventLoopError._shutdown\n            }\n            var event = kevent()\n            event.ident = 0\n            event.filter = Int16(EVFILT_USER)\n            event.fflags = UInt32(NOTE_TRIGGER | NOTE_FFNOP)\n            event.data = 0\n            event.udata = nil\n            event.flags = 0\n            try withUnsafeMutablePointer(to: &event) { ptr in\n                try self.kqueueApplyEventChangeSet(keventBuffer: UnsafeMutableBufferPointer(start: ptr, count: 1))\n            }\n        }\n    }\n}\n\nextension kevent {\n    /// Update a kevent for a given filter, file descriptor, and set of flags.\n    mutating func setEvent(fileDescriptor fd: CInt, filter: CInt, flags: UInt16, registrationID: SelectorRegistrationID)\n    {\n        self.ident = UInt(fd)\n        self.filter = Int16(filter)\n        self.flags = flags\n        self.udata = UnsafeMutableRawPointer(bitPattern: UInt(registrationID.rawValue))\n\n        // On macOS, EVFILT_EXCEPT will fire whenever there is unread data in the socket receive\n        // buffer. This is not a behaviour we want from EVFILT_EXCEPT: we only want it to tell us\n        // about actually exceptional conditions. For this reason, when we set EVFILT_EXCEPT\n        // we do it with NOTE_LOWAT set to Int.max, which will ensure that there is never enough data\n        // in the send buffer to trigger EVFILT_EXCEPT. Thanks to the sensible design of kqueue,\n        // this only affects our EXCEPT filter: EVFILT_READ behaves separately.\n        #if canImport(Darwin)\n        if filter == EVFILT_EXCEPT {\n            self.fflags = CUnsignedInt(NOTE_LOWAT)\n            self.data = Int.max\n        } else {\n            self.fflags = 0\n            self.data = 0\n        }\n        #else\n        self.fflags = 0\n        self.data = 0\n        #endif\n    }\n}\n\n/// This structure encapsulates our need to create up to three kevent entries when calculating kevent filter\n/// set changes. We want to be able to store these kevent objects on the stack, which we historically did with\n/// unsafe pointers. This object replaces that unsafe code with safe code, and attempts to achieve the same\n/// performance constraints.\nprivate struct KeventTriple {\n    // We need to store this in a tuple to achieve C-style memory layout.\n    private var kevents = (kevent(), kevent(), kevent())\n\n    private var initialized = 0\n\n    private subscript(_ event: Int) -> kevent {\n        get {\n            switch event {\n            case 0:\n                return kevents.0\n            case 1:\n                return kevents.1\n            case 2:\n                return kevents.2\n            default:\n                preconditionFailure()\n            }\n        }\n        set {\n            switch event {\n            case 0:\n                kevents.0 = newValue\n            case 1:\n                kevents.1 = newValue\n            case 2:\n                kevents.2 = newValue\n            default:\n                preconditionFailure()\n            }\n        }\n    }\n\n    mutating func appendEvent(\n        fileDescriptor fd: CInt,\n        filter: CInt,\n        flags: UInt16,\n        registrationID: SelectorRegistrationID\n    ) {\n        defer {\n            // Unchecked math is safe here: we access through the subscript, which will trap on out-of-bounds value, so we'd trap\n            // well before we overflow.\n            self.initialized &+= 1\n        }\n\n        self[self.initialized].setEvent(\n            fileDescriptor: fd,\n            filter: filter,\n            flags: flags,\n            registrationID: registrationID\n        )\n    }\n\n    mutating func withUnsafeBufferPointer(_ body: (UnsafeMutableBufferPointer<kevent>) throws -> Void) rethrows {\n        try withUnsafeMutablePointer(to: &self.kevents) { keventPtr in\n            // Pointer to a homogeneous tuple of a given type is also implicitly bound to the element type, so\n            // we can safely pun this here.\n            let typedPointer = UnsafeMutableRawPointer(keventPtr).assumingMemoryBound(to: kevent.self)\n            let typedBufferPointer = UnsafeMutableBufferPointer(start: typedPointer, count: self.initialized)\n            try body(typedBufferPointer)\n        }\n    }\n}\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectorUring.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if SWIFTNIO_USE_IO_URING\n#if os(Linux) || os(Android)\n\n/// Represents the `poll` filters/events we might use from io_uring:\n///\n///  - `hangup` corresponds to `POLLHUP`\n///  - `readHangup` corresponds to `POLLRDHUP`\n///  - `input` corresponds to `POLLIN`\n///  - `output` corresponds to `POLLOUT`\n///  - `error` corresponds to `POLLERR`\nprivate struct URingFilterSet: OptionSet, Equatable {\n    typealias RawValue = UInt8\n\n    let rawValue: RawValue\n\n    static let _none = URingFilterSet([])\n    static let hangup = URingFilterSet(rawValue: 1 << 0)\n    static let readHangup = URingFilterSet(rawValue: 1 << 1)\n    static let input = URingFilterSet(rawValue: 1 << 2)\n    static let output = URingFilterSet(rawValue: 1 << 3)\n    static let error = URingFilterSet(rawValue: 1 << 4)\n\n    init(rawValue: RawValue) {\n        self.rawValue = rawValue\n    }\n}\n\nextension URingFilterSet {\n    /// Convert NIO's `SelectorEventSet` set to a `URingFilterSet`\n    init(selectorEventSet: SelectorEventSet) {\n        var thing: URingFilterSet = [.error, .hangup]\n        if selectorEventSet.contains(.read) {\n            thing.formUnion(.input)\n        }\n        if selectorEventSet.contains(.write) {\n            thing.formUnion(.output)\n        }\n        if selectorEventSet.contains(.readEOF) {\n            thing.formUnion(.readHangup)\n        }\n        self = thing\n    }\n}\n\nextension SelectorEventSet {\n    var uringEventSet: UInt32 {\n        assert(self != ._none)\n        // POLLERR | POLLHUP is always set unconditionally anyway but it's easier to understand if we explicitly ask.\n        var filter: UInt32 = URing.POLLERR | URing.POLLHUP\n        let uringFilters = URingFilterSet(selectorEventSet: self)\n        if uringFilters.contains(.input) {\n            filter |= URing.POLLIN\n        }\n        if uringFilters.contains(.output) {\n            filter |= URing.POLLOUT\n        }\n        if uringFilters.contains(.readHangup) {\n            filter |= URing.POLLRDHUP\n        }\n        assert(filter & URing.POLLHUP != 0)  // both of these are reported\n        assert(filter & URing.POLLERR != 0)  // always and can't be masked.\n        return filter\n    }\n\n    fileprivate init(uringEvent: UInt32) {\n        var selectorEventSet: SelectorEventSet = ._none\n        if uringEvent & URing.POLLIN != 0 {\n            selectorEventSet.formUnion(.read)\n        }\n        if uringEvent & URing.POLLOUT != 0 {\n            selectorEventSet.formUnion(.write)\n        }\n        if uringEvent & URing.POLLRDHUP != 0 {\n            selectorEventSet.formUnion(.readEOF)\n        }\n        if uringEvent & URing.POLLHUP != 0 || uringEvent & URing.POLLERR != 0 {\n            selectorEventSet.formUnion(.reset)\n        }\n        self = selectorEventSet\n    }\n}\n\nextension Selector: _SelectorBackendProtocol {\n    internal func _debugPrint(_ s: @autoclosure () -> String) {\n        #if SWIFTNIO_IO_URING_DEBUG_SELECTOR\n        print(\"S [\\(NIOThread.current)] \" + s())\n        #endif\n    }\n\n    func initialiseState0() throws {\n        try ring.io_uring_queue_init()\n        self.selectorFD = ring.fd\n\n        // eventfd are always singleshot and re-register each time around\n        // as certain use cases of nio seems to generate superfluous wakeups.\n        // (at least its tested for that in some of the performance tests\n        // e.g. future_whenallsucceed_100k_deferred_off_loop, future_whenallcomplete_100k_deferred_off_loop\n        // ) - if using normal ET multishots, we would get 100k events to handle basically.\n        // so using single shot for wakeups makes those tests run 30-35% faster approx.\n\n        self.eventFD = try EventFd.eventfd(initval: 0, flags: Int32(EventFd.EFD_CLOEXEC | EventFd.EFD_NONBLOCK))\n\n        ring.io_uring_prep_poll_add(\n            fileDescriptor: self.eventFD,\n            pollMask: URing.POLLIN,\n            registrationID: SelectorRegistrationID(rawValue: 0),\n            multishot: false\n        )  // wakeups\n\n        self.lifecycleState = .open\n        _debugPrint(\"URingSelector up and running fd [\\(self.selectorFD)] wakeups on event_fd [\\(self.eventFD)]\")\n    }\n\n    func deinitAssertions0() {\n        assert(self.eventFD == -1, \"self.eventFD == \\(self.eventFD) on deinitAssertions0 deinit, forgot close?\")\n    }\n\n    func register0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        interested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        _debugPrint(\n            \"register interested \\(interested) uringEventSet [\\(interested.uringEventSet)] registrationID[\\(registrationID)]\"\n        )\n        self.deferredReregistrationsPending = true\n        ring.io_uring_prep_poll_add(\n            fileDescriptor: fileDescriptor,\n            pollMask: interested.uringEventSet,\n            registrationID: registrationID,\n            submitNow: !deferReregistrations,\n            multishot: multishot\n        )\n    }\n\n    func reregister0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        oldInterested: SelectorEventSet,\n        newInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        _debugPrint(\n            \"Re-register old \\(oldInterested) new \\(newInterested) uringEventSet [\\(oldInterested.uringEventSet)] reg.uringEventSet [\\(newInterested.uringEventSet)]\"\n        )\n\n        self.deferredReregistrationsPending = true\n        if multishot {\n            ring.io_uring_poll_update(\n                fileDescriptor: fileDescriptor,\n                newPollmask: newInterested.uringEventSet,\n                oldPollmask: oldInterested.uringEventSet,\n                registrationID: registrationID,\n                submitNow: !deferReregistrations,\n                multishot: true\n            )\n        } else {\n            ring.io_uring_prep_poll_remove(\n                fileDescriptor: fileDescriptor,\n                pollMask: oldInterested.uringEventSet,\n                registrationID: registrationID,\n                submitNow: !deferReregistrations,\n                link: true\n            )  // next event linked will cancel if this event fails\n\n            ring.io_uring_prep_poll_add(\n                fileDescriptor: fileDescriptor,\n                pollMask: newInterested.uringEventSet,\n                registrationID: registrationID,\n                submitNow: !deferReregistrations,\n                multishot: false\n            )\n        }\n    }\n\n    func deregister0(\n        selectableFD: CInt,\n        fileDescriptor: CInt,\n        oldInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        _debugPrint(\"deregister interested \\(selectable) reg.interested.uringEventSet [\\(oldInterested.uringEventSet)]\")\n\n        self.deferredReregistrationsPending = true\n        ring.io_uring_prep_poll_remove(\n            fileDescriptor: fileDescriptor,\n            pollMask: oldInterested.uringEventSet,\n            registrationID: registrationID,\n            submitNow: !deferReregistrations\n        )\n    }\n\n    private func shouldRefreshPollForEvent(selectorEvent: SelectorEventSet) -> Bool {\n        if selectorEvent.contains(.read) {\n            // as we don't do exhaustive reads, we need to prod the kernel for\n            // new events, would be even better if we knew if we had read all there is\n            return true\n        }\n        // If the event is fully handled, we can return false to avoid reregistration for multishot polls.\n        return false\n    }\n\n    /// Apply the given `SelectorStrategy` and execute `body` once it's complete (which may produce `SelectorEvent`s to handle).\n    ///\n    /// - Parameters:\n    ///   - strategy: The `SelectorStrategy` to apply\n    ///   - body: The function to execute for each `SelectorEvent` that was produced.\n    func whenReady0(\n        strategy: SelectorStrategy,\n        onLoopBegin loopStart: () -> Void,\n        _ body: (SelectorEvent<R>) throws -> Void\n    ) throws {\n        assert(self.myThread == NIOThread.current)\n        guard self.lifecycleState == .open else {\n            throw IOError(errnoCode: EBADF, reason: \"can't call whenReady for selector as it's \\(self.lifecycleState).\")\n        }\n\n        var ready: Int = 0\n\n        // flush reregistration of pending modifications if needed (nop in SQPOLL mode)\n        // basically this elides all reregistrations and deregistrations into a single\n        // syscall instead of one for each. Future improvement would be to also merge\n        // the pending pollmasks (now each change will be queued, but we could also\n        // merge the masks for reregistrations) - but the most important thing is to\n        // only trap into the kernel once for the set of changes, so needs to be measured.\n        if deferReregistrations && self.deferredReregistrationsPending {\n            self.deferredReregistrationsPending = false\n            ring.io_uring_flush()\n        }\n\n        switch strategy {\n        case .now:\n            _debugPrint(\"whenReady.now\")\n            ready = Int(\n                ring.io_uring_peek_batch_cqe(events: events, maxevents: UInt32(eventsCapacity), multishot: multishot)\n            )\n        case .blockUntilTimeout(let timeAmount):\n            _debugPrint(\"whenReady.blockUntilTimeout\")\n            ready = try Int(\n                ring.io_uring_wait_cqe_timeout(\n                    events: events,\n                    maxevents: UInt32(eventsCapacity),\n                    timeout: timeAmount,\n                    multishot: multishot\n                )\n            )\n        case .block:\n            _debugPrint(\"whenReady.block\")\n            ready = Int(\n                ring.io_uring_peek_batch_cqe(events: events, maxevents: UInt32(eventsCapacity), multishot: multishot)\n            )  // first try to consume any existing\n\n            if ready <= 0  // otherwise block (only single supported, but we will use batch peek cqe next run around...\n            {\n                ready = try ring.io_uring_wait_cqe(\n                    events: events,\n                    maxevents: UInt32(eventsCapacity),\n                    multishot: multishot\n                )\n            }\n        }\n\n        loopStart()\n\n        for i in 0..<ready {\n            let event = events[i]\n\n            switch event.fd {\n            case self.eventFD:  // we don't run these as multishots to avoid tons of events when many wakeups are done\n                _debugPrint(\"wakeup successful for event.fd [\\(event.fd)]\")\n                var val = EventFd.eventfd_t()\n                ring.io_uring_prep_poll_add(\n                    fileDescriptor: self.eventFD,\n                    pollMask: URing.POLLIN,\n                    registrationID: SelectorRegistrationID(rawValue: 0),\n                    submitNow: false,\n                    multishot: false\n                )\n                do {\n                    _ = try EventFd.eventfd_read(fd: self.eventFD, value: &val)  // consume wakeup event\n                    _debugPrint(\"read val [\\(val)] from event.fd [\\(event.fd)]\")\n                } catch {\n                }\n            default:\n                if let registration = registrations[Int(event.fd)] {\n\n                    _debugPrint(\"We found a registration for event.fd [\\(event.fd)]\")  // \\(registration)\n\n                    // The io_uring backend only has 16 bits available for the registration id\n                    guard event.registrationID == UInt16(truncatingIfNeeded: registration.registrationID.rawValue)\n                    else {\n                        _debugPrint(\n                            \"The event.registrationID [\\(event.registrationID)] !=  registration.selectableregistrationID [\\(registration.registrationID)], skipping to next event\"\n                        )\n                        continue\n                    }\n\n                    var selectorEvent = SelectorEventSet(uringEvent: event.pollMask)\n\n                    _debugPrint(\"selectorEvent [\\(selectorEvent)] registration.interested [\\(registration.interested)]\")\n\n                    // we only want what the user is currently registered for & what we got\n                    selectorEvent = selectorEvent.intersection(registration.interested)\n\n                    _debugPrint(\"intersection [\\(selectorEvent)]\")\n\n                    if selectorEvent.contains(.readEOF) {\n                        _debugPrint(\"selectorEvent.contains(.readEOF) [\\(selectorEvent.contains(.readEOF))]\")\n                    }\n\n                    if multishot == false {  // must be before guard, otherwise lost wake\n                        ring.io_uring_prep_poll_add(\n                            fileDescriptor: event.fd,\n                            pollMask: registration.interested.uringEventSet,\n                            registrationID: registration.registrationID,\n                            submitNow: false,\n                            multishot: false\n                        )\n\n                        if event.pollCancelled {\n                            _debugPrint(\"Received event.pollCancelled\")\n                        }\n                    }\n\n                    guard selectorEvent != ._none else {\n                        _debugPrint(\n                            \"selectorEvent != ._none / [\\(selectorEvent)] [\\(registration.interested)] [\\(SelectorEventSet(uringEvent: event.pollMask))] [\\(event.pollMask)] [\\(event.fd)]\"\n                        )\n                        continue\n                    }\n\n                    // This is only needed due to the edge triggered nature of liburing, possibly\n                    // we can get away with only updating (force triggering an event if available) for\n                    // partial reads (where we currently give up after N iterations)\n\n                    // can be after guard as it is multishot\n                    if multishot && self.shouldRefreshPollForEvent(selectorEvent: selectorEvent) {\n                        ring.io_uring_poll_update(\n                            fileDescriptor: event.fd,\n                            newPollmask: registration.interested.uringEventSet,\n                            oldPollmask: registration.interested.uringEventSet,\n                            registrationID: registration.registrationID,\n                            submitNow: false\n                        )\n                    }\n\n                    _debugPrint(\n                        \"running body [\\(NIOThread.current)] \\(selectorEvent) \\(SelectorEventSet(uringEvent: event.pollMask))\"\n                    )\n\n                    try body((SelectorEvent(io: selectorEvent, registration: registration)))\n\n                } else {  // remove any polling if we don't have a registration for it\n                    _debugPrint(\n                        \"We had no registration for event.fd [\\(event.fd)] event.pollMask [\\(event.pollMask)] event.registrationID [\\(event.registrationID)], it should be deregistered already\"\n                    )\n                    if multishot == false {\n                        ring.io_uring_prep_poll_remove(\n                            fileDescriptor: event.fd,\n                            pollMask: event.pollMask,\n                            registrationID: SelectorRegistrationID(rawValue: UInt32(event.registrationID)),\n                            submitNow: false\n                        )\n                    }\n                }\n            }\n        }\n\n        self.deferredReregistrationsPending = false  // none pending as we will flush here\n        ring.io_uring_flush()  // flush reregisteration of the polls if needed (nop in SQPOLL mode)\n        growEventArrayIfNeeded(ready: ready)\n    }\n\n    /// Close the `Selector`.\n    ///\n    /// After closing the `Selector` it's no longer possible to use it.\n    public func close0() throws {\n        self.externalSelectorFDLock.withLock {\n            // We try! all of the closes because close can only fail in the following ways:\n            // - EINTR, which we eat in Posix.close\n            // - EIO, which can only happen for on-disk files\n            // - EBADF, which can't happen here because we would crash as EBADF is marked unacceptable\n            // Therefore, we assert here that close will always succeed and if not, that's a NIO bug we need to know\n            // about.\n\n            ring.io_uring_queue_exit()  // This closes the ring selector fd for us\n            self.selectorFD = -1\n\n            try! Posix.close(descriptor: self.eventFD)\n            self.eventFD = -1\n        }\n        return\n    }\n\n    // attention, this may (will!) be called from outside the event loop, ie. can't access mutable shared state (such as `self.open`)\n    func wakeup0() throws {\n        assert(!NIOThread.isCurrentSlow)\n        try self.externalSelectorFDLock.withLock {\n            guard self.eventFD >= 0 else {\n                throw EventLoopError.shutdown\n            }\n            _ = try EventFd.eventfd_write(fd: self.eventFD, value: 1)\n        }\n    }\n}\n\n#endif\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SelectorWSAPoll.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if os(Windows)\nimport CNIOWindows\nimport NIOCore\nimport WinSDK\n\nextension SelectorEventSet {\n    // Use this property to create pollfd's event field. Reset and errors are (hopefully) always included.\n    // According to the docs we don't need to listen for them explicitly.\n    // Source: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/ns-winsock2-wsapollfd\n    var wsaPollEvent: Int16 {\n        var result: Int16 = 0\n        if self.contains(.read) {\n            result |= Int16(WinSDK.POLLRDNORM)\n        }\n        if self.contains(.write) || self.contains(.writeEOF) {\n            result |= Int16(WinSDK.POLLWRNORM)\n        }\n        return result\n    }\n\n    // Use this initializer to create a EventSet from the wsa pollfd's revent field\n    @usableFromInline\n    init(revents: Int16) {\n        // Event Constant   Meaning\t                What to do (Typical Socket API)\n        // POLLRDNORM       Normal data readable    Use recv, WSARecv, or ReadFile\n        // POLLRDBAND       Priority data readable  Use recv, WSARecv (with MSG_OOB for out-of-band)\n        // POLLWRNORM       Normal data writable    Use send, WSASend, or WriteFile\n        // POLLWRBAND       Priority data writable  Use send (with MSG_OOB for out-of-band data)\n        // POLLERR          Error condition         Use getsockopt with SO_ERROR; may need closesocket\n        // POLLHUP          Closed                  Usually just cleanup: closesocket\n        // POLLNVAL         Invalid fd (not open)   Fix your code; close and remove fd\n        self.rawValue = 0\n        let mapped = Int32(revents)\n        if mapped & WinSDK.POLLRDNORM != 0 {\n            self.formUnion(.read)\n        }\n        if mapped & WinSDK.POLLWRNORM != 0 {\n            self.formUnion(.write)\n        }\n        if mapped & WinSDK.POLLERR != 0 {\n            self.formUnion(.error)\n        }\n        if mapped & WinSDK.POLLHUP != 0 {\n            self.formUnion(.reset)\n        }\n        if mapped & WinSDK.POLLNVAL != 0 {\n            preconditionFailure(\"Invalid fd supplied.\")\n        }\n    }\n}\n\nextension Selector: _SelectorBackendProtocol {\n\n    func initialiseState0() throws {\n        self.pollFDs.reserveCapacity(16)\n    }\n\n    func deinitAssertions0() {\n        // no global state. nothing to check\n    }\n\n    @inlinable\n    func whenReady0(\n        strategy: SelectorStrategy,\n        onLoopBegin: () -> Void,\n        _ body: (SelectorEvent<R>) throws -> Void\n    ) throws {\n        let time: Int32 =\n            switch strategy {\n            case .now:\n                0\n\n            case .block:\n                -1\n\n            case .blockUntilTimeout(let timeAmount):\n                Int32(clamping: timeAmount.nanoseconds / 1_000_000)\n            }\n\n        // WSAPoll requires at least one pollFD structure. If we don't have any pending IO\n        // we should just sleep. By passing true as the second argument our el can be\n        // woken up by an APC (Asynchronous Procedure Call).\n        if self.pollFDs.isEmpty {\n            if time > 0 {\n                SleepEx(UInt32(time), true)\n            } else if time == -1 {\n                SleepEx(INFINITE, true)\n            }\n        } else {\n            let result = self.pollFDs.withUnsafeMutableBufferPointer { ptr in\n                WSAPoll(ptr.baseAddress!, UInt32(ptr.count), time)\n            }\n\n            if result > 0 {\n                // something has happened\n                for i in self.pollFDs.indices {\n                    let pollFD = self.pollFDs[i]\n                    guard pollFD.revents != 0 else {\n                        continue\n                    }\n                    // reset the revents\n                    self.pollFDs[i].revents = 0\n                    let fd = pollFD.fd\n\n                    // If the registration is not in the Map anymore we deregistered it during the processing of whenReady(...). In this case just skip it.\n                    guard let registration = registrations[Int(fd)] else {\n                        continue\n                    }\n\n                    var selectorEvent = SelectorEventSet(revents: pollFD.revents)\n                    // in any case we only want what the user is currently registered for & what we got\n                    selectorEvent = selectorEvent.intersection(registration.interested)\n\n                    guard selectorEvent != ._none else {\n                        continue\n                    }\n\n                    try body((SelectorEvent(io: selectorEvent, registration: registration)))\n                }\n            } else if result == 0 {\n                // nothing has happened\n            } else if result == WinSDK.SOCKET_ERROR {\n                throw IOError(winsock: WSAGetLastError(), reason: \"WSAPoll\")\n            }\n        }\n    }\n\n    func register0(\n        selectableFD: NIOBSDSocket.Handle,\n        fileDescriptor: NIOBSDSocket.Handle,\n        interested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        // TODO (@fabian): We need to replace the pollFDs array with something\n        //                 that will allow O(1) access here.\n        let poll = pollfd(fd: UInt64(fileDescriptor), events: interested.wsaPollEvent, revents: 0)\n        self.pollFDs.append(poll)\n    }\n\n    func reregister0(\n        selectableFD: NIOBSDSocket.Handle,\n        fileDescriptor: NIOBSDSocket.Handle,\n        oldInterested: SelectorEventSet,\n        newInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        fatalError(\"TODO: Unimplemented\")\n    }\n\n    func deregister0(\n        selectableFD: NIOBSDSocket.Handle,\n        fileDescriptor: NIOBSDSocket.Handle,\n        oldInterested: SelectorEventSet,\n        registrationID: SelectorRegistrationID\n    ) throws {\n        fatalError(\"TODO: Unimplemented\")\n    }\n\n    func wakeup0() throws {\n        // will be called from a different thread\n        let result = try self.myThread.withHandleUnderLock { handle in\n            QueueUserAPC(wakeupTarget, handle, 0)\n        }\n        if result == 0 {\n            let errorCode = GetLastError()\n            if let errorMsg = Windows.makeErrorMessageFromCode(errorCode) {\n                throw IOError(errnoCode: Int32(errorCode), reason: errorMsg)\n            }\n        }\n    }\n\n    func close0() throws {\n        self.pollFDs.removeAll()\n    }\n}\n\nprivate func wakeupTarget(_ ptr: UInt64) {\n    // This is the target of our wakeup call.\n    // We don't really need to do anything here. We just need any target\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/ServerSocket.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n/// A server socket that can accept new connections.\nclass ServerSocket: BaseSocket, ServerSocketProtocol {\n    typealias SocketType = ServerSocket\n    private let cleanupOnClose: Bool\n\n    public final class func bootstrap(\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        host: String,\n        port: Int\n    ) throws -> ServerSocket {\n        let socket = try ServerSocket(protocolFamily: protocolFamily)\n        try socket.bind(to: SocketAddress.makeAddressResolvingHost(host, port: port))\n        try socket.listen()\n        return socket\n    }\n\n    /// Create a new instance.\n    ///\n    /// - Parameters:\n    ///   - protocolFamily: The protocol family to use (usually `AF_INET6` or `AF_INET`).\n    ///   - protocolSubtype: The subtype of the protocol, corresponding to the `protocol`\n    ///         argument to the socket syscall. Defaults to 0.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Throws: An `IOError` if creation of the socket failed.\n    init(\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype = .default,\n        setNonBlocking: Bool = false\n    ) throws {\n        let sock = try BaseSocket.makeSocket(\n            protocolFamily: protocolFamily,\n            type: .stream,\n            protocolSubtype: protocolSubtype,\n            setNonBlocking: setNonBlocking\n        )\n        switch protocolFamily {\n        case .unix:\n            cleanupOnClose = true\n        default:\n            cleanupOnClose = false\n        }\n        try super.init(socket: sock)\n    }\n\n    /// Create a new instance.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The _Unix file descriptor_ representing the bound socket.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Throws: An `IOError` if socket is invalid.\n    #if !os(Windows)\n    @available(*, deprecated, renamed: \"init(socket:setNonBlocking:)\")\n    convenience init(descriptor: CInt, setNonBlocking: Bool = false) throws {\n        try self.init(socket: descriptor, setNonBlocking: setNonBlocking)\n    }\n    #endif\n\n    /// Create a new instance.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The _Unix file descriptor_ representing the bound socket.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Throws: An `IOError` if socket is invalid.\n    init(socket: NIOBSDSocket.Handle, setNonBlocking: Bool = false) throws {\n        cleanupOnClose = false  // socket already bound, owner must clean up\n        try super.init(socket: socket)\n        if setNonBlocking {\n            try self.setNonBlocking()\n        }\n    }\n\n    /// Start to listen for new connections.\n    ///\n    /// - Parameters:\n    ///   - backlog: The backlog to use.\n    /// - Throws: An `IOError` if creation of the socket failed.\n    func listen(backlog: Int32 = 128) throws {\n        try withUnsafeHandle {\n            _ = try NIOBSDSocket.listen(socket: $0, backlog: backlog)\n        }\n    }\n\n    /// Accept a new connection\n    ///\n    /// - Parameters:\n    ///   - setNonBlocking: set non-blocking mode on the returned `Socket`. On Linux this will use accept4 with SOCK_NONBLOCK to save a system call.\n    /// - Returns: A `Socket` once a new connection was established or `nil` if this `ServerSocket` is in non-blocking mode and there is no new connection that can be accepted when this method is called.\n    /// - Throws: An `IOError` if the operation failed.\n    func accept(setNonBlocking: Bool = false) throws -> Socket? {\n        try withUnsafeHandle { fd in\n            #if os(Linux)\n            let flags: Int32\n            if setNonBlocking {\n                flags = Linux.SOCK_NONBLOCK\n            } else {\n                flags = 0\n            }\n            let result = try Linux.accept4(descriptor: fd, addr: nil, len: nil, flags: flags)\n            #else\n            let result = try NIOBSDSocket.accept(socket: fd, address: nil, address_len: nil)\n            #endif\n\n            guard let fd = result else {\n                return nil\n            }\n\n            let sock = try Socket(socket: fd)\n\n            #if !os(Linux)\n            if setNonBlocking {\n                do {\n                    try sock.setNonBlocking()\n                } catch {\n                    // best effort\n                    try? sock.close()\n                    throw error\n                }\n            }\n            #endif\n            return sock\n        }\n    }\n\n    /// Close the socket.\n    ///\n    /// After the socket was closed all other methods will throw an `IOError` when called.\n    ///\n    /// - Throws: An `IOError` if the operation failed.\n    override func close() throws {\n        let maybePathname = self.cleanupOnClose ? (try? self.localAddress().pathname) : nil\n        try super.close()\n        if let socketPath = maybePathname {\n            try BaseSocket.cleanupSocket(unixDomainSocketPath: socketPath)\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Socket.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport CNIOLinux\nimport CNIOOpenBSD\nimport NIOCore\n\n#if canImport(WinSDK)\nimport WinSDK\n#endif\n\n/// The container used for writing multiple buffers via `writev`.\n#if canImport(WinSDK)\ntypealias IOVector = WSABUF\n#else\ntypealias IOVector = iovec\n#endif\n\n// TODO: scattering support\nclass Socket: BaseSocket, SocketProtocol {\n    typealias SocketType = Socket\n\n    /// The maximum number of bytes to write per `writev` call.\n    static let writevLimitBytes = Int(Int32.max)\n\n    /// The maximum number of `IOVector`s to write per `writev` call.\n    static let writevLimitIOVectors: Int = Posix.UIO_MAXIOV\n\n    /// Create a new instance.\n    ///\n    /// - Parameters:\n    ///   - protocolFamily: The protocol family to use (usually `AF_INET6` or `AF_INET`).\n    ///   - type: The type of the socket to create.\n    ///   - protocolSubtype: The subtype of the protocol, corresponding to the `protocolSubtype`\n    ///         argument to the socket syscall. Defaults to 0.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Throws: An `IOError` if creation of the socket failed.\n    init(\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype = .default,\n        setNonBlocking: Bool = false\n    ) throws {\n        let sock = try BaseSocket.makeSocket(\n            protocolFamily: protocolFamily,\n            type: type,\n            protocolSubtype: protocolSubtype,\n            setNonBlocking: setNonBlocking\n        )\n        try super.init(socket: sock)\n    }\n\n    /// Create a new instance out of an already established socket.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The existing socket descriptor.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Throws: An `IOError` if could not change the socket into non-blocking\n    #if !os(Windows)\n    @available(*, deprecated, renamed: \"init(socket:setNonBlocking:)\")\n    convenience init(descriptor: CInt, setNonBlocking: Bool) throws {\n        try self.init(socket: descriptor, setNonBlocking: setNonBlocking)\n    }\n    #endif\n\n    /// Create a new instance out of an already established socket.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The existing socket descriptor.\n    ///   - setNonBlocking: Set non-blocking mode on the socket.\n    /// - Throws: An `IOError` if could not change the socket into non-blocking\n    init(socket: NIOBSDSocket.Handle, setNonBlocking: Bool) throws {\n        try super.init(socket: socket)\n        if setNonBlocking {\n            try self.setNonBlocking()\n        }\n    }\n\n    /// Create a new instance.\n    ///\n    /// The ownership of the passed in descriptor is transferred to this class. A user must call `close` to close the underlying\n    /// file descriptor once it's not needed / used anymore.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The file descriptor to wrap.\n    #if !os(Windows)\n    @available(*, deprecated, renamed: \"init(socket:)\")\n    convenience init(descriptor: CInt) throws {\n        try self.init(socket: descriptor)\n    }\n    #endif\n\n    /// Create a new instance.\n    ///\n    /// The ownership of the passed in descriptor is transferred to this class. A user must call `close` to close the underlying\n    /// file descriptor once it's not needed / used anymore.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The file descriptor to wrap.\n    override init(socket: NIOBSDSocket.Handle) throws {\n        try super.init(socket: socket)\n    }\n\n    /// Connect to the `SocketAddress`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to which the connection should be established.\n    /// - Returns: `true` if the connection attempt completes, `false` if `finishConnect` must be called later to complete the connection attempt.\n    /// - Throws: An `IOError` if the operation failed.\n    func connect(to address: SocketAddress) throws -> Bool {\n        try withUnsafeHandle { fd in\n            try address.withSockAddr { (ptr, size) in\n                try NIOBSDSocket.connect(\n                    socket: fd,\n                    address: ptr,\n                    address_len: socklen_t(size)\n                )\n            }\n        }\n    }\n\n    func connect(to address: VsockAddress) throws -> Bool {\n        try withUnsafeHandle { fd in\n            try address.withSockAddr { (ptr, size) in\n                try NIOBSDSocket.connect(\n                    socket: fd,\n                    address: ptr,\n                    address_len: socklen_t(size)\n                )\n            }\n        }\n    }\n\n    /// Finish a previous non-blocking `connect` operation.\n    ///\n    /// - Throws: An `IOError` if the operation failed.\n    func finishConnect() throws {\n        let result: Int32 = try getOption(level: .socket, name: .so_error)\n        if result != 0 {\n            throw IOError(errnoCode: result, reason: \"finishing a non-blocking connect failed\")\n        }\n    }\n\n    /// Write data to the remote peer.\n    ///\n    /// - Parameters:\n    ///   - pointer: Pointer (and size) to data to write.\n    /// - Returns: The `IOResult` which indicates how much data could be written and if the operation returned before all could be written (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func write(pointer: UnsafeRawBufferPointer) throws -> IOResult<Int> {\n        try withUnsafeHandle {\n            try NIOBSDSocket.send(\n                socket: $0,\n                buffer: pointer.baseAddress!,\n                length: pointer.count\n            )\n        }\n    }\n\n    /// Write data to the remote peer (gathering writes).\n    ///\n    /// - Parameters:\n    ///   - iovecs: The `IOVector`s to write.\n    /// - Returns: The `IOResult` which indicates how much data could be written and if the operation returned before all could be written (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func writev(iovecs: UnsafeBufferPointer<IOVector>) throws -> IOResult<Int> {\n        try withUnsafeHandle {\n            try NIOBSDSocket.writev(socket: $0, iovecs: iovecs)\n        }\n    }\n\n    /// Send data to a destination.\n    ///\n    /// - Parameters:\n    ///   - pointer: Pointer (and size) to the data to send.\n    ///   - destinationPtr: The destination to which the data should be sent.\n    ///   - destinationSize: The size of the destination address given.\n    ///   - controlBytes: Extra `cmsghdr` information.\n    /// - Returns: The `IOResult` which indicates how much data could be written and if the operation returned before all could be written\n    /// (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func sendmsg(\n        pointer: UnsafeRawBufferPointer,\n        destinationPtr: UnsafePointer<sockaddr>?,\n        destinationSize: socklen_t,\n        controlBytes: UnsafeMutableRawBufferPointer\n    ) throws -> IOResult<Int> {\n        // Dubious const casts - it should be OK as there is no reason why this should get mutated\n        // just bad const declaration below us.\n        var vec = IOVector(\n            iov_base: UnsafeMutableRawPointer(mutating: pointer.baseAddress!),\n            iov_len: numericCast(pointer.count)\n        )\n        let notConstCorrectDestinationPtr = UnsafeMutableRawPointer(mutating: destinationPtr)\n\n        return try self.withUnsafeHandle { handle in\n            try withUnsafeMutablePointer(to: &vec) { vecPtr in\n                var messageHeader = msghdr()\n                messageHeader.msg_name = notConstCorrectDestinationPtr\n                messageHeader.msg_namelen = destinationSize\n                messageHeader.msg_iov = vecPtr\n                messageHeader.msg_iovlen = 1\n                messageHeader.control_ptr = controlBytes\n                messageHeader.msg_flags = 0\n                return try NIOBSDSocket.sendmsg(socket: handle, msgHdr: &messageHeader, flags: 0)\n            }\n        }\n    }\n\n    /// Read data from the socket.\n    ///\n    /// - Parameters:\n    ///   - pointer: The pointer (and size) to the storage into which the data should be read.\n    /// - Returns: The `IOResult` which indicates how much data could be read and if the operation returned before all could be read (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func read(pointer: UnsafeMutableRawBufferPointer) throws -> IOResult<Int> {\n        try withUnsafeHandle { (handle) -> IOResult<Int> in\n            #if os(Windows)\n            try Windows.recv(socket: handle, pointer: pointer.baseAddress!, size: Int32(pointer.count), flags: 0)\n            #else\n            try Posix.read(descriptor: handle, pointer: pointer.baseAddress!, size: pointer.count)\n            #endif\n        }\n    }\n\n    /// Receive data from the socket, along with aditional control information.\n    ///\n    /// - Parameters:\n    ///   - pointer: The pointer (and size) to the storage into which the data should be read.\n    ///   - storage: The address from which the data was received\n    ///   - storageLen: The size of the storage itself.\n    ///   - controlBytes: A buffer in memory for use receiving control bytes. This parameter will be modified to hold any data actually received.\n    /// - Returns: The `IOResult` which indicates how much data could be received and if the operation returned before all the data could be received\n    ///     (because the socket is in non-blocking mode)\n    /// - Throws: An `IOError` if the operation failed.\n    func recvmsg(\n        pointer: UnsafeMutableRawBufferPointer,\n        storage: inout sockaddr_storage,\n        storageLen: inout socklen_t,\n        controlBytes: inout UnsafeReceivedControlBytes\n    ) throws -> IOResult<Int> {\n        var vec = IOVector(iov_base: pointer.baseAddress, iov_len: numericCast(pointer.count))\n\n        return try withUnsafeMutablePointer(to: &vec) { vecPtr in\n            try storage.withMutableSockAddr { (sockaddrPtr, _) in\n                var messageHeader = msghdr()\n                messageHeader.msg_name = .init(sockaddrPtr)\n                messageHeader.msg_namelen = storageLen\n                messageHeader.msg_iov = vecPtr\n                messageHeader.msg_iovlen = 1\n                messageHeader.control_ptr = controlBytes.controlBytesBuffer\n                messageHeader.msg_flags = 0\n                defer {\n                    // We need to write back the length of the message.\n                    storageLen = messageHeader.msg_namelen\n                }\n\n                let result = try withUnsafeMutablePointer(to: &messageHeader) { messageHeader in\n                    try withUnsafeHandle { fd in\n                        try NIOBSDSocket.recvmsg(socket: fd, msgHdr: messageHeader, flags: 0)\n                    }\n                }\n\n                // Only look at the control bytes if all is good.\n                if case .processed = result {\n                    controlBytes.receivedControlMessages = UnsafeControlMessageCollection(messageHeader: messageHeader)\n                }\n\n                return result\n            }\n        }\n    }\n\n    /// Send the content of a file descriptor to the remote peer (if possible a zero-copy strategy is applied).\n    ///\n    /// - Parameters:\n    ///   - fd: The file descriptor of the file to send.\n    ///   - offset: The offset in the file.\n    ///   - count: The number of bytes to send.\n    /// - Returns: The `IOResult` which indicates how much data could be send and if the operation returned before all could be send (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func sendFile(fd: CInt, offset: Int, count: Int) throws -> IOResult<Int> {\n        try withUnsafeHandle {\n            try NIOBSDSocket.sendfile(\n                socket: $0,\n                fd: fd,\n                offset: off_t(offset),\n                len: off_t(count)\n            )\n        }\n    }\n\n    /// Receive `MMsgHdr`s.\n    ///\n    /// - Parameters:\n    ///   - msgs: The pointer to the `MMsgHdr`s into which the received message will be stored.\n    /// - Returns: The `IOResult` which indicates how many messages could be received and if the operation returned before all messages could be received (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func recvmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int> {\n        try withUnsafeHandle {\n            try NIOBSDSocket.recvmmsg(\n                socket: $0,\n                msgvec: msgs.baseAddress!,\n                vlen: CUnsignedInt(msgs.count),\n                flags: 0,\n                timeout: nil\n            )\n        }\n    }\n\n    /// Send `MMsgHdr`s.\n    ///\n    /// - Parameters:\n    ///   - msgs: The pointer to the `MMsgHdr`s which will be send.\n    /// - Returns: The `IOResult` which indicates how many messages could be send and if the operation returned before all messages could be send (because the socket is in non-blocking mode).\n    /// - Throws: An `IOError` if the operation failed.\n    func sendmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int> {\n        try withUnsafeHandle {\n            try NIOBSDSocket.sendmmsg(\n                socket: $0,\n                msgvec: msgs.baseAddress!,\n                vlen: CUnsignedInt(msgs.count),\n                flags: 0\n            )\n        }\n    }\n\n    /// Shutdown the socket.\n    ///\n    /// - Parameters:\n    ///   - how: the mode of `Shutdown`.\n    /// - Throws: An `IOError` if the operation failed.\n    func shutdown(how: Shutdown) throws {\n        try withUnsafeHandle {\n            try NIOBSDSocket.shutdown(socket: $0, how: how)\n        }\n    }\n\n    /// Sets the value for the 'UDP_SEGMENT' socket option.\n    func setUDPSegmentSize(_ segmentSize: CInt) throws {\n        try self.withUnsafeHandle {\n            try NIOBSDSocket.setUDPSegmentSize(segmentSize, socket: $0)\n        }\n    }\n\n    /// Returns the value of the 'UDP_SEGMENT' socket option.\n    func getUDPSegmentSize() throws -> CInt {\n        try self.withUnsafeHandle {\n            try NIOBSDSocket.getUDPSegmentSize(socket: $0)\n        }\n    }\n\n    /// Sets the value for the 'UDP_GRO' socket option.\n    func setUDPReceiveOffload(_ enabled: Bool) throws {\n        try self.withUnsafeHandle {\n            try NIOBSDSocket.setUDPReceiveOffload(enabled, socket: $0)\n        }\n    }\n\n    /// Returns the value of the 'UDP_GRO' socket option.\n    func getUDPReceiveOffload() throws -> Bool {\n        try self.withUnsafeHandle {\n            try NIOBSDSocket.getUDPReceiveOffload(socket: $0)\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SocketChannel.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport CNIOLinux\nimport NIOCore\n\n#if os(Windows)\nimport let WinSDK.ECONNABORTED\nimport let WinSDK.ECONNREFUSED\nimport let WinSDK.EMFILE\nimport let WinSDK.ENFILE\nimport let WinSDK.ENOBUFS\nimport let WinSDK.ENOMEM\nimport let WinSDK.INADDR_ANY\n\nimport struct WinSDK.ip_mreq\nimport struct WinSDK.ipv6_mreq\nimport struct WinSDK.socklen_t\n#endif\n\n#if os(OpenBSD)\nimport CNIOOpenBSD\n#endif\n\nextension ByteBuffer {\n    mutating func withMutableWritePointer(\n        body: (UnsafeMutableRawBufferPointer) throws -> IOResult<Int>\n    ) rethrows -> IOResult<Int> {\n        var singleResult: IOResult<Int>!\n        _ = try self.writeWithUnsafeMutableBytes(minimumWritableBytes: 0) { ptr in\n            let localWriteResult = try body(ptr)\n            singleResult = localWriteResult\n            switch localWriteResult {\n            case .processed(let written):\n                return written\n            case .wouldBlock(let written):\n                return written\n            }\n        }\n        return singleResult\n    }\n}\n\n/// A `Channel` for a client socket.\n///\n/// - Note: All operations on `SocketChannel` are thread-safe.\nfinal class SocketChannel: BaseStreamSocketChannel<Socket>, @unchecked Sendable {\n    private var connectTimeout: TimeAmount? = nil\n\n    init(eventLoop: SelectableEventLoop, protocolFamily: NIOBSDSocket.ProtocolFamily, enableMPTCP: Bool = false) throws\n    {\n        var protocolSubtype = NIOBSDSocket.ProtocolSubtype.default\n        if enableMPTCP {\n            guard let subtype = NIOBSDSocket.ProtocolSubtype.mptcp else {\n                throw ChannelError._operationUnsupported\n            }\n            protocolSubtype = subtype\n        }\n        let socket = try Socket(\n            protocolFamily: protocolFamily,\n            type: .stream,\n            protocolSubtype: protocolSubtype,\n            setNonBlocking: true\n        )\n        try super.init(\n            socket: socket,\n            parent: nil,\n            eventLoop: eventLoop,\n            recvAllocator: AdaptiveRecvByteBufferAllocator()\n        )\n    }\n\n    init(eventLoop: SelectableEventLoop, socket: NIOBSDSocket.Handle) throws {\n        let sock = try Socket(socket: socket, setNonBlocking: true)\n        try super.init(\n            socket: sock,\n            parent: nil,\n            eventLoop: eventLoop,\n            recvAllocator: AdaptiveRecvByteBufferAllocator()\n        )\n    }\n\n    init(socket: Socket, parent: Channel? = nil, eventLoop: SelectableEventLoop) throws {\n        try super.init(\n            socket: socket,\n            parent: parent,\n            eventLoop: eventLoop,\n            recvAllocator: AdaptiveRecvByteBufferAllocator()\n        )\n    }\n\n    override func setOption0<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.ConnectTimeoutOption:\n            connectTimeout = value as? TimeAmount\n        default:\n            try super.setOption0(option, value: value)\n        }\n    }\n\n    override func getOption0<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.ConnectTimeoutOption:\n            return connectTimeout as! Option.Value\n        case _ as ChannelOptions.Types.LocalVsockContextID:\n            #if os(Windows) || os(OpenBSD)\n            fallthrough\n            #else\n            return try self.socket.getLocalVsockContextID() as! Option.Value\n            #endif\n        default:\n            return try super.getOption0(option)\n        }\n    }\n\n    func registrationFor(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration {\n        NIORegistration(\n            channel: .socketChannel(self),\n            interested: interested,\n            registrationID: registrationID\n        )\n    }\n\n    private func scheduleConnectTimeout() {\n        if let timeout = connectTimeout {\n            connectTimeoutScheduled = eventLoop.scheduleTask(in: timeout) { () -> Void in\n                if self.pendingConnect != nil {\n                    // The connection was still not established, close the Channel which will also fail the pending promise.\n                    self.close0(error: ChannelError.connectTimeout(timeout), mode: .all, promise: nil)\n                }\n            }\n        }\n    }\n\n    override func connectSocket(to address: SocketAddress) throws -> Bool {\n        if try self.socket.connect(to: address) {\n            return true\n        }\n        self.scheduleConnectTimeout()\n        return false\n    }\n\n    override func connectSocket(to address: VsockAddress) throws -> Bool {\n        if try self.socket.connect(to: address) {\n            return true\n        }\n        self.scheduleConnectTimeout()\n        return false\n    }\n\n    override func finishConnectSocket() throws {\n        if let scheduled = self.connectTimeoutScheduled {\n            // Connection established so cancel the previous scheduled timeout.\n            self.connectTimeoutScheduled = nil\n            scheduled.cancel()\n        }\n        try self.socket.finishConnect()\n    }\n\n    override func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        try selector.register(\n            selectable: self.socket,\n            interested: interested,\n            makeRegistration: self.registrationFor\n        )\n    }\n\n    override func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws {\n        assert(mode == .all)\n        try selector.deregister(selectable: self.socket)\n    }\n\n    override func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        try selector.reregister(selectable: self.socket, interested: interested)\n    }\n}\n\n/// A `Channel` for a server socket.\n///\n/// - Note: All operations on `ServerSocketChannel` are thread-safe.\nfinal class ServerSocketChannel: BaseSocketChannel<ServerSocket>, @unchecked Sendable {\n\n    private var backlog: Int32 = 128\n    private let group: EventLoopGroup\n\n    /// The server socket channel is never writable.\n    // This is `Channel` API so must be thread-safe.\n    override public var isWritable: Bool { false }\n\n    convenience init(\n        eventLoop: SelectableEventLoop,\n        group: EventLoopGroup,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        enableMPTCP: Bool = false\n    ) throws {\n        var protocolSubtype = NIOBSDSocket.ProtocolSubtype.default\n        if enableMPTCP {\n            guard let subtype = NIOBSDSocket.ProtocolSubtype.mptcp else {\n                throw ChannelError._operationUnsupported\n            }\n            protocolSubtype = subtype\n        }\n        try self.init(\n            serverSocket: try ServerSocket(\n                protocolFamily: protocolFamily,\n                protocolSubtype: protocolSubtype,\n                setNonBlocking: true\n            ),\n            eventLoop: eventLoop,\n            group: group\n        )\n    }\n\n    init(serverSocket: ServerSocket, eventLoop: SelectableEventLoop, group: EventLoopGroup) throws {\n        self.group = group\n        try super.init(\n            socket: serverSocket,\n            parent: nil,\n            eventLoop: eventLoop,\n            recvAllocator: AdaptiveRecvByteBufferAllocator(),\n            supportReconnect: false\n        )\n    }\n\n    convenience init(socket: NIOBSDSocket.Handle, eventLoop: SelectableEventLoop, group: EventLoopGroup) throws {\n        let sock = try ServerSocket(socket: socket, setNonBlocking: true)\n        try self.init(serverSocket: sock, eventLoop: eventLoop, group: group)\n        try self.socket.listen(backlog: backlog)\n    }\n\n    func registrationFor(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration {\n        NIORegistration(\n            channel: .serverSocketChannel(self),\n            interested: interested,\n            registrationID: registrationID\n        )\n    }\n\n    override func setOption0<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.BacklogOption:\n            backlog = value as! Int32\n        default:\n            try super.setOption0(option, value: value)\n        }\n    }\n\n    override func getOption0<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.BacklogOption:\n            return backlog as! Option.Value\n        case _ as ChannelOptions.Types.LocalVsockContextID:\n            #if os(Windows) || os(OpenBSD)\n            fallthrough\n            #else\n            return try self.socket.getLocalVsockContextID() as! Option.Value\n            #endif\n        default:\n            return try super.getOption0(option)\n        }\n    }\n\n    internal enum BindTarget {\n        case socketAddress(_: SocketAddress)\n        case vsockAddress(_: VsockAddress)\n    }\n\n    internal func bind0(to target: BindTarget, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isOpen else {\n            promise?.fail(ChannelError._ioOnClosedChannel)\n            return\n        }\n\n        guard self.isRegistered else {\n            promise?.fail(ChannelError._inappropriateOperationForState)\n            return\n        }\n\n        let p = eventLoop.makePromise(of: Void.self)\n        p.futureResult.map {\n            // It's important to call the methods before we actually notify the original promise for ordering reasons.\n            self.becomeActive0(promise: promise)\n        }.whenFailure { error in\n            promise?.fail(error)\n        }\n        executeAndComplete(p) {\n            switch target {\n            case .socketAddress(let address):\n                try socket.bind(to: address)\n            #if os(Windows) || os(OpenBSD)\n            case .vsockAddress:\n                fatalError(vsockUnimplemented)\n            #else\n            case .vsockAddress(let address):\n                try socket.bind(to: address)\n            #endif\n            }\n            self.updateCachedAddressesFromSocket(updateRemote: false)\n            try self.socket.listen(backlog: backlog)\n        }\n    }\n\n    override public func bind0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.bind0(to: .socketAddress(address), promise: promise)\n    }\n\n    override func connectSocket(to address: SocketAddress) throws -> Bool {\n        throw ChannelError._operationUnsupported\n    }\n\n    override func finishConnectSocket() throws {\n        throw ChannelError._operationUnsupported\n    }\n\n    override func readFromSocket() throws -> ReadResult {\n        var result = ReadResult.none\n        for _ in 1...maxMessagesPerRead {\n            guard self.isOpen else {\n                throw ChannelError._eof\n            }\n            if let accepted = try self.socket.accept(setNonBlocking: true) {\n                readPending = false\n                result = .some\n                do {\n                    let chan = try SocketChannel(\n                        socket: accepted,\n                        parent: self,\n                        eventLoop: group.next() as! SelectableEventLoop\n                    )\n                    assert(self.isActive)\n                    self.pipeline.syncOperations.fireChannelRead(NIOAny(chan))\n                } catch {\n                    try? accepted.close()\n                    throw error\n                }\n            } else {\n                break\n            }\n        }\n        return result\n    }\n\n    override func shouldCloseOnReadError(_ err: Error) -> Bool {\n        if err is NIOFcntlFailedError {\n            // See:\n            // - https://github.com/apple/swift-nio/issues/1030\n            // - https://github.com/apple/swift-nio/issues/1598\n            // on Darwin, fcntl(fd, F_SETFL, O_NONBLOCK) or fcntl(fd, F_SETNOSIGPIPE)\n            // sometimes returns EINVAL...\n            return false\n        }\n        guard let err = err as? IOError else { return true }\n\n        switch err.errnoCode {\n        case ECONNABORTED,\n            EMFILE,\n            ENFILE,\n            ENOBUFS,\n            ENOMEM:\n            // These are errors we may be able to recover from. The user may just want to stop accepting connections for example\n            // or provide some other means of back-pressure. This could be achieved by a custom ChannelDuplexHandler.\n            return false\n        default:\n            return true\n        }\n    }\n\n    override func cancelWritesOnClose(error: Error) {\n        // No writes to cancel.\n        return\n    }\n\n    override public func channelRead0(_ data: NIOAny) {\n        self.eventLoop.assertInEventLoop()\n\n        let ch = self.unwrapData(data, as: SocketChannel.self)\n        ch.eventLoop.execute {\n            ch.register().flatMapThrowing {\n                guard ch.isOpen else {\n                    throw ChannelError._ioOnClosedChannel\n                }\n                ch.becomeActive0(promise: nil)\n            }.whenFailure { error in\n                ch.close(promise: nil)\n            }\n        }\n    }\n\n    override func hasFlushedPendingWrites() -> Bool {\n        false\n    }\n\n    override func bufferPendingWrite(data: NIOAny, promise: EventLoopPromise<Void>?) {\n        promise?.fail(ChannelError._operationUnsupported)\n    }\n\n    override func markFlushPoint() {\n        // We do nothing here: flushes are no-ops.\n    }\n\n    override func flushNow() -> IONotificationState {\n        IONotificationState.unregister\n    }\n\n    override func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        try selector.register(\n            selectable: self.socket,\n            interested: interested,\n            makeRegistration: self.registrationFor\n        )\n    }\n\n    override func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws {\n        assert(mode == .all)\n        try selector.deregister(selectable: self.socket)\n    }\n\n    override func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        try selector.reregister(selectable: self.socket, interested: interested)\n    }\n\n    override func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?) {\n        switch event {\n        case let event as VsockChannelEvents.BindToAddress:\n            self.bind0(to: .vsockAddress(event.address), promise: promise)\n        default:\n            promise?.fail(ChannelError._operationUnsupported)\n        }\n    }\n}\n\n/// A channel used with datagram sockets.\n///\n/// Currently, it does not support connected mode which is well worth adding.\nfinal class DatagramChannel: BaseSocketChannel<Socket>, @unchecked Sendable {\n    private var reportExplicitCongestionNotifications = false\n    private var receivePacketInfo = false\n    private var receiveSegmentSize = false\n\n    // Guard against re-entrance of flushNow() method.\n    private let pendingWrites: PendingDatagramWritesManager\n\n    /// Support for vector reads, if enabled.\n    private var vectorReadManager: Optional<DatagramVectorReadManager>\n    // This is `Channel` API so must be thread-safe.\n    override public var isWritable: Bool {\n        pendingWrites.isWritable\n    }\n\n    override var isOpen: Bool {\n        self.eventLoop.assertInEventLoop()\n        assert(super.isOpen == self.pendingWrites.isOpen)\n        return super.isOpen\n    }\n\n    convenience init(eventLoop: SelectableEventLoop, socket: NIOBSDSocket.Handle) throws {\n        let socket = try Socket(socket: socket)\n\n        do {\n            try self.init(socket: socket, eventLoop: eventLoop)\n        } catch {\n            try? socket.close()\n            throw error\n        }\n    }\n\n    deinit {\n        if var vectorReadManager = self.vectorReadManager {\n            vectorReadManager.deallocate()\n        }\n    }\n\n    init(\n        eventLoop: SelectableEventLoop,\n        protocolFamily: NIOBSDSocket.ProtocolFamily,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype,\n        socketType: NIOBSDSocket.SocketType = .datagram\n    ) throws {\n        self.vectorReadManager = nil\n        let socket = try Socket(\n            protocolFamily: protocolFamily,\n            type: socketType,\n            protocolSubtype: protocolSubtype\n        )\n        do {\n            try socket.setNonBlocking()\n        } catch let err {\n            try? socket.close()\n            throw err\n        }\n\n        self.pendingWrites = PendingDatagramWritesManager(\n            bufferPool: eventLoop.bufferPool,\n            msgBufferPool: eventLoop.msgBufferPool\n        )\n\n        try super.init(\n            socket: socket,\n            parent: nil,\n            eventLoop: eventLoop,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 2048),\n            supportReconnect: true\n        )\n    }\n\n    init(socket: Socket, parent: Channel? = nil, eventLoop: SelectableEventLoop) throws {\n        self.vectorReadManager = nil\n        try socket.setNonBlocking()\n        self.pendingWrites = PendingDatagramWritesManager(\n            bufferPool: eventLoop.bufferPool,\n            msgBufferPool: eventLoop.msgBufferPool\n        )\n        try super.init(\n            socket: socket,\n            parent: parent,\n            eventLoop: eventLoop,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 2048),\n            supportReconnect: true\n        )\n    }\n\n    // MARK: Datagram Channel overrides required by BaseSocketChannel\n\n    override func setOption0<Option: ChannelOption>(_ option: Option, value: Option.Value) throws {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.WriteSpinOption:\n            pendingWrites.writeSpinCount = value as! UInt\n        case _ as ChannelOptions.Types.WriteBufferWaterMarkOption:\n            pendingWrites.waterMark = value as! ChannelOptions.Types.WriteBufferWaterMark\n        case _ as ChannelOptions.Types.DatagramVectorReadMessageCountOption:\n            // We only support vector reads on these OSes. Let us know if there's another OS with this syscall!\n            #if os(Linux) || os(FreeBSD) || os(Android)\n            self.vectorReadManager.updateMessageCount(value as! Int)\n            #else\n            break\n            #endif\n        case _ as ChannelOptions.Types.ExplicitCongestionNotificationsOption:\n            let valueAsInt: CInt = value as! Bool ? 1 : 0\n            switch self.localAddress?.protocol {\n            case .some(.inet):\n                #if os(OpenBSD)\n                throw ChannelError._operationUnsupported\n                #else\n                self.reportExplicitCongestionNotifications = true\n                try self.socket.setOption(\n                    level: .ip,\n                    name: .ip_recv_tos,\n                    value: valueAsInt\n                )\n                #endif\n            case .some(.inet6):\n                self.reportExplicitCongestionNotifications = true\n                try self.socket.setOption(\n                    level: .ipv6,\n                    name: .ipv6_recv_tclass,\n                    value: valueAsInt\n                )\n            default:\n                // Explicit congestion notification is only supported for IP\n                throw ChannelError._operationUnsupported\n            }\n        case _ as ChannelOptions.Types.ReceivePacketInfo:\n            let valueAsInt: CInt = value as! Bool ? 1 : 0\n            #if os(OpenBSD)\n            throw ChannelError._operationUnsupported\n            #else\n            switch self.localAddress?.protocol {\n            case .some(.inet):\n                self.receivePacketInfo = true\n                try self.socket.setOption(\n                    level: .ip,\n                    name: .ip_recv_pktinfo,\n                    value: valueAsInt\n                )\n            case .some(.inet6):\n                self.receivePacketInfo = true\n                try self.socket.setOption(\n                    level: .ipv6,\n                    name: .ipv6_recv_pktinfo,\n                    value: valueAsInt\n                )\n            default:\n                // Receiving packet info is only supported for IP\n                throw ChannelError._operationUnsupported\n            }\n            #endif\n        case _ as ChannelOptions.Types.DatagramSegmentSize:\n            guard System.supportsUDPSegmentationOffload else {\n                throw ChannelError._operationUnsupported\n            }\n            let segmentSize = value as! ChannelOptions.Types.DatagramSegmentSize.Value\n            try self.socket.setUDPSegmentSize(segmentSize)\n        case _ as ChannelOptions.Types.DatagramReceiveOffload:\n            guard System.supportsUDPReceiveOffload else {\n                throw ChannelError._operationUnsupported\n            }\n            let enable = value as! ChannelOptions.Types.DatagramReceiveOffload.Value\n            try self.socket.setUDPReceiveOffload(enable)\n        case _ as ChannelOptions.Types.DatagramReceiveSegmentSize:\n            guard System.supportsUDPReceiveOffload else {\n                throw ChannelError._operationUnsupported\n            }\n            let enable = value as! ChannelOptions.Types.DatagramReceiveSegmentSize.Value\n            self.receiveSegmentSize = enable\n        default:\n            try super.setOption0(option, value: value)\n        }\n    }\n\n    override func getOption0<Option: ChannelOption>(_ option: Option) throws -> Option.Value {\n        self.eventLoop.assertInEventLoop()\n\n        guard isOpen else {\n            throw ChannelError._ioOnClosedChannel\n        }\n\n        switch option {\n        case _ as ChannelOptions.Types.WriteSpinOption:\n            return pendingWrites.writeSpinCount as! Option.Value\n        case _ as ChannelOptions.Types.WriteBufferWaterMarkOption:\n            return pendingWrites.waterMark as! Option.Value\n        case _ as ChannelOptions.Types.DatagramVectorReadMessageCountOption:\n            return (self.vectorReadManager?.messageCount ?? 0) as! Option.Value\n        case _ as ChannelOptions.Types.ExplicitCongestionNotificationsOption:\n            switch self.localAddress?.protocol {\n            case .some(.inet):\n                #if os(OpenBSD)\n                throw ChannelError._operationUnsupported\n                #else\n                return try\n                    (self.socket.getOption(\n                        level: .ip,\n                        name: .ip_recv_tos\n                    ) != 0) as! Option.Value\n                #endif\n            case .some(.inet6):\n                return try\n                    (self.socket.getOption(\n                        level: .ipv6,\n                        name: .ipv6_recv_tclass\n                    ) != 0) as! Option.Value\n            default:\n                // Explicit congestion notification is only supported for IP\n                throw ChannelError._operationUnsupported\n            }\n        case _ as ChannelOptions.Types.ReceivePacketInfo:\n            #if os(OpenBSD)\n            throw ChannelError._operationUnsupported\n            #else\n            switch self.localAddress?.protocol {\n            case .some(.inet):\n                return try\n                    (self.socket.getOption(\n                        level: .ip,\n                        name: .ip_recv_pktinfo\n                    ) != 0) as! Option.Value\n            case .some(.inet6):\n                return try\n                    (self.socket.getOption(\n                        level: .ipv6,\n                        name: .ipv6_recv_pktinfo\n                    ) != 0) as! Option.Value\n            default:\n                // Receiving packet info is only supported for IP\n                throw ChannelError._operationUnsupported\n            }\n            #endif\n        case _ as ChannelOptions.Types.DatagramSegmentSize:\n            guard System.supportsUDPSegmentationOffload else {\n                throw ChannelError._operationUnsupported\n            }\n            return try self.socket.getUDPSegmentSize() as! Option.Value\n        case _ as ChannelOptions.Types.DatagramReceiveOffload:\n            guard System.supportsUDPReceiveOffload else {\n                throw ChannelError._operationUnsupported\n            }\n            return try self.socket.getUDPReceiveOffload() as! Option.Value\n        case _ as ChannelOptions.Types.DatagramReceiveSegmentSize:\n            guard System.supportsUDPReceiveOffload else {\n                throw ChannelError._operationUnsupported\n            }\n            return self.receiveSegmentSize as! Option.Value\n        case _ as ChannelOptions.Types.BufferedWritableBytesOption:\n            return Int(self.pendingWrites.bufferedBytes) as! Option.Value\n        default:\n            return try super.getOption0(option)\n        }\n    }\n\n    func registrationFor(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration {\n        NIORegistration(\n            channel: .datagramChannel(self),\n            interested: interested,\n            registrationID: registrationID\n        )\n    }\n\n    override func connectSocket(to address: SocketAddress) throws -> Bool {\n        // TODO: this could be a channel option to do other things instead here, e.g. fail the connect\n        if !self.pendingWrites.isEmpty {\n            self.pendingWrites.failAll(\n                error: IOError(\n                    errnoCode: EISCONN,\n                    reason: \"Socket was connected before flushing pending write.\"\n                ),\n                close: false\n            )\n        }\n        if try self.socket.connect(to: address) {\n            self.pendingWrites.markConnected(to: address)\n            return true\n        } else {\n            preconditionFailure(\"Connect of datagram socket did not complete synchronously.\")\n        }\n    }\n\n    override func connectSocket(to address: VsockAddress) throws -> Bool {\n        throw ChannelError._operationUnsupported\n    }\n\n    override func finishConnectSocket() throws {\n        // This is not required for connected datagram channels connect is a synchronous operation.\n        throw ChannelError._operationUnsupported\n    }\n\n    override func readFromSocket() throws -> ReadResult {\n        if self.vectorReadManager != nil {\n            return try self.vectorReadFromSocket()\n        } else if self.reportExplicitCongestionNotifications || self.receivePacketInfo || self.receiveSegmentSize {\n            let pooledMsgBuffer = self.selectableEventLoop.msgBufferPool.get()\n            defer { self.selectableEventLoop.msgBufferPool.put(pooledMsgBuffer) }\n            return try pooledMsgBuffer.withUnsafePointers { _, _, controlMessageStorage in\n                try self.singleReadFromSocket(controlBytesBuffer: controlMessageStorage[0])\n            }\n        } else {\n            return try self.singleReadFromSocket(\n                controlBytesBuffer: UnsafeMutableRawBufferPointer(start: nil, count: 0)\n            )\n        }\n    }\n\n    private func singleReadFromSocket(controlBytesBuffer: UnsafeMutableRawBufferPointer) throws -> ReadResult {\n        var rawAddress = sockaddr_storage()\n        var rawAddressLength = socklen_t(MemoryLayout<sockaddr_storage>.size)\n        var readResult = ReadResult.none\n\n        for _ in 1...self.maxMessagesPerRead {\n            guard self.isOpen else {\n                throw ChannelError._eof\n            }\n\n            var controlBytes = UnsafeReceivedControlBytes(controlBytesBuffer: controlBytesBuffer)\n\n            let (buffer, result) = try self.recvBufferPool.buffer(allocator: self.allocator) { buffer in\n                try buffer.withMutableWritePointer { pointer in\n                    try self.socket.recvmsg(\n                        pointer: pointer,\n                        storage: &rawAddress,\n                        storageLen: &rawAddressLength,\n                        controlBytes: &controlBytes\n                    )\n                }\n            }\n\n            switch result {\n            case .processed(let bytesRead):\n                assert(self.isOpen)\n                let remoteAddress: SocketAddress = try rawAddress.convert()\n\n                self.recvBufferPool.record(actualReadBytes: bytesRead)\n                readPending = false\n\n                let metadata: AddressedEnvelope<ByteBuffer>.Metadata?\n                if self.reportExplicitCongestionNotifications || self.receivePacketInfo || self.receiveSegmentSize,\n                    let controlMessagesReceived = controlBytes.receivedControlMessages\n                {\n                    metadata = .init(from: controlMessagesReceived)\n                } else {\n                    metadata = nil\n                }\n\n                let msg = AddressedEnvelope(\n                    remoteAddress: remoteAddress,\n                    data: buffer,\n                    metadata: metadata\n                )\n                assert(self.isActive)\n                self.pipeline.syncOperations.fireChannelRead(NIOAny(msg))\n                readResult = .some\n            case .wouldBlock(let bytesRead):\n                assert(bytesRead == 0)\n                return readResult\n            }\n        }\n        return readResult\n    }\n\n    private func vectorReadFromSocket() throws -> ReadResult {\n        #if os(Linux) || os(FreeBSD) || os(Android)\n        var readResult = ReadResult.none\n\n        readLoop: for _ in 1...self.maxMessagesPerRead {\n            guard self.isOpen else {\n                throw ChannelError._eof\n            }\n            guard let vectorReadManager = self.vectorReadManager else {\n                // The vector read manager went away. This happens if users unset the vector read manager\n                // during channelRead. It's unlikely, but we tolerate it by aborting the read early.\n                break readLoop\n            }\n\n            let (_, result) = try self.recvBufferPool.buffer(allocator: self.allocator) {\n                buffer -> DatagramVectorReadManager.ReadResult in\n                // This force-unwrap is safe, as we checked whether this is nil in the caller.\n                try vectorReadManager.readFromSocket(\n                    socket: self.socket,\n                    buffer: &buffer,\n                    parseControlMessages: self.reportExplicitCongestionNotifications || self.receivePacketInfo\n                        || self.receiveSegmentSize\n                )\n            }\n\n            switch result {\n            case .some(let results, let totalRead):\n                assert(self.isOpen)\n                assert(self.isActive)\n\n                self.recvBufferPool.record(actualReadBytes: totalRead)\n                readPending = false\n\n                var messageIterator = results.makeIterator()\n                while self.isActive, let message = messageIterator.next() {\n                    pipeline.fireChannelRead(message)\n                }\n\n                readResult = .some\n            case .none:\n                break readLoop\n            }\n        }\n\n        return readResult\n        #else\n        fatalError(\"Cannot perform vector reads on this operating system\")\n        #endif\n    }\n\n    private func shouldCloseOnErrnoCode(_ errnoCode: CInt) -> Bool {\n        switch errnoCode {\n        // ECONNREFUSED can happen on linux if the previous sendto(...) failed.\n        // See also:\n        // -    https://bugzilla.redhat.com/show_bug.cgi?id=1375\n        // -    https://lists.gt.net/linux/kernel/39575\n        case ECONNREFUSED,\n            ENOMEM:\n            // These are errors we may be able to recover from.\n            return false\n        default:\n            return true\n        }\n    }\n\n    override func shouldCloseOnReadError(_ err: Error) -> Bool {\n        guard let err = err as? IOError else { return true }\n        return self.shouldCloseOnErrnoCode(err.errnoCode)\n    }\n\n    override func error() -> ErrorResult {\n        // Assume we can get the error from the socket.\n        do {\n            let errnoCode: CInt = try self.socket.getOption(level: .socket, name: .so_error)\n            if self.shouldCloseOnErrnoCode(errnoCode) {\n                self.reset()\n                return .fatal\n            } else {\n                self.pipeline.syncOperations.fireErrorCaught(\n                    IOError(errnoCode: errnoCode, reason: \"so_error\")\n                )\n                return .nonFatal\n            }\n        } catch {\n            // Unknown error, fatal.\n            self.reset()\n            return .fatal\n        }\n    }\n\n    /// Buffer a write in preparation for a flush.\n    ///\n    /// When the channel is unconnected, `data` _must_ be of type `AddressedEnvelope<ByteBuffer>`.\n    ///\n    /// When the channel is connected, `data` _should_ be of type `ByteBuffer`, but _may_ be of type\n    /// `AddressedEnvelope<ByteBuffer>` to allow users to provide protocol control messages via\n    /// `AddressedEnvelope.metadata`. In this case, `AddressedEnvelope.remoteAddress` _must_ match\n    /// the address of the connected peer.\n    override func bufferPendingWrite(data: NIOAny, promise: EventLoopPromise<Void>?) {\n        if let envelope = self.tryUnwrapData(data, as: AddressedEnvelope<ByteBuffer>.self) {\n            return bufferPendingAddressedWrite(envelope: envelope, promise: promise)\n        }\n        // If it's not an `AddressedEnvelope` then it must be a `ByteBuffer` so we let the common\n        // `unwrapData(_:as:)` throw the fatal error if it's some other type.\n        let data = self.unwrapData(data, as: ByteBuffer.self)\n        return bufferPendingUnaddressedWrite(data: data, promise: promise)\n    }\n\n    /// Buffer a write in preparation for a flush.\n    private func bufferPendingUnaddressedWrite(data: ByteBuffer, promise: EventLoopPromise<Void>?) {\n        // It is only appropriate to not use an AddressedEnvelope if the socket is connected.\n        guard self.remoteAddress != nil else {\n            promise?.fail(DatagramChannelError.WriteOnUnconnectedSocketWithoutAddress())\n            return\n        }\n\n        if !self.pendingWrites.add(data: data, promise: promise) {\n            assert(self.isActive)\n            self.pipeline.syncOperations.fireChannelWritabilityChanged()\n        }\n    }\n\n    /// Buffer a write in preparation for a flush.\n    private func bufferPendingAddressedWrite(envelope: AddressedEnvelope<ByteBuffer>, promise: EventLoopPromise<Void>?)\n    {\n        // Check if segment size is set on a non-Linux platform\n        #if !os(Linux)\n        if envelope.metadata?.segmentSize != nil {\n            promise?.fail(ChannelError.operationUnsupported)\n            return\n        }\n        #endif\n\n        // If the socket is connected, check the remote provided matches the connected address.\n        if let connectedRemoteAddress = self.remoteAddress {\n            guard envelope.remoteAddress == connectedRemoteAddress else {\n                promise?.fail(\n                    DatagramChannelError.WriteOnConnectedSocketWithInvalidAddress(\n                        envelopeRemoteAddress: envelope.remoteAddress,\n                        connectedRemoteAddress: connectedRemoteAddress\n                    )\n                )\n                return\n            }\n        }\n\n        if !self.pendingWrites.add(envelope: envelope, promise: promise) {\n            assert(self.isActive)\n            self.pipeline.syncOperations.fireChannelWritabilityChanged()\n        }\n    }\n\n    override final func hasFlushedPendingWrites() -> Bool {\n        self.pendingWrites.isFlushPending\n    }\n\n    /// Mark a flush point. This is called when flush is received, and instructs\n    /// the implementation to record the flush.\n    override func markFlushPoint() {\n        // Even if writable() will be called later by the EventLoop we still need to mark the flush checkpoint so we are sure all the flushed messages\n        // are actually written once writable() is called.\n        self.pendingWrites.markFlushCheckpoint()\n    }\n\n    /// Called when closing, to instruct the specific implementation to discard all pending\n    /// writes.\n    override func cancelWritesOnClose(error: Error) {\n        self.pendingWrites.failAll(error: error, close: true)\n    }\n\n    override func writeToSocket() throws -> OverallWriteResult {\n        let result = try self.pendingWrites.triggerAppropriateWriteOperations(\n            scalarWriteOperation: { (ptr, destinationPtr, destinationSize, metadata) in\n                let msgBuffer = self.selectableEventLoop.msgBufferPool.get()\n                defer { self.selectableEventLoop.msgBufferPool.put(msgBuffer) }\n                return try msgBuffer.withUnsafePointers { _, _, controlMessageStorage in\n                    var controlBytes = UnsafeOutboundControlBytes(controlBytes: controlMessageStorage[0])\n                    controlBytes.appendExplicitCongestionState(\n                        metadata: metadata,\n                        protocolFamily: self.localAddress?.protocol\n                    )\n                    controlBytes.appendUDPSegmentSize(metadata: metadata)\n                    return try self.socket.sendmsg(\n                        pointer: ptr,\n                        destinationPtr: destinationPtr,\n                        destinationSize: destinationSize,\n                        controlBytes: controlBytes.validControlBytes\n                    )\n                }\n            },\n            vectorWriteOperation: { msgs in\n                try self.socket.sendmmsg(msgs: msgs)\n            }\n        )\n        return result\n    }\n\n    // MARK: Datagram Channel overrides not required by BaseSocketChannel\n\n    override func bind0(to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.eventLoop.assertInEventLoop()\n        guard self.isRegistered else {\n            promise?.fail(ChannelError._inappropriateOperationForState)\n            return\n        }\n        do {\n            try socket.bind(to: address)\n            self.updateCachedAddressesFromSocket(updateRemote: false)\n            becomeActive0(promise: promise)\n        } catch let err {\n            promise?.fail(err)\n        }\n    }\n\n    override func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        try selector.register(\n            selectable: self.socket,\n            interested: interested,\n            makeRegistration: self.registrationFor\n        )\n    }\n\n    override func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws {\n        assert(mode == .all)\n        try selector.deregister(selectable: self.socket)\n    }\n\n    override func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {\n        try selector.reregister(selectable: self.socket, interested: interested)\n    }\n}\n\nextension SocketChannel: CustomStringConvertible {\n    var description: String {\n        \"SocketChannel { \\(self.socketDescription), active = \\(self.isActive), localAddress = \\(self.localAddress.debugDescription), remoteAddress = \\(self.remoteAddress.debugDescription) }\"\n    }\n}\n\nextension ServerSocketChannel: CustomStringConvertible {\n    var description: String {\n        \"ServerSocketChannel { \\(self.socketDescription), active = \\(self.isActive), localAddress = \\(self.localAddress.debugDescription), remoteAddress = \\(self.remoteAddress.debugDescription) }\"\n    }\n}\n\nextension DatagramChannel: CustomStringConvertible {\n    var description: String {\n        \"DatagramChannel { \\(self.socketDescription), active = \\(self.isActive), localAddress = \\(self.localAddress.debugDescription), remoteAddress = \\(self.remoteAddress.debugDescription) }\"\n    }\n}\n\nextension DatagramChannel: MulticastChannel {\n    /// The socket options for joining and leaving multicast groups are very similar.\n    /// This enum allows us to write a single function to do all the work, and then\n    /// at the last second pull out the correct socket option name.\n    private enum GroupOperation {\n        /// Join a multicast group.\n        case join\n\n        /// Leave a multicast group.\n        case leave\n\n        /// Given a socket option level, returns the appropriate socket option name for\n        /// this group operation.\n        ///\n        /// - Parameters:\n        ///   - level: The socket option level. Must be one of `IPPROTO_IP` or\n        ///         `IPPROTO_IPV6`. Will trap if an invalid value is provided.\n        /// - Returns: The socket option name to use for this group operation.\n        func optionName(level: NIOBSDSocket.OptionLevel) -> NIOBSDSocket.Option {\n            switch (self, level) {\n            case (.join, .ip):\n                return .ip_add_membership\n            case (.leave, .ip):\n                return .ip_drop_membership\n            case (.join, .ipv6):\n                return .ipv6_join_group\n            case (.leave, .ipv6):\n                return .ipv6_leave_group\n            default:\n                preconditionFailure(\"Unexpected socket option level: \\(level)\")\n            }\n        }\n    }\n\n    #if !os(Windows)\n    @available(*, deprecated, renamed: \"joinGroup(_:device:promise:)\")\n    func joinGroup(_ group: SocketAddress, interface: NIONetworkInterface?, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            self.performGroupOperation0(\n                group,\n                device: interface.map { NIONetworkDevice($0) },\n                promise: promise,\n                operation: .join\n            )\n        } else {\n            eventLoop.execute {\n                self.performGroupOperation0(\n                    group,\n                    device: interface.map { NIONetworkDevice($0) },\n                    promise: promise,\n                    operation: .join\n                )\n            }\n        }\n    }\n\n    @available(*, deprecated, renamed: \"leaveGroup(_:device:promise:)\")\n    func leaveGroup(_ group: SocketAddress, interface: NIONetworkInterface?, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            self.performGroupOperation0(\n                group,\n                device: interface.map { NIONetworkDevice($0) },\n                promise: promise,\n                operation: .leave\n            )\n        } else {\n            eventLoop.execute {\n                self.performGroupOperation0(\n                    group,\n                    device: interface.map { NIONetworkDevice($0) },\n                    promise: promise,\n                    operation: .leave\n                )\n            }\n        }\n    }\n    #endif\n\n    func joinGroup(_ group: SocketAddress, device: NIONetworkDevice?, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            self.performGroupOperation0(group, device: device, promise: promise, operation: .join)\n        } else {\n            eventLoop.execute {\n                self.performGroupOperation0(group, device: device, promise: promise, operation: .join)\n            }\n        }\n    }\n\n    func leaveGroup(_ group: SocketAddress, device: NIONetworkDevice?, promise: EventLoopPromise<Void>?) {\n        if eventLoop.inEventLoop {\n            self.performGroupOperation0(group, device: device, promise: promise, operation: .leave)\n        } else {\n            eventLoop.execute {\n                self.performGroupOperation0(group, device: device, promise: promise, operation: .leave)\n            }\n        }\n    }\n\n    /// The implementation of `joinGroup` and `leaveGroup`.\n    ///\n    /// Joining and leaving a multicast group ultimately corresponds to a single, carefully crafted, socket option.\n    private func performGroupOperation0(\n        _ group: SocketAddress,\n        device: NIONetworkDevice?,\n        promise: EventLoopPromise<Void>?,\n        operation: GroupOperation\n    ) {\n        self.eventLoop.assertInEventLoop()\n\n        guard self.isActive else {\n            promise?.fail(ChannelError._inappropriateOperationForState)\n            return\n        }\n\n        // Check if the device supports multicast\n        if let device = device {\n            guard device.multicastSupported else {\n                promise?.fail(NIOMulticastNotSupportedError(device: device))\n                return\n            }\n        }\n\n        // We need to check that we have the appropriate address types in all cases. They all need to overlap with\n        // the address type of this channel, or this cannot work.\n        guard let localAddress = self.localAddress else {\n            promise?.fail(ChannelError._unknownLocalAddress)\n            return\n        }\n\n        guard localAddress.protocol == group.protocol else {\n            promise?.fail(ChannelError._badMulticastGroupAddressFamily)\n            return\n        }\n\n        // Ok, now we need to check that the group we've been asked to join is actually a multicast group.\n        guard group.isMulticast else {\n            promise?.fail(ChannelError.illegalMulticastAddress(group))\n            return\n        }\n\n        // Ok, we now have reason to believe this will actually work. We need to pass this on to the socket.\n        do {\n            switch (group, device?.address) {\n            case (.unixDomainSocket, _):\n                preconditionFailure(\"Should not be reachable, UNIX sockets are never multicast addresses\")\n            case (.v4(let groupAddress), .some(.v4(let interfaceAddress))):\n                // IPv4Binding with specific target interface.\n                let multicastRequest = ip_mreq(\n                    imr_multiaddr: groupAddress.address.sin_addr,\n                    imr_interface: interfaceAddress.address.sin_addr\n                )\n                try self.socket.setOption(level: .ip, name: operation.optionName(level: .ip), value: multicastRequest)\n            case (.v4(let groupAddress), .none):\n                #if os(Windows)\n                var addr = in_addr()\n                addr.S_un.S_addr = INADDR_ANY\n                #else\n                let addr = in_addr(s_addr: INADDR_ANY)\n                #endif\n                // IPv4 binding without target interface.\n                let multicastRequest = ip_mreq(\n                    imr_multiaddr: groupAddress.address.sin_addr,\n                    imr_interface: addr\n                )\n                try self.socket.setOption(level: .ip, name: operation.optionName(level: .ip), value: multicastRequest)\n            case (.v6(let groupAddress), .some(.v6)):\n                // IPv6 binding with specific target interface.\n                let multicastRequest = ipv6_mreq(\n                    ipv6mr_multiaddr: groupAddress.address.sin6_addr,\n                    ipv6mr_interface: UInt32(device!.interfaceIndex)\n                )\n                try self.socket.setOption(\n                    level: .ipv6,\n                    name: operation.optionName(level: .ipv6),\n                    value: multicastRequest\n                )\n            case (.v6(let groupAddress), .none):\n                // IPv6 binding with no specific interface requested.\n                let multicastRequest = ipv6_mreq(ipv6mr_multiaddr: groupAddress.address.sin6_addr, ipv6mr_interface: 0)\n                try self.socket.setOption(\n                    level: .ipv6,\n                    name: operation.optionName(level: .ipv6),\n                    value: multicastRequest\n                )\n            case (.v4, .some(.v6)), (.v6, .some(.v4)), (.v4, .some(.unixDomainSocket)), (.v6, .some(.unixDomainSocket)):\n                // Mismatched group and interface address: this is an error.\n                throw ChannelError._badInterfaceAddressFamily\n            }\n\n            promise?.succeed(())\n        } catch {\n            promise?.fail(error)\n            return\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/SocketProtocols.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if canImport(WinSDK)\nimport struct WinSDK.socklen_t\n#endif\n\nprotocol BaseSocketProtocol: CustomStringConvertible, _NIOPosixSendableMetatype {\n    associatedtype SelectableType: Selectable\n\n    var isOpen: Bool { get }\n\n    func close() throws\n\n    func bind(to address: SocketAddress) throws\n\n    func localAddress() throws -> SocketAddress\n\n    func remoteAddress() throws -> SocketAddress\n\n    func setOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option, value: T) throws\n\n    func getOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) throws -> T\n}\n\nprotocol ServerSocketProtocol: BaseSocketProtocol {\n    func listen(backlog: Int32) throws\n\n    func accept(setNonBlocking: Bool) throws -> Socket?\n}\n\nprotocol SocketProtocol: BaseSocketProtocol {\n    func connect(to address: SocketAddress) throws -> Bool\n\n    func finishConnect() throws\n\n    func write(pointer: UnsafeRawBufferPointer) throws -> IOResult<Int>\n\n    func writev(iovecs: UnsafeBufferPointer<IOVector>) throws -> IOResult<Int>\n\n    func read(pointer: UnsafeMutableRawBufferPointer) throws -> IOResult<Int>\n\n    func recvmsg(\n        pointer: UnsafeMutableRawBufferPointer,\n        storage: inout sockaddr_storage,\n        storageLen: inout socklen_t,\n        controlBytes: inout UnsafeReceivedControlBytes\n    ) throws -> IOResult<Int>\n\n    func sendmsg(\n        pointer: UnsafeRawBufferPointer,\n        destinationPtr: UnsafePointer<sockaddr>?,\n        destinationSize: socklen_t,\n        controlBytes: UnsafeMutableRawBufferPointer\n    ) throws -> IOResult<Int>\n\n    func sendFile(fd: CInt, offset: Int, count: Int) throws -> IOResult<Int>\n\n    func recvmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>\n\n    func sendmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>\n\n    func shutdown(how: Shutdown) throws\n\n    func ignoreSIGPIPE() throws\n}\n\n#if os(Linux) || os(Android) || os(OpenBSD)\n// This is a lazily initialised global variable that when read for the first time, will ignore SIGPIPE.\nprivate let globallyIgnoredSIGPIPE: Bool = {\n    // no F_SETNOSIGPIPE on Linux :(\n    #if canImport(Glibc)\n    _ = Glibc.signal(SIGPIPE, SIG_IGN)\n    #elseif canImport(Musl)\n    _ = Musl.signal(SIGPIPE, SIG_IGN)\n    #elseif canImport(Android)\n    _ = Android.signal(SIGPIPE, SIG_IGN)\n    #else\n    #error(\"Don't know which stdlib to use\")\n    #endif\n    return true\n}()\n#endif\n\nextension BaseSocketProtocol {\n    // used by `BaseSocket` and `PipePair`.\n    internal static func ignoreSIGPIPE(descriptor fd: CInt) throws {\n        #if os(Linux) || os(Android) || os(OpenBSD)\n        let haveWeIgnoredSIGPIEThisIsHereToTriggerIgnoringIt = globallyIgnoredSIGPIPE\n        guard haveWeIgnoredSIGPIEThisIsHereToTriggerIgnoringIt else {\n            fatalError(\"BUG in NIO. We did not ignore SIGPIPE, this code path should definitely not be reachable.\")\n        }\n        #elseif os(Windows)\n        // Deliberately empty: SIGPIPE just ain't a thing on Windows\n        #else\n        assert(fd >= 0, \"illegal file descriptor \\(fd)\")\n        do {\n            try Posix.fcntl(descriptor: fd, command: F_SETNOSIGPIPE, value: 1)\n        } catch let error as IOError {\n            try? Posix.close(descriptor: fd)  // don't care about failure here\n            if error.errnoCode == EINVAL {\n                // Darwin seems to sometimes do this despite the docs claiming it can't happen\n                throw NIOFcntlFailedError()\n            }\n            throw error\n        }\n        #endif\n    }\n\n    internal static func ignoreSIGPIPE(socket handle: NIOBSDSocket.Handle) throws {\n        #if os(Windows)\n        // Deliberately empty: SIGPIPE just ain't a thing on Windows\n        #else\n        try ignoreSIGPIPE(descriptor: handle)\n        #endif\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/StructuredConcurrencyHelpers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the AsyncHTTPClient open source project\n//\n// Copyright (c) 2025 Apple Inc. and the AsyncHTTPClient project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@inlinable\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func asyncDo<R>(\n    isolation: isolated (any Actor)? = #isolation,\n    _ body: () async throws -> sending R,\n    finally: sending @escaping ((any Error)?) async throws -> Void\n) async throws -> sending R {\n    let result: R\n    do {\n        result = try await body()\n    } catch {\n        // `body` failed, we need to invoke `finally` with the `error`.\n\n        // This _looks_ unstructured but isn't really because we unconditionally always await the return.\n        // We need to have an uncancelled task here to assure this is actually running in case we hit a\n        // cancellation error.\n        try await Task {\n            try await finally(error)\n        }.value\n        throw error\n    }\n\n    // `body` succeeded, we need to invoke `finally` with `nil` (no error).\n\n    // This _looks_ unstructured but isn't really because we unconditionally always await the return.\n    // We need to have an uncancelled task here to assure this is actually running in case we hit a\n    // cancellation error.\n    try await Task {\n        try await finally(nil)\n    }.value\n    return result\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/System.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//  This file contains code that ensures errno is captured correctly when doing syscalls and no ARC traffic can happen inbetween that *could* change the errno\n//  value before we were able to read it.\n//  It's important that all static methods are declared with `@inline(never)` so it's not possible any ARC traffic happens while we need to read errno.\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if canImport(Darwin)\n@_exported import Darwin.C\nimport CNIODarwin\ninternal typealias MMsgHdr = CNIODarwin_mmsghdr\n#elseif os(Linux) || os(FreeBSD) || os(Android)\n#if canImport(Glibc)\n@_exported @preconcurrency import Glibc\n#elseif canImport(Musl)\n@_exported @preconcurrency import Musl\n#elseif canImport(Android)\n@_exported @preconcurrency import Android\n#endif\nimport CNIOLinux\ninternal typealias MMsgHdr = CNIOLinux_mmsghdr\ninternal typealias in6_pktinfo = CNIOLinux_in6_pktinfo\n#elseif os(OpenBSD)\n@_exported @preconcurrency import Glibc\nimport CNIOOpenBSD\ninternal typealias MMsgHdr = CNIOOpenBSD_mmsghdr\nlet INADDR_ANY = UInt32(0)\n#elseif os(Windows)\n@_exported import ucrt\n\nimport CNIOWindows\n\ninternal typealias MMsgHdr = CNIOWindows_mmsghdr\n#else\n#error(\"The POSIX system module was unable to identify your C library.\")\n#endif\n\n#if os(Android)\nlet INADDR_ANY = UInt32(0)  // #define INADDR_ANY ((unsigned long int) 0x00000000)\nlet IFF_BROADCAST: CUnsignedInt = numericCast(Android.IFF_BROADCAST.rawValue)\nlet IFF_POINTOPOINT: CUnsignedInt = numericCast(Android.IFF_POINTOPOINT.rawValue)\nlet IFF_MULTICAST: CUnsignedInt = numericCast(Android.IFF_MULTICAST.rawValue)\ninternal typealias in_port_t = UInt16\nextension ipv6_mreq {  // http://lkml.iu.edu/hypermail/linux/kernel/0106.1/0080.html\n    init(ipv6mr_multiaddr: in6_addr, ipv6mr_interface: UInt32) {\n        self.init(\n            ipv6mr_multiaddr: ipv6mr_multiaddr,\n            ipv6mr_ifindex: Int32(bitPattern: ipv6mr_interface)\n        )\n    }\n}\n#if arch(arm)\nlet S_IFSOCK = UInt32(Android.S_IFSOCK)\nlet S_IFMT = UInt32(Android.S_IFMT)\nlet S_IFREG = UInt32(Android.S_IFREG)\nlet S_IFDIR = UInt32(Android.S_IFDIR)\nlet S_IFLNK = UInt32(Android.S_IFLNK)\nlet S_IFBLK = UInt32(Android.S_IFBLK)\n#endif\n#endif\n\n// Declare aliases to share more code and not need to repeat #if #else blocks\n#if !os(Windows)\nprivate let sysClose = close\nprivate let sysShutdown = shutdown\nprivate let sysBind = bind\nprivate let sysFcntl: @Sendable @convention(c) (CInt, CInt, CInt) -> CInt = { fcntl($0, $1, $2) }\nprivate let sysSocket = socket\nprivate let sysSetsockopt = setsockopt\nprivate let sysGetsockopt = getsockopt\nprivate let sysListen = listen\nprivate let sysAccept = accept\nprivate let sysConnect = connect\nprivate let sysOpen: @Sendable @convention(c) (UnsafePointer<CChar>, CInt) -> CInt = { open($0, $1) }\nprivate let sysOpenWithMode: @Sendable @convention(c) (UnsafePointer<CChar>, CInt, mode_t) -> CInt = {\n    open($0, $1, $2)\n}\nprivate let sysFtruncate = ftruncate\nprivate let sysWrite = write\nprivate let sysPwrite = pwrite\nprivate let sysRead = read\nprivate let sysPread = pread\nprivate let sysLseek = lseek\nprivate let sysPoll = poll\n#else\nprivate let sysWrite = _write\nprivate let sysRead = _read\nprivate let sysLseek = _lseek\nprivate let sysFtruncate = _chsize_s\n#endif\n\n#if os(Android)\nfunc sysRecvFrom_wrapper(\n    sockfd: CInt,\n    buf: UnsafeMutableRawPointer,\n    len: CLong,\n    flags: CInt,\n    src_addr: UnsafeMutablePointer<sockaddr>,\n    addrlen: UnsafeMutablePointer<socklen_t>\n) -> CLong {\n    // src_addr is 'UnsafeMutablePointer', but it need to be 'UnsafePointer'\n    recvfrom(sockfd, buf, len, flags, src_addr, addrlen)\n    // src_addr is 'UnsafeMutablePointer', but it need to be 'UnsafePointer'\n}\nfunc sysWritev_wrapper(fd: CInt, iov: UnsafePointer<iovec>?, iovcnt: CInt) -> CLong {\n    CLong(writev(fd, iov!, iovcnt))  // cast 'Int32' to 'CLong'// cast 'Int32' to 'CLong'\n}\nprivate let sysWritev = sysWritev_wrapper\n#elseif !os(Windows)\nprivate let sysWritev: @convention(c) (Int32, UnsafePointer<iovec>?, CInt) -> CLong = writev\n#endif\n#if canImport(Android)\nprivate let sysRecvMsg: @convention(c) (CInt, UnsafeMutablePointer<msghdr>, CInt) -> ssize_t = recvmsg\nprivate let sysSendMsg: @convention(c) (CInt, UnsafePointer<msghdr>, CInt) -> ssize_t = sendmsg\n#elseif !os(Windows)\nprivate let sysRecvMsg: @convention(c) (CInt, UnsafeMutablePointer<msghdr>?, CInt) -> ssize_t = recvmsg\nprivate let sysSendMsg: @convention(c) (CInt, UnsafePointer<msghdr>?, CInt) -> ssize_t = sendmsg\n#endif\n#if os(Windows)\nprivate let sysDup: @convention(c) (CInt) -> CInt = _dup\n#else\nprivate let sysDup: @convention(c) (CInt) -> CInt = dup\n#endif\n#if canImport(Android)\nprivate let sysGetpeername:\n    @convention(c) (CInt, UnsafeMutablePointer<sockaddr>, UnsafeMutablePointer<socklen_t>) -> CInt = getpeername\nprivate let sysGetsockname:\n    @convention(c) (CInt, UnsafeMutablePointer<sockaddr>, UnsafeMutablePointer<socklen_t>) -> CInt = getsockname\n#elseif !os(Windows)\nprivate let sysGetpeername:\n    @convention(c) (CInt, UnsafeMutablePointer<sockaddr>?, UnsafeMutablePointer<socklen_t>?) -> CInt = getpeername\nprivate let sysGetsockname:\n    @convention(c) (CInt, UnsafeMutablePointer<sockaddr>?, UnsafeMutablePointer<socklen_t>?) -> CInt = getsockname\n#endif\n\n#if os(Android)\nprivate let sysIfNameToIndex: @convention(c) (UnsafePointer<CChar>) -> CUnsignedInt = if_nametoindex\n#else\nprivate let sysIfNameToIndex: @convention(c) (UnsafePointer<CChar>?) -> CUnsignedInt = if_nametoindex\n#endif\n#if canImport(Android)\nprivate let sysSocketpair: @convention(c) (CInt, CInt, CInt, UnsafeMutablePointer<CInt>) -> CInt = socketpair\n#elseif !os(Windows)\nprivate let sysSocketpair: @convention(c) (CInt, CInt, CInt, UnsafeMutablePointer<CInt>?) -> CInt = socketpair\n#endif\n\n#if os(Linux) || os(Android) || canImport(Darwin) || os(OpenBSD)\nprivate let sysFstat = fstat\nprivate let sysStat = stat\nprivate let sysLstat = lstat\nprivate let sysSymlink = symlink\nprivate let sysReadlink = readlink\nprivate let sysUnlink = unlink\nprivate let sysMkdir = mkdir\nprivate let sysOpendir = opendir\nprivate let sysReaddir = readdir\nprivate let sysClosedir = closedir\nprivate let sysRename = rename\nprivate let sysRemove = remove\n#endif\n#if os(Linux) || os(Android)\nprivate let sysSendMmsg = CNIOLinux_sendmmsg\nprivate let sysRecvMmsg = CNIOLinux_recvmmsg\n#elseif os(OpenBSD)\nprivate let sysKevent = kevent\nprivate let sysSendMmsg = CNIOOpenBSD_sendmmsg\nprivate let sysRecvMmsg = CNIOOpenBSD_recvmmsg\n#elseif canImport(Darwin)\nprivate let sysKevent = kevent\nprivate let sysMkpath = mkpath_np\nprivate let sysSendMmsg = CNIODarwin_sendmmsg\nprivate let sysRecvMmsg = CNIODarwin_recvmmsg\n#endif\n#if !os(Windows)\nprivate let sysIoctl: @convention(c) (CInt, CUnsignedLong, UnsafeMutableRawPointer) -> CInt = ioctl\n#endif  // !os(Windows)\n\n@inlinable\nfunc isUnacceptableErrno(_ code: CInt) -> Bool {\n    // On iOS, EBADF is a possible result when a file descriptor has been reaped in the background.\n    // In particular, it's possible to get EBADF from accept(), where the underlying accept() FD\n    // is valid but the accepted one is not. The right solution here is to perform a check for\n    // SO_ISDEFUNCT when we see this happen, but we haven't yet invested the time to do that.\n    // In the meantime, we just tolerate EBADF on iOS.\n    #if canImport(Darwin) && !os(macOS)\n    switch code {\n    case EFAULT:\n        return true\n    default:\n        return false\n    }\n    #else\n    switch code {\n    case EFAULT, EBADF:\n        return true\n    default:\n        return false\n    }\n    #endif\n}\n\n@inlinable\npublic func isUnacceptableErrnoOnClose(_ code: CInt) -> Bool {\n    // We treat close() differently to all other FDs: we still want to catch EBADF here.\n    switch code {\n    case EFAULT, EBADF:\n        return true\n    default:\n        return false\n    }\n}\n\n@inlinable\ninternal func isUnacceptableErrnoForbiddingEINVAL(_ code: CInt) -> Bool {\n    // We treat read() and pread() differently since we also want to catch EINVAL.\n    #if canImport(Darwin) && !os(macOS)\n    switch code {\n    case EFAULT, EINVAL:\n        return true\n    default:\n        return false\n    }\n    #else\n    switch code {\n    case EFAULT, EBADF, EINVAL:\n        return true\n    default:\n        return false\n    }\n    #endif\n}\n\n#if os(Windows)\n@inlinable\ninternal func strerror(_ errno: CInt) -> String {\n    withUnsafeTemporaryAllocation(of: CChar.self, capacity: 95) {\n        let result = strerror_s($0.baseAddress, $0.count, errno)\n        guard result == 0 else { return \"Unknown error: \\(errno)\" }\n        return String(cString: $0.baseAddress!)\n    }\n}\n#endif\n\n@inlinable\ninternal func preconditionIsNotUnacceptableErrno(err: CInt, where function: String) {\n    // strerror is documented to return \"Unknown error: ...\" for illegal value so it won't ever fail\n    #if os(Windows)\n    precondition(!isUnacceptableErrno(err), \"unacceptable errno \\(err) \\(strerror(err)) in \\(function))\")\n    #else\n    precondition(\n        !isUnacceptableErrno(err),\n        \"unacceptable errno \\(err) \\(String(cString: strerror(err)!)) in \\(function))\"\n    )\n    #endif\n}\n\n@inlinable\ninternal func preconditionIsNotUnacceptableErrnoOnClose(err: CInt, where function: String) {\n    // strerror is documented to return \"Unknown error: ...\" for illegal value so it won't ever fail\n    #if os(Windows)\n    precondition(!isUnacceptableErrnoOnClose(err), \"unacceptable errno \\(err) \\(strerror(err)) in \\(function))\")\n    #else\n    precondition(\n        !isUnacceptableErrnoOnClose(err),\n        \"unacceptable errno \\(err) \\(String(cString: strerror(err)!)) in \\(function))\"\n    )\n    #endif\n}\n\n@inlinable\ninternal func preconditionIsNotUnacceptableErrnoForbiddingEINVAL(err: CInt, where function: String) {\n    // strerror is documented to return \"Unknown error: ...\" for illegal value so it won't ever fail\n    #if os(Windows)\n    precondition(\n        !isUnacceptableErrnoForbiddingEINVAL(err),\n        \"unacceptable errno \\(err) \\(strerror(err)) in \\(function))\"\n    )\n    #else\n    precondition(\n        !isUnacceptableErrnoForbiddingEINVAL(err),\n        \"unacceptable errno \\(err) \\(String(cString: strerror(err)!)) in \\(function))\"\n    )\n    #endif\n}\n\n// Sorry, we really try hard to not use underscored attributes. In this case\n// however we seem to break the inlining threshold which makes a system call\n// take twice the time, ie. we need this exception.\n@inline(__always)\n@discardableResult\n@inlinable\ninternal func syscall<T: FixedWidthInteger>(\n    blocking: Bool,\n    where function: String = #function,\n    _ body: () throws -> T\n)\n    throws -> IOResult<T>\n{\n    while true {\n        let res = try body()\n        if res == -1 {\n            #if os(Windows)\n            var err: CInt = 0\n            _get_errno(&err)\n            #else\n            let err = errno\n            #endif\n            switch (err, blocking) {\n            case (EINTR, _):\n                continue\n            case (EWOULDBLOCK, true):\n                return .wouldBlock(0)\n            default:\n                preconditionIsNotUnacceptableErrno(err: err, where: function)\n                throw IOError(errnoCode: err, reason: function)\n            }\n        }\n        return .processed(res)\n    }\n}\n\n#if canImport(Darwin)\n@inline(__always)\n@inlinable\n@discardableResult\ninternal func syscall<T>(\n    where function: String = #function,\n    _ body: () throws -> UnsafeMutablePointer<T>?\n)\n    throws -> UnsafeMutablePointer<T>\n{\n    while true {\n        if let res = try body() {\n            return res\n        } else {\n            let err = errno\n            switch err {\n            case EINTR:\n                continue\n            default:\n                preconditionIsNotUnacceptableErrno(err: err, where: function)\n                throw IOError(errnoCode: err, reason: function)\n            }\n        }\n    }\n}\n#elseif os(Linux) || os(Android) || os(OpenBSD)\n@inline(__always)\n@inlinable\n@discardableResult\ninternal func syscall(\n    where function: String = #function,\n    _ body: () throws -> OpaquePointer?\n)\n    throws -> OpaquePointer\n{\n    while true {\n        if let res = try body() {\n            return res\n        } else {\n            let err = errno\n            switch err {\n            case EINTR:\n                continue\n            default:\n                preconditionIsNotUnacceptableErrno(err: err, where: function)\n                throw IOError(errnoCode: err, reason: function)\n            }\n        }\n    }\n}\n#endif\n\n#if !os(Windows)\n@inline(__always)\n@inlinable\n@discardableResult\ninternal func syscallOptional<T>(\n    where function: String = #function,\n    _ body: () throws -> UnsafeMutablePointer<T>?\n)\n    throws -> UnsafeMutablePointer<T>?\n{\n    while true {\n        errno = 0\n        if let res = try body() {\n            return res\n        } else {\n            let err = errno\n            switch err {\n            case 0:\n                return nil\n            case EINTR:\n                continue\n            default:\n                preconditionIsNotUnacceptableErrno(err: err, where: function)\n                throw IOError(errnoCode: err, reason: function)\n            }\n        }\n    }\n}\n#endif\n\n// Sorry, we really try hard to not use underscored attributes. In this case\n// however we seem to break the inlining threshold which makes a system call\n// take twice the time, ie. we need this exception.\n@inline(__always)\n@inlinable\n@discardableResult\ninternal func syscallForbiddingEINVAL<T: FixedWidthInteger>(\n    where function: String = #function,\n    _ body: () throws -> T\n)\n    throws -> IOResult<T>\n{\n    while true {\n        let res = try body()\n        if res == -1 {\n            #if os(Windows)\n            var err: CInt = 0\n            _get_errno(&err)\n            #else\n            let err = errno\n            #endif\n            switch err {\n            case EINTR:\n                continue\n            case EWOULDBLOCK:\n                return .wouldBlock(0)\n            default:\n                preconditionIsNotUnacceptableErrnoForbiddingEINVAL(err: err, where: function)\n                throw IOError(errnoCode: err, reason: function)\n            }\n        }\n        return .processed(res)\n    }\n}\n\n@usableFromInline\ninternal enum Posix: Sendable {\n    #if canImport(Darwin)\n    @usableFromInline\n    static let UIO_MAXIOV: Int = 1024\n    @usableFromInline\n    static let SHUT_RD: CInt = CInt(Darwin.SHUT_RD)\n    @usableFromInline\n    static let SHUT_WR: CInt = CInt(Darwin.SHUT_WR)\n    @usableFromInline\n    static let SHUT_RDWR: CInt = CInt(Darwin.SHUT_RDWR)\n    #elseif os(Linux) || os(FreeBSD) || os(Android) || os(OpenBSD)\n    #if canImport(Glibc)\n    @usableFromInline\n    static let UIO_MAXIOV: Int = Int(Glibc.UIO_MAXIOV)\n    @usableFromInline\n    static let SHUT_RD: CInt = CInt(Glibc.SHUT_RD)\n    @usableFromInline\n    static let SHUT_WR: CInt = CInt(Glibc.SHUT_WR)\n    @usableFromInline\n    static let SHUT_RDWR: CInt = CInt(Glibc.SHUT_RDWR)\n    #elseif canImport(Musl)\n    @usableFromInline\n    static let UIO_MAXIOV: Int = Int(Musl.UIO_MAXIOV)\n    @usableFromInline\n    static let SHUT_RD: CInt = CInt(Musl.SHUT_RD)\n    @usableFromInline\n    static let SHUT_WR: CInt = CInt(Musl.SHUT_WR)\n    @usableFromInline\n    static let SHUT_RDWR: CInt = CInt(Musl.SHUT_RDWR)\n    #elseif canImport(Android)\n    @usableFromInline\n    static let UIO_MAXIOV: Int = Int(Android.UIO_MAXIOV)\n    @usableFromInline\n    static let SHUT_RD: CInt = CInt(Android.SHUT_RD)\n    @usableFromInline\n    static let SHUT_WR: CInt = CInt(Android.SHUT_WR)\n    @usableFromInline\n    static let SHUT_RDWR: CInt = CInt(Android.SHUT_RDWR)\n    #endif\n    #else\n    @usableFromInline\n    static var UIO_MAXIOV: Int {\n        fatalError(\"unsupported OS\")\n    }\n    @usableFromInline\n    static var SHUT_RD: Int {\n        fatalError(\"unsupported OS\")\n    }\n    @usableFromInline\n    static var SHUT_WR: Int {\n        fatalError(\"unsupported OS\")\n    }\n    @usableFromInline\n    static var SHUT_RDWR: Int {\n        fatalError(\"unsupported OS\")\n    }\n    #endif\n\n    #if canImport(Darwin)\n    static let IPTOS_ECN_NOTECT: CInt = CNIODarwin_IPTOS_ECN_NOTECT\n    static let IPTOS_ECN_MASK: CInt = CNIODarwin_IPTOS_ECN_MASK\n    static let IPTOS_ECN_ECT0: CInt = CNIODarwin_IPTOS_ECN_ECT0\n    static let IPTOS_ECN_ECT1: CInt = CNIODarwin_IPTOS_ECN_ECT1\n    static let IPTOS_ECN_CE: CInt = CNIODarwin_IPTOS_ECN_CE\n    #elseif os(Linux) || os(FreeBSD) || os(Android)\n    #if os(Android)\n    static let IPTOS_ECN_NOTECT: CInt = CInt(CNIOLinux.IPTOS_ECN_NOTECT)\n    #else\n    static let IPTOS_ECN_NOTECT: CInt = CInt(CNIOLinux.IPTOS_ECN_NOT_ECT)\n    #endif\n    static let IPTOS_ECN_MASK: CInt = CInt(CNIOLinux.IPTOS_ECN_MASK)\n    static let IPTOS_ECN_ECT0: CInt = CInt(CNIOLinux.IPTOS_ECN_ECT0)\n    static let IPTOS_ECN_ECT1: CInt = CInt(CNIOLinux.IPTOS_ECN_ECT1)\n    static let IPTOS_ECN_CE: CInt = CInt(CNIOLinux.IPTOS_ECN_CE)\n    #elseif os(OpenBSD)\n    static let IPTOS_ECN_NOTECT: CInt = CInt(CNIOOpenBSD.IPTOS_ECN_NOTECT)\n    static let IPTOS_ECN_MASK: CInt = CInt(CNIOOpenBSD.IPTOS_ECN_MASK)\n    static let IPTOS_ECN_ECT0: CInt = CInt(CNIOOpenBSD.IPTOS_ECN_ECT0)\n    static let IPTOS_ECN_ECT1: CInt = CInt(CNIOOpenBSD.IPTOS_ECN_ECT1)\n    static let IPTOS_ECN_CE: CInt = CInt(CNIOOpenBSD.IPTOS_ECN_CE)\n    #elseif os(Windows)\n    static let IPTOS_ECN_NOTECT: CInt = CInt(0x00)\n    static let IPTOS_ECN_MASK: CInt = CInt(0x03)\n    static let IPTOS_ECN_ECT0: CInt = CInt(0x02)\n    static let IPTOS_ECN_ECT1: CInt = CInt(0x01)\n    static let IPTOS_ECN_CE: CInt = CInt(0x03)\n    #endif\n\n    #if canImport(Darwin)\n    static let IP_RECVPKTINFO: CInt = CNIODarwin.IP_RECVPKTINFO\n    static let IP_PKTINFO: CInt = CNIODarwin.IP_PKTINFO\n\n    static let IPV6_RECVPKTINFO: CInt = CNIODarwin_IPV6_RECVPKTINFO\n    static let IPV6_PKTINFO: CInt = CNIODarwin_IPV6_PKTINFO\n    #elseif os(Linux) || os(FreeBSD) || os(Android)\n    static let IP_RECVPKTINFO: CInt = CInt(CNIOLinux.IP_PKTINFO)\n    static let IP_PKTINFO: CInt = CInt(CNIOLinux.IP_PKTINFO)\n\n    static let IPV6_RECVPKTINFO: CInt = CInt(CNIOLinux.IPV6_RECVPKTINFO)\n    static let IPV6_PKTINFO: CInt = CInt(CNIOLinux.IPV6_PKTINFO)\n    #elseif os(OpenBSD)\n    static let IP_PKTINFO: CInt = CInt(-1)  // Not actually present.\n\n    static let IPV6_RECVPKTINFO: CInt = CInt(CNIOOpenBSD.IPV6_RECVPKTINFO)\n    static let IPV6_PKTINFO: CInt = CInt(CNIOOpenBSD.IPV6_PKTINFO)\n    #elseif os(Windows)\n    static let IP_RECVPKTINFO: CInt = CInt(WinSDK.IP_PKTINFO)\n    static let IP_PKTINFO: CInt = CInt(WinSDK.IP_PKTINFO)\n\n    static let IPV6_RECVPKTINFO: CInt = CInt(WinSDK.IPV6_PKTINFO)\n    static let IPV6_PKTINFO: CInt = CInt(WinSDK.IPV6_PKTINFO)\n    #endif\n\n    #if canImport(Darwin)\n    static let SOL_UDP: CInt = CInt(IPPROTO_UDP)\n    #elseif os(Linux) || os(FreeBSD) || os(Android) || os(OpenBSD)\n    static let SOL_UDP: CInt = CInt(IPPROTO_UDP)\n    #elseif os(Windows)\n    static let SOL_UDP: CInt = CInt(IPPROTO_UDP)\n    #endif\n\n    #if !os(Windows)\n    @inline(never)\n    public static func shutdown(descriptor: CInt, how: Shutdown) throws {\n        _ = try syscall(blocking: false) {\n            sysShutdown(descriptor, how.cValue)\n        }\n    }\n\n    @inline(never)\n    public static func close(descriptor: CInt) throws {\n        let res = sysClose(descriptor)\n        if res == -1 {\n            #if os(Windows)\n            var err: CInt = 0\n            _get_errno(&err)\n            #else\n            let err = errno\n            #endif\n\n            // There is really nothing \"good\" we can do when EINTR was reported on close.\n            // So just ignore it and \"assume\" everything is fine == we closed the file descriptor.\n            //\n            // For more details see:\n            //     - https://bugs.chromium.org/p/chromium/issues/detail?id=269623\n            //     - https://lwn.net/Articles/576478/\n            if err != EINTR {\n                preconditionIsNotUnacceptableErrnoOnClose(err: err, where: #function)\n                throw IOError(errnoCode: err, reason: \"close\")\n            }\n        }\n    }\n\n    @inline(never)\n    public static func bind(descriptor: CInt, ptr: UnsafePointer<sockaddr>, bytes: Int) throws {\n        _ = try syscall(blocking: false) {\n            sysBind(descriptor, ptr, socklen_t(bytes))\n        }\n    }\n\n    @inline(never)\n    @discardableResult\n    @usableFromInline\n    // TODO: Allow varargs\n    internal static func fcntl(descriptor: CInt, command: CInt, value: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            sysFcntl(descriptor, command, value)\n        }.result\n    }\n\n    @inline(never)\n    public static func socket(\n        domain: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype\n    ) throws -> CInt {\n        try syscall(blocking: false) {\n            sysSocket(domain.rawValue, type.rawValue, protocolSubtype.rawValue)\n        }.result\n    }\n\n    @inline(never)\n    public static func setsockopt(\n        socket: CInt,\n        level: CInt,\n        optionName: CInt,\n        optionValue: UnsafeRawPointer,\n        optionLen: socklen_t\n    ) throws {\n        _ = try syscall(blocking: false) {\n            sysSetsockopt(socket, level, optionName, optionValue, optionLen)\n        }\n    }\n\n    @inline(never)\n    public static func getsockopt(\n        socket: CInt,\n        level: CInt,\n        optionName: CInt,\n        optionValue: UnsafeMutableRawPointer,\n        optionLen: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        _ = try syscall(blocking: false) {\n            sysGetsockopt(socket, level, optionName, optionValue, optionLen)\n        }.result\n    }\n\n    @inline(never)\n    public static func listen(descriptor: CInt, backlog: CInt) throws {\n        _ = try syscall(blocking: false) {\n            sysListen(descriptor, backlog)\n        }\n    }\n\n    @inline(never)\n    public static func accept(\n        descriptor: CInt,\n        addr: UnsafeMutablePointer<sockaddr>?,\n        len: UnsafeMutablePointer<socklen_t>?\n    ) throws -> CInt? {\n        let result: IOResult<CInt> = try syscall(blocking: true) {\n            sysAccept(descriptor, addr, len)\n        }\n\n        if case .processed(let fd) = result {\n            return fd\n        } else {\n            return nil\n        }\n    }\n\n    @inline(never)\n    public static func connect(descriptor: CInt, addr: UnsafePointer<sockaddr>, size: socklen_t) throws -> Bool {\n        do {\n            _ = try syscall(blocking: false) {\n                sysConnect(descriptor, addr, size)\n            }\n            return true\n        } catch let err as IOError {\n            if err.errnoCode == EINPROGRESS {\n                return false\n            }\n            throw err\n        }\n    }\n\n    @inline(never)\n    public static func open(file: UnsafePointer<CChar>, oFlag: CInt, mode: mode_t) throws -> CInt {\n        try syscall(blocking: false) {\n            sysOpenWithMode(file, oFlag, mode)\n        }.result\n    }\n\n    @inline(never)\n    public static func open(file: UnsafePointer<CChar>, oFlag: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            sysOpen(file, oFlag)\n        }.result\n    }\n\n    @inline(never)\n    public static func pwrite(\n        descriptor: CInt,\n        pointer: UnsafeRawPointer,\n        size: Int,\n        offset: off_t\n    ) throws -> IOResult<Int> {\n        try syscall(blocking: true) {\n            sysPwrite(descriptor, pointer, size, offset)\n        }\n    }\n\n    @inline(never)\n    public static func writev(descriptor: CInt, iovecs: UnsafeBufferPointer<IOVector>) throws -> IOResult<Int> {\n        try syscall(blocking: true) {\n            sysWritev(descriptor, iovecs.baseAddress!, CInt(iovecs.count))\n        }\n    }\n\n    @inline(never)\n    public static func pread(\n        descriptor: CInt,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<ssize_t> {\n        try syscallForbiddingEINVAL {\n            sysPread(descriptor, pointer, size, offset)\n        }\n    }\n\n    @inline(never)\n    public static func recvmsg(\n        descriptor: CInt,\n        msgHdr: UnsafeMutablePointer<msghdr>,\n        flags: CInt\n    ) throws -> IOResult<ssize_t> {\n        try syscall(blocking: true) {\n            sysRecvMsg(descriptor, msgHdr, flags)\n        }\n    }\n\n    @inline(never)\n    public static func sendmsg(\n        descriptor: CInt,\n        msgHdr: UnsafePointer<msghdr>,\n        flags: CInt\n    ) throws -> IOResult<ssize_t> {\n        try syscall(blocking: true) {\n            sysSendMsg(descriptor, msgHdr, flags)\n        }\n    }\n    #endif\n\n    @inline(never)\n    public static func read(\n        descriptor: CInt,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t\n    ) throws -> IOResult<ssize_t> {\n        try syscallForbiddingEINVAL {\n            #if os(Windows)\n            // Windows read, reads at most UInt32. Lets clamp size there.\n            let size = UInt32(clamping: size)\n            return ssize_t(sysRead(descriptor, pointer, size))\n            #else\n            sysRead(descriptor, pointer, size)\n            #endif\n        }\n    }\n\n    @inline(never)\n    public static func write(descriptor: CInt, pointer: UnsafeRawPointer, size: Int) throws -> IOResult<Int> {\n        try syscall(blocking: true) {\n            #if os(Windows)\n            let size = UInt32(clamping: size)\n            #endif\n            return numericCast(sysWrite(descriptor, pointer, size))\n        }\n    }\n\n    @discardableResult\n    @inline(never)\n    public static func ftruncate(descriptor: CInt, size: off_t) throws -> CInt {\n        try syscall(blocking: false) {\n            sysFtruncate(descriptor, numericCast(size))\n        }.result\n    }\n\n    @discardableResult\n    @inline(never)\n    public static func lseek(descriptor: CInt, offset: off_t, whence: CInt) throws -> off_t {\n        try syscall(blocking: false) {\n            sysLseek(descriptor, offset, whence)\n        }.result\n    }\n\n    @discardableResult\n    @inline(never)\n    public static func dup(descriptor: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            sysDup(descriptor)\n        }.result\n    }\n\n    #if !os(Windows)\n    // It's not really posix but exists on Linux and MacOS / BSD so just put it here for now to keep it simple\n    @inline(never)\n    public static func sendfile(descriptor: CInt, fd: CInt, offset: off_t, count: size_t) throws -> IOResult<Int> {\n        var written: off_t = 0\n        do {\n            _ = try syscall(blocking: false) { () -> ssize_t in\n                #if canImport(Darwin)\n                var w: off_t = off_t(count)\n                let result: CInt = Darwin.sendfile(fd, descriptor, offset, &w, nil, 0)\n                written = w\n                return ssize_t(result)\n                #elseif os(Linux) || os(FreeBSD) || os(Android)\n                var off: off_t = offset\n                #if canImport(Glibc)\n                let result: ssize_t = Glibc.sendfile(descriptor, fd, &off, count)\n                #elseif canImport(Musl)\n                let result: ssize_t = Musl.sendfile(descriptor, fd, &off, count)\n                #elseif canImport(Android)\n                let result: ssize_t = Android.sendfile(descriptor, fd, &off, count)\n                #endif\n                if result >= 0 {\n                    written = off_t(result)\n                } else {\n                    written = 0\n                }\n                return result\n                #else\n                fatalError(\"unsupported OS\")\n                #endif\n            }\n            return .processed(Int(written))\n        } catch let err as IOError {\n            if err.errnoCode == EAGAIN {\n                return .wouldBlock(Int(written))\n            }\n            throw err\n        }\n    }\n\n    @inline(never)\n    public static func sendmmsg(\n        sockfd: CInt,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt\n    ) throws -> IOResult<Int> {\n        try syscall(blocking: true) {\n            Int(sysSendMmsg(sockfd, msgvec, vlen, flags))\n        }\n    }\n\n    @inline(never)\n    public static func recvmmsg(\n        sockfd: CInt,\n        msgvec: UnsafeMutablePointer<MMsgHdr>,\n        vlen: CUnsignedInt,\n        flags: CInt,\n        timeout: UnsafeMutablePointer<timespec>?\n    ) throws -> IOResult<Int> {\n        try syscall(blocking: true) {\n            Int(sysRecvMmsg(sockfd, msgvec, vlen, flags, timeout))\n        }\n    }\n\n    @inline(never)\n    public static func getpeername(\n        socket: CInt,\n        address: UnsafeMutablePointer<sockaddr>,\n        addressLength: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        _ = try syscall(blocking: false) {\n            sysGetpeername(socket, address, addressLength)\n        }\n    }\n\n    @inline(never)\n    public static func getsockname(\n        socket: CInt,\n        address: UnsafeMutablePointer<sockaddr>,\n        addressLength: UnsafeMutablePointer<socklen_t>\n    ) throws {\n        _ = try syscall(blocking: false) {\n            sysGetsockname(socket, address, addressLength)\n        }\n    }\n    #endif\n\n    @inline(never)\n    public static func if_nametoindex(_ name: UnsafePointer<CChar>?) throws -> CUnsignedInt {\n        try syscall(blocking: false) {\n            sysIfNameToIndex(name!)\n        }.result\n    }\n\n    #if !os(Windows)\n    @inline(never)\n    public static func poll(fds: UnsafeMutablePointer<pollfd>, nfds: nfds_t, timeout: CInt) throws -> CInt {\n        try syscall(blocking: false) {\n            sysPoll(fds, nfds, timeout)\n        }.result\n    }\n\n    @inline(never)\n    public static func fstat(descriptor: CInt, outStat: UnsafeMutablePointer<stat>) throws {\n        _ = try syscall(blocking: false) {\n            sysFstat(descriptor, outStat)\n        }\n    }\n\n    @inline(never)\n    public static func stat(pathname: String, outStat: UnsafeMutablePointer<stat>) throws {\n        _ = try syscall(blocking: false) {\n            sysStat(pathname, outStat)\n        }\n    }\n\n    @inline(never)\n    public static func lstat(pathname: String, outStat: UnsafeMutablePointer<stat>) throws {\n        _ = try syscall(blocking: false) {\n            sysLstat(pathname, outStat)\n        }\n    }\n\n    @inline(never)\n    public static func symlink(pathname: String, destination: String) throws {\n        _ = try syscall(blocking: false) {\n            sysSymlink(destination, pathname)\n        }\n    }\n\n    @inline(never)\n    public static func readlink(\n        pathname: String,\n        outPath: UnsafeMutablePointer<CChar>,\n        outPathSize: Int\n    ) throws -> CLong {\n        try syscall(blocking: false) {\n            sysReadlink(pathname, outPath, outPathSize)\n        }.result\n    }\n\n    @inline(never)\n    public static func unlink(pathname: String) throws {\n        _ = try syscall(blocking: false) {\n            sysUnlink(pathname)\n        }\n    }\n\n    @inline(never)\n    public static func mkdir(pathname: String, mode: mode_t) throws {\n        _ = try syscall(blocking: false) {\n            sysMkdir(pathname, mode)\n        }\n    }\n\n    #if canImport(Darwin)\n    @inline(never)\n    public static func mkpath_np(pathname: String, mode: mode_t) throws {\n        _ = try syscall(blocking: false) {\n            sysMkpath(pathname, mode)\n        }\n    }\n\n    @inline(never)\n    public static func opendir(pathname: String) throws -> UnsafeMutablePointer<DIR> {\n        try syscall {\n            sysOpendir(pathname)\n        }\n    }\n\n    @inline(never)\n    public static func readdir(dir: UnsafeMutablePointer<DIR>) throws -> UnsafeMutablePointer<dirent>? {\n        try syscallOptional {\n            sysReaddir(dir)\n        }\n    }\n\n    @inline(never)\n    public static func closedir(dir: UnsafeMutablePointer<DIR>) throws {\n        _ = try syscall(blocking: true) {\n            sysClosedir(dir)\n        }\n    }\n    #elseif os(Linux) || os(FreeBSD) || os(Android) || os(OpenBSD)\n    @inline(never)\n    public static func opendir(pathname: String) throws -> OpaquePointer {\n        try syscall {\n            sysOpendir(pathname)\n        }\n    }\n\n    @inline(never)\n    public static func readdir(dir: OpaquePointer) throws -> UnsafeMutablePointer<dirent>? {\n        try syscallOptional {\n            sysReaddir(dir)\n        }\n    }\n\n    @inline(never)\n    public static func closedir(dir: OpaquePointer) throws {\n        _ = try syscall(blocking: true) {\n            sysClosedir(dir)\n        }\n    }\n    #endif\n\n    @inline(never)\n    public static func rename(pathname: String, newName: String) throws {\n        _ = try syscall(blocking: true) {\n            sysRename(pathname, newName)\n        }\n    }\n\n    @inline(never)\n    public static func remove(pathname: String) throws {\n        _ = try syscall(blocking: true) {\n            sysRemove(pathname)\n        }\n    }\n\n    @inline(never)\n    public static func socketpair(\n        domain: NIOBSDSocket.ProtocolFamily,\n        type: NIOBSDSocket.SocketType,\n        protocolSubtype: NIOBSDSocket.ProtocolSubtype,\n        socketVector: UnsafeMutablePointer<CInt>?\n    ) throws {\n        _ = try syscall(blocking: false) {\n            sysSocketpair(domain.rawValue, type.rawValue, protocolSubtype.rawValue, socketVector!)\n        }\n    }\n    #endif\n    #if !os(Windows)\n    @inline(never)\n    public static func ioctl(fd: CInt, request: CUnsignedLong, ptr: UnsafeMutableRawPointer) throws {\n        _ = try syscall(blocking: false) {\n            /// `numericCast` to support musl which accepts `CInt` (cf. `CUnsignedLong`).\n            sysIoctl(fd, numericCast(request), ptr)\n        }\n    }\n    #endif  // !os(Windows)\n}\n\n/// `NIOFcntlFailedError` indicates that NIO was unable to perform an\n/// operation on a socket.\n///\n/// This error should never happen, unfortunately, we have seen this happen on Darwin.\npublic struct NIOFcntlFailedError: Error {}\n\n/// `NIOFailedToSetSocketNonBlockingError` indicates that NIO was unable to set a socket to non-blocking mode, either\n/// when connecting a socket as a client or when accepting a socket as a server.\n///\n/// This error should never happen because a socket should always be able to be set to non-blocking mode. Unfortunately,\n/// we have seen this happen on Darwin.\n@available(*, deprecated, renamed: \"NIOFcntlFailedError\")\npublic struct NIOFailedToSetSocketNonBlockingError: Error {}\n\n#if !os(Windows)\nextension Posix {\n    public static func setNonBlocking(socket: CInt) throws {\n        let flags = try Posix.fcntl(descriptor: socket, command: F_GETFL, value: 0)\n        do {\n            let ret = try Posix.fcntl(descriptor: socket, command: F_SETFL, value: flags | O_NONBLOCK)\n            assert(ret == 0, \"unexpectedly, fcntl(\\(socket), F_SETFL, \\(flags) | O_NONBLOCK) returned \\(ret)\")\n        } catch let error as IOError {\n            if error.errnoCode == EINVAL {\n                // Darwin seems to sometimes do this despite the docs claiming it can't happen\n                throw NIOFcntlFailedError()\n            }\n            throw error\n        }\n    }\n}\n#endif\n\n#if canImport(Darwin) || os(OpenBSD)\n#if canImport(Darwin)\ninternal typealias kevent_timespec = Darwin.timespec\n#elseif os(OpenBSD)\ninternal typealias kevent_timespec = CNIOOpenBSD.timespec\n#else\n#error(\"implementation missing\")\n#endif\n\n@usableFromInline\ninternal enum KQueue: Sendable {\n\n    // TODO: Figure out how to specify a typealias to the kevent struct without run into trouble with the swift compiler\n\n    @inline(never)\n    public static func kqueue() throws -> CInt {\n        try syscall(blocking: false) {\n            #if canImport(Darwin)\n            Darwin.kqueue()\n            #elseif os(OpenBSD)\n            CNIOOpenBSD.kqueue()\n            #else\n            #error(\"implementation missing\")\n            #endif\n        }.result\n    }\n\n    @inline(never)\n    @discardableResult\n    public static func kevent(\n        kq: CInt,\n        changelist: UnsafePointer<kevent>?,\n        nchanges: CInt,\n        eventlist: UnsafeMutablePointer<kevent>?,\n        nevents: CInt,\n        timeout: UnsafePointer<kevent_timespec>?\n    ) throws -> CInt {\n        try syscall(blocking: false) {\n            sysKevent(kq, changelist, nchanges, eventlist, nevents, timeout)\n        }.result\n    }\n}\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Thread.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2014 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOConcurrencyHelpers\n\n#if os(Linux) || os(FreeBSD) || os(Android)\nimport CNIOLinux\n#elseif os(OpenBSD)\nimport CNIOOpenBSD\n#elseif os(Windows)\nimport WinSDK\n#endif\n\nenum LowLevelThreadOperations {\n\n}\n\nprotocol ThreadOps {\n    associatedtype ThreadHandle: Sendable\n    associatedtype ThreadSpecificKey\n    associatedtype ThreadSpecificKeyDestructor\n\n    static func threadName(_ thread: ThreadHandle) -> String?\n    static func run(handle: inout ThreadHandle?, args: Box<NIOThread.ThreadBoxValue>)\n    static func isCurrentThread(_ thread: ThreadHandle) -> Bool\n    static func compareThreads(_ lhs: ThreadHandle, _ rhs: ThreadHandle) -> Bool\n    static var currentThread: ThreadHandle { get }\n    static func joinThread(_ thread: ThreadHandle)\n    static func allocateThreadSpecificValue(destructor: ThreadSpecificKeyDestructor) -> ThreadSpecificKey\n    static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey)\n    static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer?\n    static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?)\n}\n\n/// A Thread that executes some runnable block.\n///\n/// All methods exposed are thread-safe.\n@usableFromInline\nfinal class NIOThread: Sendable {\n    internal typealias ThreadBoxValue = (body: (NIOThread) -> Void, name: String?)\n    internal typealias ThreadBox = Box<ThreadBoxValue>\n\n    private let desiredName: String?\n\n    /// The thread handle used by this instance.\n    private let handle: NIOLockedValueBox<ThreadOpsSystem.ThreadHandle?>\n\n    enum Error: Swift.Error {\n        case threadAlreadyJoinedOrDetached\n    }\n\n    deinit {\n        assert(\n            self.handle.withLockedValue { $0 } == nil,\n            \"Thread leak! NIOThread released without having been .join()ed\"\n        )\n    }\n\n    func withHandleUnderLock<Return>(_ body: (ThreadOpsSystem.ThreadHandle) throws -> Return) throws -> Return {\n        try self.handle.withLockedValue { handle in\n            guard let handle else {\n                throw Error.threadAlreadyJoinedOrDetached\n            }\n            return try body(handle)\n        }\n    }\n\n    /// Create a new instance\n    ///\n    /// - arguments:\n    ///   - handle: The `ThreadOpsSystem.ThreadHandle` that is wrapped and used by the `NIOThread`.\n    internal init(handle: ThreadOpsSystem.ThreadHandle, desiredName: String?) {\n        self.handle = NIOLockedValueBox(handle)\n        self.desiredName = desiredName\n    }\n\n    /// Get current name of the `NIOThread` or `nil` if not set.\n    var currentName: String? {\n        try? self.withHandleUnderLock { handle in\n            ThreadOpsSystem.threadName(handle)\n        }\n    }\n\n    static var currentThreadName: String? {\n        #if os(Windows)\n        ThreadOpsSystem.threadName(.init(GetCurrentThread()))\n        #else\n        ThreadOpsSystem.threadName(.init(handle: pthread_self()))\n        #endif\n    }\n\n    static var currentThreadID: UInt {\n        #if os(Windows)\n        UInt(bitPattern: .init(bitPattern: ThreadOpsSystem.currentThread))\n        #else\n        UInt(bitPattern: .init(bitPattern: ThreadOpsSystem.currentThread.handle))\n        #endif\n    }\n\n    @discardableResult\n    func takeOwnership() -> ThreadOpsSystem.ThreadHandle {\n        try! self.handle.withLockedValue { handle in\n            guard let originalHandle = handle else {\n                throw Error.threadAlreadyJoinedOrDetached\n            }\n            handle = nil\n            return originalHandle\n        }\n    }\n\n    func join() {\n        let handle = try! self.withHandleUnderLock { $0 }\n        ThreadOpsSystem.joinThread(handle)\n        self.handle.withLockedValue { handle in\n            precondition(handle != nil, \"double NIOThread.join() disallowed\")\n            handle = nil\n        }\n    }\n\n    /// Spawns and runs some task in a `NIOThread`.\n    ///\n    /// - arguments:\n    ///   - name: The name of the `NIOThread` or `nil` if no specific name should be set.\n    ///   - body: The function to execute within the spawned `NIOThread`.\n    static func spawnAndRun(\n        name: String? = nil,\n        body: @escaping (NIOThread) -> Void\n    ) {\n        var handle: ThreadOpsSystem.ThreadHandle? = nil\n\n        // Store everything we want to pass into the c function in a Box so we\n        // can hand-over the reference.\n        let tuple: ThreadBoxValue = (body: body, name: name)\n        let box = ThreadBox(tuple)\n\n        ThreadOpsSystem.run(handle: &handle, args: box)\n    }\n\n    /// Returns `true` if the calling thread.\n    ///\n    /// - warning: Do not use in the performance path, this takes a lock and is slow.\n    @usableFromInline\n    var isCurrentSlow: Bool {\n        (try? self.withHandleUnderLock { handle in\n            ThreadOpsSystem.isCurrentThread(handle)\n        }) ?? false\n    }\n\n    internal static func withCurrentThread<Return>(_ body: (NIOThread) throws -> Return) rethrows -> Return {\n        let thread = NIOThread(handle: ThreadOpsSystem.currentThread, desiredName: nil)\n        defer {\n            thread.takeOwnership()\n        }\n        return try body(thread)\n    }\n}\n\nextension NIOThread: CustomStringConvertible {\n    public var description: String {\n        let desiredName = self.desiredName\n        let actualName = self.currentName\n\n        switch (desiredName, actualName) {\n        case (.some(let desiredName), .some(desiredName)):\n            // We know the current, actual name and the desired name and they match. This is hopefully the most common\n            // situation.\n            return \"NIOThread(name = \\(desiredName))\"\n        case (.some(let desiredName), .some(let actualName)):\n            // We know both names but they're not equal. That's odd but not impossible, some misbehaved library might\n            // have changed the name.\n            return \"NIOThread(desiredName = \\(desiredName), actualName = \\(actualName))\"\n        case (.some(let desiredName), .none):\n            // We only know the desired name and can't get the actual thread name. The OS might not be able to provide\n            // the name to us.\n            return \"NIOThread(desiredName = \\(desiredName))\"\n        case (.none, .some(let actualName)):\n            // We only know the actual name. This can happen when we don't have a reference to the actually spawned\n            // thread but rather ask for the current thread and then print it.\n            return \"NIOThread(actualName = \\(actualName))\"\n        case (.none, .none):\n            // We know nothing, sorry.\n            return \"NIOThread(n/a)\"\n        }\n    }\n}\n\n/// A ``ThreadSpecificVariable`` is a variable that can be read and set like a normal variable except that it holds\n/// different variables per thread.\n///\n/// ``ThreadSpecificVariable`` is thread-safe so it can be used with multiple threads at the same time but the value\n/// returned by ``currentValue`` is defined per thread.\n///\n/// - Note: Though ``ThreadSpecificVariable`` is thread-safe, it is not `Sendable` unless `Value` is `Sendable`.\n///     If ``ThreadSpecificVariable`` were unconditionally `Sendable`, it could be used to \"smuggle\"\n///     non-`Sendable` state out of an actor or other isolation domain without triggering warnings. If you\n///     are attempting to use ``ThreadSpecificVariable`` with non-`Sendable` data, consider using a dynamic\n///     enforcement tool like `NIOLoopBoundBox` to police the access.\npublic final class ThreadSpecificVariable<Value: AnyObject> {\n    // the actual type in there is `Box<(ThreadSpecificVariable<T>, T)>` but we can't use that as C functions can't capture (even types)\n    private typealias BoxedType = Box<(AnyObject, AnyObject)>\n\n    internal class Key {\n        private var underlyingKey: ThreadOpsSystem.ThreadSpecificKey\n\n        internal init(destructor: @escaping ThreadOpsSystem.ThreadSpecificKeyDestructor) {\n            self.underlyingKey = ThreadOpsSystem.allocateThreadSpecificValue(destructor: destructor)\n        }\n\n        deinit {\n            ThreadOpsSystem.deallocateThreadSpecificValue(self.underlyingKey)\n        }\n\n        public func get() -> UnsafeMutableRawPointer? {\n            ThreadOpsSystem.getThreadSpecificValue(self.underlyingKey)\n        }\n\n        public func set(value: UnsafeMutableRawPointer?) {\n            ThreadOpsSystem.setThreadSpecificValue(key: self.underlyingKey, value: value)\n        }\n    }\n\n    private let key: Key\n\n    /// Initialize a new `ThreadSpecificVariable` without a current value (`currentValue == nil`).\n    public init() {\n        self.key = Key(destructor: {\n            Unmanaged<BoxedType>.fromOpaque(($0 as UnsafeMutableRawPointer?)!).release()\n        })\n    }\n\n    /// Initialize a new `ThreadSpecificVariable` with `value` for the calling thread. After calling this, the calling\n    /// thread will see `currentValue == value` but on all other threads `currentValue` will be `nil` until changed.\n    ///\n    /// - Parameters:\n    ///   - value: The value to set for the calling thread.\n    public convenience init(value: Value) {\n        self.init()\n        self.currentValue = value\n    }\n\n    /// The value for the current thread.\n    @available(\n        *,\n        noasync,\n        message: \"threads can change between suspension points and therefore the thread specific value too\"\n    )\n    public var currentValue: Value? {\n        get {\n            self.get()\n        }\n        set {\n            self.set(newValue)\n        }\n    }\n\n    /// Get the current value for the calling thread.\n    func get() -> Value? {\n        guard let raw = self.key.get() else { return nil }\n        // parenthesize the return value to silence the cast warning\n        return\n            (Unmanaged<BoxedType>\n            .fromOpaque(raw)\n            .takeUnretainedValue()\n            .value.1 as! Value)\n    }\n\n    /// Set the current value for the calling threads. The `currentValue` for all other threads remains unchanged.\n    func set(_ newValue: Value?) {\n        if let raw = self.key.get() {\n            Unmanaged<BoxedType>.fromOpaque(raw).release()\n        }\n        self.key.set(value: newValue.map { Unmanaged.passRetained(Box((self, $0))).toOpaque() })\n    }\n}\n\nextension ThreadSpecificVariable: @unchecked Sendable where Value: Sendable {}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/ThreadPosix.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if os(Linux) || os(Android) || os(FreeBSD) || canImport(Darwin) || os(OpenBSD)\n\n#if os(Linux) || os(Android)\nimport CNIOLinux\n\nprivate let sys_pthread_getname_np = CNIOLinux_pthread_getname_np\nprivate let sys_pthread_setname_np = CNIOLinux_pthread_setname_np\n#if os(Android)\nprivate typealias ThreadDestructor = @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer\n#else\nprivate typealias ThreadDestructor = @convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?\n#endif\n#elseif os(OpenBSD)\nimport CNIOOpenBSD\n\nprivate let sys_pthread_getname_np = CNIOOpenBSD_pthread_get_name_np\nprivate let sys_pthread_setname_np = CNIOOpenBSD_pthread_set_name_np\nprivate typealias ThreadDestructor = @convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?\n#elseif canImport(Darwin)\nprivate let sys_pthread_getname_np = pthread_getname_np\n// Emulate the same method signature as pthread_setname_np on Linux.\nprivate func sys_pthread_setname_np(_ p: pthread_t, _ pointer: UnsafePointer<Int8>) -> Int32 {\n    assert(pthread_equal(pthread_self(), p) != 0)\n    pthread_setname_np(pointer)\n    // Will never fail on macOS so just return 0 which will be used on linux to signal it not failed.\n    return 0\n}\nprivate typealias ThreadDestructor = @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer?\n\n#endif\n\nprivate func sysPthread_create(\n    handle: UnsafeMutablePointer<pthread_t?>,\n    destructor: @escaping ThreadDestructor,\n    args: UnsafeMutableRawPointer?\n) -> CInt {\n    #if canImport(Darwin)\n    var attr: pthread_attr_t = .init()\n    pthread_attr_init(&attr)\n    pthread_attr_set_qos_class_np(&attr, qos_class_main(), 0)\n    let thread = pthread_create(handle, &attr, destructor, args)\n    pthread_attr_destroy(&attr)\n    return thread\n    #elseif os(OpenBSD)\n    var attr: pthread_attr_t? = .init(bitPattern: 0)\n    pthread_attr_init(&attr)\n    let thread = pthread_create(handle, &attr, destructor, args)\n    pthread_attr_destroy(&attr)\n    return thread\n    #else\n    #if canImport(Musl)\n    var handleLinux: OpaquePointer? = nil\n    let result = pthread_create(\n        &handleLinux,\n        nil,\n        destructor,\n        args\n    )\n    #else\n    var handleLinux = pthread_t()\n    #if os(Android)\n    // NDK 27 signature:\n    // int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nonnull (* _Nonnull __start_routine)(void* _Nonnull), void* _Nullable);\n    func coerceThreadDestructor(\n        _ destructor: @escaping ThreadDestructor\n    ) -> (@convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer) {\n        destructor\n    }\n\n    // NDK 28 signature:\n    // int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nullable (* _Nonnull __start_routine)(void* _Nullable), void* _Nullable);\n    func coerceThreadDestructor(\n        _ destructor: @escaping ThreadDestructor\n    ) -> (@convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?) {\n        unsafeBitCast(destructor, to: (@convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?).self)\n    }\n    #else\n    // Linux doesn't change the signature\n    func coerceThreadDestructor(_ destructor: ThreadDestructor) -> ThreadDestructor { destructor }\n    #endif\n    let result = pthread_create(\n        &handleLinux,\n        nil,\n        coerceThreadDestructor(destructor),\n        args\n    )\n    #endif\n    handle.pointee = handleLinux\n    return result\n    #endif\n}\n\ntypealias ThreadOpsSystem = ThreadOpsPosix\n\nstruct PthreadWrapper: @unchecked Sendable {\n    var handle: pthread_t\n}\n\nextension Optional where Wrapped == PthreadWrapper {\n    mutating func withHandlePointer<\n        ReturnValue\n    >(\n        _ body: (UnsafeMutablePointer<pthread_t?>) throws -> ReturnValue\n    ) rethrows -> ReturnValue {\n        var handle = self?.handle\n        defer {\n            self = handle.map { PthreadWrapper(handle: $0) }\n        }\n\n        return try body(&handle)\n    }\n}\n\nenum ThreadOpsPosix: ThreadOps {\n    typealias ThreadHandle = PthreadWrapper\n    typealias ThreadSpecificKey = pthread_key_t\n    #if canImport(Darwin)\n    typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer) -> Void\n    #else\n    typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer?) -> Void\n    #endif\n\n    static func threadName(_ thread: ThreadOpsSystem.ThreadHandle) -> String? {\n        // 64 bytes should be good enough as on Linux the limit is usually 16\n        // and it's very unlikely a user will ever set something longer\n        // anyway.\n        var chars: [CChar] = Array(repeating: 0, count: 64)\n        return chars.withUnsafeMutableBufferPointer { ptr in\n            guard sys_pthread_getname_np(thread.handle, ptr.baseAddress!, ptr.count) == 0 else {\n                return nil\n            }\n\n            let buffer: UnsafeRawBufferPointer =\n                UnsafeRawBufferPointer(UnsafeBufferPointer<CChar>(rebasing: ptr.prefix { $0 != 0 }))\n            return String(decoding: buffer, as: Unicode.UTF8.self)\n        }\n    }\n\n    static func run(\n        handle: inout ThreadOpsSystem.ThreadHandle?,\n        args: Box<NIOThread.ThreadBoxValue>\n    ) {\n        let argv0 = Unmanaged.passRetained(args).toOpaque()\n        let res = handle.withHandlePointer { handlePtr in\n            sysPthread_create(\n                handle: handlePtr,\n                destructor: {\n                    // Cast to UnsafeMutableRawPointer? and force unwrap to make the\n                    // same code work on macOS and Linux.\n                    let boxed = Unmanaged<NIOThread.ThreadBox>\n                        .fromOpaque(($0 as UnsafeMutableRawPointer?)!)\n                        .takeRetainedValue()\n                    let (body, name) = (boxed.value.body, boxed.value.name)\n                    let hThread: ThreadOpsSystem.ThreadHandle = PthreadWrapper(handle: pthread_self())\n\n                    if let name = name {\n                        let maximumThreadNameLength: Int\n                        #if os(Linux) || os(Android)\n                        maximumThreadNameLength = 15\n                        #else\n                        maximumThreadNameLength = .max\n                        #endif\n                        name.prefix(maximumThreadNameLength).withCString { namePtr in\n                            // this is non-critical so we ignore the result here, we've seen\n                            // EPERM in containers.\n                            _ = sys_pthread_setname_np(hThread.handle, namePtr)\n                        }\n                    }\n\n                    body(NIOThread(handle: hThread, desiredName: name))\n\n                    #if os(Android)\n                    return UnsafeMutableRawPointer(bitPattern: 0xdeadbee)!\n                    #else\n                    return nil\n                    #endif\n                },\n                args: argv0\n            )\n        }\n        precondition(res == 0, \"Unable to create thread: \\(res)\")\n    }\n\n    static func isCurrentThread(_ thread: ThreadOpsSystem.ThreadHandle) -> Bool {\n        pthread_equal(thread.handle, pthread_self()) != 0\n    }\n\n    static var currentThread: ThreadOpsSystem.ThreadHandle {\n        PthreadWrapper(handle: pthread_self())\n    }\n\n    static func joinThread(_ thread: ThreadOpsSystem.ThreadHandle) {\n        let err = pthread_join(thread.handle, nil)\n        assert(err == 0, \"pthread_join failed with \\(err)\")\n    }\n\n    static func allocateThreadSpecificValue(destructor: @escaping ThreadSpecificKeyDestructor) -> ThreadSpecificKey {\n        var value = pthread_key_t()\n        let result = pthread_key_create(&value, Optional(destructor))\n        precondition(result == 0, \"pthread_key_create failed: \\(result)\")\n        return value\n    }\n\n    static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey) {\n        let result = pthread_key_delete(key)\n        precondition(result == 0, \"pthread_key_delete failed: \\(result)\")\n    }\n\n    static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer? {\n        pthread_getspecific(key)\n    }\n\n    static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?) {\n        let result = pthread_setspecific(key, value)\n        precondition(result == 0, \"pthread_setspecific failed: \\(result)\")\n    }\n\n    static func compareThreads(_ lhs: ThreadOpsSystem.ThreadHandle, _ rhs: ThreadOpsSystem.ThreadHandle) -> Bool {\n        pthread_equal(lhs.handle, rhs.handle) != 0\n    }\n}\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/ThreadWindows.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if os(Windows)\n\nimport WinSDK\n\ntypealias ThreadOpsSystem = ThreadOpsWindows\nenum ThreadOpsWindows: ThreadOps {\n    typealias ThreadHandle = HANDLE\n    typealias ThreadSpecificKey = DWORD\n    typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer?) -> Void\n\n    static func threadName(_ thread: ThreadOpsSystem.ThreadHandle) -> String? {\n        var pszBuffer: PWSTR?\n        GetThreadDescription(thread, &pszBuffer)\n        guard let buffer = pszBuffer else { return nil }\n        let string: String = String(decodingCString: buffer, as: UTF16.self)\n        LocalFree(buffer)\n        return string\n    }\n\n    static func run(\n        handle: inout ThreadOpsSystem.ThreadHandle?,\n        args: Box<NIOThread.ThreadBoxValue>\n    ) {\n        let argv0 = Unmanaged.passRetained(args).toOpaque()\n\n        // FIXME(compnerd) this should use the `stdcall` calling convention\n        let routine: @convention(c) (UnsafeMutableRawPointer?) -> CUnsignedInt = {\n            let boxed = Unmanaged<NIOThread.ThreadBox>.fromOpaque($0!).takeRetainedValue()\n            let (body, name) = (boxed.value.body, boxed.value.name)\n            let hThread: ThreadOpsSystem.ThreadHandle = GetCurrentThread()\n\n            if let name = name {\n                _ = name.withCString(encodedAs: UTF16.self) {\n                    SetThreadDescription(hThread, $0)\n                }\n            }\n\n            body(NIOThread(handle: hThread, desiredName: name))\n\n            return 0\n        }\n        let hThread: HANDLE =\n            HANDLE(bitPattern: _beginthreadex(nil, 0, routine, argv0, 0, nil))!\n    }\n\n    static func isCurrentThread(_ thread: ThreadOpsSystem.ThreadHandle) -> Bool {\n        CompareObjectHandles(thread, GetCurrentThread())\n    }\n\n    static var currentThread: ThreadOpsSystem.ThreadHandle {\n        GetCurrentThread()\n    }\n\n    static func joinThread(_ thread: ThreadOpsSystem.ThreadHandle) {\n        let dwResult: DWORD = WaitForSingleObject(thread, INFINITE)\n        assert(dwResult == WAIT_OBJECT_0, \"WaitForSingleObject: \\(GetLastError())\")\n    }\n\n    static func allocateThreadSpecificValue(destructor: @escaping ThreadSpecificKeyDestructor) -> ThreadSpecificKey {\n        FlsAlloc(destructor)\n    }\n\n    static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey) {\n        let dwResult: Bool = FlsFree(key)\n        precondition(dwResult, \"FlsFree: \\(GetLastError())\")\n    }\n\n    static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer? {\n        FlsGetValue(key)\n    }\n\n    static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?) {\n        FlsSetValue(key, value)\n    }\n\n    static func compareThreads(_ lhs: ThreadOpsSystem.ThreadHandle, _ rhs: ThreadOpsSystem.ThreadHandle) -> Bool {\n        CompareObjectHandles(lhs, rhs)\n    }\n}\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Utilities.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n/// A utility function that runs the body code only in debug builds, without\n/// emitting compiler warnings.\n///\n/// This is currently the only way to do this in Swift: see\n/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.\n@inlinable\ninternal func debugOnly(_ body: () -> Void) {\n    assert(\n        {\n            body()\n            return true\n        }()\n    )\n}\n\n/// Allows to \"box\" another value.\nfinal class Box<T> {\n    let value: T\n    init(_ value: T) { self.value = value }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/VsockAddress.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\n#if canImport(Darwin)\nimport CNIODarwin\n#elseif os(Linux) || os(Android)\n#if canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#endif\nimport CNIOLinux\n#endif\nlet vsockUnimplemented = \"VSOCK support is not implemented for this platform\"\n\n// MARK: - Public API that's available on all platforms.\n\n/// A vsock socket address.\n///\n/// A socket address is defined as a combination of a Context Identifier (CID) and a port number.\n/// The CID identifies the source or destination, which is either a virtual machine or the host.\n/// The port number differentiates between multiple services running on a single machine.\n///\n/// For well-known CID values and port numbers, see ``VsockAddress/ContextID`` and ``VsockAddress/Port-swift.struct``.\npublic struct VsockAddress: Hashable, Sendable {\n    /// The context ID associated with the address.\n    public var cid: ContextID\n\n    /// The port associated with the address.\n    public var port: Port\n\n    /// Creates a new vsock address.\n    ///\n    /// - Parameters:\n    ///   - cid: the context ID.\n    ///   - port: the target port.\n    public init(cid: ContextID, port: Port) {\n        self.cid = cid\n        self.port = port\n    }\n\n    /// A vsock Context Identifier (CID).\n    ///\n    /// The CID identifies the source or destination, which is either a virtual machine or the host.\n    public struct ContextID: RawRepresentable, ExpressibleByIntegerLiteral, Hashable, Sendable {\n        public var rawValue: UInt32\n\n        @inlinable\n        public init(rawValue: UInt32) {\n            self.rawValue = rawValue\n        }\n\n        @inlinable\n        public init(integerLiteral value: UInt32) {\n            self.init(rawValue: value)\n        }\n\n        @inlinable\n        public init(_ value: Int) {\n            self.init(rawValue: UInt32(bitPattern: Int32(truncatingIfNeeded: value)))\n        }\n\n        /// Wildcard, matches any address.\n        ///\n        /// On all platforms, using this value with `bind(2)` means \"any address\".\n        ///\n        /// On Darwin platforms, the man page states this can be used with `connect(2)` to mean \"this host\".\n        ///\n        /// This is equal to `VMADDR_CID_ANY (-1U)`.\n        @inlinable\n        public static var any: Self { Self(rawValue: UInt32(bitPattern: -1)) }\n\n        /// The address of the hypervisor.\n        ///\n        /// This is equal to `VMADDR_CID_HYPERVISOR (0)`.\n        @inlinable\n        public static var hypervisor: Self { Self(rawValue: 0) }\n\n        /// The address of the host.\n        ///\n        /// This is equal to `VMADDR_CID_HOST (2)`.\n        @inlinable\n        public static var host: Self { Self(rawValue: 2) }\n\n        /// The address for local communication (loopback).\n        ///\n        /// This directs packets to the same host that generated them.  This is useful for testing\n        /// applications on a single host and for debugging.\n        ///\n        /// The local context ID obtained with `getLocalContextID(_:)` can be used for the same\n        /// purpose, but it is preferable to use `local`.\n        ///\n        /// This is equal to `VMADDR_CID_LOCAL (1)` on platforms that define it.\n        ///\n        /// - Warning: `VMADDR_CID_LOCAL (1)` is available from Linux 5.6. Its use is unsupported on\n        /// other platforms.\n        ///\n        /// - SeeAlso: https://man7.org/linux/man-pages/man7/vsock.7.html\n        @inlinable\n        public static var local: Self { Self(rawValue: 1) }\n\n    }\n\n    /// A vsock port number.\n    ///\n    /// The vsock port number differentiates between multiple services running on a single machine.\n    public struct Port: RawRepresentable, ExpressibleByIntegerLiteral, Hashable, Sendable {\n        public var rawValue: UInt32\n\n        @inlinable\n        public init(rawValue: UInt32) {\n            self.rawValue = rawValue\n        }\n\n        @inlinable\n        public init(integerLiteral value: UInt32) {\n            self.init(rawValue: value)\n        }\n\n        @inlinable\n        public init(_ value: Int) {\n            self.init(rawValue: UInt32(bitPattern: Int32(truncatingIfNeeded: value)))\n        }\n\n        /// Used to bind to any port number.\n        ///\n        /// This is equal to `VMADDR_PORT_ANY (-1U)`.\n        @inlinable\n        public static var any: Self { Self(rawValue: UInt32(bitPattern: -1)) }\n    }\n}\n\nextension VsockAddress.ContextID: CustomStringConvertible {\n    public var description: String {\n        self == .any ? \"-1\" : self.rawValue.description\n    }\n}\n\nextension VsockAddress.Port: CustomStringConvertible {\n    public var description: String {\n        self == .any ? \"-1\" : self.rawValue.description\n    }\n}\n\nextension VsockAddress: CustomStringConvertible {\n    public var description: String {\n        \"[VSOCK]\\(self.cid):\\(self.port)\"\n    }\n}\n\nextension ChannelOptions {\n    /// - seealso: `LocalVsockContextID`\n    public static let localVsockContextID = Types.LocalVsockContextID()\n}\n\nextension ChannelOption where Self == ChannelOptions.Types.LocalVsockContextID {\n    public static var localVsockContextID: Self { .init() }\n}\n\nextension ChannelOptions.Types {\n    /// This get-only option is used on channels backed by vsock sockets to get the local VSOCK context ID.\n    public struct LocalVsockContextID: ChannelOption, Sendable {\n        public typealias Value = VsockAddress.ContextID\n        public init() {}\n    }\n}\n\n// MARK: - Public API that might throw runtime error if not implemented on the platform.\n\nextension NIOBSDSocket.AddressFamily {\n    /// Address for vsock.\n    public static var vsock: NIOBSDSocket.AddressFamily {\n        #if canImport(Darwin) || os(Linux) || os(Android)\n        NIOBSDSocket.AddressFamily(rawValue: AF_VSOCK)\n        #else\n        fatalError(vsockUnimplemented)\n        #endif\n    }\n}\n\nextension NIOBSDSocket.ProtocolFamily {\n    /// Address for vsock.\n    public static var vsock: NIOBSDSocket.ProtocolFamily {\n        #if canImport(Darwin) || os(Linux) || os(Android)\n        NIOBSDSocket.ProtocolFamily(rawValue: PF_VSOCK)\n        #else\n        fatalError(vsockUnimplemented)\n        #endif\n    }\n}\n\nextension VsockAddress {\n    public func withSockAddr<T>(_ body: (UnsafePointer<sockaddr>, Int) throws -> T) rethrows -> T {\n        #if canImport(Darwin) || os(Linux) || os(Android)\n        return try self.address.withSockAddr({ try body($0, $1) })\n        #else\n        fatalError(vsockUnimplemented)\n        #endif\n    }\n}\n\n// MARK: - Internal functions that are only available on supported platforms.\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nextension VsockAddress.ContextID {\n    /// Get the context ID of the local machine.\n    ///\n    /// - Parameters:\n    ///   - socketFD: the file descriptor for the open socket.\n    ///\n    /// This function wraps the `IOCTL_VM_SOCKETS_GET_LOCAL_CID` `ioctl()` request.\n    ///\n    /// To provide a consistent API on Linux and Darwin, this API takes a socket parameter, which is unused on Linux:\n    ///\n    /// - On Darwin, the `ioctl()` request operates on a socket.\n    /// - On Linux, the `ioctl()` request operates on the `/dev/vsock` device.\n    ///\n    /// - Note: The semantics of this `ioctl` vary between vsock transports on Linux; ``local`` may be more suitable.\n    static func getLocalContextID(_ socketFD: NIOBSDSocket.Handle) throws -> Self {\n        #if canImport(Darwin)\n        let request = CNIODarwin_IOCTL_VM_SOCKETS_GET_LOCAL_CID\n        let fd = socketFD\n        #elseif os(Linux) || os(Android)\n        let request = CNIOLinux_IOCTL_VM_SOCKETS_GET_LOCAL_CID\n        let fd = try Posix.open(file: \"/dev/vsock\", oFlag: O_RDONLY | O_CLOEXEC)\n        defer { try! Posix.close(descriptor: fd) }\n        #endif\n        var cid = Self.any.rawValue\n        try Posix.ioctl(fd: fd, request: request, ptr: &cid)\n        return Self(rawValue: cid)\n    }\n}\n\nextension sockaddr_vm {\n    func withSockAddr<R>(_ body: (UnsafePointer<sockaddr>, Int) throws -> R) rethrows -> R {\n        try withUnsafeBytes(of: self) { p in\n            try body(p.baseAddress!.assumingMemoryBound(to: sockaddr.self), p.count)\n        }\n    }\n}\n\nextension VsockAddress {\n    /// The libc socket address for a vsock socket.\n    var address: sockaddr_vm {\n        var addr = sockaddr_vm()\n        addr.svm_family = sa_family_t(NIOBSDSocket.AddressFamily.vsock.rawValue)\n        addr.svm_cid = self.cid.rawValue\n        addr.svm_port = self.port.rawValue\n        return addr\n    }\n}\n\nextension sockaddr_storage {\n    /// Converts the `socketaddr_storage` to a `sockaddr_vm`.\n    ///\n    /// This will crash if `ss_family` != AF_VSOCK!\n    func convert() -> sockaddr_vm {\n        precondition(self.ss_family == NIOBSDSocket.AddressFamily.vsock.rawValue)\n        return withUnsafeBytes(of: self) {\n            $0.load(as: sockaddr_vm.self)\n        }\n    }\n}\n\nextension BaseSocket {\n    func bind(to address: VsockAddress) throws {\n        try self.withUnsafeHandle { fd in\n            try address.withSockAddr {\n                try NIOBSDSocket.bind(socket: fd, address: $0, address_len: socklen_t($1))\n            }\n        }\n    }\n\n    func getLocalVsockContextID() throws -> VsockAddress.ContextID {\n        try self.withUnsafeHandle { fd in\n            try VsockAddress.ContextID.getLocalContextID(fd)\n        }\n    }\n}\n\n#endif  // canImport(Darwin) || os(Linux) || os(Android)\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/VsockChannelEvents.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\nimport NIOCore\n\npublic enum VsockChannelEvents: Sendable {\n    /// Fired as an outbound event when NIO would like to ask itself to bind the socket.\n    ///\n    /// This flow for connect is required because we cannot extend `enum SocketAddress` without\n    /// breaking public API.\n    public struct BindToAddress: Hashable, Sendable {\n        public var address: VsockAddress\n\n        public init(_ address: VsockAddress) {\n            self.address = address\n        }\n    }\n\n    /// Fired as an outbound event when NIO would like to ask itself to connect the socket.\n    ///\n    /// This flow for connect is required because we cannot extend `enum SocketAddress` without\n    /// breaking public API.\n    public struct ConnectToAddress: Hashable, Sendable {\n        public var address: VsockAddress\n\n        public init(_ address: VsockAddress) {\n            self.address = address\n        }\n    }\n}\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOPosix/Windows.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if !os(WASI)\n\n#if os(Windows)\nimport NIOCore\nimport WinSDK\nimport CNIOWindows\n\ntypealias ssize_t = SSIZE_T\n\nlet missingPipeSupportWindows = \"Unimplemented: NIOPosix does not support PipeChannel on Windows\"\n\n// overwrite the windows write method, as the one without underscore is deprecated.\n// also we can use this to downcast the count Int to UInt32\nfunc write(_ fd: Int32, _ ptr: UnsafeRawPointer?, _ count: Int) -> Int32 {\n    _write(fd, ptr, UInt32(clamping: count))\n}\n\nvar errno: Int32 {\n    CNIOWindows_errno()\n}\n\nextension NIOCore.Windows {\n    /// Call this to get a string representation from an error code that was returned from `GetLastError`.\n    static func makeErrorMessageFromCode(_ errorCode: DWORD) -> String? {\n        var errorMsg = UnsafeMutablePointer<CHAR>?.none\n        CNIOWindows_FormatGetLastError(errorCode, &errorMsg)\n\n        if let errorMsg {\n            let result = String(cString: errorMsg)\n            LocalFree(errorMsg)\n            return result\n        } else {\n            // we could check GetLastError here again. But that feels quite recursive.\n            return nil\n        }\n    }\n\n    static func recv(\n        socket: SOCKET,\n        pointer: UnsafeMutableRawPointer,\n        size: Int32,\n        flags: Int32\n    ) throws -> IOResult<Int> {\n        let result = WinSDK.recv(socket, pointer.assumingMemoryBound(to: CChar.self), size, flags)\n        if result == WinSDK.SOCKET_ERROR {\n            throw IOError(winsock: WSAGetLastError(), reason: \"accept\")\n        }\n        return .processed(Int(result))\n    }\n\n    static func pread(\n        descriptor: CInt,\n        pointer: UnsafeMutableRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<ssize_t> {\n        var overlapped = OVERLAPPED()\n        // off_t is Int32 anyway. Therefore high is always zero.\n        precondition(off_t.self == Int32.self)\n        overlapped.OffsetHigh = 0\n        overlapped.Offset = UInt32(offset)\n\n        let file = HANDLE(bitPattern: _get_osfhandle(descriptor))\n        SetLastError(0)\n        var readBytes: DWORD = 0\n        let clampedSize = UInt32(clamping: size)\n        let rf = ReadFile(file, pointer, clampedSize, &readBytes, &overlapped)\n        let lastError = GetLastError()\n        if rf == false && lastError != ERROR_HANDLE_EOF {\n            throw IOError(errnoCode: Self.windowsErrorToPosixErrno(lastError), reason: \"pread\")\n        }\n        return .processed(Int64(readBytes))\n    }\n\n    static func pwrite(\n        descriptor: CInt,\n        pointer: UnsafeRawPointer,\n        size: size_t,\n        offset: off_t\n    ) throws -> IOResult<ssize_t> {\n        var overlapped = OVERLAPPED()\n        // off_t is Int32 anyway. Therefore high is always zero.\n        precondition(off_t.self == Int32.self)\n        overlapped.OffsetHigh = 0\n        overlapped.Offset = UInt32(offset)\n\n        let file = HANDLE(bitPattern: _get_osfhandle(descriptor))\n        SetLastError(0)\n        var writtenBytes: DWORD = 0\n        let clampedSize = UInt32(clamping: size)\n        if !WriteFile(file, pointer, clampedSize, &writtenBytes, &overlapped) {\n            throw IOError(errnoCode: Self.windowsErrorToPosixErrno(GetLastError()), reason: \"pwrite\")\n        }\n        return .processed(Int64(writtenBytes))\n    }\n\n    private static func windowsErrorToPosixErrno(_ dwError: DWORD) -> Int32 {\n        switch Int32(dwError) {\n        case ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND:\n            return ENOENT\n        case ERROR_TOO_MANY_OPEN_FILES:\n            return EMFILE\n        case ERROR_ACCESS_DENIED:\n            return EACCES\n        case ERROR_INVALID_HANDLE:\n            return EBADF\n        case ERROR_NOT_ENOUGH_MEMORY, ERROR_OUTOFMEMORY:\n            return ENOMEM\n        case ERROR_NOT_READY, ERROR_CRC:\n            return EIO\n        case ERROR_SHARING_VIOLATION, ERROR_LOCK_VIOLATION:\n            return EBUSY\n        case ERROR_HANDLE_EOF:\n            return 0\n        case ERROR_BROKEN_PIPE:\n            return EPIPE\n        default:\n            return EINVAL\n        }\n    }\n}\n\n#endif\n#endif  // !os(WASI)\n"
  },
  {
    "path": "Sources/NIOTCPEchoClient/Client.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\n@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)\n@main\nstruct Client {\n    /// The host to connect to.\n    private let host: String\n    /// The port to connect to.\n    private let port: Int\n    /// The client's event loop group.\n    private let eventLoopGroup: MultiThreadedEventLoopGroup\n\n    static func main() async throws {\n        let client = Client(\n            host: \"localhost\",\n            port: 8765,\n            eventLoopGroup: .singleton\n        )\n        try await client.run()\n    }\n\n    /// This method sends a bunch of requests.\n    func run() async throws {\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            for i in 0...20 {\n                group.addTask {\n                    try await self.sendRequest(number: i)\n                }\n            }\n\n            try await group.waitForAll()\n        }\n    }\n\n    private func sendRequest(number: Int) async throws {\n        let channel = try await ClientBootstrap(group: self.eventLoopGroup)\n            .connect(\n                host: self.host,\n                port: self.port\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    // We are using two simple handlers here to frame our messages with \"\\n\"\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(NewlineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(NewlineDelimiterCoder()))\n\n                    return try NIOAsyncChannel(\n                        wrappingChannelSynchronously: channel,\n                        configuration: NIOAsyncChannel.Configuration(\n                            inboundType: String.self,\n                            outboundType: String.self\n                        )\n                    )\n                }\n            }\n\n        try await channel.executeThenClose { inbound, outbound in\n            print(\"Connection(\\(number)): Writing request\")\n            try await outbound.write(\"Hello on connection \\(number)\")\n\n            for try await inboundData in inbound {\n                print(\"Connection(\\(number)): Received response (\\(inboundData))\")\n\n                // We only expect a single response so we can exit here.\n                // Once, we exit out of this loop and the references to the `NIOAsyncChannel` are dropped\n                // the connection is going to close itself.\n                break\n            }\n        }\n    }\n}\n\n/// A simple newline based encoder and decoder.\nprivate final class NewlineDelimiterCoder: ByteToMessageDecoder, MessageToByteEncoder {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = String\n\n    private let newLine = UInt8(ascii: \"\\n\")\n\n    init() {}\n\n    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        let readableBytes = buffer.readableBytesView\n\n        if let firstLine = readableBytes.firstIndex(of: self.newLine).map({ readableBytes[..<$0] }) {\n            buffer.moveReaderIndex(forwardBy: firstLine.count + 1)\n            // Fire a read without a newline\n            context.fireChannelRead(Self.wrapInboundOut(String(buffer: ByteBuffer(firstLine))))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n\n    func encode(data: String, out: inout ByteBuffer) throws {\n        out.writeString(data)\n        out.writeInteger(self.newLine)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOTCPEchoClient/README.md",
    "content": "# NIOTCPEchoClient\n\nThis sample application provides a simple TCP echo client that will send multiple messages to an\necho server and wait for a response of all of them. Before running this client, make sure to start\nthe `NIOTCPEchoServer`.\n\nTo run this client execute the following from the root of the repository:\n\n```bash\nswift run NIOTCPEchoClient\n```\n"
  },
  {
    "path": "Sources/NIOTCPEchoServer/README.md",
    "content": "# NIOTCPEchoServer\n\nThis sample application provides a simple TCP server that sends clients back whatever they send it.\n\nTo run this server execute the following from the root of the repository:\n\n```bash\nswift run NIOTCPEchoServer\n```\n\nYou can then use the `NIOTCPEchoClient` to send requests to the server.\n"
  },
  {
    "path": "Sources/NIOTCPEchoServer/Server.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOPosix\n\n@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)\n@main\nstruct Server {\n    /// The server's host.\n    private let host: String\n    /// The server's port.\n    private let port: Int\n    /// The server's event loop group.\n    private let eventLoopGroup: MultiThreadedEventLoopGroup\n\n    static func main() async throws {\n        let server = Server(\n            host: \"localhost\",\n            port: 8765,\n            eventLoopGroup: .singleton\n        )\n        try await server.run()\n    }\n\n    /// This method starts the server and handles incoming connections.\n    func run() async throws {\n        let channel = try await ServerBootstrap(group: self.eventLoopGroup)\n            .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n            .bind(\n                host: self.host,\n                port: self.port\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    // We are using two simple handlers here to frame our messages with \"\\n\"\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(NewlineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(NewlineDelimiterCoder()))\n\n                    return try NIOAsyncChannel(\n                        wrappingChannelSynchronously: channel,\n                        configuration: NIOAsyncChannel.Configuration(\n                            inboundType: String.self,\n                            outboundType: String.self\n                        )\n                    )\n                }\n            }\n\n        // We are handling each incoming connection in a separate child task. It is important\n        // to use a discarding task group here which automatically discards finished child tasks.\n        // A normal task group retains all child tasks and their outputs in memory until they are\n        // consumed by iterating the group or by exiting the group. Since, we are never consuming\n        // the results of the group we need the group to automatically discard them; otherwise, this\n        // would result in a memory leak over time.\n        try await withThrowingDiscardingTaskGroup { group in\n            try await channel.executeThenClose { inbound in\n                for try await connectionChannel in inbound {\n                    group.addTask {\n                        print(\"Handling new connection\")\n                        await self.handleConnection(channel: connectionChannel)\n                        print(\"Done handling connection\")\n                    }\n                }\n            }\n        }\n    }\n\n    /// This method handles a single connection by echoing back all inbound data.\n    private func handleConnection(channel: NIOAsyncChannel<String, String>) async {\n        // Note that this method is non-throwing and we are catching any error.\n        // We do this since we don't want to tear down the whole server when a single connection\n        // encounters an error.\n        do {\n            try await channel.executeThenClose { inbound, outbound in\n                for try await inboundData in inbound {\n                    print(\"Received request (\\(inboundData))\")\n                    try await outbound.write(inboundData)\n                }\n            }\n        } catch {\n            print(\"Hit error: \\(error)\")\n        }\n    }\n}\n\n/// A simple newline based encoder and decoder.\nprivate final class NewlineDelimiterCoder: ByteToMessageDecoder, MessageToByteEncoder {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = String\n\n    private let newLine = UInt8(ascii: \"\\n\")\n\n    init() {}\n\n    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        let readableBytes = buffer.readableBytesView\n\n        if let firstLine = readableBytes.firstIndex(of: self.newLine).map({ readableBytes[..<$0] }) {\n            buffer.moveReaderIndex(forwardBy: firstLine.count + 1)\n            // Fire a read without a newline\n            context.fireChannelRead(Self.wrapInboundOut(String(buffer: ByteBuffer(firstLine))))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n\n    func encode(data: String, out: inout ByteBuffer) throws {\n        out.writeString(data)\n        out.writeInteger(self.newLine)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOTLS/ApplicationProtocolNegotiationHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// The result of an ALPN negotiation.\n///\n/// In a system expecting an ALPN negotiation to occur, a wide range of\n/// possible things can happen. In the best case scenario it is possible for\n/// the server and client to agree on a protocol to speak, in which case this\n/// will be `.negotiated` with the relevant protocol provided as the associated\n/// value. However, if for any reason it was not possible to negotiate a\n/// protocol, whether because one peer didn't support ALPN or because there was no\n/// protocol overlap, we should `fallback` to a default choice of some kind.\n///\n/// Exactly what to do when falling back is the responsibility of a specific\n/// implementation.\npublic enum ALPNResult: Equatable, Sendable {\n    /// ALPN negotiation succeeded. The associated value is the ALPN token that\n    /// was negotiated.\n    case negotiated(String)\n\n    /// ALPN negotiation either failed, or never took place. The application\n    /// should fall back to a default protocol choice or close the connection.\n    case fallback\n\n    init(negotiated: String?) {\n        if let negotiated = negotiated {\n            self = .negotiated(negotiated)\n        } else {\n            self = .fallback\n        }\n    }\n}\n\n/// A helper `ChannelInboundHandler` that makes it easy to swap channel pipelines\n/// based on the result of an ALPN negotiation.\n///\n/// The standard pattern used by applications that want to use ALPN is to select\n/// an application protocol based on the result, optionally falling back to some\n/// default protocol. To do this in SwiftNIO requires that the channel pipeline be\n/// reconfigured based on the result of the ALPN negotiation. This channel handler\n/// encapsulates that logic in a generic form that doesn't depend on the specific\n/// TLS implementation in use by using `TLSUserEvent`\n///\n/// The user of this channel handler provides a single closure that is called with\n/// an `ALPNResult` when the ALPN negotiation is complete. Based on that result\n/// the user is free to reconfigure the `ChannelPipeline` as required, and should\n/// return an `EventLoopFuture` that will complete when the pipeline is reconfigured.\n///\n/// Until the `EventLoopFuture` completes, this channel handler will buffer inbound\n/// data. When the `EventLoopFuture` completes, the buffered data will be replayed\n/// down the channel. Then, finally, this channel handler will automatically remove\n/// itself from the channel pipeline, leaving the pipeline in its final\n/// configuration.\npublic final class ApplicationProtocolNegotiationHandler: ChannelInboundHandler, RemovableChannelHandler {\n    public typealias InboundIn = Any\n    public typealias InboundOut = Any\n\n    private let completionHandler: (ALPNResult, Channel) -> EventLoopFuture<Void>\n    private var stateMachine = ProtocolNegotiationHandlerStateMachine<Void>()\n\n    /// Create an `ApplicationProtocolNegotiationHandler` with the given completion\n    /// callback.\n    ///\n    /// - Parameter alpnCompleteHandler: The closure that will fire when ALPN\n    ///   negotiation has completed.\n    public init(alpnCompleteHandler: @escaping (ALPNResult, Channel) -> EventLoopFuture<Void>) {\n        self.completionHandler = alpnCompleteHandler\n    }\n\n    /// Create an `ApplicationProtocolNegotiationHandler` with the given completion\n    /// callback.\n    ///\n    /// - Parameter alpnCompleteHandler: The closure that will fire when ALPN\n    ///   negotiation has completed.\n    public convenience init(alpnCompleteHandler: @escaping (ALPNResult) -> EventLoopFuture<Void>) {\n        self.init { result, _ in\n            alpnCompleteHandler(result)\n        }\n    }\n\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch self.stateMachine.userInboundEventTriggered(event: event) {\n        case .fireUserInboundEventTriggered:\n            context.fireUserInboundEventTriggered(event)\n\n        case .invokeUserClosure(let result):\n            self.invokeUserClosure(context: context, result: result)\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch self.stateMachine.channelRead(data: data) {\n        case .fireChannelRead:\n            context.fireChannelRead(data)\n\n        case .none:\n            break\n        }\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        self.stateMachine.channelInactive()\n\n        context.fireChannelInactive()\n    }\n\n    private func invokeUserClosure(context: ChannelHandlerContext, result: ALPNResult) {\n        let switchFuture = self.completionHandler(result, context.channel)\n        let loopBoundSelfAndContext = NIOLoopBound((self, context), eventLoop: context.eventLoop)\n\n        switchFuture\n            .hop(to: context.eventLoop)\n            .whenComplete { result in\n                let (`self`, context) = loopBoundSelfAndContext.value\n                self.userFutureCompleted(context: context, result: result)\n            }\n    }\n\n    private func userFutureCompleted(context: ChannelHandlerContext, result: Result<Void, Error>) {\n        context.eventLoop.assertInEventLoop()\n\n        switch self.stateMachine.userFutureCompleted(with: result) {\n        case .fireErrorCaughtAndRemoveHandler(let error):\n            context.fireErrorCaught(error)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .fireErrorCaughtAndStartUnbuffering(let error):\n            context.fireErrorCaught(error)\n            self.unbuffer(context: context)\n\n        case .startUnbuffering:\n            self.unbuffer(context: context)\n\n        case .removeHandler:\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .none:\n            break\n        }\n    }\n\n    private func unbuffer(context: ChannelHandlerContext) {\n        context.eventLoop.assertInEventLoop()\n\n        while true {\n            switch self.stateMachine.unbuffer() {\n            case .fireChannelRead(let data):\n                context.fireChannelRead(data)\n\n            case .fireChannelReadCompleteAndRemoveHandler:\n                context.fireChannelReadComplete()\n                context.pipeline.syncOperations.removeHandler(self, promise: nil)\n                return\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension ApplicationProtocolNegotiationHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOTLS/NIOTypedApplicationProtocolNegotiationHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// A helper `ChannelInboundHandler` that makes it easy to swap channel pipelines\n/// based on the result of an ALPN negotiation.\n///\n/// The standard pattern used by applications that want to use ALPN is to select\n/// an application protocol based on the result, optionally falling back to some\n/// default protocol. To do this in SwiftNIO requires that the channel pipeline be\n/// reconfigured based on the result of the ALPN negotiation. This channel handler\n/// encapsulates that logic in a generic form that doesn't depend on the specific\n/// TLS implementation in use by using ``TLSUserEvent``\n///\n/// The user of this channel handler provides a single closure that is called with\n/// an ``ALPNResult`` when the ALPN negotiation is complete. Based on that result\n/// the user is free to reconfigure the `ChannelPipeline` as required, and should\n/// return an `EventLoopFuture` that will complete when the pipeline is reconfigured.\n///\n/// Until the `EventLoopFuture` completes, this channel handler will buffer inbound\n/// data. When the `EventLoopFuture` completes, the buffered data will be replayed\n/// down the channel. Then, finally, this channel handler will automatically remove\n/// itself from the channel pipeline, leaving the pipeline in its final\n/// configuration.\n///\n/// Importantly, this is a typed variant of the ``ApplicationProtocolNegotiationHandler`` and allows the user to\n/// specify a type that must be returned from the supplied closure. The result will then be used to succeed the ``NIOTypedApplicationProtocolNegotiationHandler/protocolNegotiationResult``\n/// promise. This allows us to construct pipelines that include protocol negotiation handlers and be able to bridge them into `NIOAsyncChannel`\n/// based bootstraps.\n@preconcurrency\npublic final class NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult: Sendable>: ChannelInboundHandler,\n    RemovableChannelHandler\n{\n    public typealias InboundIn = Any\n\n    public typealias InboundOut = Any\n\n    public var protocolNegotiationResult: EventLoopFuture<NegotiationResult> {\n        self.negotiatedPromise.futureResult\n    }\n\n    private var negotiatedPromise: EventLoopPromise<NegotiationResult> {\n        precondition(\n            self._negotiatedPromise != nil,\n            \"Tried to access the protocol negotiation result before the handler was added to a pipeline\"\n        )\n        return self._negotiatedPromise!\n    }\n    private var _negotiatedPromise: EventLoopPromise<NegotiationResult>?\n\n    private let completionHandler: (ALPNResult, Channel) -> EventLoopFuture<NegotiationResult>\n    private var stateMachine = ProtocolNegotiationHandlerStateMachine<NegotiationResult>()\n\n    /// Create an `ApplicationProtocolNegotiationHandler` with the given completion\n    /// callback.\n    ///\n    /// - Parameter alpnCompleteHandler: The closure that will fire when ALPN\n    ///   negotiation has completed.\n    public init(alpnCompleteHandler: @escaping (ALPNResult, Channel) -> EventLoopFuture<NegotiationResult>) {\n        self.completionHandler = alpnCompleteHandler\n    }\n\n    /// Create an `ApplicationProtocolNegotiationHandler` with the given completion\n    /// callback.\n    ///\n    /// - Parameter alpnCompleteHandler: The closure that will fire when ALPN\n    ///   negotiation has completed.\n    public convenience init(alpnCompleteHandler: @escaping (ALPNResult) -> EventLoopFuture<NegotiationResult>) {\n        self.init { result, _ in\n            alpnCompleteHandler(result)\n        }\n    }\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self._negotiatedPromise = context.eventLoop.makePromise()\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        switch self.stateMachine.handlerRemoved() {\n        case .failPromise:\n            self.negotiatedPromise.fail(ChannelError.inappropriateOperationForState)\n\n        case .none:\n            break\n        }\n    }\n\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch self.stateMachine.userInboundEventTriggered(event: event) {\n        case .fireUserInboundEventTriggered:\n            context.fireUserInboundEventTriggered(event)\n\n        case .invokeUserClosure(let result):\n            self.invokeUserClosure(context: context, result: result)\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch self.stateMachine.channelRead(data: data) {\n        case .fireChannelRead:\n            context.fireChannelRead(data)\n\n        case .none:\n            break\n        }\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        self.stateMachine.channelInactive()\n\n        self.negotiatedPromise.fail(ChannelError.outputClosed)\n        context.fireChannelInactive()\n    }\n\n    private func invokeUserClosure(context: ChannelHandlerContext, result: ALPNResult) {\n        let switchFuture = self.completionHandler(result, context.channel)\n        let loopBoundSelfAndContext = NIOLoopBound((self, context), eventLoop: context.eventLoop)\n\n        switchFuture\n            .hop(to: context.eventLoop)\n            .whenComplete { result in\n                let (`self`, context) = loopBoundSelfAndContext.value\n                self.userFutureCompleted(context: context, result: result)\n            }\n    }\n\n    private func userFutureCompleted(context: ChannelHandlerContext, result: Result<NegotiationResult, Error>) {\n        switch self.stateMachine.userFutureCompleted(with: result) {\n        case .fireErrorCaughtAndRemoveHandler(let error):\n            self.negotiatedPromise.fail(error)\n            context.fireErrorCaught(error)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .fireErrorCaughtAndStartUnbuffering(let error):\n            self.negotiatedPromise.fail(error)\n            context.fireErrorCaught(error)\n            self.unbuffer(context: context)\n\n        case .startUnbuffering(let value):\n            self.negotiatedPromise.succeed(value)\n            self.unbuffer(context: context)\n\n        case .removeHandler(let value):\n            self.negotiatedPromise.succeed(value)\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n\n        case .none:\n            break\n        }\n    }\n\n    private func unbuffer(context: ChannelHandlerContext) {\n        while true {\n            switch self.stateMachine.unbuffer() {\n            case .fireChannelRead(let data):\n                context.fireChannelRead(data)\n\n            case .fireChannelReadCompleteAndRemoveHandler:\n                context.fireChannelReadComplete()\n                context.pipeline.syncOperations.removeHandler(self, promise: nil)\n                return\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension NIOTypedApplicationProtocolNegotiationHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOTLS/ProtocolNegotiationHandlerStateMachine.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOCore\n\nstruct ProtocolNegotiationHandlerStateMachine<NegotiationResult> {\n    enum State {\n        /// The state before we received a TLSUserEvent. We are just forwarding any read at this point.\n        case initial\n        /// The state after we received a ``TLSUserEvent`` and are waiting for the future of the user to complete.\n        case waitingForUser(buffer: Deque<NIOAny>)\n        /// The state after the users future finished and we are unbuffering all the reads.\n        case unbuffering(buffer: Deque<NIOAny>)\n        /// The state once the negotiation is done and we are finished with unbuffering.\n        case finished\n    }\n\n    private var state = State.initial\n\n    @usableFromInline\n    enum HandlerRemovedAction {\n        case failPromise\n    }\n\n    @inlinable\n    mutating func handlerRemoved() -> HandlerRemovedAction? {\n        switch self.state {\n        case .initial, .waitingForUser, .unbuffering:\n            return .failPromise\n\n        case .finished:\n            return .none\n        }\n    }\n\n    @usableFromInline\n    enum UserInboundEventTriggeredAction {\n        case fireUserInboundEventTriggered\n        case invokeUserClosure(ALPNResult)\n    }\n\n    @inlinable\n    mutating func userInboundEventTriggered(event: Any) -> UserInboundEventTriggeredAction {\n        if case .handshakeCompleted(let negotiated) = event as? TLSUserEvent {\n            switch self.state {\n            case .initial:\n                self.state = .waitingForUser(buffer: .init())\n\n                return .invokeUserClosure(.init(negotiated: negotiated))\n            case .waitingForUser, .unbuffering:\n                preconditionFailure(\"Unexpectedly received two TLSUserEvents\")\n\n            case .finished:\n                // This is weird but we can tolerate it and just forward the event\n                return .fireUserInboundEventTriggered\n            }\n        } else {\n            return .fireUserInboundEventTriggered\n        }\n    }\n\n    @usableFromInline\n    enum ChannelReadAction {\n        case fireChannelRead\n    }\n\n    @inlinable\n    mutating func channelRead(data: NIOAny) -> ChannelReadAction? {\n        switch self.state {\n        case .initial, .finished:\n            return .fireChannelRead\n\n        case .waitingForUser(var buffer):\n            buffer.append(data)\n            self.state = .waitingForUser(buffer: buffer)\n\n            return .none\n\n        case .unbuffering(var buffer):\n            buffer.append(data)\n            self.state = .unbuffering(buffer: buffer)\n\n            return .none\n        }\n    }\n\n    @usableFromInline\n    enum UserFutureCompletedAction {\n        case fireErrorCaughtAndRemoveHandler(Error)\n        case fireErrorCaughtAndStartUnbuffering(Error)\n        case startUnbuffering(NegotiationResult)\n        case removeHandler(NegotiationResult)\n    }\n\n    @inlinable\n    mutating func userFutureCompleted(with result: Result<NegotiationResult, Error>) -> UserFutureCompletedAction? {\n        switch self.state {\n        case .initial:\n            preconditionFailure(\"Invalid state \\(self.state)\")\n\n        case .waitingForUser(let buffer):\n\n            switch result {\n            case .success(let value):\n                if !buffer.isEmpty {\n                    self.state = .unbuffering(buffer: buffer)\n                    return .startUnbuffering(value)\n                } else {\n                    self.state = .finished\n                    return .removeHandler(value)\n                }\n\n            case .failure(let error):\n                if !buffer.isEmpty {\n                    self.state = .unbuffering(buffer: buffer)\n                    return .fireErrorCaughtAndStartUnbuffering(error)\n                } else {\n                    self.state = .finished\n                    return .fireErrorCaughtAndRemoveHandler(error)\n                }\n            }\n\n        case .unbuffering:\n            preconditionFailure(\"Invalid state \\(self.state)\")\n\n        case .finished:\n            // It might be that the user closed the channel in his closure. We have to tolerate this.\n            return .none\n        }\n    }\n\n    @usableFromInline\n    enum UnbufferAction {\n        case fireChannelRead(NIOAny)\n        case fireChannelReadCompleteAndRemoveHandler\n    }\n\n    @inlinable\n    mutating func unbuffer() -> UnbufferAction {\n        switch self.state {\n        case .initial, .waitingForUser, .finished:\n            preconditionFailure(\"Invalid state \\(self.state)\")\n\n        case .unbuffering(var buffer):\n            if let element = buffer.popFirst() {\n                self.state = .unbuffering(buffer: buffer)\n\n                return .fireChannelRead(element)\n            } else {\n                self.state = .finished\n\n                return .fireChannelReadCompleteAndRemoveHandler\n            }\n        }\n    }\n\n    @inlinable\n    mutating func channelInactive() {\n        switch self.state {\n        case .initial, .unbuffering, .waitingForUser:\n            self.state = .finished\n\n        case .finished:\n            break\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOTLS/SNIHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// The length of the TLS record header in bytes.\nprivate let tlsRecordHeaderLength = 5\n\n/// The content type identifier for a TLS handshake record.\nprivate let tlsContentTypeHandshake: UInt8 = 22\n\n/// The handshake type identifier for ClientHello records.\nprivate let handshakeTypeClientHello: UInt8 = 1\n\n/// The extension type for the SNI extension.\nprivate let sniExtensionType: UInt16 = 0\n\n/// The ServerName type for DNS host names.\nprivate let sniHostNameType: UInt8 = 0\n\n/// The result of the SNI parsing. If `hostname`, then the enum also\n/// contains the hostname received in the SNI extension. If `fallback`,\n/// then either we could not parse the SNI extension or it was not there\n/// at all.\npublic enum SNIResult: Equatable, Sendable {\n    case fallback\n    case hostname(String)\n}\n\nprivate enum InternalSNIErrors: Error {\n    case invalidLengthInRecord\n    case invalidRecord\n    case recordIncomplete\n}\n\nextension ByteBuffer {\n    fileprivate mutating func moveReaderIndexIfPossible(forwardBy distance: Int) throws {\n        guard self.readableBytes >= distance else {\n            throw InternalSNIErrors.invalidLengthInRecord\n        }\n        self.moveReaderIndex(forwardBy: distance)\n    }\n\n    fileprivate mutating func readIntegerIfPossible<T: FixedWidthInteger>() throws -> T {\n        guard let integer: T = self.readInteger() else {\n            throw InternalSNIErrors.invalidLengthInRecord\n        }\n        return integer\n    }\n}\n\nextension Sequence where Element == UInt8 {\n    fileprivate func decodeStringValidatingASCII() -> String? {\n        var bytesIterator = self.makeIterator()\n        var scalars: [Unicode.Scalar] = []\n        scalars.reserveCapacity(self.underestimatedCount)\n        var decoder = Unicode.ASCII.Parser()\n        decode: while true {\n            switch decoder.parseScalar(from: &bytesIterator) {\n            case .valid(let v):\n                scalars.append(Unicode.Scalar(v[0]))\n            case .emptyInput:\n                break decode\n            case .error:\n                return nil\n            }\n        }\n        return String(scalars.map(Character.init))\n    }\n}\n\n/// A channel handler that can be used to arbitrarily edit a channel\n/// pipeline based on the hostname requested in the Server Name Indication\n/// portion of the TLS Client Hello.\n///\n/// This handler is most commonly used when configuring TLS, to control\n/// which certificates are going to be shown to the client. It can also be used\n/// to ensure that only the resources required to serve a given virtual host are\n/// actually present in the channel pipeline.\n///\n/// This handler does not depend on any specific TLS implementation. Instead, it parses\n/// the Client Hello itself, directly. This allows it to be generic across all possible\n/// TLS backends that can be used with NIO. It also allows for the pipeline change to\n/// be done asynchronously, providing more flexibility about how the user configures the\n/// pipeline.\npublic final class SNIHandler: ByteToMessageDecoder {\n    public var cumulationBuffer: Optional<ByteBuffer>\n    public typealias InboundIn = ByteBuffer\n    public typealias InboundOut = ByteBuffer\n\n    private let completionHandler: (SNIResult) -> EventLoopFuture<Void>\n    private var waitingForUser: Bool\n\n    public init(sniCompleteHandler: @escaping (SNIResult) -> EventLoopFuture<Void>) {\n        self.cumulationBuffer = nil\n        self.completionHandler = sniCompleteHandler\n        self.waitingForUser = false\n    }\n\n    public func decodeLast(\n        context: ChannelHandlerContext,\n        buffer: inout ByteBuffer,\n        seenEOF: Bool\n    ) throws -> DecodingState {\n        context.fireChannelRead(NIOAny(buffer))\n        return .needMoreData\n    }\n\n    // A note to maintainers: this method *never* returns `.continue`.\n    public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) -> DecodingState {\n        // If we've asked the user to mutate the pipeline already, we're not interested in\n        // this data. Keep waiting.\n        if waitingForUser {\n            return .needMoreData\n        }\n\n        let serverName: String?\n        do {\n            serverName = try parseTLSDataForServerName(buffer: buffer)\n        } catch InternalSNIErrors.recordIncomplete {\n            // Nothing bad here, we just don't have enough data.\n            return .needMoreData\n        } catch {\n            // Some error occurred. Fall back and let the TLS stack\n            // handle it.\n            sniComplete(result: .fallback, context: context)\n            return .needMoreData\n        }\n\n        if let serverName = serverName {\n            sniComplete(result: .hostname(serverName), context: context)\n        } else {\n            sniComplete(result: .fallback, context: context)\n        }\n        return .needMoreData\n    }\n\n    /// Given a buffer of data that may contain a TLS Client Hello, parses the buffer looking for\n    /// a server name extension. If it can be found, returns the host name in that extension. If\n    /// no host name or extension is present, returns nil. If an error is encountered, throws. If\n    /// there is not enough data in the buffer yet, throws recordIncomplete.\n    private func parseTLSDataForServerName(buffer: ByteBuffer) throws -> String? {\n        // We're taking advantage of value semantics here: this copy of the buffer will reference\n        // the same underlying storage as the one we were passed, but any changes to it will not\n        // be reflected in the outer buffer. That saves us from needing to maintain offsets\n        // manually in this code. Thanks, Swift!\n        var tempBuffer = buffer\n\n        // First, parse the header.\n        let contentLength = try parseRecordHeader(buffer: &tempBuffer)\n        guard tempBuffer.readableBytes >= contentLength else {\n            throw InternalSNIErrors.recordIncomplete\n        }\n\n        // At this point we know we have enough, at least according to the outer layer. We now want to\n        // take a slice of our temp buffer so that we can make confident assertions about\n        // all of the length. This also prevents us messing stuff up.\n        //\n        // From this point onwards if we don't have enough data to satisfy a read, this is an error and\n        // we will fall back to let the upper layers handle it.\n\n        // length check above\n        tempBuffer = tempBuffer.getSlice(at: tempBuffer.readerIndex, length: Int(contentLength))!\n\n        // Now parse the handshake header. If the length of the handshake message is not exactly the\n        // length of this record, something has gone wrong and we should give up.\n        let handshakeLength = try parseHandshakeHeader(buffer: &tempBuffer)\n        guard tempBuffer.readableBytes == handshakeLength else {\n            throw InternalSNIErrors.invalidRecord\n        }\n\n        // Now parse the client hello header. If the remaining length, which should be entirely extensions,\n        // is not exactly the length of this record, something has gone wrong and we should give up.\n        let extensionsLength = try parseClientHelloHeader(buffer: &tempBuffer)\n        guard tempBuffer.readableBytes == extensionsLength else {\n            throw InternalSNIErrors.invalidLengthInRecord\n        }\n\n        return try parseExtensionsForServerName(buffer: &tempBuffer)\n    }\n\n    /// Parses the TLS Record Header, ensuring that this is a handshake record and that\n    /// the basics of the data appear to be correct.\n    ///\n    /// Returns the content-length of the record.\n    private func parseRecordHeader(buffer: inout ByteBuffer) throws -> Int {\n        // First, the obvious check: are there enough bytes for us to parse a complete\n        // header? Because of this check we can use unsafe integer reads in the rest of\n        // this function, as we'll only ever read tlsRecordHeaderLength number of bytes\n        // here.\n        guard buffer.readableBytes >= tlsRecordHeaderLength else {\n            throw InternalSNIErrors.recordIncomplete\n        }\n\n        // Check the content type.\n        let contentType: UInt8 = buffer.readInteger()!  // length check above\n        guard contentType == tlsContentTypeHandshake else {\n            // Whatever this is, it's not a handshake message, so something has gone\n            // wrong. We're going to fall back to the default handler here and let\n            // that handler try to clean up this mess.\n            throw InternalSNIErrors.invalidRecord\n        }\n\n        // Now, check the major version.\n        let majorVersion: UInt8 = buffer.readInteger()!  // length check above\n        guard majorVersion == 3 else {\n            // A major version of 3 is the major version used for SSLv3 and all subsequent versions\n            // of the protocol. If that's not what this is, we don't know what's happening here.\n            // Again, let the default handler make sense of this.\n            throw InternalSNIErrors.invalidRecord\n        }\n\n        // Skip the minor version byte, then grab the content length.\n        buffer.moveReaderIndex(forwardBy: 1)\n        let contentLength: UInt16 = buffer.readInteger()!  // length check above\n        return Int(contentLength)\n    }\n\n    /// Parses the header of a TLS Handshake Record. Returns the expected number\n    /// of bytes in the handshake body, or throws if this is not a ClientHello or\n    /// has some other problem.\n    private func parseHandshakeHeader(buffer: inout ByteBuffer) throws -> Int {\n        // Ok, we're looking at a handshake message. That looks like this:\n        // (see https://tools.ietf.org/html/rfc5246#section-7.4).\n        //\n        //      struct {\n        //          HandshakeType msg_type;    /* handshake type */\n        //          uint24 length;             /* bytes in message */\n        //          select (HandshakeType) {\n        //              case hello_request:       HelloRequest;\n        //              case client_hello:        ClientHello;\n        //              case server_hello:        ServerHello;\n        //              case certificate:         Certificate;\n        //              case server_key_exchange: ServerKeyExchange;\n        //              case certificate_request: CertificateRequest;\n        //              case server_hello_done:   ServerHelloDone;\n        //              case certificate_verify:  CertificateVerify;\n        //              case client_key_exchange: ClientKeyExchange;\n        //              case finished:            Finished;\n        //          } body;\n        //      } Handshake;\n        //\n        // For the sake of our own happiness, we should check the handshake type and\n        // validate its length. uint24 is a stupid type, so we have to play some\n        // games here to get this to work. If we check that we have 4 bytes up-front\n        // we can use unsafe reads: fewer than 4 bytes makes this message bogus.\n        guard buffer.readableBytes >= 4 else {\n            throw InternalSNIErrors.invalidRecord\n        }\n\n        let handshakeTypeAndLength: UInt32 = buffer.readInteger()!\n        let handshakeType: UInt8 = UInt8((handshakeTypeAndLength & 0xFF00_0000) >> 24)\n        let handshakeLength: UInt32 = handshakeTypeAndLength & 0x00FF_FFFF\n        guard handshakeType == handshakeTypeClientHello else {\n            throw InternalSNIErrors.invalidRecord\n        }\n\n        return Int(handshakeLength)\n    }\n\n    /// Parses the header of the Client Hello record, and returns the total number of bytes\n    /// used for extensions, or throws if the header is invalid or corrupted in some way.\n    private func parseClientHelloHeader(buffer: inout ByteBuffer) throws -> Int {\n        // Ok dear reader, you've made it this far, now you get to see the true face of the\n        // ClientHello record. For context, this comes from\n        // https://tools.ietf.org/html/rfc5246#section-7.4.1.2\n        //\n        //      struct {\n        //          ProtocolVersion client_version;\n        //          Random random;\n        //          SessionID session_id;\n        //          CipherSuite cipher_suites<2..2^16-2>;\n        //          CompressionMethod compression_methods<1..2^8-1>;\n        //          select (extensions_present) {\n        //              case false:\n        //                  struct {};\n        //              case true:\n        //                  Extension extensions<0..2^16-1>;\n        //          };\n        //      } ClientHello;\n        //\n        // We want to go straight down to the extensions, but we can't do that because\n        // the SessionID, CipherSuite and CompressionMethod fields are variable length.\n        // So we skip to them, and then parse. The ProtocolVersion field is two bytes:\n        // the Random field is a 32-bit integer timestamp followed by a 28-byte array,\n        // totalling 32 bytes. All-in-all we want to skip forward 34 bytes.\n        // Unlike in other parsing methods we don't do an explicit length check here\n        // because we don't know how long these fields are supposed to be: all we do know\n        // is that the size of the ByteBuffer provides an upper bound on the size of this\n        // header, so we use safe reads which will throw if the buffer is too short.\n        try buffer.moveReaderIndexIfPossible(forwardBy: 34)\n\n        let sessionIDLength: UInt8 = try buffer.readIntegerIfPossible()\n        try buffer.moveReaderIndexIfPossible(forwardBy: Int(sessionIDLength))\n\n        let cipherSuitesLength: UInt16 = try buffer.readIntegerIfPossible()\n        try buffer.moveReaderIndexIfPossible(forwardBy: Int(cipherSuitesLength))\n\n        let compressionMethodLength: UInt8 = try buffer.readIntegerIfPossible()\n        try buffer.moveReaderIndexIfPossible(forwardBy: Int(compressionMethodLength))\n\n        // Ok, we're at the extensions! Return the length.\n        let extensionsLength: UInt16 = try buffer.readIntegerIfPossible()\n        return Int(extensionsLength)\n    }\n\n    /// Parses the extensions portion of a Client Hello looking for a ServerName extension.\n    /// Returns the host name in the ServerName extension, if any. If there is invalid data,\n    /// throws. If no host name can be found, either due to the ServerName extension not containing\n    /// one or due to no such extension being present, returns nil.\n    private func parseExtensionsForServerName(buffer: inout ByteBuffer) throws -> String? {\n        // The minimum number of bytes in an extension is 4: if we have fewer than that\n        // we're done.\n        while buffer.readableBytes >= 4 {\n            let extensionType: UInt16 = try buffer.readIntegerIfPossible()\n            let extensionLength: UInt16 = try buffer.readIntegerIfPossible()\n\n            guard buffer.readableBytes >= extensionLength else {\n                throw InternalSNIErrors.invalidLengthInRecord\n            }\n\n            guard extensionType == sniExtensionType else {\n                // Move forward by the length of this extension.\n                try buffer.moveReaderIndexIfPossible(forwardBy: Int(extensionLength))\n                continue\n            }\n\n            // We've found the server name extension. It's possible a malicious client could attempt a confused\n            // deputy attack by giving us contradictory lengths, so we again want to trim the bytebuffer down\n            // so that we never read past the advertised length of this extension.\n            buffer = buffer.getSlice(at: buffer.readerIndex, length: Int(extensionLength))!\n            return try parseServerNameExtension(buffer: &buffer)\n        }\n        return nil\n    }\n\n    /// Parses a ServerName extension and returns the host name contained within, if any. If the extension\n    /// is invalid for any reason, this will throw. If the extension does not contain a hostname, returns\n    /// nil.\n    private func parseServerNameExtension(buffer: inout ByteBuffer) throws -> String? {\n        // The format of the SNI extension is here: https://tools.ietf.org/html/rfc6066#page-6\n        //\n        //      struct {\n        //          NameType name_type;\n        //          select (name_type) {\n        //              case host_name: HostName;\n        //          } name;\n        //      } ServerName;\n        //\n        //      enum {\n        //          host_name(0), (255)\n        //      } NameType;\n        //\n        //      opaque HostName<1..2^16-1>;\n        //\n        //      struct {\n        //          ServerName server_name_list<1..2^16-1>\n        //      } ServerNameList;\n        //\n        // Note, however, that this is pretty academic. The SNI extension forbids multiple entries\n        // in the ServerNameList that have the same NameType. As only one NameType is defined, we\n        // could safely assume this list is one entry long.\n        //\n        // HOWEVER! It is a bad idea to write code that assumes that an extension point will\n        // never be used, so let's try to parse this properly. We're going to parse only until we\n        // find a host_name entry.\n        //\n        // This also uses unsafe reads: at this point, if the buffer is short then we're screwed.\n        let nameBufferLength: UInt16 = try buffer.readIntegerIfPossible()\n        guard buffer.readableBytes >= nameBufferLength else {\n            throw InternalSNIErrors.invalidLengthInRecord\n        }\n\n        // We are never looking for another extension, so this is now all that we care about in the\n        // world. Slice our way down to just that.\n        buffer = buffer.getSlice(at: buffer.readerIndex, length: Int(nameBufferLength))!\n        while buffer.readableBytes > 0 {\n            let nameType: UInt8 = try buffer.readIntegerIfPossible()\n\n            // From the RFC:\n            // \"For backward compatibility, all future data structures associated with new NameTypes\n            // MUST begin with a 16-bit length field.\"\n            let nameLength: UInt16 = try buffer.readIntegerIfPossible()\n            guard nameType == sniHostNameType else {\n                try buffer.moveReaderIndexIfPossible(forwardBy: Int(nameLength))\n                continue\n            }\n\n            let hostname = buffer.withUnsafeReadableBytes { ptr -> String? in\n                let nameLength = Int(nameLength)\n                guard nameLength <= ptr.count else {\n                    return nil\n                }\n                return UnsafeRawBufferPointer(rebasing: ptr.prefix(nameLength)).decodeStringValidatingASCII()\n            }\n            if let hostname = hostname {\n                return hostname\n            } else {\n                throw InternalSNIErrors.invalidRecord\n            }\n        }\n        return nil\n    }\n\n    /// Called when we either know the hostname being queried, or we know we can't\n    /// work it out. Either way, we're done now.\n    ///\n    /// The processing here is as follows:\n    ///\n    /// 1. Call the user back with the result of the SNI lookup. At this point we're going to\n    ///    allow them to tweak the channel pipeline as they see fit.\n    /// 2. Wait for them to complete. In this time, we will continue to buffer all inbound\n    ///    data.\n    /// 3. When the user completes, remove ourselves from the pipeline. This will trigger the\n    ///    ByteToMessageDecoder to automatically deliver the buffered bytes to the next handler\n    ///    in the pipeline, which is now responsible for the work.\n    private func sniComplete(result: SNIResult, context: ChannelHandlerContext) {\n        let boundContext = NIOLoopBound(context, eventLoop: context.eventLoop)\n        waitingForUser = true\n        completionHandler(result).hop(to: context.eventLoop).whenSuccess {\n            let context = boundContext.value\n            context.pipeline.syncOperations.removeHandler(context: context, promise: nil)\n        }\n    }\n}\n\n@available(*, unavailable)\nextension SNIHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOTLS/TLSEvents.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Common user events sent by all TLS implementations.\npublic enum TLSUserEvent: Equatable, Sendable {\n    /// The TLS handshake has completed. If ALPN or NPN were used,\n    /// the negotiated protocol is provided as `negotiatedProtocol`.\n    case handshakeCompleted(negotiatedProtocol: String?)\n\n    /// The TLS connection has been successfully and cleanly shut down.\n    /// No further application data can be sent or received at this time.\n    case shutdownCompleted\n}\n"
  },
  {
    "path": "Sources/NIOTestUtils/ByteToMessageDecoderVerifier.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\n\npublic enum ByteToMessageDecoderVerifier: Sendable {\n    /// - seealso: verifyDecoder(inputOutputPairs:decoderFactory:)\n    ///\n    /// Verify `ByteToMessageDecoder`s with `String` inputs\n    public static func verifyDecoder<Decoder: ByteToMessageDecoder>(\n        stringInputOutputPairs: [(String, [Decoder.InboundOut])],\n        decoderFactory: () -> Decoder\n    ) throws where Decoder.InboundOut: Equatable {\n        let alloc = ByteBufferAllocator()\n        let ioPairs = stringInputOutputPairs.map {\n            (ioPair: (String, [Decoder.InboundOut])) -> (ByteBuffer, [Decoder.InboundOut]) in\n            (alloc.buffer(string: ioPair.0), ioPair.1)\n        }\n\n        try ByteToMessageDecoderVerifier.verifyDecoder(inputOutputPairs: ioPairs, decoderFactory: decoderFactory)\n    }\n\n    /// Verifies a `ByteToMessageDecoder` by performing a number of tests.\n    ///\n    /// This method is mostly useful in unit tests for `ByteToMessageDecoder`s. It feeds the inputs from\n    /// `inputOutputPairs` into the decoder in various ways and expects the decoder to produce the outputs from\n    /// `inputOutputPairs`.\n    ///\n    /// The verification performs various tests, for example:\n    ///\n    ///  - drip feeding the bytes, one by one\n    ///  - sending many messages in one `ByteBuffer`\n    ///  - sending each complete message in one `ByteBuffer`\n    ///\n    /// For `ExampleDecoder` that produces `ExampleDecoderOutput`s you would use this method the following way:\n    ///\n    ///     var exampleInput1 = channel.allocator.buffer(capacity: 16)\n    ///     exampleInput1.writeString(\"example-in1\")\n    ///     var exampleInput2 = channel.allocator.buffer(capacity: 16)\n    ///     exampleInput2.writeString(\"example-in2\")\n    ///     let expectedInOuts = [(exampleInput1, [ExampleDecoderOutput(\"1\")]),\n    ///                           (exampleInput2, [ExampleDecoderOutput(\"2\")])\n    ///                          ]\n    ///     XCTAssertNoThrow(try ByteToMessageDecoderVerifier.verifyDecoder(inputOutputPairs: expectedInOuts,\n    ///                                                                     decoderFactory: { ExampleDecoder() }))\n    public static func verifyDecoder<Decoder: ByteToMessageDecoder>(\n        inputOutputPairs: [(ByteBuffer, [Decoder.InboundOut])],\n        decoderFactory: () -> Decoder\n    ) throws where Decoder.InboundOut: Equatable {\n        typealias Out = Decoder.InboundOut\n\n        func verifySimple(channel: RecordingChannel) throws {\n            for (input, expectedOutputs) in inputOutputPairs.shuffled() {\n                try channel.writeInbound(input)\n                for expectedOutput in expectedOutputs {\n                    guard let actualOutput = try channel.readInbound(as: Out.self) else {\n                        throw VerificationError<Out>(\n                            inputs: channel.inboundWrites,\n                            errorCode: .underProduction(expectedOutput)\n                        )\n                    }\n                    guard actualOutput == expectedOutput else {\n                        throw VerificationError<Out>(\n                            inputs: channel.inboundWrites,\n                            errorCode: .wrongProduction(\n                                actual: actualOutput,\n                                expected: expectedOutput\n                            )\n                        )\n                    }\n                }\n                let actualExtraOutput = try channel.readInbound(as: Out.self)\n                guard actualExtraOutput == nil else {\n                    throw VerificationError<Out>(\n                        inputs: channel.inboundWrites,\n                        errorCode: .overProduction(actualExtraOutput!)\n                    )\n                }\n            }\n        }\n\n        func verifyDripFeed(channel: RecordingChannel) throws {\n            for _ in 0..<10 {\n                for (input, expectedOutputs) in inputOutputPairs.shuffled() {\n                    for c in input.readableBytesView {\n                        var buffer = channel.allocator.buffer(capacity: 12)\n                        buffer.writeString(\"BEFORE\")\n                        buffer.writeInteger(c)\n                        buffer.writeString(\"AFTER\")\n                        buffer.moveReaderIndex(forwardBy: 6)\n                        buffer.moveWriterIndex(to: buffer.readerIndex + 1)\n                        try channel.writeInbound(buffer)\n                    }\n                    for expectedOutput in expectedOutputs {\n                        guard let actualOutput = try channel.readInbound(as: Out.self) else {\n                            throw VerificationError<Out>(\n                                inputs: channel.inboundWrites,\n                                errorCode: .underProduction(expectedOutput)\n                            )\n                        }\n                        guard actualOutput == expectedOutput else {\n                            throw VerificationError<Out>(\n                                inputs: channel.inboundWrites,\n                                errorCode: .wrongProduction(\n                                    actual: actualOutput,\n                                    expected: expectedOutput\n                                )\n                            )\n                        }\n                    }\n                    let actualExtraOutput = try channel.readInbound(as: Out.self)\n                    guard actualExtraOutput == nil else {\n                        throw VerificationError<Out>(\n                            inputs: channel.inboundWrites,\n                            errorCode: .overProduction(actualExtraOutput!)\n                        )\n                    }\n                }\n            }\n        }\n\n        func verifyManyAtOnce(channel: RecordingChannel) throws {\n            var overallBuffer = channel.allocator.buffer(capacity: 1024)\n            var overallExpecteds: [Out] = []\n\n            for _ in 0..<10 {\n                for (var input, expectedOutputs) in inputOutputPairs.shuffled() {\n                    overallBuffer.writeBuffer(&input)\n                    overallExpecteds.append(contentsOf: expectedOutputs)\n                }\n            }\n\n            try channel.writeInbound(overallBuffer)\n            for expectedOutput in overallExpecteds {\n                guard let actualOutput = try channel.readInbound(as: Out.self) else {\n                    throw VerificationError<Out>(\n                        inputs: channel.inboundWrites,\n                        errorCode: .underProduction(expectedOutput)\n                    )\n                }\n                guard actualOutput == expectedOutput else {\n                    throw VerificationError<Out>(\n                        inputs: channel.inboundWrites,\n                        errorCode: .wrongProduction(\n                            actual: actualOutput,\n                            expected: expectedOutput\n                        )\n                    )\n                }\n            }\n        }\n\n        let decoder: Decoder = decoderFactory()\n        let channel = RecordingChannel(EmbeddedChannel(handler: ByteToMessageHandler<Decoder>(decoder)))\n\n        try verifySimple(channel: channel)\n        try verifyDripFeed(channel: channel)\n        try verifyManyAtOnce(channel: channel)\n\n        if case .leftOvers(inbound: let ib, outbound: let ob, pendingOutbound: let pob) = try channel.finish() {\n            throw VerificationError<Out>(\n                inputs: channel.inboundWrites,\n                errorCode: .leftOversOnDeconstructingChannel(\n                    inbound: ib,\n                    outbound: ob,\n                    pendingOutbound: pob\n                )\n            )\n        }\n    }\n}\n\nextension ByteToMessageDecoderVerifier {\n    private class RecordingChannel {\n        private let actualChannel: EmbeddedChannel\n        private(set) var inboundWrites: [ByteBuffer] = []\n\n        init(_ actualChannel: EmbeddedChannel) {\n            self.actualChannel = actualChannel\n        }\n\n        func readInbound<T>(as type: T.Type = T.self) throws -> T? {\n            try self.actualChannel.readInbound()\n        }\n\n        @discardableResult public func writeInbound(_ data: ByteBuffer) throws -> EmbeddedChannel.BufferState {\n            self.inboundWrites.append(data)\n            return try self.actualChannel.writeInbound(data)\n        }\n\n        var allocator: ByteBufferAllocator {\n            self.actualChannel.allocator\n        }\n\n        func finish() throws -> EmbeddedChannel.LeftOverState {\n            try self.actualChannel.finish()\n        }\n    }\n}\n\nextension ByteToMessageDecoderVerifier {\n    /// A `VerificationError` is thrown when the verification of a `ByteToMessageDecoder` failed.\n    public struct VerificationError<OutputType: Equatable>: Error {\n        /// Contains the `inputs` that were passed to the `ByteToMessageDecoder` at the point where it failed\n        /// verification.\n        public var inputs: [ByteBuffer]\n\n        /// `errorCode` describes the concrete problem that was detected.\n        public var errorCode: ErrorCode\n\n        public enum ErrorCode {\n            /// The `errorCode` will be `wrongProduction` when the `expected` output didn't match the `actual`\n            /// output.\n            case wrongProduction(actual: OutputType, expected: OutputType)\n\n            /// The `errorCode` will be set to `overProduction` when a decoding result was yielded where\n            /// nothing was expected.\n            case overProduction(OutputType)\n\n            /// The `errorCode` will be set to `underProduction` when a decoder didn't yield output when output was\n            /// expected. The expected output is delivered as the associated value.\n            case underProduction(OutputType)\n\n            /// The `errorCode` will be set to `leftOversOnDeconstructionChannel` if there were left-over items\n            /// in the `Channel` on deconstruction. This usually means that your `ByteToMessageDecoder` did not process\n            /// certain items.\n            case leftOversOnDeconstructingChannel(inbound: [NIOAny], outbound: [NIOAny], pendingOutbound: [NIOAny])\n        }\n    }\n}\n\n@available(*, unavailable)\nextension ByteToMessageDecoderVerifier.VerificationError.ErrorCode: Sendable {}\n\n/// `VerificationError` conforms to `Error` and therefore needs to conform to `Sendable` too.\n/// `VerificationError` has a stored property `errorCode` of type `ErrorCode` which can store `NIOAny` which is not and can not be `Sendable`.\n/// In addtion, `ErrorCode` can also store a user defined `OutputType` which is not required to be `Sendable` but we could require it to be `Sendable`.\n/// We have two choices:\n///  - we could lie and conform `ErrorCode` to `Sendable` with `@unchecked`\n///  - do the same but for `VerificationError`\n/// As `VerificationError` already conforms to `Sendable` (because it conforms to `Error` and `Error` inherits from `Sendable`)\n/// it sound like the best option to just stick to the conformances we already have and **not** lie twice by making `VerificationError` conform to `Sendable` too.\n/// Note that this still allows us to adopt `Sendable` for `ErrorCode` later if we change our opinion.\nextension ByteToMessageDecoderVerifier.VerificationError: @unchecked Sendable {}\n"
  },
  {
    "path": "Sources/NIOTestUtils/EventCounterHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\n\n/// `EventCounterHandler` is a `ChannelHandler` that counts and forwards all the events that it sees coming through\n/// the `ChannelPipeline`.\n///\n/// Adding `EventCounterHandler` to any point of your `ChannelPipeline` should not change the program's behaviour.\n/// `EventCounterHandler` is mostly useful in unit tests to validate other `ChannelHandler`'s behaviour.\n///\n/// - Note: Contrary to most `ChannelHandler`s, all of `EventCounterHandler`'s API is thread-safe meaning that you can\n///         query the events received from any thread.\npublic final class EventCounterHandler: Sendable {\n    private let _channelRegisteredCalls = ManagedAtomic<Int>(0)\n    private let _channelUnregisteredCalls = ManagedAtomic<Int>(0)\n    private let _channelActiveCalls = ManagedAtomic<Int>(0)\n    private let _channelInactiveCalls = ManagedAtomic<Int>(0)\n    private let _channelReadCalls = ManagedAtomic<Int>(0)\n    private let _channelReadCompleteCalls = ManagedAtomic<Int>(0)\n    private let _channelWritabilityChangedCalls = ManagedAtomic<Int>(0)\n    private let _userInboundEventTriggeredCalls = ManagedAtomic<Int>(0)\n    private let _errorCaughtCalls = ManagedAtomic<Int>(0)\n    private let _registerCalls = ManagedAtomic<Int>(0)\n    private let _bindCalls = ManagedAtomic<Int>(0)\n    private let _connectCalls = ManagedAtomic<Int>(0)\n    private let _writeCalls = ManagedAtomic<Int>(0)\n    private let _flushCalls = ManagedAtomic<Int>(0)\n    private let _readCalls = ManagedAtomic<Int>(0)\n    private let _closeCalls = ManagedAtomic<Int>(0)\n    private let _triggerUserOutboundEventCalls = ManagedAtomic<Int>(0)\n\n    public init() {}\n}\n\n// MARK: Public API\nextension EventCounterHandler {\n    public struct ValidityError: Error {\n        public var reason: String\n\n        init(_ reason: String) {\n            self.reason = reason\n        }\n    }\n\n    /// Returns the number of `channelRegistered` events seen so far in the `ChannelPipeline`.\n    public var channelRegisteredCalls: Int {\n        self._channelRegisteredCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `channelUnregistered` events seen so far in the `ChannelPipeline`.\n    public var channelUnregisteredCalls: Int {\n        self._channelUnregisteredCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `channelActive` events seen so far in the `ChannelPipeline`.\n    public var channelActiveCalls: Int {\n        self._channelActiveCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `channelInactive` events seen so far in the `ChannelPipeline`.\n    public var channelInactiveCalls: Int {\n        self._channelInactiveCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `channelRead` events seen so far in the `ChannelPipeline`.\n    public var channelReadCalls: Int {\n        self._channelReadCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `channelReadComplete` events seen so far in the `ChannelPipeline`.\n    public var channelReadCompleteCalls: Int {\n        self._channelReadCompleteCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `channelWritabilityChanged` events seen so far in the `ChannelPipeline`.\n    public var channelWritabilityChangedCalls: Int {\n        self._channelWritabilityChangedCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `userInboundEventTriggered` events seen so far in the `ChannelPipeline`.\n    public var userInboundEventTriggeredCalls: Int {\n        self._userInboundEventTriggeredCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `errorCaught` events seen so far in the `ChannelPipeline`.\n    public var errorCaughtCalls: Int {\n        self._errorCaughtCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `register` events seen so far in the `ChannelPipeline`.\n    public var registerCalls: Int {\n        self._registerCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `bind` events seen so far in the `ChannelPipeline`.\n    public var bindCalls: Int {\n        self._bindCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `connect` events seen so far in the `ChannelPipeline`.\n    public var connectCalls: Int {\n        self._connectCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `write` events seen so far in the `ChannelPipeline`.\n    public var writeCalls: Int {\n        self._writeCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `flush` events seen so far in the `ChannelPipeline`.\n    public var flushCalls: Int {\n        self._flushCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `read` events seen so far in the `ChannelPipeline`.\n    public var readCalls: Int {\n        self._readCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `close` events seen so far in the `ChannelPipeline`.\n    public var closeCalls: Int {\n        self._closeCalls.load(ordering: .relaxed)\n    }\n\n    /// Returns the number of `triggerUserOutboundEvent` events seen so far in the `ChannelPipeline`.\n    public var triggerUserOutboundEventCalls: Int {\n        self._triggerUserOutboundEventCalls.load(ordering: .relaxed)\n    }\n\n    /// Validate some basic assumptions about the number of events and if any of those assumptions are violated, throw\n    /// an error.\n    ///\n    /// For example, any `Channel` should only be registered with the `Selector` at most once. That means any\n    /// `ChannelHandler` should see no more than one `register` event. If `EventCounterHandler` sees more than one\n    /// `register` event and you call `checkValidity`, it will throw `EventCounterHandler.ValidityError` with an\n    /// appropriate explanation.\n    ///\n    /// - Note: This API is thread-safe, you may call it from any thread. The results of this API may vary though if you\n    ///         call it whilst the `Channel` this `ChannelHandler` is in is still in use.\n    public func checkValidity() throws {\n        guard self.channelRegisteredCalls <= 1 else {\n            throw ValidityError(\"channelRegistered should be called no more than once\")\n        }\n        guard self.channelUnregisteredCalls <= 1 else {\n            throw ValidityError(\"channelUnregistered should be called no more than once\")\n        }\n        guard self.channelActiveCalls <= 1 else {\n            throw ValidityError(\"channelActive should be called no more than once\")\n        }\n        guard self.channelInactiveCalls <= 1 else {\n            throw ValidityError(\"channelInactive should be called no more than once\")\n        }\n        guard self.registerCalls <= 1 else {\n            throw ValidityError(\"register should be called no more than once\")\n        }\n        guard self.bindCalls <= 1 else {\n            throw ValidityError(\"bind should be called no more than once\")\n        }\n        guard self.connectCalls <= 1 else {\n            throw ValidityError(\"connect should be called no more than once\")\n        }\n    }\n\n    /// Return all event descriptions that have triggered.\n    ///\n    /// This is most useful in unit tests where you want to make sure only certain events have been triggered.\n    ///\n    /// - Note: This API is thread-safe, you may call it from any thread. The results of this API may vary though if you\n    ///         call it whilst the `Channel` this `ChannelHandler` is in is still in use.\n    public func allTriggeredEvents() -> Set<String> {\n        var allEvents: Set<String> = []\n\n        if self.channelRegisteredCalls != 0 {\n            allEvents.insert(\"channelRegistered\")\n        }\n\n        if self.channelUnregisteredCalls != 0 {\n            allEvents.insert(\"channelUnregistered\")\n        }\n\n        if self.channelActiveCalls != 0 {\n            allEvents.insert(\"channelActive\")\n        }\n\n        if self.channelInactiveCalls != 0 {\n            allEvents.insert(\"channelInactive\")\n        }\n\n        if self.channelReadCalls != 0 {\n            allEvents.insert(\"channelRead\")\n        }\n\n        if self.channelReadCompleteCalls != 0 {\n            allEvents.insert(\"channelReadComplete\")\n        }\n\n        if self.channelWritabilityChangedCalls != 0 {\n            allEvents.insert(\"channelWritabilityChanged\")\n        }\n\n        if self.userInboundEventTriggeredCalls != 0 {\n            allEvents.insert(\"userInboundEventTriggered\")\n        }\n\n        if self.errorCaughtCalls != 0 {\n            allEvents.insert(\"errorCaught\")\n        }\n\n        if self.registerCalls != 0 {\n            allEvents.insert(\"register\")\n        }\n\n        if self.bindCalls != 0 {\n            allEvents.insert(\"bind\")\n        }\n\n        if self.connectCalls != 0 {\n            allEvents.insert(\"connect\")\n        }\n\n        if self.writeCalls != 0 {\n            allEvents.insert(\"write\")\n        }\n\n        if self.flushCalls != 0 {\n            allEvents.insert(\"flush\")\n        }\n\n        if self.readCalls != 0 {\n            allEvents.insert(\"read\")\n        }\n\n        if self.closeCalls != 0 {\n            allEvents.insert(\"close\")\n        }\n\n        if self.triggerUserOutboundEventCalls != 0 {\n            allEvents.insert(\"triggerUserOutboundEvent\")\n        }\n\n        return allEvents\n    }\n}\n\n// MARK: ChannelHandler API\nextension EventCounterHandler: ChannelDuplexHandler {\n    public typealias InboundIn = Any\n    public typealias InboundOut = Any\n    public typealias OutboundIn = Any\n    public typealias OutboundOut = Any\n\n    /// @see: `_ChannelInboundHandler.channelRegistered`\n    public func channelRegistered(context: ChannelHandlerContext) {\n        self._channelRegisteredCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelRegistered()\n    }\n\n    /// @see: `_ChannelInboundHandler.channelUnregistered`\n    public func channelUnregistered(context: ChannelHandlerContext) {\n        self._channelUnregisteredCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelUnregistered()\n    }\n\n    /// @see: `_ChannelInboundHandler.channelActive`\n    public func channelActive(context: ChannelHandlerContext) {\n        self._channelActiveCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelActive()\n    }\n\n    /// @see: `_ChannelInboundHandler.channelInactive`\n    public func channelInactive(context: ChannelHandlerContext) {\n        self._channelInactiveCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelInactive()\n    }\n\n    /// @see: `_ChannelInboundHandler.channelRead`\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self._channelReadCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelRead(data)\n    }\n\n    /// @see: `_ChannelInboundHandler.channelReadComplete`\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        self._channelReadCompleteCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelReadComplete()\n    }\n\n    /// @see: `_ChannelInboundHandler.channelWritabilityChanged`\n    public func channelWritabilityChanged(context: ChannelHandlerContext) {\n        self._channelWritabilityChangedCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireChannelWritabilityChanged()\n    }\n\n    /// @see: `_ChannelInboundHandler.userInboundEventTriggered`\n    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        self._userInboundEventTriggeredCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    /// @see: `_ChannelInboundHandler.errorCaught`\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self._errorCaughtCalls.wrappingIncrement(ordering: .relaxed)\n        context.fireErrorCaught(error)\n    }\n\n    /// @see: `_ChannelOutboundHandler.register`\n    public func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        self._registerCalls.wrappingIncrement(ordering: .relaxed)\n        context.register(promise: promise)\n    }\n\n    /// @see: `_ChannelOutboundHandler.bind`\n    public func bind(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self._bindCalls.wrappingIncrement(ordering: .relaxed)\n        context.bind(to: to, promise: promise)\n    }\n\n    /// @see: `_ChannelOutboundHandler.connect`\n    public func connect(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self._connectCalls.wrappingIncrement(ordering: .relaxed)\n        context.connect(to: to, promise: promise)\n    }\n\n    /// @see: `_ChannelOutboundHandler.write`\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self._writeCalls.wrappingIncrement(ordering: .relaxed)\n        context.write(data, promise: promise)\n    }\n\n    /// @see: `_ChannelOutboundHandler.flush`\n    public func flush(context: ChannelHandlerContext) {\n        self._flushCalls.wrappingIncrement(ordering: .relaxed)\n        context.flush()\n    }\n\n    /// @see: `_ChannelOutboundHandler.read`\n    public func read(context: ChannelHandlerContext) {\n        self._readCalls.wrappingIncrement(ordering: .relaxed)\n        context.read()\n    }\n\n    /// @see: `_ChannelOutboundHandler.close`\n    public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self._closeCalls.wrappingIncrement(ordering: .relaxed)\n        context.close(mode: mode, promise: promise)\n    }\n\n    /// @see: `_ChannelOutboundHandler.triggerUserOutboundEvent`\n    public func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {\n        self._triggerUserOutboundEventCalls.wrappingIncrement(ordering: .relaxed)\n        context.triggerUserOutboundEvent(event, promise: promise)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOTestUtils/ManualTaskExecutor.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport Synchronization\n\n/// Provide a `ManualTaskExecutor` for the duration of the given `body`.\n///\n/// The executor can be used for setting the executor preference of tasks and fully control\n/// when execution of the tasks is performed.\n///\n/// Example usage:\n/// ```swift\n///     await withDiscardingTaskGroup { group in\n///         await withManualTaskExecutor { taskExecutor in\n///             group.addTask(executorPreference: taskExecutor) {\n///                 print(\"Running\")\n///             }\n///             taskExecutor.runUntilQueueIsEmpty()  // Run the task synchronously\n///         }\n///     }\n/// ```\n///\n/// - warning: Do not escape the task executor from the closure for later use and make sure that\n///            all tasks running on the executor are completely finished before `body` returns.\n///            It is highly recommended to use structured concurrency with this task executor.\n///\n/// - Parameters:\n///   - body: The closure that will accept the task executor.\n///\n/// - Throws: When `body` throws.\n///\n/// - Returns: The value returned by `body`.\n@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n@inlinable\npackage func withManualTaskExecutor<T, Failure>(\n    body: (ManualTaskExecutor) async throws(Failure) -> T\n) async throws(Failure) -> T {\n    let taskExecutor = ManualTaskExecutor()\n    defer { taskExecutor.shutdown() }\n    return try await body(taskExecutor)\n}\n\n/// Provide two `ManualTaskExecutor`s for the duration of the given `body`.\n///\n/// The executors can be used for setting the executor preference of tasks and fully control\n/// when execution of the tasks is performed.\n///\n/// Example usage:\n/// ```swift\n///     await withDiscardingTaskGroup { group in\n///         await withManualTaskExecutor { taskExecutor1, taskExecutor2 in\n///             group.addTask(executorPreference: taskExecutor1) {\n///                 print(\"Running 1\")\n///             }\n///             group.addTask(executorPreference: taskExecutor2) {\n///                 print(\"Running 2\")\n///             }\n///             taskExecutor2.runUntilQueueIsEmpty()  // Run second task synchronously\n///             taskExecutor1.runUntilQueueIsEmpty()  // Run first task synchronously\n///         }\n///     }\n/// ```\n///\n/// - warning: Do not escape the task executors from the closure for later use and make sure that\n///            all tasks running on the executors are completely finished before `body` returns.\n///            It is highly recommended to use structured concurrency with these task executors.\n///\n/// - Parameters:\n///   - body: The closure that will accept the task executors.\n///\n/// - Throws: When `body` throws.\n///\n/// - Returns: The value returned by `body`.\n@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n@inlinable\npackage func withManualTaskExecutors<T, Failure>(\n    body: (ManualTaskExecutor, ManualTaskExecutor) async throws(Failure) -> T\n) async throws(Failure) -> T {\n    let taskExecutor1 = ManualTaskExecutor()\n    defer { taskExecutor1.shutdown() }\n\n    let taskExecutor2 = ManualTaskExecutor()\n    defer { taskExecutor2.shutdown() }\n\n    return try await body(taskExecutor1, taskExecutor2)\n}\n\n/// Manual task executor.\n///\n/// A `TaskExecutor` that does not use any threadpool or similar mechanism to run the jobs.\n/// Jobs are manually run by calling the `runUntilQueueIsEmpty` method.\n///\n@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n@usableFromInline\npackage final class ManualTaskExecutor: TaskExecutor {\n    struct Storage {\n        var isShutdown = false\n        var jobs = Deque<UnownedJob>()\n    }\n\n    private let storage = Mutex<Storage>(.init())\n\n    @usableFromInline\n    init() {}\n\n    /// Run jobs until queue is empty.\n    ///\n    /// Synchronously runs all enqueued jobs, including any jobs that are enqueued while running.\n    /// When this function returns, it means that each task running on this executor is either:\n    /// - suspended\n    /// - moved (temporarily) to a different executor\n    /// - finished\n    ///\n    /// If not all tasks are finished, this function must be called again.\n    package func runUntilQueueIsEmpty() {\n        while let job = self.storage.withLock({ $0.jobs.popFirst() }) {\n            job.runSynchronously(on: self.asUnownedTaskExecutor())\n        }\n    }\n\n    /// Enqueue a job.\n    ///\n    /// Called by the concurrency runtime.\n    ///\n    /// - Parameter job: The job to enqueue.\n    @usableFromInline\n    package func enqueue(_ job: UnownedJob) {\n        self.storage.withLock { storage in\n            if storage.isShutdown {\n                fatalError(\"A job is enqueued after manual executor shutdown\")\n            }\n            storage.jobs.append(job)\n        }\n    }\n\n    /// Shutdown.\n    ///\n    /// Since the manual task executor is not running anything in the background, this is purely to catch\n    /// any issues due to incorrect usage of the executor. The shutdown verifies that the queue is empty\n    /// and makes sure that no new jobs can be enqueued.\n    @usableFromInline\n    func shutdown() {\n        self.storage.withLock { storage in\n            if !storage.jobs.isEmpty {\n                fatalError(\"Shutdown of manual executor with jobs in queue\")\n            }\n            storage.isShutdown = true\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOTestUtils/NIOHTTP1TestServer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\n\ntypealias SendableHTTPServerResponsePart = HTTPPart<HTTPResponseHead, ByteBuffer>\n\nextension HTTPServerResponsePart {\n    init(_ target: SendableHTTPServerResponsePart) {\n        switch target {\n        case .head(let head):\n            self = .head(head)\n        case .body(let body):\n            self = .body(.byteBuffer(body))\n        case .end(let end):\n            self = .end(end)\n        }\n    }\n}\n\nextension SendableHTTPServerResponsePart {\n    init(_ target: HTTPServerResponsePart) throws {\n        switch target {\n        case .head(let head):\n            self = .head(head)\n        case .body(.byteBuffer(let body)):\n            self = .body(body)\n        case .body(.fileRegion):\n            throw NIOHTTP1TestServerError(\n                reason: \"FileRegion is not Sendable and cannot be passed across concurrency domains\"\n            )\n        case .end(let end):\n            self = .end(end)\n        }\n    }\n}\n\n/// A helper handler to transform a Sendable response into a\n/// non-Sendable one, to manage warnings.\nprivate final class TransformerHandler: ChannelOutboundHandler {\n    typealias OutboundIn = SendableHTTPServerResponsePart\n    typealias OutboundOut = HTTPServerResponsePart\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let response = self.unwrapOutboundIn(data)\n        context.write(self.wrapOutboundOut(.init(response)), promise: promise)\n    }\n}\n\nprivate final class BlockingQueue<Element> {\n    private let condition = ConditionLock(value: false)\n    private var buffer = CircularBuffer<Result<Element, Error>>()\n\n    public struct TimeoutError: Error {}\n\n    internal func append(_ element: Result<Element, Error>) {\n        self.condition.lock()\n        self.buffer.append(element)\n        self.condition.unlock(withValue: true)\n    }\n\n    internal var isEmpty: Bool {\n        self.condition.lock()\n        defer { self.condition.unlock() }\n        return self.buffer.isEmpty\n    }\n\n    internal func popFirst(deadline: NIODeadline) throws -> Element {\n        let secondsUntilDeath = deadline - NIODeadline.now()\n        guard\n            self.condition.lock(\n                whenValue: true,\n                timeoutSeconds: .init(secondsUntilDeath.nanoseconds / 1_000_000_000)\n            )\n        else {\n            throw TimeoutError()\n        }\n        let first = self.buffer.removeFirst()\n        self.condition.unlock(withValue: !self.buffer.isEmpty)\n        return try first.get()\n    }\n}\n\nextension BlockingQueue: @unchecked Sendable where Element: Sendable {}\n\nprivate final class WebServerHandler: ChannelDuplexHandler {\n    typealias InboundIn = HTTPServerRequestPart\n    typealias OutboundIn = HTTPServerResponsePart\n    typealias OutboundOut = HTTPServerResponsePart\n\n    private let webServer: NIOHTTP1TestServer\n\n    init(webServer: NIOHTTP1TestServer) {\n        self.webServer = webServer\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.webServer.pushError(error)\n        context.close(promise: nil)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.webServer.pushChannelRead(Self.unwrapInboundIn(data))\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let loopBoundContext = context.loopBound\n        switch Self.unwrapOutboundIn(data) {\n        case .head(var head):\n            head.headers.replaceOrAdd(name: \"connection\", value: \"close\")\n            head.headers.remove(name: \"keep-alive\")\n            context.write(Self.wrapOutboundOut(.head(head)), promise: promise)\n        case .body:\n            context.write(data, promise: promise)\n        case .end:\n            context.write(data).map {\n                let context = loopBoundContext.value\n                context.close(promise: nil)\n            }.cascade(to: promise)\n        }\n    }\n}\n\nprivate final class AggregateBodyHandler: ChannelInboundHandler {\n    typealias InboundIn = HTTPServerRequestPart\n    typealias InboundOut = HTTPServerRequestPart\n\n    var receivedSoFar: ByteBuffer? = nil\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch Self.unwrapInboundIn(data) {\n        case .head:\n            context.fireChannelRead(data)\n        case .body(var buffer):\n            self.receivedSoFar.setOrWriteBuffer(&buffer)\n        case .end:\n            if let receivedSoFar = self.receivedSoFar {\n                context.fireChannelRead(Self.wrapInboundOut(.body(receivedSoFar)))\n            }\n            context.fireChannelRead(data)\n        }\n    }\n}\n\n/// HTTP1 server that accepts and process only one request at a time.\n/// This helps writing tests against a real server while keeping the ability to\n/// write tests and assertions the same way we would if we were testing a\n/// `ChannelHandler` in isolation.\n/// `NIOHTTP1TestServer` enables writing test cases for HTTP1 clients that have\n/// complex behaviours like client implementing a protocol where an high level\n/// operation translates into several, possibly parallel, HTTP requests.\n///\n/// With `NIOHTTP1TestServer` we have:\n///  - visibility on the `HTTPServerRequestPart`s received by the server;\n///  - control over the `HTTPServerResponsePart`s send by the server.\n///\n/// The following code snippet shows an example test case where the client\n/// under test sends a request to the server.\n///\n///     // Setup the test environment.\n///     let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n///     let allocator = ByteBufferAllocator()\n///     let testServer = NIOHTTP1TestServer(group: group)\n///     defer {\n///         XCTAssertNoThrow(try testServer.stop())\n///         XCTAssertNoThrow(try group.syncShutdownGracefully())\n///     }\n///\n///     // Use your library to send a request to the server.\n///     let requestBody = \"ping\"\n///     var requestComplete: EventLoopFuture<String>!\n///     XCTAssertNoThrow(requestComplete = try sendRequestTo(\n///         URL(string: \"http://127.0.0.1:\\(testServer.serverPort)/some-route\")!,\n///         body: requestBody))\n///\n///     // Assert the server received the expected request.\n///     XCTAssertNoThrow(try testServer.receiveHeadAndVerify { head in\n///         XCTAssertEqual(head, .init(version: .http1_1,\n///                                    method: .GET,\n///                                    uri: \"/some-route\",\n///                                    headers: .init([\n///                                        (\"Content-Type\", \"text/plain; charset=utf-8\"),\n///                                        (\"Content-Length\", \"4\")])))\n///     })\n///     var requestBuffer = allocator.buffer(capacity: 128)\n///     requestBuffer.writeString(requestBody)\n///     XCTAssertNoThrow(try testServer.receiveBodyAndVerify { body in\n///         XCTAssertEqual(body, requestBuffer)\n///     })\n///     XCTAssertNoThrow(try testServer.receiveEndAndVerify { trailers in\n///         XCTAssertNil(trailers)\n///     })\n///\n///     // Make the server send a response to the client.\n///     let responseBody = \"pong\"\n///     var responseBuffer = allocator.buffer(capacity: 128)\n///     responseBuffer.writeString(responseBody)\n///     XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n///     XCTAssertNoThrow(try testServer.writeOutbound(.body(.byteBuffer(responseBuffer))))\n///     XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n///\n///     // Assert that the client received the response from the server.\n///     XCTAssertNoThrow(XCTAssertEqual(responseBody, try requestComplete.wait()))\npublic final class NIOHTTP1TestServer {\n    private let eventLoop: EventLoop\n    private let aggregateBody: Bool\n    // all protected by eventLoop\n    private let inboundBuffer: BlockingQueue<HTTPServerRequestPart> = .init()\n    private var currentClientChannel: Channel? = nil\n    private var serverChannel: Channel! = nil\n\n    enum State {\n        case channelsAvailable(CircularBuffer<Channel>)\n        case waitingForChannel(EventLoopPromise<Void>)\n        case idle\n        case stopped\n    }\n    private var state: State = .idle\n\n    func handleChannels() {\n        self.eventLoop.assertInEventLoop()\n\n        let channel: Channel\n        switch self.state {\n        case .channelsAvailable(var channels):\n            channel = channels.removeFirst()\n            if channels.isEmpty {\n                self.state = .idle\n            } else {\n                self.state = .channelsAvailable(channels)\n            }\n        case .idle:\n            let promise = self.eventLoop.makePromise(of: Void.self)\n            promise.futureResult.whenSuccess {\n                self.handleChannels()\n            }\n            self.state = .waitingForChannel(promise)\n            return\n        case .waitingForChannel:\n            preconditionFailure(\"illegal state \\(self.state)\")\n        case .stopped:\n            return\n        }\n\n        assert(self.currentClientChannel == nil)\n        self.currentClientChannel = channel\n        channel.closeFuture.whenSuccess {\n            self.currentClientChannel = nil\n            self.handleChannels()\n            return\n        }\n        do {\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline()\n            if self.aggregateBody {\n                try channel.pipeline.syncOperations.addHandler(AggregateBodyHandler())\n            }\n            try channel.pipeline.syncOperations.addHandler(WebServerHandler(webServer: self))\n            try channel.pipeline.syncOperations.addHandler(TransformerHandler())\n            _ = try channel.syncOptions!.setOption(.autoRead, value: true)\n        } catch {\n            // This happens when the channel has been closed while it was waiting in\n            // the pipeline. It's benign: the closure passed to the close future above will\n            // have executed already, and started working on getting the next channel.\n            channel.close(promise: nil)\n        }\n    }\n\n    public convenience init(group: EventLoopGroup) {\n        self.init(group: group, aggregateBody: true)\n    }\n\n    public init(group: EventLoopGroup, aggregateBody: Bool) {\n        self.eventLoop = group.next()\n        self.aggregateBody = aggregateBody\n\n        self.serverChannel = try! ServerBootstrap(group: self.eventLoop)\n            .childChannelOption(.autoRead, value: false)\n            .childChannelInitializer { channel in\n                switch self.state {\n                case .channelsAvailable(var channels):\n                    channels.append(channel)\n                    self.state = .channelsAvailable(channels)\n                case .waitingForChannel(let promise):\n                    self.state = .channelsAvailable([channel])\n                    promise.succeed(())\n                case .idle:\n                    self.state = .channelsAvailable([channel])\n                case .stopped:\n                    channel.close(promise: nil)\n                }\n                return channel.eventLoop.makeSucceededFuture(())\n            }\n            .bind(host: \"127.0.0.1\", port: 0)\n            .map { channel in\n                self.handleChannels()\n                return channel\n            }\n            .wait()\n    }\n}\n\n// MARK: - Public API for test driver\nextension NIOHTTP1TestServer {\n    struct NonEmptyInboundBufferOnStop: Error {}\n\n    public func stop() throws {\n        assert(!self.eventLoop.inEventLoop)\n        try self.eventLoop.flatSubmit { () -> EventLoopFuture<Void> in\n            switch self.state {\n            case .channelsAvailable(let channels):\n                self.state = .stopped\n                for channel in channels {\n                    channel.close(promise: nil)\n                }\n            case .waitingForChannel(let promise):\n                self.state = .stopped\n                promise.fail(ChannelError.ioOnClosedChannel)\n            case .idle:\n                self.state = .stopped\n            case .stopped:\n                preconditionFailure(\"double stopped NIOHTTP1TestServer\")\n            }\n            return self.serverChannel.close().flatMapThrowing {\n                self.serverChannel = nil\n                guard self.inboundBuffer.isEmpty else {\n                    throw NonEmptyInboundBufferOnStop()\n                }\n            }.always { _ in\n                self.currentClientChannel?.close(promise: nil)\n            }\n        }.wait()\n    }\n\n    public func readInbound(deadline: NIODeadline = .now() + .seconds(10)) throws -> HTTPServerRequestPart {\n        self.eventLoop.assertNotInEventLoop()\n        return try self.eventLoop.submit { () -> BlockingQueue<HTTPServerRequestPart> in\n            self.inboundBuffer\n        }.wait().popFirst(deadline: deadline)\n    }\n\n    public func writeOutbound(_ data: HTTPServerResponsePart) throws {\n        self.eventLoop.assertNotInEventLoop()\n\n        let transformed = try SendableHTTPServerResponsePart(data)\n        try self.eventLoop.flatSubmit { () -> EventLoopFuture<Void> in\n            if let channel = self.currentClientChannel {\n                return channel.writeAndFlush(transformed)\n            } else {\n                return self.eventLoop.makeFailedFuture(ChannelError.ioOnClosedChannel)\n            }\n        }.wait()\n    }\n\n    public var serverPort: Int {\n        self.eventLoop.assertNotInEventLoop()\n        return self.serverChannel!.localAddress!.port!\n    }\n}\n\n// All mutable state is protected through `eventLoop`\nextension NIOHTTP1TestServer: @unchecked Sendable {}\n\n// MARK: - API for HTTP server\nextension NIOHTTP1TestServer {\n    fileprivate func pushChannelRead(_ state: HTTPServerRequestPart) {\n        self.eventLoop.assertInEventLoop()\n        self.inboundBuffer.append(.success(state))\n    }\n\n    fileprivate func pushError(_ error: Error) {\n        self.eventLoop.assertInEventLoop()\n        self.inboundBuffer.append(.failure(error))\n    }\n}\n\nextension NIOHTTP1TestServer {\n    /// Waits for a message part to be received and checks that it was a `.head` before returning\n    /// the `HTTPRequestHead` it contained.\n    ///\n    /// - Parameters:\n    ///   - deadline: The deadline by which a part must have been received.\n    /// - Throws: If the part was not a `.head` or nothing was read before the deadline.\n    /// - Returns: The `HTTPRequestHead` from the `.head`.\n    public func receiveHead(deadline: NIODeadline = .now() + .seconds(10)) throws -> HTTPRequestHead {\n        let part = try self.readInbound(deadline: deadline)\n        switch part {\n        case .head(let head):\n            return head\n        default:\n            throw NIOHTTP1TestServerError(reason: \"Expected .head but got '\\(part)'\")\n        }\n    }\n\n    /// Waits for a message part to be received and checks that it was a `.head` before passing\n    /// it to the `verify` block.\n    ///\n    /// - Parameters:\n    ///   - deadline: The deadline by which a part must have been received.\n    ///   - verify: A closure which can be used to verify the contents of the `HTTPRequestHead`.\n    /// - Throws: If the part was not a `.head` or nothing was read before the deadline.\n    public func receiveHeadAndVerify(\n        deadline: NIODeadline = .now() + .seconds(10),\n        _ verify: (HTTPRequestHead) throws -> Void = { _ in }\n    ) throws {\n        try verify(self.receiveHead(deadline: deadline))\n    }\n\n    /// Waits for a message part to be received and checks that it was a `.body` before returning\n    /// the `ByteBuffer` it contained.\n    ///\n    /// - Parameters:\n    ///   - deadline: The deadline by which a part must have been received.\n    /// - Throws: If the part was not a `.body` or nothing was read before the deadline.\n    /// - Returns: The `ByteBuffer` from the `.body`.\n    public func receiveBody(deadline: NIODeadline = .now() + .seconds(10)) throws -> ByteBuffer {\n        let part = try self.readInbound(deadline: deadline)\n        switch part {\n        case .body(let buffer):\n            return buffer\n        default:\n            throw NIOHTTP1TestServerError(reason: \"Expected .body but got '\\(part)'\")\n        }\n    }\n\n    /// Waits for a message part to be received and checks that it was a `.body` before passing\n    /// it to the `verify` block.\n    ///\n    /// - Parameters:\n    ///   - deadline: The deadline by which a part must have been received.\n    ///   - verify: A closure which can be used to verify the contents of the `ByteBuffer`.\n    /// - Throws: If the part was not a `.body` or nothing was read before the deadline.\n    public func receiveBodyAndVerify(\n        deadline: NIODeadline = .now() + .seconds(10),\n        _ verify: (ByteBuffer) throws -> Void = { _ in }\n    ) throws {\n        try verify(self.receiveBody(deadline: deadline))\n    }\n\n    /// Waits for a message part to be received and checks that it was a `.end` before returning\n    /// the `HTTPHeaders?` it contained.\n    ///\n    /// - Parameters:\n    ///   - deadline: The deadline by which a part must have been received.\n    /// - Throws: If the part was not a `.end` or nothing was read before the deadline.\n    /// - Returns: The `HTTPHeaders?` from the `.end`.\n    public func receiveEnd(deadline: NIODeadline = .now() + .seconds(10)) throws -> HTTPHeaders? {\n        let part = try self.readInbound(deadline: deadline)\n        switch part {\n        case .end(let trailers):\n            return trailers\n        default:\n            throw NIOHTTP1TestServerError(reason: \"Expected .end but got '\\(part)'\")\n        }\n    }\n\n    /// Waits for a message part to be received and checks that it was a `.end` before passing\n    /// it to the `verify` block.\n    ///\n    /// - Parameters:\n    ///   - deadline: The deadline by which a part must have been received.\n    ///   - verify: A closure which can be used to verify the contents of the `HTTPHeaders?`.\n    /// - Throws: If the part was not a `.end` or nothing was read before the deadline.\n    public func receiveEndAndVerify(\n        deadline: NIODeadline = .now() + .seconds(10),\n        _ verify: (HTTPHeaders?) throws -> Void = { _ in }\n    ) throws {\n        try verify(self.receiveEnd())\n    }\n}\n\npublic struct NIOHTTP1TestServerError: Error, Hashable, CustomStringConvertible {\n    public var reason: String\n\n    public init(reason: String) {\n        self.reason = reason\n    }\n\n    public var description: String {\n        self.reason\n    }\n}\n"
  },
  {
    "path": "Sources/NIOUDPEchoClient/README.md",
    "content": "# NIOUDPEchoClient\n\nThis sample application provides a simple UDP echo client that will send a single line to a UDP echo server and wait for a response. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOUDPEchoClient # Connects to a server on ::1, server UDP port 9999 and listening port 8888.\nswift run NIOUDPEchoClient 9899 9888 # Connects to a server on ::1, server UDP port 9899 and listening port 9888\nswift run NIOUDPEchoClient echo.example.com 9899 9888 # Connects to a server on echo.example.com:9899 and listens on UDP port 9888\n```\n\n"
  },
  {
    "path": "Sources/NIOUDPEchoClient/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOPosix\n\nprint(\"Please enter line to send to the server\")\nlet line = readLine(strippingNewline: true)!\n\nprivate final class EchoHandler: ChannelInboundHandler {\n    public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n    private var numBytes = 0\n\n    private let remoteAddressInitializer: () throws -> SocketAddress\n\n    init(remoteAddressInitializer: @escaping () throws -> SocketAddress) {\n        self.remoteAddressInitializer = remoteAddressInitializer\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n\n        do {\n            // Channel is available. It's time to send the message to the server to initialize the ping-pong sequence.\n\n            // Get the server address.\n            let remoteAddress = try self.remoteAddressInitializer()\n\n            // Set the transmission data.\n            let buffer = context.channel.allocator.buffer(string: line)\n            self.numBytes = buffer.readableBytes\n\n            // Forward the data.\n            let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buffer)\n\n            context.writeAndFlush(Self.wrapOutboundOut(envelope), promise: nil)\n\n        } catch {\n            print(\"Could not resolve remote address\")\n        }\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let envelope = Self.unwrapInboundIn(data)\n        let byteBuffer = envelope.data\n\n        self.numBytes -= byteBuffer.readableBytes\n\n        if self.numBytes <= 0 {\n            let string = String(buffer: byteBuffer)\n            print(\"Received: '\\(string)' back from the server, closing channel.\")\n            context.close(promise: nil)\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n}\n\n// First argument is the program path\nvar arguments = CommandLine.arguments\n// Support for `--connect` if it appears as the first argument.\nlet connectedMode: Bool\nif let connectedModeFlagIndex = arguments.firstIndex(where: { $0 == \"--connect\" }) {\n    connectedMode = true\n    arguments.remove(at: connectedModeFlagIndex)\n} else {\n    connectedMode = false\n}\n// Now process the positional arguments.\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst(2).first\nlet arg3 = arguments.dropFirst(3).first\n\n// If only writing to the destination address, bind to local port 0 and address 0.0.0.0 or ::.\nlet defaultHost = \"::1\"\n// If the server and the client are running on the same computer, these will need to differ from each other.\nlet defaultServerPort: Int = 9999\nlet defaultListeningPort: Int = 8888\n\nenum ConnectTo {\n    case ip(host: String, sendPort: Int, listeningPort: Int)\n    case unixDomainSocket(sendPath: String, listeningPath: String)\n}\n\nlet connectTarget: ConnectTo\n\nswitch (arg1, arg1.flatMap(Int.init), arg2, arg2.flatMap(Int.init), arg3.flatMap(Int.init)) {\ncase (.some(let h), .none, _, .some(let sp), .some(let lp)):\n    // We received three arguments (String Int Int), let's interpret that as a server host with a server port and a local listening port\n    connectTarget = .ip(host: h, sendPort: sp, listeningPort: lp)\ncase (.some(let sp), .none, .some(let lp), .none, _):\n    // We received two arguments (String String), let's interpret that as sending socket path and listening socket path\n    assert(sp != lp, \"The sending and listening sockets should differ.\")\n    connectTarget = .unixDomainSocket(sendPath: sp, listeningPath: lp)\ncase (_, .some(let sp), _, .some(let lp), _):\n    // We received two argument (Int Int), let's interpret that as the server port and a listening port on the default host.\n    connectTarget = .ip(host: defaultHost, sendPort: sp, listeningPort: lp)\ndefault:\n    connectTarget = .ip(host: defaultHost, sendPort: defaultServerPort, listeningPort: defaultListeningPort)\n}\n\nlet remoteAddress = { @Sendable () -> SocketAddress in\n    switch connectTarget {\n    case .ip(let host, let sendPort, _):\n        return try SocketAddress.makeAddressResolvingHost(host, port: sendPort)\n    case .unixDomainSocket(let sendPath, _):\n        return try SocketAddress(unixDomainSocketPath: sendPath)\n    }\n}\n\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\nlet bootstrap = DatagramBootstrap(group: group)\n    // Enable SO_REUSEADDR.\n    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n    .channelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandler(EchoHandler(remoteAddressInitializer: remoteAddress))\n        }\n    }\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\nlet channel = try { () -> Channel in\n    switch connectTarget {\n    case .ip(let host, _, let listeningPort):\n        return try bootstrap.bind(host: host, port: listeningPort).wait()\n    case .unixDomainSocket(_, let listeningPath):\n        return try bootstrap.bind(unixDomainSocketPath: listeningPath).wait()\n    }\n}()\n\nif connectedMode {\n    let remoteAddress = try remoteAddress()\n    print(\"Connecting to remote: \\(remoteAddress)\")\n    try channel.connect(to: remoteAddress).wait()\n}\n\n// Will be closed after we echo-ed back to the server.\ntry channel.closeFuture.wait()\n\nprint(\"Client closed\")\n"
  },
  {
    "path": "Sources/NIOUDPEchoServer/README.md",
    "content": "# NIOUDPEchoServer\n\nThis sample application provides a simple UDP echo server that sends clients back whatever data they send it. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOUDPEchoServer  # Binds the server on ::1, port 9999.\nswift run NIOUDPEchoServer 9899  # Binds the server on ::1, port 9899\nswift run NIOUDPEchoServer /path/to/unix/socket  # Binds the server using the given UNIX socket\nswift run NIOUDPEchoServer 192.168.0.5 9899  # Binds the server on 192.168.0.5:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOUDPEchoServer/main.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOPosix\n\nprivate final class EchoHandler: ChannelInboundHandler {\n    public typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    public typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.write(data, promise: nil)\n    }\n\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.flush()\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        print(\"error: \", error)\n\n        // As we are not really interested getting notified on success or failure we just pass nil as promise to\n        // reduce allocations.\n        context.close(promise: nil)\n    }\n}\n\n// We don't need more than one thread, as we're creating only one datagram channel.\nlet group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\nvar bootstrap = DatagramBootstrap(group: group)\n    // Specify backlog and enable SO_REUSEADDR\n    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n\n    // Set the handlers that are applied to the bound channel\n    .channelInitializer { channel in\n        channel.eventLoop.makeCompletedFuture {\n            try channel.pipeline.syncOperations.addHandler(EchoHandler())\n        }\n    }\n\ndefer {\n    try! group.syncShutdownGracefully()\n}\n\nvar arguments = CommandLine.arguments.dropFirst(0)  // just to get an ArraySlice<String> from [String]\nif arguments.dropFirst().first == .some(\"--enable-gathering-reads\") {\n    bootstrap = bootstrap.channelOption(.datagramVectorReadMessageCount, value: 30)\n    bootstrap = bootstrap.channelOption(\n        .recvAllocator,\n        value: FixedSizeRecvByteBufferAllocator(capacity: 30 * 2048)\n    )\n    arguments = arguments.dropFirst()\n}\nlet arg1 = arguments.dropFirst().first\nlet arg2 = arguments.dropFirst().dropFirst().first\n\nlet defaultHost = \"::1\"\nlet defaultPort = 9999\n\nenum BindTo {\n    case ip(host: String, port: Int)\n    case unixDomainSocket(path: String)\n}\n\nlet bindTarget: BindTo\nswitch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {\ncase (.some(let h), _, .some(let p)):\n    // we got two arguments, let's interpret that as host and port\n    bindTarget = .ip(host: h, port: p)\ncase (.some(let portString), .none, _):\n    // couldn't parse as number, expecting unix domain socket path\n    bindTarget = .unixDomainSocket(path: portString)\ncase (_, .some(let p), _):\n    // only one argument --> port\n    bindTarget = .ip(host: defaultHost, port: p)\ndefault:\n    bindTarget = .ip(host: defaultHost, port: defaultPort)\n}\n\nlet channel = try { () -> Channel in\n    switch bindTarget {\n    case .ip(let host, let port):\n        return try bootstrap.bind(host: host, port: port).wait()\n    case .unixDomainSocket(let path):\n        return try bootstrap.bind(unixDomainSocketPath: path).wait()\n    }\n}()\n\nprint(\"Server started and listening on \\(channel.localAddress!)\")\n\n// This will never unblock as we don't close the channel\ntry channel.closeFuture.wait()\n\nprint(\"Server closed\")\n"
  },
  {
    "path": "Sources/NIOWebSocket/NIOWebSocketClientUpgrader.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOHTTP1\nimport _NIOBase64\n\n@available(*, deprecated, renamed: \"NIOWebSocketClientUpgrader\")\npublic typealias NIOWebClientSocketUpgrader = NIOWebSocketClientUpgrader\n\n/// A `HTTPClientProtocolUpgrader` that knows how to do the WebSocket upgrade dance.\n///\n/// This upgrader assumes that the `HTTPClientUpgradeHandler` will create and send the upgrade request.\n/// This upgrader also assumes that the `HTTPClientUpgradeHandler` will appropriately mutate the\n/// pipeline to remove the HTTP `ChannelHandler`s.\npublic final class NIOWebSocketClientUpgrader: NIOHTTPClientProtocolUpgrader, Sendable {\n    /// RFC 6455 specs this as the required entry in the Upgrade header.\n    public let supportedProtocol: String = \"websocket\"\n    /// None of the websocket headers are actually defined as 'required'.\n    public let requiredUpgradeHeaders: [String] = []\n\n    private let requestKey: String\n    private let maxFrameSize: Int\n    private let automaticErrorHandling: Bool\n    private let upgradePipelineHandler: @Sendable (Channel, HTTPResponseHead) -> EventLoopFuture<Void>\n\n    /// - Parameters:\n    ///   - requestKey: sent to the server in the `Sec-WebSocket-Key` HTTP header. Default is random request key.\n    ///   - maxFrameSize: largest incoming `WebSocketFrame` size in bytes. Default is 16,384 bytes.\n    ///   - automaticErrorHandling: If true, adds `WebSocketProtocolErrorHandler` to the channel pipeline to catch and respond to WebSocket protocol errors. Default is true.\n    ///   - upgradePipelineHandler: called once the upgrade was successful\n    public init(\n        requestKey: String = randomRequestKey(),\n        maxFrameSize: Int = 1 << 14,\n        automaticErrorHandling: Bool = true,\n        upgradePipelineHandler: @escaping @Sendable (Channel, HTTPResponseHead) -> EventLoopFuture<Void>\n    ) {\n        precondition(requestKey != \"\", \"The request key must contain a valid Sec-WebSocket-Key\")\n        precondition(maxFrameSize <= UInt32.max, \"invalid overlarge max frame size\")\n        self.requestKey = requestKey\n        self.upgradePipelineHandler = upgradePipelineHandler\n        self.maxFrameSize = maxFrameSize\n        self.automaticErrorHandling = automaticErrorHandling\n    }\n\n    /// Add additional headers that are needed for a WebSocket upgrade request.\n    public func addCustom(upgradeRequestHeaders: inout HTTPHeaders) {\n        _addCustom(upgradeRequestHeaders: &upgradeRequestHeaders, requestKey: self.requestKey)\n    }\n\n    public func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n        _shouldAllowUpgrade(upgradeResponse: upgradeResponse, requestKey: self.requestKey)\n    }\n\n    public func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void> {\n        _upgrade(\n            channel: context.channel,\n            upgradeResponse: upgradeResponse,\n            maxFrameSize: self.maxFrameSize,\n            enableAutomaticErrorHandling: self.automaticErrorHandling,\n            upgradePipelineHandler: self.upgradePipelineHandler\n        )\n    }\n}\n\n/// A `NIOTypedHTTPClientProtocolUpgrader` that knows how to do the WebSocket upgrade dance.\n///\n/// This upgrader assumes that the `HTTPClientUpgradeHandler` will create and send the upgrade request.\n/// This upgrader also assumes that the `HTTPClientUpgradeHandler` will appropriately mutate the\n/// pipeline to remove the HTTP `ChannelHandler`s.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic final class NIOTypedWebSocketClientUpgrader<UpgradeResult: Sendable>: NIOTypedHTTPClientProtocolUpgrader {\n    /// RFC 6455 specs this as the required entry in the Upgrade header.\n    public let supportedProtocol: String = \"websocket\"\n    /// None of the websocket headers are actually defined as 'required'.\n    public let requiredUpgradeHeaders: [String] = []\n\n    private let requestKey: String\n    private let maxFrameSize: Int\n    private let enableAutomaticErrorHandling: Bool\n    private let upgradePipelineHandler: @Sendable (Channel, HTTPResponseHead) -> EventLoopFuture<UpgradeResult>\n\n    /// - Parameters:\n    ///   - requestKey: Sent to the server in the `Sec-WebSocket-Key` HTTP header. Default is random request key.\n    ///   - maxFrameSize: Largest incoming `WebSocketFrame` size in bytes. Default is 16,384 bytes.\n    ///   - enableAutomaticErrorHandling: If true, adds `WebSocketProtocolErrorHandler` to the channel pipeline to catch and respond to WebSocket protocol errors. Default is true.\n    ///   - upgradePipelineHandler: Called once the upgrade was successful.\n    public init(\n        requestKey: String = NIOWebSocketClientUpgrader.randomRequestKey(),\n        maxFrameSize: Int = 1 << 14,\n        enableAutomaticErrorHandling: Bool = true,\n        upgradePipelineHandler: @escaping @Sendable (Channel, HTTPResponseHead) -> EventLoopFuture<UpgradeResult>\n    ) {\n        precondition(requestKey != \"\", \"The request key must contain a valid Sec-WebSocket-Key\")\n        precondition(maxFrameSize <= UInt32.max, \"invalid overlarge max frame size\")\n        self.requestKey = requestKey\n        self.upgradePipelineHandler = upgradePipelineHandler\n        self.maxFrameSize = maxFrameSize\n        self.enableAutomaticErrorHandling = enableAutomaticErrorHandling\n    }\n\n    public func addCustom(upgradeRequestHeaders: inout NIOHTTP1.HTTPHeaders) {\n        _addCustom(upgradeRequestHeaders: &upgradeRequestHeaders, requestKey: self.requestKey)\n    }\n\n    public func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n        _shouldAllowUpgrade(upgradeResponse: upgradeResponse, requestKey: self.requestKey)\n    }\n\n    public func upgrade(channel: Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<UpgradeResult> {\n        _upgrade(\n            channel: channel,\n            upgradeResponse: upgradeResponse,\n            maxFrameSize: self.maxFrameSize,\n            enableAutomaticErrorHandling: self.enableAutomaticErrorHandling,\n            upgradePipelineHandler: self.upgradePipelineHandler\n        )\n    }\n}\n\nextension NIOWebSocketClientUpgrader {\n    /// Generates a random WebSocket Request Key by generating 16 bytes randomly and encoding them as a base64 string as defined in RFC6455 https://tools.ietf.org/html/rfc6455#section-4.1\n    /// - Parameter generator: the `RandomNumberGenerator` used as a the source of randomness\n    /// - Returns: base64 encoded request key\n    @inlinable\n    public static func randomRequestKey<Generator>(\n        using generator: inout Generator\n    ) -> String where Generator: RandomNumberGenerator {\n        var buffer = ByteBuffer()\n        buffer.reserveCapacity(minimumWritableBytes: 16)\n        /// we may want to use `randomBytes(count:)` once the proposal is accepted: https://forums.swift.org/t/pitch-requesting-larger-amounts-of-randomness-from-systemrandomnumbergenerator/27226\n        buffer.writeMultipleIntegers(\n            UInt64.random(in: UInt64.min...UInt64.max, using: &generator),\n            UInt64.random(in: UInt64.min...UInt64.max, using: &generator)\n        )\n        return String(_base64Encoding: buffer.readableBytesView)\n    }\n    /// Generates a random WebSocket Request Key by generating 16 bytes randomly using the `SystemRandomNumberGenerator` and encoding them as a base64 string as defined in RFC6455 https://tools.ietf.org/html/rfc6455#section-4.1.\n    /// - Returns: base64 encoded request key\n    @inlinable\n    public static func randomRequestKey() -> String {\n        var generator = SystemRandomNumberGenerator()\n        return NIOWebSocketClientUpgrader.randomRequestKey(using: &generator)\n    }\n}\n\n/// Add additional headers that are needed for a WebSocket upgrade request.\nprivate func _addCustom(upgradeRequestHeaders: inout HTTPHeaders, requestKey: String) {\n    upgradeRequestHeaders.add(name: \"Sec-WebSocket-Key\", value: requestKey)\n    upgradeRequestHeaders.add(name: \"Sec-WebSocket-Version\", value: \"13\")\n}\n\n/// Allow or deny the upgrade based on the upgrade HTTP response\n/// headers containing the correct accept key.\nprivate func _shouldAllowUpgrade(upgradeResponse: HTTPResponseHead, requestKey: String) -> Bool {\n    let acceptValueHeader = upgradeResponse.headers[\"Sec-WebSocket-Accept\"]\n\n    guard acceptValueHeader.count == 1 else {\n        return false\n    }\n\n    // Validate the response key in 'Sec-WebSocket-Accept'.\n    var hasher = SHA1()\n    hasher.update(string: requestKey)\n    hasher.update(string: magicWebSocketGUID)\n    let expectedAcceptValue = String(_base64Encoding: hasher.finish())\n\n    return expectedAcceptValue == acceptValueHeader[0]\n}\n\n/// Called when the upgrade response has been flushed and it is safe to mutate the channel\n/// pipeline. Adds channel handlers for websocket frame encoding, decoding and errors.\nprivate func _upgrade<UpgradeResult: Sendable>(\n    channel: Channel,\n    upgradeResponse: HTTPResponseHead,\n    maxFrameSize: Int,\n    enableAutomaticErrorHandling: Bool,\n    upgradePipelineHandler: @escaping @Sendable (Channel, HTTPResponseHead) -> EventLoopFuture<UpgradeResult>\n) -> EventLoopFuture<UpgradeResult> {\n    channel.eventLoop.makeCompletedFuture {\n        try channel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder())\n        try channel.pipeline.syncOperations.addHandler(\n            ByteToMessageHandler(WebSocketFrameDecoder(maxFrameSize: maxFrameSize))\n        )\n        if enableAutomaticErrorHandling {\n            try channel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler(isServer: false))\n        }\n    }\n    .flatMap {\n        upgradePipelineHandler(channel, upgradeResponse)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/NIOWebSocketFrameAggregator.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// `NIOWebSocketFrameAggregator` buffers inbound fragmented `WebSocketFrame`'s and aggregates them into a single `WebSocketFrame`.\n/// It guarantees that a `WebSocketFrame` with an `opcode` of `.continuation` is never forwarded.\n/// Frames which are not fragmented are just forwarded without any processing.\n/// Fragmented frames are unmasked, concatenated and forwarded as a new `WebSocketFrame` which is either a `.binary` or `.text` frame.\n/// `extensionData`, `rsv1`, `rsv2` and `rsv3` are lost if a frame is fragmented because they cannot be concatenated.\n/// - Note: `.ping`, `.pong`, `.closeConnection` frames are forwarded during frame aggregation\npublic final class NIOWebSocketFrameAggregator: ChannelInboundHandler {\n    public enum Error: Swift.Error {\n        case nonFinalFragmentSizeIsTooSmall\n        case tooManyFragments\n        case accumulatedFrameSizeIsTooLarge\n        case receivedNewFrameWithoutFinishingPrevious\n        case didReceiveFragmentBeforeReceivingTextOrBinaryFrame\n    }\n    public typealias InboundIn = WebSocketFrame\n    public typealias InboundOut = WebSocketFrame\n\n    private let minNonFinalFragmentSize: Int\n    private let maxAccumulatedFrameCount: Int\n    private let maxAccumulatedFrameSize: Int\n\n    private var bufferedFrames: [WebSocketFrame] = []\n    private var accumulatedFrameSize: Int = 0\n\n    /// Configures a `NIOWebSocketFrameAggregator`.\n    /// - Parameters:\n    ///   - minNonFinalFragmentSize: Minimum size in bytes of a fragment which is not the last fragment of a complete frame. Used to defend against many really small payloads.\n    ///   - maxAccumulatedFrameCount: Maximum number of fragments which are allowed to result in a complete frame.\n    ///   - maxAccumulatedFrameSize: Maximum accumulated size in bytes of buffered fragments. It is essentially the maximum allowed size of an incoming frame after all fragments are concatenated.\n    public init(\n        minNonFinalFragmentSize: Int,\n        maxAccumulatedFrameCount: Int,\n        maxAccumulatedFrameSize: Int\n    ) {\n        self.minNonFinalFragmentSize = minNonFinalFragmentSize\n        self.maxAccumulatedFrameCount = maxAccumulatedFrameCount\n        self.maxAccumulatedFrameSize = maxAccumulatedFrameSize\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let frame = NIOWebSocketFrameAggregator.unwrapInboundIn(data)\n        do {\n            switch frame.opcode {\n            case .continuation:\n                guard let firstFrameOpcode = self.bufferedFrames.first?.opcode else {\n                    throw Error.didReceiveFragmentBeforeReceivingTextOrBinaryFrame\n                }\n                try self.bufferFrame(frame)\n\n                guard frame.fin else { break }\n                // final frame received\n\n                let aggregatedFrame = self.aggregateFrames(\n                    opcode: firstFrameOpcode,\n                    allocator: context.channel.allocator\n                )\n                self.clearBuffer()\n\n                context.fireChannelRead(wrapInboundOut(aggregatedFrame))\n            case .binary, .text:\n                if frame.fin {\n                    guard self.bufferedFrames.isEmpty else {\n                        throw Error.receivedNewFrameWithoutFinishingPrevious\n                    }\n                    // fast path: no need to check any constraints nor unmask and copy data\n                    context.fireChannelRead(data)\n                } else {\n                    try self.bufferFrame(frame)\n                }\n            default:\n                // control frames can't be fragmented\n                context.fireChannelRead(data)\n            }\n        } catch {\n            // free memory early\n            self.clearBuffer()\n            context.fireErrorCaught(error)\n        }\n    }\n\n    private func bufferFrame(_ frame: WebSocketFrame) throws {\n        guard self.bufferedFrames.isEmpty || frame.opcode == .continuation else {\n            throw Error.receivedNewFrameWithoutFinishingPrevious\n        }\n        guard frame.fin || frame.length >= self.minNonFinalFragmentSize else {\n            throw Error.nonFinalFragmentSizeIsTooSmall\n        }\n        guard self.bufferedFrames.count < self.maxAccumulatedFrameCount else {\n            throw Error.tooManyFragments\n        }\n\n        // if this is not a final frame, we will at least receive one more frame\n        guard frame.fin || (self.bufferedFrames.count + 1) < self.maxAccumulatedFrameCount else {\n            throw Error.tooManyFragments\n        }\n\n        self.bufferedFrames.append(frame)\n        self.accumulatedFrameSize += frame.length\n\n        guard self.accumulatedFrameSize <= self.maxAccumulatedFrameSize else {\n            throw Error.accumulatedFrameSizeIsTooLarge\n        }\n    }\n\n    private func aggregateFrames(opcode: WebSocketOpcode, allocator: ByteBufferAllocator) -> WebSocketFrame {\n        var dataBuffer = allocator.buffer(capacity: self.accumulatedFrameSize)\n\n        for frame in self.bufferedFrames {\n            var unmaskedData = frame.unmaskedData\n            dataBuffer.writeBuffer(&unmaskedData)\n        }\n\n        return WebSocketFrame(fin: true, opcode: opcode, data: dataBuffer)\n    }\n\n    private func clearBuffer() {\n        self.bufferedFrames.removeAll(keepingCapacity: true)\n        self.accumulatedFrameSize = 0\n    }\n}\n\n@available(*, unavailable)\nextension NIOWebSocketFrameAggregator: Sendable {}\n"
  },
  {
    "path": "Sources/NIOWebSocket/NIOWebSocketServerUpgrader.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOSHA1\nimport NIOCore\nimport NIOHTTP1\nimport _NIOBase64\n\nlet magicWebSocketGUID = \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"\n\n@available(*, deprecated, renamed: \"NIOWebSocketServerUpgrader\")\npublic typealias WebSocketUpgrader = NIOWebSocketServerUpgrader\n\n/// Errors that can be thrown by `NIOWebSocket` during protocol upgrade.\npublic struct NIOWebSocketUpgradeError: Error, Equatable {\n    private enum ActualError {\n        case invalidUpgradeHeader\n        case unsupportedWebSocketTarget\n    }\n\n    private let actualError: ActualError\n\n    private init(actualError: ActualError) {\n        self.actualError = actualError\n    }\n    /// A HTTP header on the upgrade request was invalid.\n    public static let invalidUpgradeHeader = NIOWebSocketUpgradeError(actualError: .invalidUpgradeHeader)\n\n    /// The HTTP request targets a websocket pipeline that does not support\n    /// it in some way.\n    public static let unsupportedWebSocketTarget = NIOWebSocketUpgradeError(actualError: .unsupportedWebSocketTarget)\n}\n\nextension HTTPHeaders {\n    fileprivate func nonListHeader(_ name: String) throws -> String {\n        let fields = self[canonicalForm: name]\n        guard fields.count == 1 else {\n            throw NIOWebSocketUpgradeError.invalidUpgradeHeader\n        }\n        return String(fields.first!)\n    }\n}\n\n/// A `HTTPServerProtocolUpgrader` that knows how to do the WebSocket upgrade dance.\n///\n/// Users may frequently want to offer multiple websocket endpoints on the same port. For this\n/// reason, this `WebServerSocketUpgrader` only knows how to do the required parts of the upgrade and to\n/// complete the handshake. Users are expected to provide a callback that examines the HTTP headers\n/// (including the path) and determines whether this is a websocket upgrade request that is acceptable\n/// to them.\n///\n/// This upgrader assumes that the `HTTPServerUpgradeHandler` will appropriately mutate the pipeline to\n/// remove the HTTP `ChannelHandler`s.\npublic final class NIOWebSocketServerUpgrader: HTTPServerProtocolUpgrader, Sendable {\n\n    private typealias ShouldUpgrade = @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>\n    private typealias UpgradePipelineHandler = @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<Void>\n    /// RFC 6455 specs this as the required entry in the Upgrade header.\n    public let supportedProtocol: String = \"websocket\"\n\n    /// We deliberately do not actually set any required headers here, because the websocket\n    /// spec annoyingly does not actually force the client to send these in the Upgrade header,\n    /// which NIO requires. We check for these manually.\n    public let requiredUpgradeHeaders: [String] = []\n\n    private let shouldUpgrade: ShouldUpgrade\n    private let upgradePipelineHandler: UpgradePipelineHandler\n    private let maxFrameSize: Int\n    private let automaticErrorHandling: Bool\n\n    /// Create a new `NIOWebSocketServerUpgrader`.\n    ///\n    /// - Parameters:\n    ///   - automaticErrorHandling: Whether the pipeline should automatically handle protocol\n    ///         errors by sending error responses and closing the connection. Defaults to `true`,\n    ///         may be set to `false` if the user wishes to handle their own errors.\n    ///   - shouldUpgrade: A callback that determines whether the websocket request should be\n    ///         upgraded. This callback is responsible for creating a `HTTPHeaders` object with\n    ///         any headers that it needs on the response *except for* the `Upgrade`, `Connection`,\n    ///         and `Sec-WebSocket-Accept` headers, which this upgrader will handle. Should return\n    ///         an `EventLoopFuture` containing `nil` if the upgrade should be refused.\n    ///   - upgradePipelineHandler: A function that will be called once the upgrade response is\n    ///         flushed, and that is expected to mutate the `Channel` appropriately to handle the\n    ///         websocket protocol. This only needs to add the user handlers: the\n    ///         `WebSocketFrameEncoder` and `WebSocketFrameDecoder` will have been added to the\n    ///         pipeline automatically.\n    @preconcurrency\n    public convenience init(\n        automaticErrorHandling: Bool = true,\n        shouldUpgrade: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>,\n        upgradePipelineHandler: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<Void>\n    ) {\n        self.init(\n            maxFrameSize: 1 << 14,\n            automaticErrorHandling: automaticErrorHandling,\n            shouldUpgrade: shouldUpgrade,\n            upgradePipelineHandler: upgradePipelineHandler\n        )\n    }\n\n    /// Create a new `NIOWebSocketServerUpgrader`.\n    ///\n    /// - Parameters:\n    ///   - maxFrameSize: The maximum frame size the decoder is willing to tolerate from the\n    ///         remote peer. WebSockets in principle allows frame sizes up to `2**64` bytes, but\n    ///         this is an objectively unreasonable maximum value (on AMD64 systems it is not\n    ///         possible to even. Users may set this to any value up to `UInt32.max`.\n    ///   - automaticErrorHandling: Whether the pipeline should automatically handle protocol\n    ///         errors by sending error responses and closing the connection. Defaults to `true`,\n    ///         may be set to `false` if the user wishes to handle their own errors.\n    ///   - shouldUpgrade: A callback that determines whether the websocket request should be\n    ///         upgraded. This callback is responsible for creating a `HTTPHeaders` object with\n    ///         any headers that it needs on the response *except for* the `Upgrade`, `Connection`,\n    ///         and `Sec-WebSocket-Accept` headers, which this upgrader will handle. Should return\n    ///         an `EventLoopFuture` containing `nil` if the upgrade should be refused.\n    ///   - upgradePipelineHandler: A function that will be called once the upgrade response is\n    ///         flushed, and that is expected to mutate the `Channel` appropriately to handle the\n    ///         websocket protocol. This only needs to add the user handlers: the\n    ///         `WebSocketFrameEncoder` and `WebSocketFrameDecoder` will have been added to the\n    ///         pipeline automatically.\n    @preconcurrency\n    public convenience init(\n        maxFrameSize: Int,\n        automaticErrorHandling: Bool = true,\n        shouldUpgrade: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>,\n        upgradePipelineHandler: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<Void>\n    ) {\n        self.init(\n            _maxFrameSize: maxFrameSize,\n            automaticErrorHandling: automaticErrorHandling,\n            shouldUpgrade: shouldUpgrade,\n            upgradePipelineHandler: upgradePipelineHandler\n        )\n    }\n\n    private init(\n        _maxFrameSize maxFrameSize: Int,\n        automaticErrorHandling: Bool,\n        shouldUpgrade: @escaping ShouldUpgrade,\n        upgradePipelineHandler: @escaping UpgradePipelineHandler\n    ) {\n        precondition(maxFrameSize <= UInt32.max, \"invalid overlarge max frame size\")\n        self.shouldUpgrade = shouldUpgrade\n        self.upgradePipelineHandler = upgradePipelineHandler\n        self.maxFrameSize = maxFrameSize\n        self.automaticErrorHandling = automaticErrorHandling\n    }\n\n    public func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        _buildUpgradeResponse(\n            channel: channel,\n            upgradeRequest: upgradeRequest,\n            initialResponseHeaders: initialResponseHeaders,\n            shouldUpgrade: self.shouldUpgrade\n        )\n    }\n\n    public func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        _upgrade(\n            channel: context.channel,\n            upgradeRequest: upgradeRequest,\n            maxFrameSize: self.maxFrameSize,\n            automaticErrorHandling: self.automaticErrorHandling,\n            upgradePipelineHandler: self.upgradePipelineHandler\n        )\n    }\n}\n\n/// A `NIOTypedHTTPServerProtocolUpgrader` that knows how to do the WebSocket upgrade dance.\n///\n/// Users may frequently want to offer multiple websocket endpoints on the same port. For this\n/// reason, this `WebServerSocketUpgrader` only knows how to do the required parts of the upgrade and to\n/// complete the handshake. Users are expected to provide a callback that examines the HTTP headers\n/// (including the path) and determines whether this is a websocket upgrade request that is acceptable\n/// to them.\n///\n/// This upgrader assumes that the `HTTPServerUpgradeHandler` will appropriately mutate the pipeline to\n/// remove the HTTP `ChannelHandler`s.\npublic final class NIOTypedWebSocketServerUpgrader<UpgradeResult: Sendable>: NIOTypedHTTPServerProtocolUpgrader,\n    Sendable\n{\n    private typealias ShouldUpgrade = @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>\n    private typealias UpgradePipelineHandler = @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<UpgradeResult>\n\n    /// RFC 6455 specs this as the required entry in the Upgrade header.\n    public let supportedProtocol: String = \"websocket\"\n\n    /// We deliberately do not actually set any required headers here, because the websocket\n    /// spec annoyingly does not actually force the client to send these in the Upgrade header,\n    /// which NIO requires. We check for these manually.\n    public let requiredUpgradeHeaders: [String] = []\n\n    private let shouldUpgrade: ShouldUpgrade\n    private let upgradePipelineHandler: UpgradePipelineHandler\n    private let maxFrameSize: Int\n    private let enableAutomaticErrorHandling: Bool\n\n    /// Create a new ``NIOTypedWebSocketServerUpgrader``.\n    ///\n    /// - Parameters:\n    ///   - maxFrameSize: The maximum frame size the decoder is willing to tolerate from the\n    ///         remote peer. WebSockets in principle allows frame sizes up to `2**64` bytes, but\n    ///         this is an objectively unreasonable maximum value (on AMD64 systems it is not\n    ///         possible to even. Users may set this to any value up to `UInt32.max`.\n    ///   - enableAutomaticErrorHandling: Whether the pipeline should automatically handle protocol\n    ///         errors by sending error responses and closing the connection. Defaults to `true`,\n    ///         may be set to `false` if the user wishes to handle their own errors.\n    ///   - shouldUpgrade: A callback that determines whether the websocket request should be\n    ///         upgraded. This callback is responsible for creating a `HTTPHeaders` object with\n    ///         any headers that it needs on the response *except for* the `Upgrade`, `Connection`,\n    ///         and `Sec-WebSocket-Accept` headers, which this upgrader will handle. Should return\n    ///         an `EventLoopFuture` containing `nil` if the upgrade should be refused.\n    ///         `WebSocketFrameEncoder` and `WebSocketFrameDecoder` will have been added to the\n    ///         pipeline automatically.to WebSocket protocol errors. Default is true.\n    ///   - upgradePipelineHandler: called once the upgrade was successful.\n    public init(\n        maxFrameSize: Int = 1 << 14,\n        enableAutomaticErrorHandling: Bool = true,\n        shouldUpgrade: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>,\n        upgradePipelineHandler: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<UpgradeResult>\n    ) {\n        precondition(maxFrameSize <= UInt32.max, \"invalid overlarge max frame size\")\n        self.shouldUpgrade = shouldUpgrade\n        self.upgradePipelineHandler = upgradePipelineHandler\n        self.maxFrameSize = maxFrameSize\n        self.enableAutomaticErrorHandling = enableAutomaticErrorHandling\n    }\n\n    public func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        _buildUpgradeResponse(\n            channel: channel,\n            upgradeRequest: upgradeRequest,\n            initialResponseHeaders: initialResponseHeaders,\n            shouldUpgrade: self.shouldUpgrade\n        )\n    }\n\n    public func upgrade(channel: Channel, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<UpgradeResult> {\n        _upgrade(\n            channel: channel,\n            upgradeRequest: upgradeRequest,\n            maxFrameSize: self.maxFrameSize,\n            automaticErrorHandling: self.enableAutomaticErrorHandling,\n            upgradePipelineHandler: self.upgradePipelineHandler\n        )\n    }\n}\n\nprivate func _buildUpgradeResponse(\n    channel: Channel,\n    upgradeRequest: HTTPRequestHead,\n    initialResponseHeaders: HTTPHeaders,\n    shouldUpgrade: @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>\n) -> EventLoopFuture<HTTPHeaders> {\n    let key: String\n    let version: String\n\n    do {\n        key = try upgradeRequest.headers.nonListHeader(\"Sec-WebSocket-Key\")\n        version = try upgradeRequest.headers.nonListHeader(\"Sec-WebSocket-Version\")\n    } catch {\n        return channel.eventLoop.makeFailedFuture(error)\n    }\n\n    // The version must be 13.\n    guard version == \"13\" else {\n        return channel.eventLoop.makeFailedFuture(NIOWebSocketUpgradeError.invalidUpgradeHeader)\n    }\n\n    return shouldUpgrade(channel, upgradeRequest)\n        .flatMapThrowing { extraHeaders in\n            guard var extraHeaders = extraHeaders else {\n                throw NIOWebSocketUpgradeError.unsupportedWebSocketTarget\n            }\n\n            // Cool, we're good to go! Let's do our upgrade. We do this by concatenating the magic\n            // GUID to the base64-encoded key and taking a SHA1 hash of the result.\n            let acceptValue: String\n            do {\n                var hasher = SHA1()\n                hasher.update(string: key)\n                hasher.update(string: magicWebSocketGUID)\n                acceptValue = String(_base64Encoding: hasher.finish())\n            }\n\n            extraHeaders.replaceOrAdd(name: \"Upgrade\", value: \"websocket\")\n            extraHeaders.add(name: \"Sec-WebSocket-Accept\", value: acceptValue)\n            extraHeaders.replaceOrAdd(name: \"Connection\", value: \"upgrade\")\n\n            return extraHeaders\n        }\n}\n\nprivate func _upgrade<UpgradeResult: Sendable>(\n    channel: Channel,\n    upgradeRequest: HTTPRequestHead,\n    maxFrameSize: Int,\n    automaticErrorHandling: Bool,\n    upgradePipelineHandler: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<UpgradeResult>\n) -> EventLoopFuture<UpgradeResult> {\n    /// We never use the automatic error handling feature of the WebSocketFrameDecoder: we always use the separate channel\n    /// handler.\n    channel.eventLoop.makeCompletedFuture {\n        try channel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder())\n        try channel.pipeline.syncOperations.addHandler(\n            ByteToMessageHandler(WebSocketFrameDecoder(maxFrameSize: maxFrameSize))\n        )\n\n        if automaticErrorHandling {\n            try channel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler())\n        }\n    }.flatMap {\n        upgradePipelineHandler(channel, upgradeRequest)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/SHA1.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOSHA1\n\n/// A single SHA1 hasher.\n///\n/// This structure is basically a shim around the SHA1 C implementation from\n/// FreeBSD that can be found in `CNIOSHA1`. The fact that we are bringing our\n/// own SHA1 implementation along with us is a bit disappointing, but currently\n/// it is very difficult to use the operating system native libraries to get this\n/// done without forcing a hard dependency on our libressl bindings (which would\n/// bring along a dependency cycle for the ride).\n///\n/// We were disinclined to roll our own because we don't want to have to trust\n/// ourselves to get it right: the FreeBSD implementation here is battle-tested and\n/// extremely trustworthy, and so is a far better solution than rolling our own.\n///\n/// At some point in the future the Swift standard library or Foundation may include\n/// some hashing functions, or we may have platform-specific conditional deps in\n/// SwiftPM. Until that time, we commit the minor sin of needing to call into C for\n/// this.\ninternal struct SHA1 {\n    private var sha1Ctx: SHA1_CTX\n\n    /// Create a brand-new hash context.\n    init() {\n        self.sha1Ctx = SHA1_CTX()\n        c_nio_sha1_init(&self.sha1Ctx)\n    }\n\n    /// Feed the given string into the hash context as a sequence of UTF-8 bytes.\n    ///\n    /// - Parameters:\n    ///   - string: The string that will be UTF-8 encoded and fed into the\n    ///         hash context.\n    mutating func update(string: String) {\n        let isAvailable: ()? = string.utf8.withContiguousStorageIfAvailable {\n            self.update($0)\n        }\n        if isAvailable != nil {\n            return\n        }\n        let buffer = Array(string.utf8)\n        buffer.withUnsafeBufferPointer {\n            self.update($0)\n        }\n    }\n\n    /// Feed the bytes into the hash context.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to feed into the hash context.\n    mutating func update(_ bytes: UnsafeBufferPointer<UInt8>) {\n        c_nio_sha1_loop(&self.sha1Ctx, bytes.baseAddress!, bytes.count)\n    }\n\n    /// Complete the hashing.\n    ///\n    /// - Returns: A 20-byte array of bytes.\n    mutating func finish() -> [UInt8] {\n        var hashResult: [UInt8] = Array(repeating: 0, count: 20)\n        hashResult.withUnsafeMutableBufferPointer {\n            $0.baseAddress!.withMemoryRebound(to: Int8.self, capacity: 20) {\n                c_nio_sha1_result(&self.sha1Ctx, $0)\n            }\n        }\n        return hashResult\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/WebSocketErrorCodes.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// An enum that represents websocket error codes.\n///\n/// This enum provides names to all non-reserved code numbers,\n/// to avoid users needing to remember the specific numerical values\n/// of those codes.\npublic enum WebSocketErrorCode: Sendable {\n    /// Indicates a normal closure, meaning that the purpose for\n    /// which the connection was established has been fulfilled.\n    /// Corresponds to code 1000.\n    case normalClosure\n\n    /// Indicates that an endpoint is \"going away\", such as a server\n    /// going down or a browser having navigated away from a page.\n    /// Corresponds to code 1001.\n    case goingAway\n\n    /// Indicates that an endpoint is terminating the connection due\n    /// to a protocol error.\n    /// Corresponds to code 1002.\n    case protocolError\n\n    /// Indicates that an endpoint is terminating the connection\n    /// because it has received a type of data it cannot accept (e.g. an\n    /// endpoint that understands only text data may send this if it\n    /// receives a binary message).\n    /// Corresponds to code 1003.\n    case unacceptableData\n\n    /// Indicates that an endpoint is terminating the connection\n    /// because it has received data within a message that was not\n    /// consistent with the type of the message (e.g. non-UTF-8\n    /// data within a text message).\n    /// Corresponds to code 1007.\n    case dataInconsistentWithMessage\n\n    /// Indicates that an endpoint is terminating the connection\n    /// because it has received a message that violates its policy.  This\n    /// is a generic status code that can be returned when there is no\n    /// other more suitable status code (e.g. 1003 or 1009) or if there\n    /// is a need to hide specific details about the policy.\n    /// Corresponds to code 1008.\n    case policyViolation\n\n    /// Indicates that an endpoint is terminating the connection\n    /// because it has received a message that is too big for it to\n    /// process.\n    /// Corresponds to code 1009.\n    case messageTooLarge\n\n    /// Indicates that an endpoint (client) is terminating the\n    /// connection because it has expected the server to negotiate one or\n    /// more extension, but the server didn't return them in the response\n    /// message of the WebSocket handshake.  The list of extensions that\n    /// are needed should appear in the `reason` part of the Close frame.\n    /// Note that this status code is not used by the server, because it\n    /// can fail the WebSocket handshake instead.\n    /// Corresponds to code 1010.\n    case missingExtension\n\n    /// Indicates that a server is terminating the connection because\n    /// it encountered an unexpected condition that prevented it from\n    /// fulfilling the request.\n    /// Corresponds to code 1011.\n    case unexpectedServerError\n\n    /// We don't have a better name for this error code.\n    case unknown(UInt16)\n\n    /// Create an error code from a raw 16-bit integer as sent on the\n    /// network.\n    ///\n    /// - Parameters:\n    ///     integer: The integer form of the status code.\n    internal init(networkInteger integer: UInt16) {\n        switch integer {\n        case 1000:\n            self = .normalClosure\n        case 1001:\n            self = .goingAway\n        case 1002:\n            self = .protocolError\n        case 1003:\n            self = .unacceptableData\n        case 1007:\n            self = .dataInconsistentWithMessage\n        case 1008:\n            self = .policyViolation\n        case 1009:\n            self = .messageTooLarge\n        case 1010:\n            self = .missingExtension\n        case 1011:\n            self = .unexpectedServerError\n        default:\n            self = .unknown(integer)\n        }\n    }\n\n    /// Create an error code from an integer.\n    ///\n    /// Will trap if the error code is not in the valid range.\n    ///\n    /// - Parameters:\n    ///   - codeNumber: The integer form of the status code.\n    public init(codeNumber: Int) {\n        self.init(networkInteger: UInt16(codeNumber))\n    }\n}\n\nextension WebSocketErrorCode: Equatable {}\n\nextension ByteBuffer {\n    /// Read a websocket error code from a byte buffer.\n    ///\n    /// This method increments the reader index.\n    ///\n    /// - Returns: The error code, or `nil` if there were not enough readable bytes.\n    public mutating func readWebSocketErrorCode() -> WebSocketErrorCode? {\n        self.readInteger(as: UInt16.self).map { WebSocketErrorCode(networkInteger: $0) }\n    }\n\n    /// Get a websocket error code from a byte buffer.\n    ///\n    /// This method does not increment the reader index, and may be used to read an error\n    /// code from outside the readable range of bytes.\n    ///\n    /// - Parameters:\n    ///   - index: The index into the buffer to read the error code from.\n    /// - Returns: The error code, or `nil` if there were not enough bytes at that index.\n    public func getWebSocketErrorCode(at index: Int) -> WebSocketErrorCode? {\n        self.getInteger(at: index, as: UInt16.self).map { WebSocketErrorCode(networkInteger: $0) }\n    }\n\n    /// Write the given error code to the buffer.\n    ///\n    /// - Parameters:\n    ///   - code: The code to write into the buffer.\n    public mutating func write(webSocketErrorCode code: WebSocketErrorCode) {\n        self.writeInteger(UInt16(webSocketErrorCode: code))\n    }\n\n    /// Read a `WebSocketErrorCode` from 2 bytes at the current `readerIndex`. Does not move the reader index.\n    ///\n    /// This method is equivalent to calling `getWebSocketErrorCode(at: readerIndex)`.\n    ///\n    /// - Returns: The error code, or `nil` if there are not enough bytes to read the code.\n    @inlinable\n    public func peekWebSocketErrorCode() -> WebSocketErrorCode? {\n        self.getWebSocketErrorCode(at: self.readerIndex)\n    }\n}\n\nextension UInt16 {\n    /// Create a UInt16 corresponding to a given `WebSocketErrorCode`.\n    ///\n    /// - Parameters:\n    ///   - code: The `WebSocketErrorCode`.\n    public init(webSocketErrorCode code: WebSocketErrorCode) {\n        switch code {\n        case .normalClosure:\n            self = 1000\n        case .goingAway:\n            self = 1001\n        case .protocolError:\n            self = 1002\n        case .unacceptableData:\n            self = 1003\n        case .dataInconsistentWithMessage:\n            self = 1007\n        case .policyViolation:\n            self = 1008\n        case .messageTooLarge:\n            self = 1009\n        case .missingExtension:\n            self = 1010\n        case .unexpectedServerError:\n            self = 1011\n        case .unknown(let i):\n            self = i\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/WebSocketFrame.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nextension UInt8 {\n    @usableFromInline\n    internal func isAnyBitSetInMask(_ mask: UInt8) -> Bool {\n        self & mask != 0\n    }\n\n    @usableFromInline\n    internal mutating func changingBitsInMask(_ mask: UInt8, to: Bool) {\n        if to {\n            self |= mask\n        } else {\n            self &= ~mask\n        }\n    }\n}\n\n/// A single 4-byte websocket masking key.\n///\n/// WebSockets uses a masking key to prevent malicious users from injecting\n/// predictable binary sequences into websocket data streams. This structure provides\n/// a more convenient method of interacting with a masking key than simply by passing\n/// around a four-tuple.\npublic struct WebSocketMaskingKey: Sendable {\n    @usableFromInline internal let _key: (UInt8, UInt8, UInt8, UInt8)\n\n    public init?<T: Collection>(_ buffer: T) where T.Element == UInt8 {\n        guard buffer.count == 4 else {\n            return nil\n        }\n\n        self._key = (\n            buffer[buffer.startIndex],\n            buffer[buffer.index(buffer.startIndex, offsetBy: 1)],\n            buffer[buffer.index(buffer.startIndex, offsetBy: 2)],\n            buffer[buffer.index(buffer.startIndex, offsetBy: 3)]\n        )\n    }\n\n    /// Creates a websocket masking key from the network-encoded\n    /// representation.\n    ///\n    /// - Parameters:\n    ///   - integer: The encoded network representation of the\n    ///         masking key.\n    @usableFromInline\n    internal init(networkRepresentation integer: UInt32) {\n        self._key = (\n            UInt8((integer & 0xFF00_0000) >> 24),\n            UInt8((integer & 0x00FF_0000) >> 16),\n            UInt8((integer & 0x0000_FF00) >> 8),\n            UInt8(integer & 0x0000_00FF)\n        )\n    }\n}\n\nextension WebSocketMaskingKey: ExpressibleByArrayLiteral {\n    public typealias ArrayLiteralElement = UInt8\n\n    public init(arrayLiteral elements: UInt8...) {\n        precondition(elements.count == 4, \"WebSocketMaskingKeys must be exactly 4 bytes long\")\n        self.init(elements)!  // length precondition above\n    }\n}\n\nextension WebSocketMaskingKey {\n    /// Returns a random masking key, using the given generator as a source for randomness.\n    /// - Parameter generator: The random number generator to use when creating the\n    ///     new random masking key.\n    /// - Returns: A random masking key\n    @inlinable\n    public static func random<Generator>(\n        using generator: inout Generator\n    ) -> WebSocketMaskingKey where Generator: RandomNumberGenerator {\n        WebSocketMaskingKey(networkRepresentation: .random(in: UInt32.min...UInt32.max, using: &generator))\n    }\n\n    /// Returns a random masking key, using the `SystemRandomNumberGenerator` as a source for randomness.\n    /// - Returns: A random masking key\n    @inlinable\n    public static func random() -> WebSocketMaskingKey {\n        var generator = SystemRandomNumberGenerator()\n        return .random(using: &generator)\n    }\n}\n\nextension WebSocketMaskingKey: Equatable {\n    public static func == (lhs: WebSocketMaskingKey, rhs: WebSocketMaskingKey) -> Bool {\n        lhs._key == rhs._key\n    }\n}\n\nextension WebSocketMaskingKey: Collection {\n    public typealias Element = UInt8\n    public typealias Index = Int\n\n    public var startIndex: Int { 0 }\n    public var endIndex: Int { 4 }\n\n    public func index(after: Int) -> Int {\n        after + 1\n    }\n\n    public subscript(index: Int) -> UInt8 {\n        switch index {\n        case 0:\n            return self._key.0\n        case 1:\n            return self._key.1\n        case 2:\n            return self._key.2\n        case 3:\n            return self._key.3\n        default:\n            fatalError(\"Invalid index on WebSocketMaskingKey: \\(index)\")\n        }\n    }\n\n    @inlinable\n    public func withContiguousStorageIfAvailable<R>(_ body: (UnsafeBufferPointer<UInt8>) throws -> R) rethrows -> R? {\n        try withUnsafeBytes(of: self._key) { ptr in\n            // this is boilerplate necessary to convert from UnsafeRawBufferPointer to UnsafeBufferPointer<UInt8>\n            // we know ptr is bound since we defined self._key as let\n            let typedPointer = ptr.baseAddress?.assumingMemoryBound(to: UInt8.self)\n            let typedBufferPointer = UnsafeBufferPointer(start: typedPointer, count: ptr.count)\n            return try body(typedBufferPointer)\n        }\n    }\n}\n\n/// A structured representation of a single WebSocket frame.\npublic struct WebSocketFrame {\n    private var _storage: WebSocketFrame._Storage\n\n    /// The masking key, if any.\n    ///\n    /// A masking key is used to prevent specific byte sequences from appearing in the network\n    /// stream. This is primarily used by entities like browsers, but should be used any time it\n    /// is possible for a malicious user to control the data that appears in a websocket stream.\n    ///\n    /// If this value is `nil`, and this frame was *received from* the network, the data in `data`\n    /// is not masked. If this value is `nil`, and this frame is being *sent to* the network, the\n    /// data in `data` will not be masked.\n    public var maskKey: WebSocketMaskingKey? = nil\n\n    /// Rather than unpack all the fields from the first byte, and thus take up loads\n    /// of storage in the structure, we keep them in their packed form in this byte and\n    /// use computed properties to unpack them.\n    @usableFromInline\n    internal var firstByte: UInt8 = 0\n\n    /// The value of the `fin` bit. If set, this is the last frame in a fragmented frame. If not\n    /// set, this frame is one of the intermediate frames in a fragmented frame. Must be set if\n    /// a frame is not fragmented at all.\n    @inlinable\n    public var fin: Bool {\n        get {\n            self.firstByte.isAnyBitSetInMask(0x80)\n        }\n        set {\n            self.firstByte.changingBitsInMask(0x80, to: newValue)\n        }\n    }\n\n    /// The value of the first reserved bit. Must be `false` unless using an extension that defines its use.\n    @inlinable\n    public var rsv1: Bool {\n        get {\n            self.firstByte.isAnyBitSetInMask(0x40)\n        }\n        set {\n            self.firstByte.changingBitsInMask(0x40, to: newValue)\n        }\n    }\n\n    /// The value of the second reserved bit. Must be `false` unless using an extension that defines its use.\n    @inlinable\n    public var rsv2: Bool {\n        get {\n            self.firstByte.isAnyBitSetInMask(0x20)\n        }\n        set {\n            self.firstByte.changingBitsInMask(0x20, to: newValue)\n        }\n    }\n\n    /// The value of the third reserved bit. Must be `false` unless using an extension that defines its use.\n    @inlinable\n    public var rsv3: Bool {\n        get {\n            self.firstByte.isAnyBitSetInMask(0x10)\n        }\n        set {\n            self.firstByte.changingBitsInMask(0x10, to: newValue)\n        }\n    }\n\n    /// The opcode for this frame.\n    @inlinable\n    public var opcode: WebSocketOpcode {\n        get {\n            // this is a public initialiser which only fails if the opcode is invalid. But all opcodes in 0...0xF\n            // space are valid so this can never fail.\n            WebSocketOpcode(encodedWebSocketOpcode: firstByte & 0x0F)!\n        }\n        set {\n            self.firstByte = (self.firstByte & 0xF0) + UInt8(webSocketOpcode: newValue)\n        }\n    }\n\n    /// The total length of the data in the frame.\n    @inlinable\n    public var length: Int {\n        data.readableBytes + (extensionData?.readableBytes ?? 0)\n    }\n\n    /// The application data.\n    ///\n    /// On frames received from the network, this data is not necessarily unmasked. This is to provide as much\n    /// information as possible. If unmasked data is desired, either use the computed `unmaskedData` property to\n    /// obtain it, or transform this data directly by calling `data.unmask(maskKey)`.\n    public var data: ByteBuffer {\n        get {\n            self._storage.data\n        }\n        set {\n            if !isKnownUniquelyReferenced(&self._storage) {\n                self._storage = _Storage(copying: self._storage)\n            }\n            self._storage.data = newValue\n        }\n    }\n\n    /// The extension data, if any.\n    ///\n    /// On frames received from the network, this data is not necessarily unmasked. This is to provide as much\n    /// information as possible. If unmasked data is desired, either use the computed `unmaskedExtensionData` property to\n    /// obtain it, or transform this data directly by calling `extensionData.unmask(maskKey)`.\n    public var extensionData: ByteBuffer? {\n        get {\n            self._storage.extensionData\n        }\n        set {\n            if !isKnownUniquelyReferenced(&self._storage) {\n                self._storage = _Storage(copying: self._storage)\n            }\n            self._storage.extensionData = newValue\n        }\n    }\n\n    /// The unmasked application data.\n    ///\n    /// If a masking key is present on the frame, this property will automatically unmask the underlying data\n    /// and return the unmasked data to the user. This is a convenience method that should only be used when\n    /// persisting the underlying masked data is worthwhile: otherwise, performance will often be better to\n    /// manually unmask the data with `data.unmask(maskKey)`.\n    public var unmaskedData: ByteBuffer {\n        get {\n            guard let maskKey = self.maskKey else {\n                return self.data\n            }\n            var data = self.data\n            data.webSocketUnmask(maskKey, indexOffset: (self.extensionData?.readableBytes ?? 0) % 4)\n            return data\n        }\n    }\n\n    /// The unmasked extension data.\n    ///\n    /// If a masking key is present on the frame, this property will automatically unmask the underlying data\n    /// and return the unmasked data to the user. This is a convenience method that should only be used when\n    /// persisting the underlying masked data is worthwhile: otherwise, performance will often be better to\n    /// manually unmask the data with `data.unmask(maskKey)`.\n    public var unmaskedExtensionData: ByteBuffer? {\n        get {\n            guard let maskKey = self.maskKey else {\n                return self.extensionData\n            }\n            var extensionData = self.extensionData\n            extensionData?.webSocketUnmask(maskKey)\n            return extensionData\n        }\n    }\n\n    /// Creates an empty `WebSocketFrame`.\n    ///\n    /// - Parameters:\n    ///   - allocator: The `ByteBufferAllocator` to use when editing the empty buffers.\n    public init(allocator: ByteBufferAllocator) {\n        self._storage = .init(data: allocator.buffer(capacity: 0), extensionData: nil)\n    }\n\n    /// Create a `WebSocketFrame` with the given properties.\n    ///\n    /// - Parameters:\n    ///   - fin: The value of the `fin` bit. Defaults to `false`.\n    ///   - rsv1: The value of the first reserved bit. Defaults to `false`.\n    ///   - rsv2: The value of the second reserved bit. Defaults to `false`.\n    ///   - rsv3: The value of the third reserved bit. Defaults to `false`.\n    ///   - opcode: The opcode for the frame. Defaults to `.continuation`.\n    ///   - maskKey: The masking key for the frame, if any. Defaults to `nil`.\n    ///   - data: The application data for the frame.\n    ///   - extensionData: The extension data for the frame.\n    public init(\n        fin: Bool = false,\n        rsv1: Bool = false,\n        rsv2: Bool = false,\n        rsv3: Bool = false,\n        opcode: WebSocketOpcode = .continuation,\n        maskKey: WebSocketMaskingKey? = nil,\n        data: ByteBuffer,\n        extensionData: ByteBuffer? = nil\n    ) {\n        self._storage = .init(data: data, extensionData: extensionData)\n        self.fin = fin\n        self.rsv1 = rsv1\n        self.rsv2 = rsv2\n        self.rsv3 = rsv3\n        self.opcode = opcode\n        self.maskKey = maskKey\n    }\n\n    /// Create a `WebSocketFrame` from the underlying data representation.\n    internal init(firstByte: UInt8, maskKey: WebSocketMaskingKey?, applicationData: ByteBuffer) {\n        self._storage = .init(data: applicationData, extensionData: nil)\n        self.firstByte = firstByte\n        self.maskKey = maskKey\n    }\n}\n\nextension WebSocketFrame: @unchecked Sendable {}\n\nextension WebSocketFrame: Equatable {}\n\nextension WebSocketFrame {\n    fileprivate class _Storage {\n        var data: ByteBuffer\n        var extensionData: Optional<ByteBuffer>\n\n        fileprivate init(data: ByteBuffer, extensionData: ByteBuffer?) {\n            self.data = data\n            self.extensionData = extensionData\n        }\n\n        fileprivate init(copying original: WebSocketFrame._Storage) {\n            self.data = original.data\n            self.extensionData = original.extensionData\n        }\n    }\n}\n\n@available(*, unavailable)\nextension WebSocketFrame._Storage: Sendable {}\n\nextension WebSocketFrame._Storage: Equatable {\n    static func == (lhs: WebSocketFrame._Storage, rhs: WebSocketFrame._Storage) -> Bool {\n        lhs.data == rhs.data && lhs.extensionData == rhs.extensionData\n    }\n}\n\nextension WebSocketFrame: CustomStringConvertible {\n    /// A `String` describing this `WebSocketFrame`. Example:\n    ///\n    ///     WebSocketFrame {\n    ///     maskKey: Optional(NIOWebSocket.WebSocketMaskingKey(_key: (187, 28, 185, 79))),\n    ///     fin: true,\n    ///     rsv1: true,\n    ///     rsv2: true,\n    ///     rsv3: true,\n    ///     opcode: WebSocketOpcode.binary,\n    ///     length: 0,\n    ///     data: ByteBuffer { readerIndex: 0, writerIndex: 0, readableBytes: 0, capacity: 0, storageCapacity: 0, slice: _ByteBufferSlice { 0..<0 }, storage: 0x00006000028246b0 (0 bytes) },\n    ///     extensionData: nil,\n    ///     unmaskedData: ByteBuffer { readerIndex: 0, writerIndex: 0, readableBytes: 0, capacity: 0, storageCapacity: 0, slice: _ByteBufferSlice { 0..<0 }, storage: 0x0000600002824800 (0 bytes) },\n    ///     unmaskedDataExtension: nil\n    ///     }\n    ///\n    /// The format of the description is not API.\n    ///\n    /// - Returns: A description of this `WebSocketFrame`.\n    public var description: String {\n        \"\"\"\n        maskKey: \\(String(describing: self.maskKey)), \\\n        fin: \\(self.fin), \\\n        rsv1: \\(self.rsv1), \\\n        rsv2: \\(self.rsv2), \\\n        rsv3: \\(self.rsv3), \\\n        opcode: \\(self.opcode), \\\n        length: \\(self.length), \\\n        data: \\(String(describing: self.data)), \\\n        extensionData: \\(String(describing: self.extensionData)), \\\n        unmaskedData: \\(String(describing: self.unmaskedData)), \\\n        unmaskedDataExtension: \\(String(describing: self.unmaskedExtensionData))\n        \"\"\"\n    }\n}\n\nextension WebSocketFrame: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        \"(\\(self.description))\"\n    }\n}\n\nextension WebSocketFrame {\n    /// WebSocketFrame reserved bits option set\n    public struct ReservedBits: OptionSet, Sendable {\n        public var rawValue: UInt8\n\n        @inlinable\n        public init(rawValue: UInt8) {\n            self.rawValue = rawValue\n        }\n\n        @inlinable\n        public static var rsv1: Self { .init(rawValue: 0x40) }\n        @inlinable\n        public static var rsv2: Self { .init(rawValue: 0x20) }\n        @inlinable\n        public static var rsv3: Self { .init(rawValue: 0x10) }\n        @inlinable\n        public static var all: Self { .init(rawValue: 0x70) }\n    }\n\n    /// The value of all the reserved bits. Must be `empty` unless using an extension that defines their use.\n    @inlinable\n    public var reservedBits: ReservedBits {\n        get {\n            .init(rawValue: self.firstByte & 0x70)\n        }\n        set {\n            self.firstByte = (self.firstByte & 0x8F) + newValue.rawValue\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/WebSocketFrameDecoder.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Errors thrown by the NIO websocket module.\npublic enum NIOWebSocketError: Error {\n    /// The frame being sent is larger than the configured maximum\n    /// acceptable frame size\n    case invalidFrameLength\n\n    /// A control frame may not be fragmented.\n    case fragmentedControlFrame\n\n    /// A control frame may not have a length more than 125 bytes.\n    case multiByteControlFrameLength\n}\n\nextension WebSocketErrorCode {\n    init(_ error: NIOWebSocketError) {\n        switch error {\n        case .invalidFrameLength:\n            self = .messageTooLarge\n        case .fragmentedControlFrame,\n            .multiByteControlFrameLength:\n            self = .protocolError\n        }\n    }\n}\n\nextension ByteBuffer {\n    /// Applies the WebSocket unmasking operation.\n    ///\n    /// - Parameters:\n    ///   - maskingKey: The masking key.\n    ///   - indexOffset: An integer offset to apply to the index into the masking key.\n    ///         This is used when masking multiple \"contiguous\" byte buffers, to ensure that\n    ///         the masking key is applied uniformly to the collection rather than from the\n    ///         start each time.\n    public mutating func webSocketUnmask(_ maskingKey: WebSocketMaskingKey, indexOffset: Int = 0) {\n        /// Shhhh: secretly unmasking and masking are the same operation!\n        webSocketMask(maskingKey, indexOffset: indexOffset)\n    }\n\n    /// Applies the websocket masking operation.\n    ///\n    /// - Parameters:\n    ///   - maskingKey: The masking key.\n    ///   - indexOffset: An integer offset to apply to the index into the masking key.\n    ///         This is used when masking multiple \"contiguous\" byte buffers, to ensure that\n    ///         the masking key is applied uniformly to the collection rather than from the\n    ///         start each time.\n    public mutating func webSocketMask(_ maskingKey: WebSocketMaskingKey, indexOffset: Int = 0) {\n        self.withUnsafeMutableReadableBytes {\n            for (index, byte) in $0.enumerated() {\n                $0[index] = byte ^ maskingKey[(index + indexOffset) % 4]\n            }\n        }\n    }\n}\n\n/// The current state of the frame decoder.\nenum DecoderState {\n    /// Waiting for a frame.\n    case idle\n\n    /// The initial frame byte has been received, but the length byte\n    /// has not.\n    case firstByteReceived(firstByte: UInt8)\n\n    /// The length byte indicates that we need to wait for the length word, and we're\n    /// currently waiting for it.\n    case waitingForLengthWord(firstByte: UInt8, masked: Bool)\n\n    /// The length byte indicates that we need to wait for the length qword, and\n    /// we're currently waiting for it.\n    case waitingForLengthQWord(firstByte: UInt8, masked: Bool)\n\n    /// The mask bit indicates we are expecting a mask key.\n    case waitingForMask(firstByte: UInt8, length: Int)\n\n    /// All the header data is complete, we are waiting for the application data.\n    case waitingForData(firstByte: UInt8, length: Int, maskingKey: WebSocketMaskingKey?)\n}\n\nenum ParseResult {\n    case insufficientData\n    case continueParsing\n    case result(WebSocketFrame)\n}\n\n/// An incremental websocket frame parser.\n///\n/// This parser attempts to parse a websocket frame incrementally, keeping as much parsing state around as possible to ensure that\n/// we don't repeatedly partially parse the data.\nstruct WSParser {\n    /// The current state of the decoder during incremental parse.\n    var state: DecoderState = .idle\n\n    mutating func parseStep(_ buffer: inout ByteBuffer) -> ParseResult {\n        switch self.state {\n        case .idle:\n            // This is a new buffer. We want to find the first octet and save it off.\n            guard let firstByte = buffer.readInteger(as: UInt8.self) else {\n                return .insufficientData\n            }\n            self.state = .firstByteReceived(firstByte: firstByte)\n            return .continueParsing\n\n        case .firstByteReceived(let firstByte):\n            // Now we're looking for the length. We begin by finding the length byte to see if we\n            // need any more data.\n            guard let lengthByte = buffer.readInteger(as: UInt8.self) else {\n                return .insufficientData\n            }\n\n            let masked = (lengthByte & 0x80) != 0\n\n            switch (lengthByte & 0x7F, masked) {\n            case (126, _):\n                self.state = .waitingForLengthWord(firstByte: firstByte, masked: masked)\n            case (127, _):\n                self.state = .waitingForLengthQWord(firstByte: firstByte, masked: masked)\n            case (let len, true):\n                assert(len <= 125)\n                self.state = .waitingForMask(firstByte: firstByte, length: Int(len))\n            case (let len, false):\n                assert(len <= 125)\n                self.state = .waitingForData(firstByte: firstByte, length: Int(len), maskingKey: nil)\n            }\n            return .continueParsing\n\n        case .waitingForLengthWord(let firstByte, let masked):\n            // We've got a one-word length here.\n            guard let lengthWord = buffer.readInteger(as: UInt16.self) else {\n                return .insufficientData\n            }\n\n            if masked {\n                self.state = .waitingForMask(firstByte: firstByte, length: Int(lengthWord))\n            } else {\n                self.state = .waitingForData(firstByte: firstByte, length: Int(lengthWord), maskingKey: nil)\n            }\n            return .continueParsing\n\n        case .waitingForLengthQWord(let firstByte, let masked):\n            // We've got a qword of length here.\n            guard let lengthQWord = buffer.readInteger(as: UInt64.self) else {\n                return .insufficientData\n            }\n\n            if masked {\n                self.state = .waitingForMask(firstByte: firstByte, length: Int(lengthQWord))\n            } else {\n                self.state = .waitingForData(firstByte: firstByte, length: Int(lengthQWord), maskingKey: nil)\n            }\n            return .continueParsing\n\n        case .waitingForMask(let firstByte, let length):\n            // We're waiting for the masking key.\n            guard let maskingKey = buffer.readInteger(as: UInt32.self) else {\n                return .insufficientData\n            }\n\n            self.state = .waitingForData(\n                firstByte: firstByte,\n                length: length,\n                maskingKey: WebSocketMaskingKey(networkRepresentation: maskingKey)\n            )\n            return .continueParsing\n\n        case .waitingForData(let firstByte, let length, let maskingKey):\n            guard let data = buffer.readSlice(length: length) else {\n                return .insufficientData\n            }\n\n            let frame = WebSocketFrame(firstByte: firstByte, maskKey: maskingKey, applicationData: data)\n            self.state = .idle\n            return .result(frame)\n        }\n    }\n\n    /// Apply a number of validations to the incremental state, ensuring that the frame we're\n    /// receiving is valid.\n    func validateState(maxFrameSize: Int) throws {\n        switch self.state {\n        case .waitingForMask(let firstByte, let length), .waitingForData(let firstByte, let length, _):\n            if length > maxFrameSize {\n                throw NIOWebSocketError.invalidFrameLength\n            }\n\n            let isControlFrame = (firstByte & 0x08) != 0\n            let isFragment = (firstByte & 0x80) == 0\n\n            if isControlFrame && isFragment {\n                throw NIOWebSocketError.fragmentedControlFrame\n            }\n            if isControlFrame && length > 125 {\n                throw NIOWebSocketError.multiByteControlFrameLength\n            }\n        case .idle, .firstByteReceived, .waitingForLengthWord, .waitingForLengthQWord:\n            // No validation necessary in this state as we have no length to validate.\n            break\n        }\n    }\n}\n\n/// An inbound `ChannelHandler` that deserializes websocket frames into a structured\n/// format for further processing.\n///\n/// This decoder has limited enforcement of compliance to RFC 6455. In particular, to guarantee\n/// that the decoder can handle arbitrary extensions, only normative MUST/MUST NOTs that do not\n/// relate to extensions (e.g. the requirement that control frames not have lengths larger than\n/// 125 bytes) are enforced by this decoder.\n///\n/// This decoder does not have any support for decoding extensions. If you wish to support\n/// extensions, you should implement a message-to-message decoder that performs the appropriate\n/// frame transformation as needed. All the frame data is assumed to be application data by this\n/// parser.\npublic final class WebSocketFrameDecoder: ByteToMessageDecoder {\n    public typealias InboundIn = ByteBuffer\n    public typealias InboundOut = WebSocketFrame\n    public typealias OutboundOut = WebSocketFrame\n\n    /// The maximum frame size the decoder is willing to tolerate from the remote peer.\n    let maxFrameSize: Int\n\n    /// Our parser state.\n    private var parser = WSParser()\n\n    /// Construct a new `WebSocketFrameDecoder`\n    ///\n    /// - Parameters:\n    ///   - maxFrameSize: The maximum frame size the decoder is willing to tolerate from the\n    ///         remote peer. WebSockets in principle allows frame sizes up to `2**64` bytes, but\n    ///         this is an objectively unreasonable maximum value (on AMD64 systems it is not\n    ///         possible to even allocate a buffer large enough to handle this size), so we\n    ///         set a lower one. The default value is the same as the default HTTP/2 max frame\n    ///         size, `2**14` bytes. Users may override this to any value up to `UInt32.max`.\n    ///         Users are strongly encouraged not to increase this value unless they absolutely\n    ///         must, as the decoder will not produce partial frames, meaning that it will hold\n    ///         on to data until the *entire* body is received.\n    public init(maxFrameSize: Int = 1 << 14) {\n        precondition(maxFrameSize <= UInt32.max, \"invalid overlarge max frame size\")\n        self.maxFrameSize = maxFrameSize\n    }\n\n    public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        // Even though the calling code will loop around calling us in `decode`, we can't quite\n        // rely on that: sometimes we have zero-length elements to parse, and the caller doesn't\n        // guarantee to call us with zero-length bytes.\n        while true {\n            switch parser.parseStep(&buffer) {\n            case .result(let frame):\n                context.fireChannelRead(WebSocketFrameDecoder.wrapInboundOut(frame))\n                return .continue\n            case .continueParsing:\n                try self.parser.validateState(maxFrameSize: self.maxFrameSize)\n            // loop again, might be 'waiting' for 0 bytes\n            case .insufficientData:\n                return .needMoreData\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension WebSocketFrameDecoder: Sendable {}\n"
  },
  {
    "path": "Sources/NIOWebSocket/WebSocketFrameEncoder.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nprivate let maxOneByteSize = 125\nprivate let maxTwoByteSize = Int(UInt16.max)\n#if arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n// on 32-bit platforms we can't put a whole UInt32 in an Int\nprivate let maxNIOFrameSize = Int(UInt32.max / 2)\n#else\n// on 64-bit platforms this works just fine\nprivate let maxNIOFrameSize = Int(UInt32.max)\n#endif\n\n/// An inbound `ChannelHandler` that serializes structured websocket frames into a byte stream\n/// for sending on the network.\n///\n/// This encoder has limited enforcement of compliance to RFC 6455. In particular, to guarantee\n/// that the encoder can handle arbitrary extensions, only normative MUST/MUST NOTs that do not\n/// relate to extensions (e.g. the requirement that control frames not have lengths larger than\n/// 125 bytes) are enforced by this encoder.\n///\n/// This encoder does not have any support for encoder extensions. If you wish to support\n/// extensions, you should implement a message-to-message encoder that performs the appropriate\n/// frame transformation as needed.\npublic final class WebSocketFrameEncoder: ChannelOutboundHandler {\n    public typealias OutboundIn = WebSocketFrame\n    public typealias OutboundOut = ByteBuffer\n\n    /// This buffer is used to write frame headers into. We hold a buffer here as it's possible we'll be\n    /// able to avoid some allocations by re-using it.\n    private var headerBuffer: ByteBuffer? = nil\n\n    /// The maximum size of a websocket frame header. One byte for the frame \"first byte\", one more for the first\n    /// length byte and the mask bit, potentially up to 8 more bytes for a 64-bit length field, and potentially 4 bytes\n    /// for a mask key.\n    private static let maximumFrameHeaderLength: Int = (2 + 4 + 8)\n\n    public init() {}\n\n    public func handlerAdded(context: ChannelHandlerContext) {\n        self.headerBuffer = context.channel.allocator.buffer(capacity: WebSocketFrameEncoder.maximumFrameHeaderLength)\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        self.headerBuffer = nil\n    }\n\n    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let data = WebSocketFrameEncoder.unwrapOutboundIn(data)\n\n        // First, we explode the frame structure and apply the mask.\n        let frameHeader = FrameHeader(frame: data)\n        var (extensionData, applicationData) = self.mask(\n            key: frameHeader.maskKey,\n            extensionData: data.extensionData,\n            applicationData: data.data\n        )\n\n        // Now we attempt to prepend the frame header to the first buffer. If we can't, we'll write to the header buffer. If we have\n        // an extension data buffer, that's the first buffer, and we'll also write it here.\n        if var unwrappedExtensionData = extensionData {\n            extensionData = nil  // Again, forcibly nil to drop the reference.\n\n            if !unwrappedExtensionData.prependFrameHeaderIfPossible(frameHeader) {\n                self.writeSeparateHeaderBuffer(frameHeader, context: context)\n            }\n            context.write(WebSocketFrameEncoder.wrapOutboundOut(unwrappedExtensionData), promise: nil)\n        } else if !applicationData.prependFrameHeaderIfPossible(frameHeader) {\n            self.writeSeparateHeaderBuffer(frameHeader, context: context)\n        }\n\n        // Ok, now we need to write the application data buffer.\n        context.write(WebSocketFrameEncoder.wrapOutboundOut(applicationData), promise: promise)\n    }\n\n    /// Applies the websocket masking operation based on the passed byte buffers.\n    private func mask(\n        key: WebSocketMaskingKey?,\n        extensionData: ByteBuffer?,\n        applicationData: ByteBuffer\n    ) -> (ByteBuffer?, ByteBuffer) {\n        guard let key = key else {\n            return (extensionData, applicationData)\n        }\n\n        // We take local \"copies\" here. This is only an issue if someone else is holding onto the parent buffers.\n        var extensionData = extensionData\n        var applicationData = applicationData\n\n        extensionData?.webSocketMask(key)\n        applicationData.webSocketMask(key, indexOffset: (extensionData?.readableBytes ?? 0) % 4)\n        return (extensionData, applicationData)\n    }\n\n    private func writeSeparateHeaderBuffer(_ frameHeader: FrameHeader, context: ChannelHandlerContext) {\n        // Grab the header buffer. We nil it out while we're in this call to avoid the risk of CoWing when we\n        // write to it.\n        guard var buffer = self.headerBuffer else {\n            fatalError(\"Channel handler lifecycle violated: did not allocate header buffer\")\n        }\n        self.headerBuffer = nil\n\n        // We couldn't prepend the frame header, write it to the header buffer.\n        buffer.clear()\n        buffer.writeFrameHeader(frameHeader)\n\n        // Ok, frame header away! Before we send it we save it back onto ourselves in case we get recursively called.\n        self.headerBuffer = buffer\n        context.write(WebSocketFrameEncoder.wrapOutboundOut(buffer), promise: nil)\n    }\n}\n\n@available(*, unavailable)\nextension WebSocketFrameEncoder: Sendable {}\n\nextension ByteBuffer {\n    fileprivate mutating func prependFrameHeaderIfPossible(_ frameHeader: FrameHeader) -> Bool {\n        let written: Int? = self.modifyIfUniquelyOwned { buffer in\n            let startIndex = buffer.readerIndex - frameHeader.requiredBytes\n\n            guard startIndex >= 0 else {\n                return 0\n            }\n\n            let written = buffer.setFrameHeader(frameHeader, at: startIndex)\n            buffer.moveReaderIndex(to: startIndex)\n            return written\n        }\n\n        switch written {\n        case .none, .some(0):\n            return false\n        case .some(let x):\n            assert(x == frameHeader.requiredBytes)\n            return true\n        }\n    }\n\n    @discardableResult\n    fileprivate mutating func writeFrameHeader(_ frameHeader: FrameHeader) -> Int {\n        let written = self.setFrameHeader(frameHeader, at: self.writerIndex)\n        self.moveWriterIndex(forwardBy: written)\n        return written\n    }\n\n    @discardableResult\n    private mutating func setFrameHeader(_ frameHeader: FrameHeader, at index: Int) -> Int {\n        var writeIndex = index\n\n        // Calculate some information about the mask.\n        let maskBitMask: UInt8 = frameHeader.maskKey != nil ? 0x80 : 0x00\n        let frameLength = frameHeader.length\n\n        // Time to add the extra bytes. To avoid checking this twice, we also start writing stuff out here.\n        switch frameLength {\n        case 0...maxOneByteSize:\n            writeIndex += self.setInteger(frameHeader.firstByte, at: writeIndex)\n            writeIndex += self.setInteger(UInt8(frameLength) | maskBitMask, at: writeIndex)\n        case (maxOneByteSize + 1)...maxTwoByteSize:\n            writeIndex += self.setInteger(frameHeader.firstByte, at: writeIndex)\n            writeIndex += self.setInteger(UInt8(126) | maskBitMask, at: writeIndex)\n            writeIndex += self.setInteger(UInt16(frameLength), at: writeIndex)\n        case (maxTwoByteSize + 1)...maxNIOFrameSize:\n            writeIndex += self.setInteger(frameHeader.firstByte, at: writeIndex)\n            writeIndex += self.setInteger(UInt8(127) | maskBitMask, at: writeIndex)\n            writeIndex += self.setInteger(UInt64(frameLength), at: writeIndex)\n        default:\n            fatalError(\"NIO cannot serialize frames longer than \\(maxNIOFrameSize)\")\n        }\n\n        if let maskKey = frameHeader.maskKey {\n            writeIndex += self.setBytes(maskKey, at: writeIndex)\n        }\n\n        return writeIndex - index\n    }\n}\n\n/// A helper object that holds only a websocket frame header. Used to avoid accidentally CoWing on some paths.\nprivate struct FrameHeader {\n    var length: Int\n    var maskKey: WebSocketMaskingKey?\n    var firstByte: UInt8 = 0\n\n    init(frame: WebSocketFrame) {\n        self.maskKey = frame.maskKey\n        self.firstByte = frame.firstByte\n        self.length = frame.length\n    }\n\n    var requiredBytes: Int {\n        var size = 2  // First byte and initial length byte\n\n        switch self.length {\n        case 0...maxOneByteSize:\n            // Only requires the initial length byte\n            break\n        case (maxOneByteSize + 1)...maxTwoByteSize:\n            // Requires an extra UInt16\n            size += MemoryLayout<UInt16>.size\n        case (maxTwoByteSize + 1)...maxNIOFrameSize:\n            size += MemoryLayout<UInt64>.size\n        default:\n            fatalError(\"NIO cannot serialize frames longer than \\(maxNIOFrameSize)\")\n        }\n\n        if maskKey != nil {\n            size += 4  // Masking key\n        }\n\n        return size\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/WebSocketOpcode.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// An operation code for a websocket frame.\npublic struct WebSocketOpcode: Sendable {\n    @usableFromInline\n    let networkRepresentation: UInt8\n\n    @inlinable\n    public static var continuation: WebSocketOpcode {\n        WebSocketOpcode(rawValue: 0x0)\n    }\n\n    @inlinable\n    public static var text: WebSocketOpcode {\n        WebSocketOpcode(rawValue: 0x1)\n    }\n\n    @inlinable\n    public static var binary: WebSocketOpcode {\n        WebSocketOpcode(rawValue: 0x2)\n    }\n\n    @inlinable\n    public static var connectionClose: WebSocketOpcode {\n        WebSocketOpcode(rawValue: 0x8)\n    }\n\n    @inlinable\n    public static var ping: WebSocketOpcode {\n        WebSocketOpcode(rawValue: 0x9)\n    }\n\n    @inlinable\n    public static var pong: WebSocketOpcode {\n        WebSocketOpcode(rawValue: 0xA)\n    }\n\n    /// Create an opcode from the encoded representation.\n    ///\n    /// - Parameters\n    ///   - encoded: The encoded representation of the opcode as an 8-bit integer.\n    ///          Must be no more than 4 bits large.\n    @inlinable\n    public init?(encodedWebSocketOpcode encoded: UInt8) {\n        guard encoded < 0x10 else {\n            return nil\n        }\n\n        self.networkRepresentation = encoded\n    }\n\n    /// Create an opcode directly with no validation.\n    ///\n    /// Used only to create the static vars on this structure.\n    @inlinable\n    init(rawValue: UInt8) {\n        self.networkRepresentation = rawValue\n    }\n\n    /// Whether the opcode is in the control range: that is, if the\n    /// high bit of the opcode nibble is `1`.\n    @inlinable\n    public var isControlOpcode: Bool {\n        self.networkRepresentation & 0x8 == 0x8\n    }\n}\n\nextension WebSocketOpcode: Equatable {}\n\nextension WebSocketOpcode: Hashable {}\n\nextension WebSocketOpcode: CaseIterable {\n    @inlinable\n    public static var allCases: [WebSocketOpcode] {\n        get { (0..<0x10).map { WebSocketOpcode(rawValue: $0) } }\n\n        @available(*, deprecated)\n        set {}\n    }\n}\n\nextension WebSocketOpcode: CustomStringConvertible {\n    public var description: String {\n        switch self {\n        case .continuation:\n            return \"WebSocketOpcode.continuation\"\n        case .text:\n            return \"WebSocketOpcode.text\"\n        case .binary:\n            return \"WebSocketOpcode.binary\"\n        case .connectionClose:\n            return \"WebSocketOpcode.connectionClose\"\n        case .ping:\n            return \"WebSocketOpcode.ping\"\n        case .pong:\n            return \"WebSocketOpcode.pong\"\n        case let x where x.isControlOpcode:\n            return \"WebSocketOpcode.unknownControl(\\(x.networkRepresentation))\"\n        case let x:\n            return \"WebSocketOpcode.unknownNonControl(\\(x.networkRepresentation))\"\n        }\n    }\n}\n\nextension UInt8 {\n    /// Create a UInt8 corresponding to a given `WebSocketOpcode`.\n    ///\n    /// This places the opcode in the four least-significant bits, in\n    /// a form suitable for sending on the wire.\n    ///\n    /// - Parameters:\n    ///   - opcode: The `WebSocketOpcode`.\n    @inlinable\n    public init(webSocketOpcode opcode: WebSocketOpcode) {\n        precondition(opcode.networkRepresentation < 0x10)\n        self = opcode.networkRepresentation\n    }\n}\n\nextension Int {\n    /// Create a UInt8 corresponding to the integer value for a given `WebSocketOpcode`.\n    ///\n    /// - Parameters:\n    ///   - opcode: The `WebSocketOpcode`.\n    @inlinable\n    public init(webSocketOpcode opcode: WebSocketOpcode) {\n        precondition(opcode.networkRepresentation < 0x10)\n        self = Int(opcode.networkRepresentation)\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocket/WebSocketProtocolErrorHandler.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\n\n/// A simple `ChannelHandler` that catches protocol errors emitted by the\n/// `WebSocketFrameDecoder` and automatically generates protocol error responses.\n///\n/// This `ChannelHandler` provides default error handling for basic errors in the\n/// WebSocket protocol, and can be used by users when custom behaviour is not required.\npublic final class WebSocketProtocolErrorHandler: ChannelInboundHandler {\n    public typealias InboundIn = Never\n    public typealias OutboundOut = WebSocketFrame\n\n    /// Indicate that this `ChannelHandeler` is used by a WebSocket server or client. Default is true.\n    private let isServer: Bool\n\n    public init() {\n        self.isServer = true\n    }\n\n    /// Initialize this `ChannelHandler` to be used by a WebSocket server or client.\n    ///\n    /// - Parameters:\n    ///     - isServer: indicate whether this `ChannelHandler` is used by a WebSocket server or client.\n    public init(isServer: Bool) {\n        self.isServer = isServer\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        let loopBoundContext = context.loopBound\n        if let error = error as? NIOWebSocketError {\n            var data = context.channel.allocator.buffer(capacity: 2)\n            data.write(webSocketErrorCode: WebSocketErrorCode(error))\n            let frame = WebSocketFrame(\n                fin: true,\n                opcode: .connectionClose,\n                maskKey: self.makeMaskingKey(),\n                data: data\n            )\n            context.writeAndFlush(\n                WebSocketProtocolErrorHandler.wrapOutboundOut(frame)\n            ).whenComplete { (_: Result<Void, Error>) in\n                let context = loopBoundContext.value\n                context.close(promise: nil)\n            }\n        }\n\n        // Regardless of whether this is an error we want to handle or not, we always\n        // forward the error on to let others see it.\n        context.fireErrorCaught(error)\n    }\n\n    private func makeMaskingKey() -> WebSocketMaskingKey? {\n        // According to RFC 6455 Section 5, a client *must* mask all frames that it sends to the server.\n        // A server *must not* mask any frames that it sends to the client\n        self.isServer ? nil : .random()\n    }\n}\n\n@available(*, unavailable)\nextension WebSocketProtocolErrorHandler: Sendable {}\n"
  },
  {
    "path": "Sources/NIOWebSocketClient/Client.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\nimport NIOWebSocket\n\n@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)\n@main\nstruct Client {\n    /// The host to connect to.\n    private let host: String\n    /// The port to connect to.\n    private let port: Int\n    /// The client's event loop group.\n    private let eventLoopGroup: MultiThreadedEventLoopGroup\n\n    enum UpgradeResult {\n        case websocket(NIOAsyncChannel<WebSocketFrame, WebSocketFrame>)\n        case notUpgraded\n    }\n\n    static func main() async throws {\n        let client = Client(\n            host: \"localhost\",\n            port: 8888,\n            eventLoopGroup: .singleton\n        )\n        try await client.run()\n    }\n\n    /// This method starts the client and tries to setup a WebSocket connection.\n    func run() async throws {\n        let upgradeResult: EventLoopFuture<UpgradeResult> = try await ClientBootstrap(group: self.eventLoopGroup)\n            .connect(\n                host: self.host,\n                port: self.port\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let upgrader = NIOTypedWebSocketClientUpgrader<UpgradeResult>(\n                        upgradePipelineHandler: { (channel, _) in\n                            channel.eventLoop.makeCompletedFuture {\n                                let asyncChannel = try NIOAsyncChannel<WebSocketFrame, WebSocketFrame>(\n                                    wrappingChannelSynchronously: channel\n                                )\n                                return UpgradeResult.websocket(asyncChannel)\n                            }\n                        }\n                    )\n\n                    var headers = HTTPHeaders()\n                    headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n                    headers.add(name: \"Content-Length\", value: \"0\")\n\n                    let requestHead = HTTPRequestHead(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/\",\n                        headers: headers\n                    )\n\n                    let clientUpgradeConfiguration = NIOTypedHTTPClientUpgradeConfiguration(\n                        upgradeRequestHead: requestHead,\n                        upgraders: [upgrader],\n                        notUpgradingCompletionHandler: { channel in\n                            channel.eventLoop.makeCompletedFuture {\n                                UpgradeResult.notUpgraded\n                            }\n                        }\n                    )\n\n                    let negotiationResultFuture = try channel.pipeline.syncOperations\n                        .configureUpgradableHTTPClientPipeline(\n                            configuration: .init(upgradeConfiguration: clientUpgradeConfiguration)\n                        )\n\n                    return negotiationResultFuture\n                }\n            }\n\n        // We are awaiting and handling the upgrade result now.\n        try await self.handleUpgradeResult(upgradeResult)\n    }\n\n    /// This method handles the upgrade result.\n    private func handleUpgradeResult(_ upgradeResult: EventLoopFuture<UpgradeResult>) async throws {\n        switch try await upgradeResult.get() {\n        case .websocket(let websocketChannel):\n            print(\"Handling websocket connection\")\n            try await self.handleWebsocketChannel(websocketChannel)\n            print(\"Done handling websocket connection\")\n        case .notUpgraded:\n            // The upgrade to websocket did not succeed. We are just exiting in this case.\n            print(\"Upgrade declined\")\n        }\n    }\n\n    private func handleWebsocketChannel(_ channel: NIOAsyncChannel<WebSocketFrame, WebSocketFrame>) async throws {\n        // We are sending a ping frame and then\n        // start to handle all inbound frames.\n\n        let pingFrame = WebSocketFrame(fin: true, opcode: .ping, data: ByteBuffer(string: \"Hello!\"))\n        try await channel.executeThenClose { inbound, outbound in\n            try await outbound.write(pingFrame)\n\n            for try await frame in inbound {\n                switch frame.opcode {\n                case .pong:\n                    print(\"Received pong: \\(String(buffer: frame.data))\")\n\n                case .text:\n                    print(\"Received: \\(String(buffer: frame.data))\")\n\n                case .connectionClose:\n                    // Handle a received close frame. We're just going to close by returning from this method.\n                    print(\"Received Close instruction from server\")\n                    return\n                case .binary, .continuation, .ping:\n                    // We ignore these frames.\n                    break\n                default:\n                    // Unknown frames are errors.\n                    return\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NIOWebSocketClient/README.md",
    "content": "# NIOWebSocketClient\n\nThis sample application provides a simple WebSocket client. First it performs an upgrade from a HTTP connection. Once upgraded, it sends a 'ping' frame, with a body, to the server. It then checks that the body matches in the returning 'pong' frame. It also prints out any text frame received from the server. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOWebSocketClient  # Connects to a server on ::1, port 8888.\nswift run NIOWebSocketClient 9899  # Connects to a server on ::1, port 9899\nswift run NIOWebSocketClient /path/to/unix/socket  # Connects to a server using the given UNIX socket\nswift run NIOWebSocketClient echo.example.com 9899  # Connects to a server on echo.example.com:9899\n```\n\n"
  },
  {
    "path": "Sources/NIOWebSocketServer/README.md",
    "content": "# NIOWebSocketServer\n\nThis sample application provides a simple WebSocket server which replies to a limited number of WebSocket message types. Initially, it sends clients back a test page response to a valid HTTP1 GET request. A 405 error will be reported for any other type of request. Once upgraded to WebSocket responses it will respond to a number of WebSocket message opcodes. Invoke it using one of the following syntaxes:\n\n```bash\nswift run NIOWebSocketServer  # Binds the server on 'localhost', port 8888.\nswift run NIOWebSocketServer 9899  # Binds the server on 'localhost', port 9899\nswift run NIOWebSocketServer /path/to/unix/socket  # Binds the server using the given UNIX socket\nswift run NIOWebSocketServer 192.168.0.5 9899  # Binds the server on 192.168.0.5:9899\n```\n\n## Message Type Opcodes\n\nThe WebSocket server responds to the following message type opcodes:\n\n- `connectionClose`: closes the connection.\n- `ping`: replies with a 'pong' message containing frame data matching the received message.\n- `text`: prints the received string out on the server console.\n\nAll other message types are ignored.\n"
  },
  {
    "path": "Sources/NIOWebSocketServer/Server.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\nimport NIOWebSocket\n\nlet websocketResponse = \"\"\"\n    <!DOCTYPE html>\n    <html>\n      <head>\n        <meta charset=\"utf-8\">\n        <title>Swift NIO WebSocket Test Page</title>\n        <script>\n            var wsconnection = new WebSocket(\"ws://localhost:8888/websocket\");\n            wsconnection.onmessage = function (msg) {\n                var element = document.createElement(\"p\");\n                element.innerHTML = msg.data;\n\n                var textDiv = document.getElementById(\"websocket-stream\");\n                textDiv.insertBefore(element, null);\n            };\n        </script>\n      </head>\n      <body>\n        <h1>WebSocket Stream</h1>\n        <div id=\"websocket-stream\"></div>\n      </body>\n    </html>\n    \"\"\"\n\n@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)\n@main\nstruct Server {\n    /// The server's host.\n    private let host: String\n    /// The server's port.\n    private let port: Int\n    /// The server's event loop group.\n    private let eventLoopGroup: MultiThreadedEventLoopGroup\n\n    private static let responseBody = ByteBuffer(string: websocketResponse)\n\n    enum UpgradeResult {\n        case websocket(NIOAsyncChannel<WebSocketFrame, WebSocketFrame>)\n        case notUpgraded(NIOAsyncChannel<HTTPServerRequestPart, HTTPPart<HTTPResponseHead, ByteBuffer>>)\n    }\n\n    static func main() async throws {\n        let server = Server(\n            host: \"localhost\",\n            port: 8888,\n            eventLoopGroup: .singleton\n        )\n        try await server.run()\n    }\n\n    /// This method starts the server and handles incoming connections.\n    func run() async throws {\n        let channel: NIOAsyncChannel<EventLoopFuture<UpgradeResult>, Never> = try await ServerBootstrap(\n            group: self.eventLoopGroup\n        )\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .bind(\n            host: self.host,\n            port: self.port\n        ) { channel in\n            channel.eventLoop.makeCompletedFuture {\n                let upgrader = NIOTypedWebSocketServerUpgrader<UpgradeResult>(\n                    shouldUpgrade: { (channel, head) in\n                        channel.eventLoop.makeSucceededFuture(HTTPHeaders())\n                    },\n                    upgradePipelineHandler: { (channel, _) in\n                        channel.eventLoop.makeCompletedFuture {\n                            let asyncChannel = try NIOAsyncChannel<WebSocketFrame, WebSocketFrame>(\n                                wrappingChannelSynchronously: channel\n                            )\n                            return UpgradeResult.websocket(asyncChannel)\n                        }\n                    }\n                )\n\n                let serverUpgradeConfiguration = NIOTypedHTTPServerUpgradeConfiguration(\n                    upgraders: [upgrader],\n                    notUpgradingCompletionHandler: { channel in\n                        channel.eventLoop.makeCompletedFuture {\n                            try channel.pipeline.syncOperations.addHandler(HTTPByteBufferResponsePartHandler())\n                            let asyncChannel = try NIOAsyncChannel<\n                                HTTPServerRequestPart, HTTPPart<HTTPResponseHead, ByteBuffer>\n                            >(wrappingChannelSynchronously: channel)\n                            return UpgradeResult.notUpgraded(asyncChannel)\n                        }\n                    }\n                )\n\n                let negotiationResultFuture = try channel.pipeline.syncOperations.configureUpgradableHTTPServerPipeline(\n                    configuration: .init(upgradeConfiguration: serverUpgradeConfiguration)\n                )\n\n                return negotiationResultFuture\n            }\n        }\n\n        // We are handling each incoming connection in a separate child task. It is important\n        // to use a discarding task group here which automatically discards finished child tasks.\n        // A normal task group retains all child tasks and their outputs in memory until they are\n        // consumed by iterating the group or by exiting the group. Since, we are never consuming\n        // the results of the group we need the group to automatically discard them; otherwise, this\n        // would result in a memory leak over time.\n        try await withThrowingDiscardingTaskGroup { group in\n            try await channel.executeThenClose { inbound in\n                for try await upgradeResult in inbound {\n                    group.addTask {\n                        await self.handleUpgradeResult(upgradeResult)\n                    }\n                }\n            }\n        }\n    }\n\n    /// This method handles a single connection by echoing back all inbound data.\n    private func handleUpgradeResult(_ upgradeResult: EventLoopFuture<UpgradeResult>) async {\n        // Note that this method is non-throwing and we are catching any error.\n        // We do this since we don't want to tear down the whole server when a single connection\n        // encounters an error.\n        do {\n            switch try await upgradeResult.get() {\n            case .websocket(let websocketChannel):\n                print(\"Handling websocket connection\")\n                try await self.handleWebsocketChannel(websocketChannel)\n                print(\"Done handling websocket connection\")\n            case .notUpgraded(let httpChannel):\n                print(\"Handling HTTP connection\")\n                try await self.handleHTTPChannel(httpChannel)\n                print(\"Done handling HTTP connection\")\n            }\n        } catch {\n            print(\"Hit error: \\(error)\")\n        }\n    }\n\n    private func handleWebsocketChannel(_ channel: NIOAsyncChannel<WebSocketFrame, WebSocketFrame>) async throws {\n        try await channel.executeThenClose { inbound, outbound in\n            try await withThrowingTaskGroup(of: Void.self) { group in\n                group.addTask {\n                    for try await frame in inbound {\n                        switch frame.opcode {\n                        case .ping:\n                            print(\"Received ping\")\n                            var frameData = frame.data\n                            let maskingKey = frame.maskKey\n\n                            if let maskingKey = maskingKey {\n                                frameData.webSocketUnmask(maskingKey)\n                            }\n\n                            let responseFrame = WebSocketFrame(fin: true, opcode: .pong, data: frameData)\n                            try await outbound.write(responseFrame)\n\n                        case .connectionClose:\n                            // This is an unsolicited close. We're going to send a response frame and\n                            // then, when we've sent it, close up shop. We should send back the close code the remote\n                            // peer sent us, unless they didn't send one at all.\n                            print(\"Received close\")\n                            var data = frame.unmaskedData\n                            let closeDataCode = data.readSlice(length: 2) ?? ByteBuffer()\n                            let closeFrame = WebSocketFrame(fin: true, opcode: .connectionClose, data: closeDataCode)\n                            try await outbound.write(closeFrame)\n                            return\n                        case .binary, .continuation, .pong:\n                            // We ignore these frames.\n                            break\n                        default:\n                            // Unknown frames are errors.\n                            return\n                        }\n                    }\n                }\n\n                group.addTask {\n                    // This is our main business logic where we are just sending the current time\n                    // every second.\n                    while true {\n                        // We can't really check for error here, but it's also not the purpose of the\n                        // example so let's not worry about it.\n                        let theTime = ContinuousClock().now\n                        var buffer = channel.channel.allocator.buffer(capacity: 12)\n                        buffer.writeString(\"\\(theTime)\")\n\n                        let frame = WebSocketFrame(fin: true, opcode: .text, data: buffer)\n\n                        print(\"Sending time\")\n                        try await outbound.write(frame)\n                        try await Task.sleep(for: .seconds(1))\n                    }\n                }\n\n                try await group.next()\n                group.cancelAll()\n            }\n        }\n    }\n\n    private func handleHTTPChannel(\n        _ channel: NIOAsyncChannel<HTTPServerRequestPart, HTTPPart<HTTPResponseHead, ByteBuffer>>\n    ) async throws {\n        try await channel.executeThenClose { inbound, outbound in\n            for try await requestPart in inbound {\n                // We're not interested in request bodies here: we're just serving up GET responses\n                // to get the client to initiate a websocket request.\n                guard case .head(let head) = requestPart else {\n                    return\n                }\n\n                // GETs only.\n                guard case .GET = head.method else {\n                    try await self.respond405(writer: outbound)\n                    return\n                }\n\n                var headers = HTTPHeaders()\n                headers.add(name: \"Content-Type\", value: \"text/html\")\n                headers.add(name: \"Content-Length\", value: String(Self.responseBody.readableBytes))\n                headers.add(name: \"Connection\", value: \"close\")\n                let responseHead = HTTPResponseHead(\n                    version: .init(major: 1, minor: 1),\n                    status: .ok,\n                    headers: headers\n                )\n\n                try await outbound.write(\n                    contentsOf: [\n                        .head(responseHead),\n                        .body(Self.responseBody),\n                        .end(nil),\n                    ]\n                )\n            }\n        }\n    }\n\n    private func respond405(writer: NIOAsyncChannelOutboundWriter<HTTPPart<HTTPResponseHead, ByteBuffer>>) async throws\n    {\n        var headers = HTTPHeaders()\n        headers.add(name: \"Connection\", value: \"close\")\n        headers.add(name: \"Content-Length\", value: \"0\")\n        let head = HTTPResponseHead(\n            version: .http1_1,\n            status: .methodNotAllowed,\n            headers: headers\n        )\n\n        try await writer.write(\n            contentsOf: [\n                .head(head),\n                .end(nil),\n            ]\n        )\n    }\n}\n\nfinal class HTTPByteBufferResponsePartHandler: ChannelOutboundHandler {\n    typealias OutboundIn = HTTPPart<HTTPResponseHead, ByteBuffer>\n    typealias OutboundOut = HTTPServerResponsePart\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let part = Self.unwrapOutboundIn(data)\n        switch part {\n        case .head(let head):\n            context.write(Self.wrapOutboundOut(.head(head)), promise: promise)\n        case .body(let buffer):\n            context.write(Self.wrapOutboundOut(.body(.byteBuffer(buffer))), promise: promise)\n        case .end(let trailers):\n            context.write(Self.wrapOutboundOut(.end(trailers)), promise: promise)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOBase64/Base64.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// This is a simplified vendored version from:\n// https://github.com/fabianfett/swift-base64-kit\n\nextension String {\n    /// Base64 encode a collection of UInt8 to a string, without the use of Foundation.\n    @available(*, deprecated, message: \"This API was unintentionally made public.\")\n    @inlinable\n    public init<Buffer: Collection>(base64Encoding bytes: Buffer) where Buffer.Element == UInt8 {\n        self.init(_base64Encoding: bytes)\n    }\n\n    @available(*, deprecated, message: \"This API was unintentionally made public.\")\n    @inlinable\n    public func base64Decoded() throws -> [UInt8] {\n        try self._base64Decoded()\n    }\n\n    /// Base64 encode a collection of UInt8 to a string, without the use of Foundation.\n    @inlinable\n    public init<Buffer: Collection>(_base64Encoding bytes: Buffer) where Buffer.Element == UInt8 {\n        self = Base64.encode(bytes: bytes)\n    }\n\n    @inlinable\n    public func _base64Decoded() throws -> [UInt8] {\n        try Base64.decode(string: self)\n    }\n}\n\npublic enum Base64Error: Error {\n    case invalidLength\n    case invalidCharacter\n}\n\n@usableFromInline\ninternal enum Base64: Sendable {\n\n    @inlinable\n    static func encode<Buffer: Collection>(bytes: Buffer) -> String where Buffer.Element == UInt8 {\n        guard !bytes.isEmpty else {\n            return \"\"\n        }\n\n        // In Base64, 3 bytes become 4 output characters, and we pad to the\n        // nearest multiple of four.\n        let base64StringLength = ((bytes.count + 2) / 3) * 4\n        let alphabet = Base64.encodingTable\n\n        return String(customUnsafeUninitializedCapacity: base64StringLength) { backingStorage in\n            var input = bytes.makeIterator()\n            var offset = 0\n            while let firstByte = input.next() {\n                let secondByte = input.next()\n                let thirdByte = input.next()\n\n                backingStorage[offset] = Base64.encode(alphabet: alphabet, firstByte: firstByte)\n                backingStorage[offset + 1] = Base64.encode(\n                    alphabet: alphabet,\n                    firstByte: firstByte,\n                    secondByte: secondByte\n                )\n                backingStorage[offset + 2] = Base64.encode(\n                    alphabet: alphabet,\n                    secondByte: secondByte,\n                    thirdByte: thirdByte\n                )\n                backingStorage[offset + 3] = Base64.encode(alphabet: alphabet, thirdByte: thirdByte)\n                offset += 4\n            }\n            return offset\n        }\n    }\n\n    @inlinable\n    static func decode(string: String) throws -> [UInt8] {\n        guard string.count % 4 == 0 else {\n            throw Base64Error.invalidLength\n        }\n\n        let bytes = string.utf8.map { $0 }\n        var decoded = [UInt8]()\n\n        // Go over the encoded string in groups of 4 characters,\n        // and build groups of 3 bytes from them.\n        for i in stride(from: 0, to: bytes.count, by: 4) {\n            guard let byte0Index = Base64.encodingTable.firstIndex(of: bytes[i]),\n                let byte1Index = Base64.encodingTable.firstIndex(of: bytes[i + 1])\n            else {\n                throw Base64Error.invalidCharacter\n            }\n\n            let byte0 = (UInt8(byte0Index) << 2 | UInt8(byte1Index) >> 4)\n            decoded.append(byte0)\n\n            // Check if the 3rd char is not a padding character, and decode the 2nd byte\n            if bytes[i + 2] != Base64.encodePaddingCharacter {\n                guard let byte2Index = Base64.encodingTable.firstIndex(of: bytes[i + 2]) else {\n                    throw Base64Error.invalidCharacter\n                }\n\n                let second = (UInt8(byte1Index) << 4 | UInt8(byte2Index) >> 2)\n                decoded.append(second)\n            }\n\n            // Check if the 4th character is not a padding, and decode the 3rd byte\n            if bytes[i + 3] != Base64.encodePaddingCharacter {\n                guard let byte3Index = Base64.encodingTable.firstIndex(of: bytes[i + 3]),\n                    let byte2Index = Base64.encodingTable.firstIndex(of: bytes[i + 2])\n                else {\n                    throw Base64Error.invalidCharacter\n                }\n                let third = (UInt8(byte2Index) << 6 | UInt8(byte3Index))\n                decoded.append(third)\n            }\n        }\n        return decoded\n    }\n\n    // MARK: Internal\n\n    // The base64 unicode table.\n    @usableFromInline\n    static let encodingTable: [UInt8] = [\n        UInt8(ascii: \"A\"), UInt8(ascii: \"B\"), UInt8(ascii: \"C\"), UInt8(ascii: \"D\"),\n        UInt8(ascii: \"E\"), UInt8(ascii: \"F\"), UInt8(ascii: \"G\"), UInt8(ascii: \"H\"),\n        UInt8(ascii: \"I\"), UInt8(ascii: \"J\"), UInt8(ascii: \"K\"), UInt8(ascii: \"L\"),\n        UInt8(ascii: \"M\"), UInt8(ascii: \"N\"), UInt8(ascii: \"O\"), UInt8(ascii: \"P\"),\n        UInt8(ascii: \"Q\"), UInt8(ascii: \"R\"), UInt8(ascii: \"S\"), UInt8(ascii: \"T\"),\n        UInt8(ascii: \"U\"), UInt8(ascii: \"V\"), UInt8(ascii: \"W\"), UInt8(ascii: \"X\"),\n        UInt8(ascii: \"Y\"), UInt8(ascii: \"Z\"), UInt8(ascii: \"a\"), UInt8(ascii: \"b\"),\n        UInt8(ascii: \"c\"), UInt8(ascii: \"d\"), UInt8(ascii: \"e\"), UInt8(ascii: \"f\"),\n        UInt8(ascii: \"g\"), UInt8(ascii: \"h\"), UInt8(ascii: \"i\"), UInt8(ascii: \"j\"),\n        UInt8(ascii: \"k\"), UInt8(ascii: \"l\"), UInt8(ascii: \"m\"), UInt8(ascii: \"n\"),\n        UInt8(ascii: \"o\"), UInt8(ascii: \"p\"), UInt8(ascii: \"q\"), UInt8(ascii: \"r\"),\n        UInt8(ascii: \"s\"), UInt8(ascii: \"t\"), UInt8(ascii: \"u\"), UInt8(ascii: \"v\"),\n        UInt8(ascii: \"w\"), UInt8(ascii: \"x\"), UInt8(ascii: \"y\"), UInt8(ascii: \"z\"),\n        UInt8(ascii: \"0\"), UInt8(ascii: \"1\"), UInt8(ascii: \"2\"), UInt8(ascii: \"3\"),\n        UInt8(ascii: \"4\"), UInt8(ascii: \"5\"), UInt8(ascii: \"6\"), UInt8(ascii: \"7\"),\n        UInt8(ascii: \"8\"), UInt8(ascii: \"9\"), UInt8(ascii: \"+\"), UInt8(ascii: \"/\"),\n    ]\n\n    @inlinable\n    static var encodePaddingCharacter: UInt8 { UInt8(ascii: \"=\") }\n\n    @usableFromInline\n    static func encode(alphabet: [UInt8], firstByte: UInt8) -> UInt8 {\n        let index = firstByte >> 2\n        return alphabet[Int(index)]\n    }\n\n    @usableFromInline\n    static func encode(alphabet: [UInt8], firstByte: UInt8, secondByte: UInt8?) -> UInt8 {\n        var index = (firstByte & 0b00000011) << 4\n        if let secondByte = secondByte {\n            index += (secondByte & 0b11110000) >> 4\n        }\n        return alphabet[Int(index)]\n    }\n\n    @usableFromInline\n    static func encode(alphabet: [UInt8], secondByte: UInt8?, thirdByte: UInt8?) -> UInt8 {\n        guard let secondByte = secondByte else {\n            // No second byte means we are just emitting padding.\n            return Base64.encodePaddingCharacter\n        }\n        var index = (secondByte & 0b00001111) << 2\n        if let thirdByte = thirdByte {\n            index += (thirdByte & 0b11000000) >> 6\n        }\n        return alphabet[Int(index)]\n    }\n\n    @usableFromInline\n    static func encode(alphabet: [UInt8], thirdByte: UInt8?) -> UInt8 {\n        guard let thirdByte = thirdByte else {\n            // No third byte means just padding.\n            return Base64.encodePaddingCharacter\n        }\n        let index = thirdByte & 0b00111111\n        return alphabet[Int(index)]\n    }\n}\n\nextension String {\n    /// This is a backport of a proposed String initializer that will allow writing directly into an uninitialized String's backing memory.\n    ///\n    /// As this API does not exist prior to 5.3 on Linux, or on older Apple platforms, we fake it out with a pointer and accept the extra copy.\n    @inlinable\n    init(\n        backportUnsafeUninitializedCapacity capacity: Int,\n        initializingUTF8With initializer: (_ buffer: UnsafeMutableBufferPointer<UInt8>) throws -> Int\n    ) rethrows {\n\n        // The buffer will store zero terminated C string\n        let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: capacity + 1)\n        defer {\n            buffer.deallocate()\n        }\n\n        let initializedCount = try initializer(buffer)\n        precondition(initializedCount <= capacity, \"Overran buffer in initializer!\")\n\n        // add zero termination\n        buffer[initializedCount] = 0\n\n        self = String(cString: buffer.baseAddress!)\n    }\n}\n\n// Frustratingly, Swift 5.3 shipped before the macOS 11 SDK did, so we cannot gate the availability of\n// this declaration on having the 5.3 compiler. This has caused a number of build issues. While updating\n// to newer Xcodes does work, we can save ourselves some hassle and just wait until 5.4 to get this\n// enhancement on Apple platforms.\nextension String {\n\n    @inlinable\n    init(\n        customUnsafeUninitializedCapacity capacity: Int,\n        initializingUTF8With initializer: (_ buffer: UnsafeMutableBufferPointer<UInt8>) throws -> Int\n    ) rethrows {\n        if #available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) {\n            try self.init(unsafeUninitializedCapacity: capacity, initializingUTF8With: initializer)\n        } else {\n            try self.init(backportUnsafeUninitializedCapacity: capacity, initializingUTF8With: initializer)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOConcurrency/Empty.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// NOTE: All the helper methods that where located here, have been moved to NIOCore. This module\n//       only exists to not break adopters code for now. Please remove all your dependencies on\n//       `_NIOConcurrency`. We want to remove this module soon.\n\nimport NIOCore\n"
  },
  {
    "path": "Sources/_NIODataStructures/Heap.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n#if canImport(Darwin)\nimport Darwin.C\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(WASILibc)\n@preconcurrency import WASILibc\n#elseif os(Windows)\nimport ucrt\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#else\n#error(\"The Heap module was unable to identify your C library.\")\n#endif\n\n@usableFromInline\ninternal struct Heap<Element: Comparable> {\n    @usableFromInline\n    internal private(set) var storage: [Element]\n\n    @inlinable\n    internal init() {\n        self.storage = []\n    }\n\n    @inlinable\n    internal func comparator(_ lhs: Element, _ rhs: Element) -> Bool {\n        // This heap is always a min-heap.\n        lhs < rhs\n    }\n\n    // named `PARENT` in CLRS\n    @inlinable\n    internal func parentIndex(_ i: Int) -> Int {\n        (i - 1) / 2\n    }\n\n    // named `LEFT` in CLRS\n    @inlinable\n    internal func leftIndex(_ i: Int) -> Int {\n        2 * i + 1\n    }\n\n    // named `RIGHT` in CLRS\n    @inlinable\n    internal func rightIndex(_ i: Int) -> Int {\n        2 * i + 2\n    }\n\n    // named `MAX-HEAPIFY` in CLRS\n    @inlinable\n    mutating func _heapify(_ index: Int) {\n        let left = self.leftIndex(index)\n        let right = self.rightIndex(index)\n\n        var root: Int\n        if left <= (self.storage.count - 1) && self.comparator(storage[left], storage[index]) {\n            root = left\n        } else {\n            root = index\n        }\n\n        if right <= (self.storage.count - 1) && self.comparator(storage[right], storage[root]) {\n            root = right\n        }\n\n        if root != index {\n            self.storage.swapAt(index, root)\n            self._heapify(root)\n        }\n    }\n\n    // named `HEAP-INCREASE-KEY` in CRLS\n    @inlinable\n    mutating func _heapRootify(index: Int, key: Element) {\n        var index = index\n        if self.comparator(storage[index], key) {\n            fatalError(\"New key must be closer to the root than current key\")\n        }\n\n        self.storage[index] = key\n        while index > 0 && self.comparator(self.storage[index], self.storage[self.parentIndex(index)]) {\n            self.storage.swapAt(index, self.parentIndex(index))\n            index = self.parentIndex(index)\n        }\n    }\n\n    @inlinable\n    internal mutating func append(_ value: Element) {\n        var i = self.storage.count\n        self.storage.append(value)\n        while i > 0 && self.comparator(self.storage[i], self.storage[self.parentIndex(i)]) {\n            self.storage.swapAt(i, self.parentIndex(i))\n            i = self.parentIndex(i)\n        }\n    }\n\n    @discardableResult\n    @inlinable\n    internal mutating func removeRoot() -> Element? {\n        self._remove(index: 0)\n    }\n\n    @discardableResult\n    @inlinable\n    internal mutating func remove(value: Element) -> Bool {\n        if let idx = self.storage.firstIndex(of: value) {\n            self._remove(index: idx)\n            return true\n        } else {\n            return false\n        }\n    }\n\n    @discardableResult\n    @inlinable\n    internal mutating func removeFirst(where shouldBeRemoved: (Element) throws -> Bool) rethrows -> Element? {\n        guard self.storage.count > 0 else {\n            return nil\n        }\n\n        guard let index = try self.storage.firstIndex(where: shouldBeRemoved) else {\n            return nil\n        }\n\n        return self._remove(index: index)\n    }\n\n    @discardableResult\n    @inlinable\n    mutating func _remove(index: Int) -> Element? {\n        guard self.storage.count > 0 else {\n            return nil\n        }\n        let element = self.storage[index]\n        if self.storage.count == 1 || self.storage[index] == self.storage[self.storage.count - 1] {\n            self.storage.removeLast()\n        } else if !self.comparator(self.storage[index], self.storage[self.storage.count - 1]) {\n            self._heapRootify(index: index, key: self.storage[self.storage.count - 1])\n            self.storage.removeLast()\n        } else {\n            self.storage[index] = self.storage[self.storage.count - 1]\n            self.storage.removeLast()\n            self._heapify(index)\n        }\n        return element\n    }\n}\n\nextension Heap: CustomDebugStringConvertible {\n    @inlinable\n    var debugDescription: String {\n        guard self.storage.count > 0 else {\n            return \"<empty heap>\"\n        }\n        let descriptions = self.storage.map { String(describing: $0) }\n        let maxLen: Int = descriptions.map { $0.count }.max()!  // storage checked non-empty above\n        let paddedDescs = descriptions.map { (desc: String) -> String in\n            var desc = desc\n            while desc.count < maxLen {\n                if desc.count % 2 == 0 {\n                    desc = \" \\(desc)\"\n                } else {\n                    desc = \"\\(desc) \"\n                }\n            }\n            return desc\n        }\n\n        var all = \"\\n\"\n        let spacing = String(repeating: \" \", count: maxLen)\n        func subtreeWidths(rootIndex: Int) -> (Int, Int) {\n            let lcIdx = self.leftIndex(rootIndex)\n            let rcIdx = self.rightIndex(rootIndex)\n            var leftSpace = 0\n            var rightSpace = 0\n            if lcIdx < self.storage.count {\n                let sws = subtreeWidths(rootIndex: lcIdx)\n                leftSpace += sws.0 + sws.1 + maxLen\n            }\n            if rcIdx < self.storage.count {\n                let sws = subtreeWidths(rootIndex: rcIdx)\n                rightSpace += sws.0 + sws.1 + maxLen\n            }\n            return (leftSpace, rightSpace)\n        }\n        for (index, desc) in paddedDescs.enumerated() {\n            let (leftWidth, rightWidth) = subtreeWidths(rootIndex: index)\n            all += String(repeating: \" \", count: leftWidth)\n            all += desc\n            all += String(repeating: \" \", count: rightWidth)\n\n            func height(index: Int) -> Int {\n                Int(log2(Double(index + 1)))\n            }\n            let myHeight = height(index: index)\n            let nextHeight = height(index: index + 1)\n            if myHeight != nextHeight {\n                all += \"\\n\"\n            } else {\n                all += spacing\n            }\n        }\n        all += \"\\n\"\n        return all\n    }\n}\n\n@usableFromInline\nstruct HeapIterator<Element: Comparable>: IteratorProtocol {\n    @usableFromInline\n    var _heap: Heap<Element>\n\n    @inlinable\n    init(heap: Heap<Element>) {\n        self._heap = heap\n    }\n\n    @inlinable\n    mutating func next() -> Element? {\n        self._heap.removeRoot()\n    }\n}\n\nextension Heap: Sequence {\n    @inlinable\n    var startIndex: Int {\n        self.storage.startIndex\n    }\n\n    @inlinable\n    var endIndex: Int {\n        self.storage.endIndex\n    }\n\n    @inlinable\n    var underestimatedCount: Int {\n        self.storage.count\n    }\n\n    @inlinable\n    func makeIterator() -> HeapIterator<Element> {\n        HeapIterator(heap: self)\n    }\n\n    @inlinable\n    subscript(position: Int) -> Element {\n        self.storage[position]\n    }\n\n    @inlinable\n    func index(after i: Int) -> Int {\n        i + 1\n    }\n\n    @inlinable\n    var count: Int {\n        self.storage.count\n    }\n}\n\nextension Heap: Sendable where Element: Sendable {}\nextension HeapIterator: Sendable where Element: Sendable {}\n"
  },
  {
    "path": "Sources/_NIODataStructures/PriorityQueue.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\npublic struct PriorityQueue<Element: Comparable> {\n    @usableFromInline\n    internal var _heap: Heap<Element>\n\n    @inlinable\n    public init() {\n        self._heap = Heap()\n    }\n\n    @inlinable\n    public mutating func remove(_ key: Element) {\n        self._heap.remove(value: key)\n    }\n\n    @discardableResult\n    @inlinable\n    public mutating func removeFirst(where shouldBeRemoved: (Element) throws -> Bool) rethrows -> Element? {\n        try self._heap.removeFirst(where: shouldBeRemoved)\n    }\n\n    @inlinable\n    public mutating func push(_ key: Element) {\n        self._heap.append(key)\n    }\n\n    @inlinable\n    public func peek() -> Element? {\n        self._heap.storage.first\n    }\n\n    @inlinable\n    public var isEmpty: Bool {\n        self._heap.storage.isEmpty\n    }\n\n    @inlinable\n    @discardableResult\n    public mutating func pop() -> Element? {\n        self._heap.removeRoot()\n    }\n\n    @inlinable\n    public mutating func clear() {\n        self._heap = Heap()\n    }\n}\n\nextension PriorityQueue: Equatable {\n    @inlinable\n    public static func == (lhs: PriorityQueue, rhs: PriorityQueue) -> Bool {\n        lhs.count == rhs.count && lhs.elementsEqual(rhs)\n    }\n}\n\nextension PriorityQueue: Sequence {\n    public struct Iterator: IteratorProtocol {\n\n        @usableFromInline\n        var _queue: PriorityQueue<Element>\n\n        @inlinable\n        public init(queue: PriorityQueue<Element>) {\n            self._queue = queue\n        }\n\n        @inlinable\n        public mutating func next() -> Element? {\n            self._queue.pop()\n        }\n    }\n\n    @inlinable\n    public func makeIterator() -> Iterator {\n        Iterator(queue: self)\n    }\n}\n\nextension PriorityQueue {\n    @inlinable\n    public var count: Int {\n        self._heap.count\n    }\n}\n\nextension PriorityQueue: CustomStringConvertible {\n    @inlinable\n    public var description: String {\n        \"PriorityQueue(count: \\(self.count)): \\(Array(self))\"\n    }\n}\n\nextension PriorityQueue: Sendable where Element: Sendable {}\nextension PriorityQueue.Iterator: Sendable where Element: Sendable {}\n"
  },
  {
    "path": "Sources/_NIODataStructures/_TinyArray.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftCertificates open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftCertificates project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftCertificates project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// ``TinyArray`` is a ``RandomAccessCollection`` optimised to store zero or one ``Element``.\n/// It supports arbitrary many elements but if only up to one ``Element`` is stored it does **not** allocate separate storage on the heap\n/// and instead stores the ``Element`` inline.\npublic struct _TinyArray<Element> {\n    @usableFromInline\n    enum Storage {\n        case one(Element)\n        case arbitrary([Element])\n    }\n\n    @usableFromInline\n    var storage: Storage\n}\n\n// MARK: - TinyArray \"public\" interface\n\nextension _TinyArray: Equatable where Element: Equatable {}\nextension _TinyArray: Hashable where Element: Hashable {}\nextension _TinyArray: Sendable where Element: Sendable {}\n\nextension _TinyArray: RandomAccessCollection {\n    public typealias Element = Element\n\n    public typealias Index = Int\n\n    @inlinable\n    public func makeIterator() -> Iterator {\n        Iterator(storage: self.storage)\n    }\n\n    public struct Iterator: IteratorProtocol {\n        @usableFromInline\n        let _storage: Storage\n        @usableFromInline\n        var _index: Index\n\n        @usableFromInline\n        init(storage: Storage) {\n            self._storage = storage\n            self._index = storage.startIndex\n        }\n\n        @inlinable\n        public mutating func next() -> Element? {\n            if self._index == self._storage.endIndex {\n                return nil\n            }\n\n            defer {\n                self._index &+= 1\n            }\n\n            return self._storage[self._index]\n        }\n    }\n\n    @inlinable\n    public subscript(position: Int) -> Element {\n        get {\n            self.storage[position]\n        }\n    }\n\n    @inlinable\n    public var startIndex: Int {\n        self.storage.startIndex\n    }\n\n    @inlinable\n    public var endIndex: Int {\n        self.storage.endIndex\n    }\n}\n\nextension _TinyArray.Iterator: Sendable where Element: Sendable {}\n\nextension _TinyArray {\n    @inlinable\n    public init(_ elements: some Sequence<Element>) {\n        self.storage = .init(elements)\n    }\n\n    @inlinable\n    public init(_ elements: some Sequence<Result<Element, some Error>>) throws {\n        self.storage = try .init(elements)\n    }\n\n    @inlinable\n    public init() {\n        self.storage = .init()\n    }\n\n    @inlinable\n    public mutating func append(_ newElement: Element) {\n        self.storage.append(newElement)\n    }\n\n    @inlinable\n    public mutating func append(contentsOf newElements: some Sequence<Element>) {\n        self.storage.append(contentsOf: newElements)\n    }\n\n    @discardableResult\n    @inlinable\n    public mutating func remove(at index: Int) -> Element {\n        self.storage.remove(at: index)\n    }\n\n    @inlinable\n    public mutating func removeAll(where shouldBeRemoved: (Element) throws -> Bool) rethrows {\n        try self.storage.removeAll(where: shouldBeRemoved)\n    }\n\n    @inlinable\n    public mutating func sort(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows {\n        try self.storage.sort(by: areInIncreasingOrder)\n    }\n}\n\n// MARK: - TinyArray.Storage \"private\" implementation\n\nextension _TinyArray.Storage: Equatable where Element: Equatable {\n    @inlinable\n    static func == (lhs: Self, rhs: Self) -> Bool {\n        switch (lhs, rhs) {\n        case (.one(let lhs), .one(let rhs)):\n            return lhs == rhs\n        case (.arbitrary(let lhs), .arbitrary(let rhs)):\n            // we don't use lhs.elementsEqual(rhs) so we can hit the fast path from Array\n            // if both arrays share the same underlying storage: https://github.com/apple/swift/blob/b42019005988b2d13398025883e285a81d323efa/stdlib/public/core/Array.swift#L1775\n            return lhs == rhs\n\n        case (.one(let element), .arbitrary(let array)),\n            (.arbitrary(let array), .one(let element)):\n            guard array.count == 1 else {\n                return false\n            }\n            return element == array[0]\n\n        }\n    }\n}\nextension _TinyArray.Storage: Hashable where Element: Hashable {\n    @inlinable\n    func hash(into hasher: inout Hasher) {\n        // same strategy as Array: https://github.com/apple/swift/blob/b42019005988b2d13398025883e285a81d323efa/stdlib/public/core/Array.swift#L1801\n        hasher.combine(count)\n        for element in self {\n            hasher.combine(element)\n        }\n    }\n}\nextension _TinyArray.Storage: Sendable where Element: Sendable {}\n\nextension _TinyArray.Storage: RandomAccessCollection {\n    @inlinable\n    subscript(position: Int) -> Element {\n        get {\n            switch self {\n            case .one(let element):\n                guard position == 0 else {\n                    fatalError(\"index \\(position) out of bounds\")\n                }\n                return element\n            case .arbitrary(let elements):\n                return elements[position]\n            }\n        }\n    }\n\n    @inlinable\n    var startIndex: Int {\n        0\n    }\n\n    @inlinable\n    var endIndex: Int {\n        switch self {\n        case .one: return 1\n        case .arbitrary(let elements): return elements.endIndex\n        }\n    }\n}\n\nextension _TinyArray.Storage {\n    @inlinable\n    init(_ elements: some Sequence<Element>) {\n        self = .arbitrary([])\n        self.append(contentsOf: elements)\n    }\n\n    @inlinable\n    init(_ newElements: some Sequence<Result<Element, some Error>>) throws {\n        var iterator = newElements.makeIterator()\n        guard let firstElement = try iterator.next()?.get() else {\n            self = .arbitrary([])\n            return\n        }\n        guard let secondElement = try iterator.next()?.get() else {\n            // newElements just contains a single element\n            // and we hit the fast path\n            self = .one(firstElement)\n            return\n        }\n\n        var elements: [Element] = []\n        elements.reserveCapacity(newElements.underestimatedCount)\n        elements.append(firstElement)\n        elements.append(secondElement)\n        while let nextElement = try iterator.next()?.get() {\n            elements.append(nextElement)\n        }\n        self = .arbitrary(elements)\n    }\n\n    @inlinable\n    init() {\n        self = .arbitrary([])\n    }\n\n    @inlinable\n    mutating func append(_ newElement: Element) {\n        self.append(contentsOf: CollectionOfOne(newElement))\n    }\n\n    @inlinable\n    mutating func append(contentsOf newElements: some Sequence<Element>) {\n        switch self {\n        case .one(let firstElement):\n            var iterator = newElements.makeIterator()\n            guard let secondElement = iterator.next() else {\n                // newElements is empty, nothing to do\n                return\n            }\n            var elements: [Element] = []\n            elements.reserveCapacity(1 + newElements.underestimatedCount)\n            elements.append(firstElement)\n            elements.append(secondElement)\n            elements.appendRemainingElements(from: &iterator)\n            self = .arbitrary(elements)\n\n        case .arbitrary(var elements):\n            if elements.isEmpty {\n                // if `self` is currently empty and `newElements` just contains a single\n                // element, we skip allocating an array and set `self` to `.one(firstElement)`\n                var iterator = newElements.makeIterator()\n                guard let firstElement = iterator.next() else {\n                    // newElements is empty, nothing to do\n                    return\n                }\n                guard let secondElement = iterator.next() else {\n                    // newElements just contains a single element\n                    // and we hit the fast path\n                    self = .one(firstElement)\n                    return\n                }\n                elements.reserveCapacity(elements.count + newElements.underestimatedCount)\n                elements.append(firstElement)\n                elements.append(secondElement)\n                elements.appendRemainingElements(from: &iterator)\n                self = .arbitrary(elements)\n\n            } else {\n                elements.append(contentsOf: newElements)\n                self = .arbitrary(elements)\n            }\n\n        }\n    }\n\n    @discardableResult\n    @inlinable\n    mutating func remove(at index: Int) -> Element {\n        switch self {\n        case .one(let oldElement):\n            guard index == 0 else {\n                fatalError(\"index \\(index) out of bounds\")\n            }\n            self = .arbitrary([])\n            return oldElement\n\n        case .arbitrary(var elements):\n            defer {\n                self = .arbitrary(elements)\n            }\n            return elements.remove(at: index)\n\n        }\n    }\n\n    @inlinable\n    mutating func removeAll(where shouldBeRemoved: (Element) throws -> Bool) rethrows {\n        switch self {\n        case .one(let oldElement):\n            if try shouldBeRemoved(oldElement) {\n                self = .arbitrary([])\n            }\n\n        case .arbitrary(var elements):\n            defer {\n                self = .arbitrary(elements)\n            }\n            return try elements.removeAll(where: shouldBeRemoved)\n\n        }\n    }\n\n    @inlinable\n    mutating func sort(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows {\n        switch self {\n        case .one:\n            // a collection of just one element is always sorted, nothing to do\n            break\n        case .arbitrary(var elements):\n            defer {\n                self = .arbitrary(elements)\n            }\n\n            try elements.sort(by: areInIncreasingOrder)\n        }\n    }\n}\n\nextension Array {\n    @inlinable\n    mutating func appendRemainingElements(from iterator: inout some IteratorProtocol<Element>) {\n        while let nextElement = iterator.next() {\n            append(nextElement)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Array+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension Array where Element == UInt8 {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let byteBuffer = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(maximumSizeAllowed: maximumSizeAllowed)\n        }\n\n        self = Self(buffer: byteBuffer)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystem/ArraySlice+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ArraySlice where Element == UInt8 {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let bytes = try await Array(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: fileSystem\n        )\n\n        self = Self(bytes)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystem/BufferedReader.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOCore\n\n/// A reader which maintains a buffer of bytes read from the file.\n///\n/// You can create a reader from a ``ReadableFileHandleProtocol`` by calling\n/// ``ReadableFileHandleProtocol/bufferedReader(startingAtAbsoluteOffset:capacity:)``. Call\n/// ``read(_:)`` to read a fixed number of bytes from the file or ``read(while:)-8aukk`` to read\n/// from the file while the bytes match a predicate.\n///\n/// You can also read bytes without returning them to caller by calling ``drop(_:)`` and\n/// ``drop(while:)``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct BufferedReader<Handle: ReadableFileHandleProtocol> {\n    /// The handle to read from.\n    private let handle: Handle\n\n    /// The offset for the next read from the file.\n    private var offset: Int64\n\n    /// Whether the reader has read to the end of the file.\n    private var readEOF = false\n\n    /// A buffer containing the read bytes.\n    private var buffer: ByteBuffer\n\n    /// The capacity of the buffer.\n    public let capacity: Int\n\n    /// The number of bytes currently in the buffer.\n    public var count: Int {\n        self.buffer.readableBytes\n    }\n\n    internal init(wrapping readableHandle: Handle, initialOffset: Int64, capacity: Int) {\n        precondition(\n            initialOffset >= 0,\n            \"initialOffset (\\(initialOffset)) must be greater than or equal to zero\"\n        )\n        precondition(capacity > 0, \"capacity (\\(capacity)) must be greater than zero\")\n        self.handle = readableHandle\n        self.offset = initialOffset\n        self.capacity = capacity\n        self.buffer = ByteBuffer()\n    }\n\n    private mutating func readFromFile(_ count: Int) async throws -> ByteBuffer {\n        let bytes = try await self.handle.readChunk(\n            fromAbsoluteOffset: self.offset,\n            length: .bytes(Int64(count))\n        )\n        // Reading short means reading end-of-file.\n        self.readEOF = bytes.readableBytes < count\n        self.offset += Int64(bytes.readableBytes)\n        return bytes\n    }\n\n    /// Read at most `count` bytes from the file; reads short if not enough bytes are available.\n    ///\n    /// - Parameters:\n    ///   - count: The number of bytes to read.\n    /// - Returns: The bytes read from the buffer.\n    public mutating func read(_ count: ByteCount) async throws -> ByteBuffer {\n        let byteCount = Int(count.bytes)\n        guard byteCount > 0 else { return ByteBuffer() }\n\n        if let bytes = self.buffer.readSlice(length: byteCount) {\n            return bytes\n        } else {\n            // Not enough bytes: read enough for the caller and to fill the buffer back to capacity.\n            var buffer = self.buffer\n            self.buffer = ByteBuffer()\n\n            // The bytes to read from the chunk is the difference in what the caller requested\n            // and is already stored in buffer. Note that if we get to the end of the file this\n            // number could be larger than the available number of bytes.\n            let bytesFromChunk = byteCount &- buffer.readableBytes\n            let bytesToRead = bytesFromChunk + self.capacity\n\n            // Read a chunk from the file and store it.\n            let chunk = try await self.readFromFile(bytesToRead)\n            self.buffer.writeImmutableBuffer(chunk)\n\n            // Finally read off the required bytes from the chunk we just read. If we read short\n            // then the chunk we just appended might not less than 'bytesFromChunk', that's fine,\n            // just take what's available.\n            var slice = self.buffer.readSlice(length: min(bytesFromChunk, chunk.readableBytes))!\n            buffer.writeBuffer(&slice)\n\n            return buffer\n        }\n    }\n\n    /// Reads from  the current position in the file until `predicate` returns `false` and returns\n    /// the read bytes.\n    ///\n    /// - Parameters:\n    ///   - predicate: A predicate which evaluates to `true` for all bytes returned.\n    /// - Returns: A tuple containing the bytes read from the file in its first component, and a boolean\n    /// indicating whether we've stopped reading because EOF has been reached, or because the predicate\n    /// condition doesn't hold true anymore.\n    public mutating func read(\n        while predicate: (UInt8) -> Bool\n    ) async throws -> (bytes: ByteBuffer, readEOF: Bool) {\n        // Check if the required bytes are in the buffer already.\n        let view = self.buffer.readableBytesView\n\n        if let index = view.firstIndex(where: { !predicate($0) }) {\n            // Got an index; slice off the front of the buffer.\n            let prefix = view[..<index]\n            let buffer = ByteBuffer(prefix)\n            self.buffer.moveReaderIndex(forwardBy: buffer.readableBytes)\n\n            // If we reached this codepath, it's because at least one element\n            // in the buffer makes the predicate false. This means that we have\n            // stopped reading because the condition doesn't hold true anymore.\n            return (buffer, false)\n        }\n\n        // The predicate holds true for all bytes in the buffer, start consuming chunks from the\n        // iterator.\n        while !self.readEOF {\n            var chunk = try await self.readFromFile(self.capacity)\n            let view = chunk.readableBytesView\n\n            if let index = view.firstIndex(where: { !predicate($0) }) {\n                // Found a byte for which the predicate doesn't hold. Consume the entire buffer and\n                // the front of this slice.\n                let chunkPrefix = view[..<index]\n                self.buffer.writeBytes(chunkPrefix)\n                chunk.moveReaderIndex(forwardBy: chunkPrefix.count)\n\n                let buffer = self.buffer\n                self.buffer = chunk\n\n                // If we reached this codepath, it's because at least one element\n                // in the buffer makes the predicate false. This means that we have\n                // stopped reading because the condition doesn't hold true anymore.\n                return (buffer, false)\n            } else {\n                // Predicate holds for all bytes. Continue reading.\n                self.buffer.writeBuffer(&chunk)\n            }\n        }\n\n        // Read end-of-file and the predicate still holds for all bytes:\n        // clear the buffer and return all bytes.\n        let buffer = self.buffer\n        self.buffer = ByteBuffer()\n        return (buffer, true)\n    }\n\n    /// Reads and discards the given number of bytes.\n    ///\n    /// - Parameter count: The number of bytes to read and discard.\n    public mutating func drop(_ count: Int) async throws {\n        if count > self.buffer.readableBytes {\n            self.offset += Int64(count &- self.buffer.readableBytes)\n            self.buffer.clear()\n        } else {\n            self.buffer.moveReaderIndex(forwardBy: count)\n        }\n    }\n\n    /// Reads and discards bytes until `predicate` returns `false.`\n    ///\n    /// - Parameters:\n    ///   - predicate: A predicate which evaluates to `true` for all dropped bytes.\n    public mutating func drop(while predicate: (UInt8) -> Bool) async throws {\n        let view = self.buffer.readableBytesView\n\n        if let index = view.firstIndex(where: { !predicate($0) }) {\n            let slice = view[..<index]\n            self.buffer.moveReaderIndex(forwardBy: slice.count)\n            return\n        }\n\n        // Didn't hit the predicate for buffered bytes; drop them all and consume the source.\n        self.buffer.clear(minimumCapacity: min(self.buffer.capacity, self.capacity))\n\n        while !self.readEOF {\n            var chunk = try await self.readFromFile(self.capacity)\n            let view = chunk.readableBytesView\n\n            if let index = view.firstIndex(where: { !predicate($0) }) {\n                let slice = view[..<index]\n                chunk.moveReaderIndex(forwardBy: slice.count)\n                self.buffer.writeBuffer(&chunk)\n                return\n            }\n        }\n    }\n}\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedReader {\n    /// Reads from  the current position in the file until `predicate` returns `false` and returns\n    /// the read bytes.\n    ///\n    /// - Parameters:\n    ///   - predicate: A predicate which evaluates to `true` for all bytes returned.\n    /// - Returns: The bytes read from the file.\n    /// - Important: This method has been deprecated: use ``read(while:)-8aukk`` instead.\n    @available(*, deprecated, message: \"Use the read(while:) method returning a (ByteBuffer, Bool) tuple instead.\")\n    public mutating func read(\n        while predicate: (UInt8) -> Bool\n    ) async throws -> ByteBuffer {\n        try await self.read(while: predicate).bytes\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ReadableFileHandleProtocol {\n    /// Creates a new ``BufferedReader`` for this file handle.\n    ///\n    /// - Parameters:\n    ///   - initialOffset: The offset to begin reading from, defaults to zero.\n    ///   - capacity: The capacity of the buffer in bytes, as a ``ByteCount``. Defaults to 512 KiB.\n    /// - Returns: A ``BufferedReader``.\n    public func bufferedReader(\n        startingAtAbsoluteOffset initialOffset: Int64 = 0,\n        capacity: ByteCount = .kibibytes(512)\n    ) -> BufferedReader<Self> {\n        BufferedReader(wrapping: self, initialOffset: initialOffset, capacity: Int(capacity.bytes))\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedReader: Sendable where Handle: Sendable {}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/BufferedWriter.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// A writer which buffers bytes in memory before writing them to the file system.\n///\n/// You can create a ``BufferedWriter`` by calling\n/// ``WritableFileHandleProtocol/bufferedWriter(startingAtAbsoluteOffset:capacity:)`` on\n/// ``WritableFileHandleProtocol`` and write bytes to it with one of the following methods:\n/// - ``BufferedWriter/write(contentsOf:)-1rkf6``\n/// - ``BufferedWriter/write(contentsOf:)-7cs3v``\n/// - ``BufferedWriter/write(contentsOf:)-66cts``\n///\n/// If a call to one of the write functions reaches the buffers ``BufferedWriter/capacity`` the\n/// buffer automatically writes its contents to the file.\n///\n/// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n///   configured size.\n///\n/// To write the bytes in the buffer to the file system before the buffer is full\n/// use ``BufferedWriter/flush()``.\n///\n/// - Important: You should you call ``BufferedWriter/flush()`` when you have finished appending\n///   to write any remaining data to the file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct BufferedWriter<Handle: WritableFileHandleProtocol> {\n    private let handle: Handle\n    /// Offset for the next write.\n    private var offset: Int64\n    /// A buffer of bytes to write.\n    private var buffer: [UInt8] = []\n\n    /// The maximum number of bytes to buffer before the buffer is automatically flushed.\n    public let capacity: Int\n\n    /// The number of bytes in the buffer.\n    ///\n    /// You can flush the buffer manually by calling ``flush()``.\n    public var bufferedBytes: Int {\n        self.buffer.count\n    }\n\n    /// The capacity of the buffer.\n    @_spi(Testing)\n    public var bufferCapacity: Int {\n        self.buffer.capacity\n    }\n\n    internal init(wrapping writableHandle: Handle, initialOffset: Int64, capacity: Int) {\n        precondition(\n            initialOffset >= 0,\n            \"initialOffset (\\(initialOffset)) must be greater than or equal to zero\"\n        )\n        precondition(capacity > 0, \"capacity (\\(capacity)) must be greater than zero\")\n        self.handle = writableHandle\n        self.offset = initialOffset\n        self.capacity = capacity\n    }\n\n    /// Write the contents of the collection of bytes to the buffer.\n    ///\n    /// If the number of bytes in the buffer exceeds the size of the buffer then they're\n    /// automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter bytes: The bytes to write to the buffer.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write(contentsOf bytes: some Sequence<UInt8>) async throws -> Int64 {\n        let bufferSize = Int64(self.buffer.count)\n        self.buffer.append(contentsOf: bytes)\n        let bytesWritten = Int64(self.buffer.count) &- bufferSize\n\n        if self.buffer.count >= self.capacity {\n            try await self.flush()\n        }\n\n        return bytesWritten\n    }\n\n    /// Write the contents of the `ByteBuffer` into the buffer.\n    ///\n    /// If the number of bytes in the buffer exceeds the size of the buffer then they're\n    /// automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter bytes: The bytes to write to the buffer.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write(contentsOf bytes: ByteBuffer) async throws -> Int64 {\n        try await self.write(contentsOf: bytes.readableBytesView)\n    }\n\n    /// Write the contents of the `AsyncSequence` of byte chunks to the buffer.\n    ///\n    /// If appending a chunk to the buffer causes it to exceed the capacity of the buffer then the\n    /// contents of the buffer are automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter chunks: The `AsyncSequence` of byte chunks to write to the buffer.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write<Chunks: AsyncSequence>(\n        contentsOf chunks: Chunks\n    ) async throws -> Int64 where Chunks.Element: Sequence<UInt8> {\n        var bytesWritten: Int64 = 0\n        do {\n            for try await chunk in chunks {\n                bytesWritten += try await self.write(contentsOf: chunk)\n            }\n        } catch let error as FileSystemError {\n            // From call to 'write'.\n            throw error\n        } catch let error {\n            // From iterating the async sequence.\n            throw FileSystemError(\n                code: .unknown,\n                message: \"AsyncSequence of bytes threw error while writing to the buffered writer.\",\n                cause: error,\n                location: .here()\n            )\n        }\n        return bytesWritten\n    }\n\n    /// Write the contents of the `AsyncSequence` of `ByteBuffer`s into the buffer.\n    ///\n    /// If appending a chunk to the buffer causes it to exceed the capacity of the buffer then the\n    /// contents of the buffer are automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter chunks: The `AsyncSequence` of `ByteBuffer`s to write.\n    /// - Returns: The number of bytes written into the buffered writer.\n    @discardableResult\n    public mutating func write<Chunks: AsyncSequence>(\n        contentsOf chunks: Chunks\n    ) async throws -> Int64 where Chunks.Element == ByteBuffer {\n        try await self.write(contentsOf: chunks.map { $0.readableBytesView })\n    }\n\n    /// Write the contents of the `AsyncSequence` of bytes the buffer.\n    ///\n    /// If appending a byte to the buffer causes it to exceed the capacity of the buffer then the\n    /// contents of the buffer are automatically written to the file system.\n    ///\n    /// - Remark: The writer reclaims the buffer's memory when it grows to more than twice the\n    ///   configured size.\n    ///\n    /// To manually flush bytes use ``flush()``.\n    ///\n    /// - Parameter bytes: The `AsyncSequence` of bytes to write to the buffer.\n    @discardableResult\n    public mutating func write<Bytes: AsyncSequence>(\n        contentsOf bytes: Bytes\n    ) async throws -> Int64 where Bytes.Element == UInt8 {\n        try await self.write(contentsOf: bytes.map { CollectionOfOne($0) })\n    }\n\n    /// Flush any buffered bytes to the file system.\n    ///\n    /// - Important: You should you call ``flush()`` when you have finished writing to ensure the\n    ///   buffered writer writes any remaining data to the file system.\n    public mutating func flush() async throws {\n        if self.buffer.isEmpty { return }\n\n        try await self.handle.write(contentsOf: self.buffer, toAbsoluteOffset: self.offset)\n        self.offset += Int64(self.buffer.count)\n\n        // The buffer may grow beyond the specified buffer size. Keep the capacity if it's less than\n        // double the intended size, otherwise reclaim the memory.\n        let keepCapacity = self.buffer.capacity <= (self.capacity * 2)\n        self.buffer.removeAll(keepingCapacity: keepCapacity)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension WritableFileHandleProtocol {\n    /// Creates a new ``BufferedWriter`` for this file handle.\n    ///\n    /// - Parameters:\n    ///   - initialOffset: The offset to begin writing at, defaults to zero.\n    ///   - capacity: The capacity of the buffer in bytes, as a ``ByteCount``. The writer writes the contents of its\n    ///     buffer to the file system when it exceeds this capacity. Defaults to 512 KiB.\n    /// - Returns: A ``BufferedWriter``.\n    public func bufferedWriter(\n        startingAtAbsoluteOffset initialOffset: Int64 = 0,\n        capacity: ByteCount = .kibibytes(512)\n    ) -> BufferedWriter<Self> {\n        BufferedWriter(\n            wrapping: self,\n            initialOffset: initialOffset,\n            capacity: Int(capacity.bytes)\n        )\n    }\n\n    /// Convenience function that creates a buffered reader, executes\n    /// the closure that writes the contents into the buffer and calls 'flush()'.\n    ///\n    /// - Parameters:\n    ///   - initialOffset: The offset to begin writing at, defaults to zero.\n    ///   - capacity: The capacity of the buffer in bytes, as a ``ByteCount``. The writer writes the contents of its\n    ///     buffer to the file system when it exceeds this capacity. Defaults to 512 KiB.\n    ///   - body: The closure that writes the contents to the buffer created in this method.\n    /// - Returns: The result of the executed closure.\n    public func withBufferedWriter<Result>(\n        startingAtAbsoluteOffset initialOffset: Int64 = 0,\n        capacity: ByteCount = .kibibytes(512),\n        execute body: (inout BufferedWriter<Self>) async throws -> Result\n    ) async throws -> Result {\n        var bufferedWriter = self.bufferedWriter(startingAtAbsoluteOffset: initialOffset, capacity: capacity)\n        return try await withUncancellableTearDown {\n            try await body(&bufferedWriter)\n        } tearDown: { _ in\n            try await bufferedWriter.flush()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedWriter: Sendable where Handle: Sendable {}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/ByteBuffer+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ByteBuffer {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        self = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(\n                fromAbsoluteOffset: 0,\n                maximumSizeAllowed: maximumSizeAllowed\n            )\n        }\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n\n    /// Writes the readable bytes of the ``ByteBuffer`` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await self.readableBytesView.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: fileSystem\n        )\n    }\n\n    /// Writes the readable bytes of the ``ByteBuffer`` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/ByteCount.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// Represents the number of bytes.\npublic struct ByteCount: Hashable, Sendable {\n    /// The number of bytes\n    public var bytes: Int64\n\n    /// Returns a ``ByteCount`` with a given number of bytes\n    /// - Parameter count: The number of bytes\n    public static func bytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of kilobytes\n    ///\n    /// One kilobyte is 1000 bytes.\n    ///\n    /// - Parameter count: The number of kilobytes\n    public static func kilobytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1000 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of megabytes\n    ///\n    /// One megabyte is 1,000,000 bytes.\n    ///\n    /// - Parameter count: The number of megabytes\n    public static func megabytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1000 * 1000 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of gigabytes\n    ///\n    /// One gigabyte is 1,000,000,000 bytes.\n    ///\n    /// - Parameter count: The number of gigabytes\n    public static func gigabytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1000 * 1000 * 1000 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of kibibytes\n    ///\n    /// One kibibyte is 1024 bytes.\n    ///\n    /// - Parameter count: The number of kibibytes\n    public static func kibibytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1024 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of mebibytes\n    ///\n    /// One mebibyte is 10,485,760 bytes.\n    ///\n    /// - Parameter count: The number of mebibytes\n    public static func mebibytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1024 * 1024 * count)\n    }\n\n    /// Returns a ``ByteCount`` with a given number of gibibytes\n    ///\n    /// One gibibyte is 10,737,418,240 bytes.\n    ///\n    /// - Parameter count: The number of gibibytes\n    public static func gibibytes(_ count: Int64) -> ByteCount {\n        ByteCount(bytes: 1024 * 1024 * 1024 * count)\n    }\n}\n\nextension ByteCount {\n    /// A ``ByteCount`` for the maximum amount of bytes that can be written to `ByteBuffer`.\n    internal static var byteBufferCapacity: ByteCount {\n        #if arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n        // on 32-bit platforms we can't make use of a whole UInt32.max (as it doesn't fit in an Int)\n        let byteBufferMaxIndex = UInt32(Int.max)\n        #else\n        // on 64-bit platforms we're good\n        let byteBufferMaxIndex = UInt32.max\n        #endif\n\n        return ByteCount(bytes: Int64(byteBufferMaxIndex))\n    }\n\n    /// A ``ByteCount`` for an unlimited amount of bytes.\n    public static var unlimited: ByteCount {\n        ByteCount(bytes: .max)\n    }\n}\n\nextension ByteCount: AdditiveArithmetic {\n    public static var zero: ByteCount { ByteCount(bytes: 0) }\n\n    public static func + (lhs: ByteCount, rhs: ByteCount) -> ByteCount {\n        ByteCount(bytes: lhs.bytes + rhs.bytes)\n    }\n\n    public static func - (lhs: ByteCount, rhs: ByteCount) -> ByteCount {\n        ByteCount(bytes: lhs.bytes - rhs.bytes)\n    }\n}\n\nextension ByteCount: Comparable {\n    public static func < (lhs: ByteCount, rhs: ByteCount) -> Bool {\n        lhs.bytes < rhs.bytes\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Convenience.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\nextension String {\n    /// Writes the UTF8 encoded `String` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the `String` to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await self.utf8.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: fileSystem\n        )\n    }\n\n    /// Writes the UTF8 encoded `String` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the `String` to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n\nextension Sequence<UInt8> where Self: Sendable {\n    /// Writes the contents of the `Sequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await fileSystem.withFileHandle(forWritingAt: path, options: options) { handle in\n            try await handle.write(contentsOf: self, toAbsoluteOffset: offset)\n        }\n    }\n\n    /// Writes the contents of the `Sequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence where Self.Element: Sequence<UInt8>, Self: Sendable {\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await fileSystem.withFileHandle(forWritingAt: path, options: options) { handle in\n            var writer = handle.bufferedWriter(startingAtAbsoluteOffset: offset)\n            let bytesWritten = try await writer.write(contentsOf: self)\n            try await writer.flush()\n            return bytesWritten\n        }\n    }\n\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence where Self.Element == UInt8, Self: Sendable {\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        fileSystem: some FileSystemProtocol\n    ) async throws -> Int64 {\n        try await fileSystem.withFileHandle(forWritingAt: path, options: options) { handle in\n            var writer = handle.bufferedWriter(startingAtAbsoluteOffset: offset)\n            let bytesWritten = try await writer.write(contentsOf: self)\n            try await writer.flush()\n            return bytesWritten\n        }\n    }\n\n    /// Writes the contents of the `AsyncSequence` to a file.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to write the contents of the sequence to.\n    ///   - offset: The offset into the file to write to, defaults to zero.\n    ///   - options: Options for opening the file, defaults to creating a new file.\n    /// - Returns: The number of bytes written to the file.\n    @discardableResult\n    public func write(\n        toFileAt path: FilePath,\n        absoluteOffset offset: Int64 = 0,\n        options: OpenOptions.Write = .newFile(replaceExisting: false)\n    ) async throws -> Int64 {\n        try await self.write(\n            toFileAt: path,\n            absoluteOffset: offset,\n            options: options,\n            fileSystem: .shared\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/DirectoryEntries.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIODarwin\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n/// An `AsyncSequence` of entries in a directory.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct DirectoryEntries: AsyncSequence, Sendable {\n    public typealias AsyncIterator = DirectoryIterator\n    public typealias Element = DirectoryEntry\n\n    /// The sequence.\n    private let batchedSequence: Batched\n\n    /// Creates a new ``DirectoryEntries`` sequence.\n    internal init(handle: SystemFileHandle, recursive: Bool) {\n        self.batchedSequence = Batched(handle: handle, recursive: recursive)\n    }\n\n    /// Creates a ``DirectoryEntries`` sequence by wrapping an `AsyncSequence` of _batches_ of\n    /// directory entries.\n    @preconcurrency\n    public init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n    where S.Element == Batched.Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {\n        self.batchedSequence = Batched(wrapping: sequence)\n    }\n\n    public func makeAsyncIterator() -> DirectoryIterator {\n        DirectoryIterator(iterator: self.batchedSequence.makeAsyncIterator())\n    }\n\n    /// Returns a sequence of directory entry batches.\n    ///\n    /// The batched sequence has its element type as `Array<DirectoryEntry>` rather\n    /// than `DirectoryEntry`. This can enable better performance by reducing the number of\n    /// executor hops.\n    public func batched() -> Batched {\n        self.batchedSequence\n    }\n\n    /// An `AsyncIteratorProtocol` of `DirectoryEntry`.\n    public struct DirectoryIterator: AsyncIteratorProtocol {\n        /// The batched iterator to consume from.\n        private var iterator: Batched.AsyncIterator\n        /// A slice of the current batch being iterated.\n        private var currentBatch: ArraySlice<DirectoryEntry>\n\n        init(iterator: Batched.AsyncIterator) {\n            self.iterator = iterator\n            self.currentBatch = []\n        }\n\n        public mutating func next() async throws -> DirectoryEntry? {\n            if self.currentBatch.isEmpty {\n                let batch = try await self.iterator.next()\n                self.currentBatch = (batch ?? [])[...]\n            }\n\n            return self.currentBatch.popFirst()\n        }\n    }\n}\n\n@available(*, unavailable)\nextension DirectoryEntries.AsyncIterator: Sendable {}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension DirectoryEntries {\n    /// An `AsyncSequence` of batches of directory entries.\n    ///\n    /// The ``Batched`` sequence uses `Array<DirectoryEntry>` as its element type rather\n    /// than `DirectoryEntry`. This can enable better performance by reducing the number of\n    /// executor hops at the cost of ease-of-use.\n    public struct Batched: AsyncSequence, Sendable {\n        public typealias AsyncIterator = BatchedIterator\n        public typealias Element = [DirectoryEntry]\n\n        private let stream: BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>\n\n        /// Creates a ``DirectoryEntries/Batched`` sequence by wrapping an `AsyncSequence`\n        /// of directory entry batches.\n        @preconcurrency\n        public init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n        where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {\n            self.stream = BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>(wrapping: sequence)\n        }\n\n        fileprivate init(handle: SystemFileHandle, recursive: Bool) {\n            // Expanding the batches yields watermarks of 256 and 512 directory entries.\n            let stream = NIOThrowingAsyncSequenceProducer.makeBatchedDirectoryEntryStream(\n                handle: handle,\n                recursive: recursive,\n                entriesPerBatch: 64,\n                lowWatermark: 4,\n                highWatermark: 8\n            )\n\n            self.stream = BufferedOrAnyStream(wrapping: stream)\n        }\n\n        public func makeAsyncIterator() -> BatchedIterator {\n            BatchedIterator(wrapping: self.stream.makeAsyncIterator())\n        }\n\n        /// An `AsyncIteratorProtocol` of `Array<DirectoryEntry>`.\n        public struct BatchedIterator: AsyncIteratorProtocol {\n            private var iterator: BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>.AsyncIterator\n\n            fileprivate init(\n                wrapping iterator: BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>.AsyncIterator\n            ) {\n                self.iterator = iterator\n            }\n\n            public mutating func next() async throws -> [DirectoryEntry]? {\n                try await self.iterator.next()\n            }\n        }\n    }\n}\n\n@available(*, unavailable)\nextension DirectoryEntries.Batched.AsyncIterator: Sendable {}\n\n// MARK: - Internal\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOThrowingAsyncSequenceProducer\nwhere\n    Element == [DirectoryEntry],\n    Failure == (any Error),\n    Strategy == NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n    Delegate == DirectoryEntryProducer\n{\n    fileprivate static func makeBatchedDirectoryEntryStream(\n        handle: SystemFileHandle,\n        recursive: Bool,\n        entriesPerBatch: Int,\n        lowWatermark: Int,\n        highWatermark: Int\n    ) -> NIOThrowingAsyncSequenceProducer<\n        [DirectoryEntry], any Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n        DirectoryEntryProducer\n    > {\n        let producer = DirectoryEntryProducer(\n            handle: handle,\n            recursive: recursive,\n            entriesPerBatch: entriesPerBatch\n        )\n\n        let nioThrowingAsyncSequence = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: [DirectoryEntry].self,\n            backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark(\n                lowWatermark: lowWatermark,\n                highWatermark: highWatermark\n            ),\n            finishOnDeinit: false,\n            delegate: producer\n        )\n\n        producer.setSequenceProducerSource(nioThrowingAsyncSequence.source)\n\n        return nioThrowingAsyncSequence.sequence\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate typealias DirectoryEntrySequenceProducer = NIOThrowingAsyncSequenceProducer<\n    [DirectoryEntry], Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, DirectoryEntryProducer\n>\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate final class DirectoryEntryProducer: NIOAsyncSequenceProducerDelegate {\n    let state: NIOLockedValueBox<DirectoryEnumerator>\n    let entriesPerBatch: Int\n\n    init(handle: SystemFileHandle, recursive: Bool, entriesPerBatch: Int) {\n        let state = DirectoryEnumerator(handle: handle, recursive: recursive)\n        self.state = NIOLockedValueBox(state)\n        self.entriesPerBatch = entriesPerBatch\n    }\n\n    func didTerminate() {\n        guard let threadPool = self.state.withLockedValue({ $0.threadPoolForClosing() }) else {\n            return\n        }\n\n        threadPool.submit { _ in  // always run, even if cancelled\n            self.state.withLockedValue { state in\n                state.closeIfNecessary()\n            }\n        }\n    }\n\n    /// sets the source within the producer state\n    func setSequenceProducerSource(_ sequenceProducerSource: DirectoryEntrySequenceProducer.Source) {\n        self.state.withLockedValue { state in\n            switch state.state {\n            case .idle:\n                state.sequenceProducerSource = sequenceProducerSource\n            case .done:\n                sequenceProducerSource.finish()\n            case .open, .openPausedProducing:\n                fatalError()\n            case .modifying:\n                fatalError()\n            }\n        }\n    }\n\n    func clearSource() {\n        self.state.withLockedValue { state in\n            state.sequenceProducerSource = nil\n        }\n    }\n\n    /// The 'entry point' for producing elements.\n    ///\n    /// Calling this function will start producing directory entries asynchronously by dispatching\n    /// work to the IO executor and feeding the result back to the stream source. On yielding to the\n    /// source it will either produce more or be scheduled to produce more. Stopping production\n    /// is signalled via the stream's 'onTermination' handler.\n    func produceMore() {\n        let threadPool = self.state.withLockedValue { state in\n            state.produceMore()\n        }\n\n        // No thread pool means we're done.\n        guard let threadPool = threadPool else { return }\n\n        threadPool.submit {\n            let result: Result<[DirectoryEntry], Error>\n            switch $0 {\n            case .active:\n                result = Result { try self.nextBatch() }\n            case .cancelled:\n                result = .failure(CancellationError())\n            }\n            self.onNextBatchResult(result)\n        }\n    }\n\n    func pauseProducing() {\n        self.state.withLockedValue { state in\n            state.pauseProducing()\n        }\n    }\n\n    private func nextBatch() throws -> [DirectoryEntry] {\n        try self.state.withLockedValue { state in\n            try state.next(self.entriesPerBatch)\n        }\n    }\n\n    private func onNextBatchResult(_ result: Result<[DirectoryEntry], Error>) {\n        switch result {\n        case let .success(entries):\n            self.onNextBatch(entries)\n        case let .failure(error):\n            // Failed to read more entries: close and notify the stream so consumers receive the\n            // error.\n            self.close()\n            let source = self.state.withLockedValue { state in\n                state.sequenceProducerSource\n            }\n            source?.finish(error)\n            self.clearSource()\n        }\n    }\n\n    private func onNextBatch(_ entries: [DirectoryEntry]) {\n        let source = self.state.withLockedValue { state in\n            state.sequenceProducerSource\n        }\n\n        guard let source else {\n            assertionFailure(\"unexpectedly missing source\")\n            return\n        }\n\n        // No entries were read: this must be the end (as the batch size must be greater than zero).\n        if entries.isEmpty {\n            source.finish()\n            self.clearSource()\n            return\n        }\n\n        // Reading short means reading EOF. The enumerator closes itself in that case.\n        let readEOF = entries.count < self.entriesPerBatch\n\n        // Entries were produced: yield them and maybe produce more.\n        let writeResult = source.yield(contentsOf: CollectionOfOne(entries))\n\n        // Exit early if EOF was read; no use in trying to produce more.\n        if readEOF {\n            source.finish()\n            self.clearSource()\n            return\n        }\n\n        switch writeResult {\n        case .produceMore:\n            self.produceMore()\n        case .stopProducing:\n            self.pauseProducing()\n        case .dropped:\n            // The source is finished; mark ourselves as done.\n            self.close()\n        }\n    }\n\n    private func close() {\n        guard let threadPool = self.state.withLockedValue({ $0.threadPoolForClosing() }) else {\n            return\n        }\n\n        threadPool.submit { _ in  // always run, even if cancelled\n            self.state.withLockedValue { state in\n                state.closeIfNecessary()\n            }\n        }\n    }\n}\n\n/// Enumerates a directory in batches.\n///\n/// Note that this is not a `Sequence` because we allow for errors to be thrown on `next()`.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate struct DirectoryEnumerator: Sendable {\n    internal enum State: @unchecked Sendable {\n        case modifying\n        case idle(SystemFileHandle.SendableView, recursive: Bool)\n        case open(NIOThreadPool, Source, [DirectoryEntry])\n        case openPausedProducing(NIOThreadPool, Source, [DirectoryEntry])\n        case done\n    }\n\n    /// The source of directory entries.\n    internal enum Source {\n        case readdir(CInterop.DirPointer)\n        case fts(CInterop.FTSPointer)\n    }\n\n    /// The current state of enumeration.\n    internal var state: State\n\n    /// The path to the directory being enumerated.\n    private let path: FilePath\n\n    /// The route via which directory entry batches are yielded,\n    /// the sourcing end of the `DirectoryEntrySequenceProducer`\n    internal var sequenceProducerSource: DirectoryEntrySequenceProducer.Source?\n\n    /// Information about an entry returned by FTS. See 'fts(3)'.\n    private enum FTSInfo: Hashable, Sendable {\n        case directoryPreOrder\n        case directoryCausingCycle\n        case ftsDefault\n        case directoryUnreadable\n        case dotFile\n        case directoryPostOrder\n        case error\n        case regularFile\n        case noStatInfoAvailable\n        case noStatInfoRequested\n        case symbolicLink\n        case symbolicLinkToNonExistentTarget\n\n        init?(rawValue: UInt16) {\n            switch Int32(rawValue) {\n            case FTS_D:\n                self = .directoryPreOrder\n            case FTS_DC:\n                self = .directoryCausingCycle\n            case FTS_DEFAULT:\n                self = .ftsDefault\n            case FTS_DNR:\n                self = .directoryUnreadable\n            case FTS_DOT:\n                self = .dotFile\n            case FTS_DP:\n                self = .directoryPostOrder\n            case FTS_ERR:\n                self = .error\n            case FTS_F:\n                self = .regularFile\n            case FTS_NS:\n                self = .noStatInfoAvailable\n            case FTS_NSOK:\n                self = .noStatInfoRequested\n            case FTS_SL:\n                self = .symbolicLink\n            case FTS_SLNONE:\n                self = .symbolicLinkToNonExistentTarget\n            default:\n                return nil\n            }\n        }\n    }\n\n    internal init(handle: SystemFileHandle, recursive: Bool) {\n        self.state = .idle(handle.sendableView, recursive: recursive)\n        self.path = handle.path\n    }\n\n    internal mutating func produceMore() -> NIOThreadPool? {\n        switch self.state {\n        case let .idle(handle, _):\n            return handle.threadPool\n        case let .open(threadPool, _, _):\n            return threadPool\n        case .openPausedProducing(let threadPool, let source, let array):\n            self.state = .open(threadPool, source, array)\n            return threadPool\n        case .done:\n            return nil\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    internal mutating func pauseProducing() {\n        switch self.state {\n        case .open(let threadPool, let source, let array):\n            self.state = .openPausedProducing(threadPool, source, array)\n        case .idle:\n            ()  // we won't apply back pressure until something has been read\n        case .openPausedProducing, .done:\n            ()  // no-op\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    internal func threadPoolForClosing() -> NIOThreadPool? {\n        switch self.state {\n        case .open(let threadPool, _, _), .openPausedProducing(let threadPool, _, _):\n            return threadPool\n        case .idle, .done:\n            // Don't need to close in the idle state: we don't own the handle.\n            return nil\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    /// Returns the next batch of directory entries.\n    internal mutating func next(_ count: Int) throws -> [DirectoryEntry] {\n        while true {\n            switch self.process(count) {\n            case let .yield(result):\n                return try result.get()\n            case .continue:\n                ()\n            }\n        }\n    }\n\n    /// Closes the descriptor, if necessary.\n    internal mutating func closeIfNecessary() {\n        switch self.state {\n        case .idle:\n            // We don't own the handle so don't close it.\n            self.state = .done\n\n        case .open(_, let mode, _), .openPausedProducing(_, let mode, _):\n            self.state = .done\n            switch mode {\n            case .readdir(let dir):\n                _ = Libc.closedir(dir)\n            case .fts(let fts):\n                _ = Libc.ftsClose(fts)\n            }\n\n        case .done:\n            ()\n\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    private enum ProcessResult {\n        case yield(Result<[DirectoryEntry], FileSystemError>)\n        case `continue`\n    }\n\n    private mutating func makeReaddirSource(\n        _ handle: SystemFileHandle.SendableView\n    ) -> Result<Source, FileSystemError> {\n        handle._duplicate().mapError { dupError in\n            FileSystemError(\n                message: \"Unable to open directory stream for '\\(handle.path)'.\",\n                wrapping: dupError\n            )\n        }.flatMap { descriptor in\n            // We own the descriptor and cede ownership if 'opendir' succeeds; if it doesn't we need\n            // to close it.\n            descriptor.opendir().mapError { errno in\n                // Close the descriptor on error.\n                try? descriptor.close()\n                return FileSystemError.fdopendir(errno: errno, path: handle.path, location: .here())\n            }\n        }.map {\n            .readdir($0)\n        }\n    }\n\n    private mutating func makeFTSSource(\n        _ handle: SystemFileHandle.SendableView\n    ) -> Result<Source, FileSystemError> {\n        Libc.ftsOpen(handle.path, options: [.noChangeDir, .physical]).mapError { errno in\n            FileSystemError.open(\"fts_open\", error: errno, path: handle.path, location: .here())\n        }.map {\n            .fts($0)\n        }\n    }\n\n    private mutating func processOpenState(\n        threadPool: NIOThreadPool,\n        dir: CInterop.DirPointer,\n        entries: inout [DirectoryEntry],\n        count: Int\n    ) -> (State, ProcessResult) {\n        entries.removeAll(keepingCapacity: true)\n        entries.reserveCapacity(count)\n\n        while entries.count < count {\n            switch Libc.readdir(dir) {\n            case let .success(.some(entry)):\n                // Skip \".\" and \"..\" (and empty paths)\n                if self.isThisOrParentDirectory(entry.pointee) {\n                    continue\n                }\n\n                let fileType = FileType(direntType: entry.pointee.d_type)\n                let name: FilePath.Component\n                #if canImport(Darwin)\n                // Safe to force unwrap: may be nil if empty, a root, or more than one component.\n                // Empty is checked for above, root can't exist within a directory, and directory\n                // items must be a single path component.\n                name = FilePath.Component(platformString: CNIODarwin_dirent_dname(entry))!\n                #else\n                name = FilePath.Component(platformString: CNIOLinux_dirent_dname(entry))!\n                #endif\n\n                let fullPath = self.path.appending(name)\n                // '!' is okay here: the init returns nil if there is an empty path which we know\n                // isn't the case as 'self.path' is non-empty.\n                entries.append(DirectoryEntry(path: fullPath, type: fileType)!)\n\n            case .success(.none):\n                // Nothing we can do on failure so ignore the result.\n                _ = Libc.closedir(dir)\n                return (.done, .yield(.success(entries)))\n\n            case let .failure(errno):\n                // Nothing we can do on failure so ignore the result.\n                _ = Libc.closedir(dir)\n                let error = FileSystemError.readdir(\n                    errno: errno,\n                    path: self.path,\n                    location: .here()\n                )\n                return (.done, .yield(.failure(error)))\n            }\n        }\n\n        // We must have hit our 'count' limit.\n        return (.open(threadPool, .readdir(dir), entries), .yield(.success(entries)))\n    }\n\n    private mutating func processOpenState(\n        threadPool: NIOThreadPool,\n        fts: CInterop.FTSPointer,\n        entries: inout [DirectoryEntry],\n        count: Int\n    ) -> (State, ProcessResult) {\n        entries.removeAll(keepingCapacity: true)\n        entries.reserveCapacity(count)\n\n        while entries.count < count {\n            switch Libc.ftsRead(fts) {\n            case .success(.some(let entry)):\n                let info = FTSInfo(rawValue: entry.pointee.fts_info)\n                switch info {\n                case .directoryPreOrder:\n                    let entry = DirectoryEntry(path: entry.path, type: .directory)!\n                    entries.append(entry)\n\n                case .directoryPostOrder:\n                    ()  // Don't visit directories twice.\n\n                case .regularFile:\n                    let entry = DirectoryEntry(path: entry.path, type: .regular)!\n                    entries.append(entry)\n\n                case .symbolicLink, .symbolicLinkToNonExistentTarget:\n                    let entry = DirectoryEntry(path: entry.path, type: .symlink)!\n                    entries.append(entry)\n\n                case .ftsDefault:\n                    // File type is unknown.\n                    let entry = DirectoryEntry(path: entry.path, type: .unknown)!\n                    entries.append(entry)\n\n                case .error:\n                    let errno = Errno(rawValue: entry.pointee.fts_errno)\n                    let error = FileSystemError(\n                        code: .unknown,\n                        message: \"Can't read file system tree.\",\n                        cause: FileSystemError.SystemCallError(systemCall: \"fts_read\", errno: errno),\n                        location: .here()\n                    )\n                    _ = Libc.ftsClose(fts)\n                    return (.done, .yield(.failure(error)))\n\n                case .directoryCausingCycle:\n                    ()  // Cycle found, ignore it and continue.\n                case .directoryUnreadable:\n                    ()  // Can't read directory, ignore it and continue iterating.\n                case .dotFile:\n                    ()  // Ignore \".\" and \"..\"\n                case .noStatInfoAvailable:\n                    ()  // No stat info available so we can't list the entry, ignore it.\n                case .noStatInfoRequested:\n                    ()  // Shouldn't happen.\n\n                case nil:\n                    ()  // Unknown, ignore.\n                }\n\n            case .success(.none):\n                // No entries left to iterate.\n                _ = Libc.ftsClose(fts)\n                return (.done, .yield(.success(entries)))\n\n            case .failure(let errno):\n                // Nothing we can do on failure so ignore the result.\n                _ = Libc.ftsClose(fts)\n                let error = FileSystemError.ftsRead(\n                    errno: errno,\n                    path: self.path,\n                    location: .here()\n                )\n                return (.done, .yield(.failure(error)))\n            }\n        }\n\n        // We must have hit our 'count' limit.\n        return (.open(threadPool, .fts(fts), entries), .yield(.success(entries)))\n    }\n\n    private mutating func process(_ count: Int) -> ProcessResult {\n        switch self.state {\n        case let .idle(handle, recursive):\n            let result: Result<Source, FileSystemError>\n\n            if recursive {\n                result = self.makeFTSSource(handle)\n            } else {\n                result = self.makeReaddirSource(handle)\n            }\n\n            switch result {\n            case let .success(source):\n                self.state = .open(handle.threadPool, source, [])\n                return .continue\n\n            case let .failure(error):\n                self.state = .done\n                return .yield(.failure(error))\n            }\n\n        case .open(let threadPool, let mode, var entries):\n            self.state = .modifying\n\n            switch mode {\n            case .readdir(let dir):\n                let (state, result) = self.processOpenState(\n                    threadPool: threadPool,\n                    dir: dir,\n                    entries: &entries,\n                    count: count\n                )\n                self.state = state\n                return result\n\n            case .fts(let fts):\n                let (state, result) = self.processOpenState(\n                    threadPool: threadPool,\n                    fts: fts,\n                    entries: &entries,\n                    count: count\n                )\n                self.state = state\n                return result\n            }\n\n        case .openPausedProducing:\n            return .yield(.success([]))\n\n        case .done:\n            return .yield(.success([]))\n\n        case .modifying:\n            fatalError()\n        }\n    }\n\n    private func isThisOrParentDirectory(_ entry: CInterop.DirEnt) -> Bool {\n        let dot = CChar(bitPattern: UInt8(ascii: \".\"))\n        switch (entry.d_name.0, entry.d_name.1, entry.d_name.2) {\n        case (0, _, _), (dot, 0, _), (dot, dot, 0):\n            return true\n        default:\n            return false\n        }\n    }\n}\n\nextension UnsafeMutablePointer<CInterop.FTSEnt> {\n    fileprivate var path: FilePath {\n        FilePath(platformString: self.pointee.fts_path!)\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/DirectoryEntry.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// Information about an item within a directory.\npublic struct DirectoryEntry: Sendable, Hashable, Equatable {\n    /// The path of the directory entry.\n    ///\n    /// - Precondition: The path must have at least one component.\n    public let path: FilePath\n\n    /// The name of the entry; the final component of the ``path``.\n    ///\n    /// If `path` is \"/Users/tim/path-to-4T.key\" then `name` will be \"path-to-4T.key\".\n    public var name: FilePath.Component {\n        self.path.lastComponent!\n    }\n\n    /// The type of entry.\n    public var type: FileType\n\n    /// Creates a directory entry; returns `nil` if `path` has no components.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory entry which must contain at least one component.\n    ///   - type: The type of entry.\n    public init?(path: FilePath, type: FileType) {\n        if path.components.isEmpty {\n            return nil\n        }\n\n        self.path = path\n        self.type = type\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Docs.docc/Extensions/DirectoryFileHandleProtocol.md",
    "content": "# ``_NIOFileSystem/DirectoryFileHandleProtocol``\n\n## Topics\n\n### Iterating a directory\n\n- ``listContents()``\n\n### Opening files with managed lifecycles\n\nOpen files and directories at paths relative to the directory handle. These methods manage\nthe lifecycle of the handles by closing them when the `execute` closure returns.\n\n- ``withFileHandle(forReadingAt:options:execute:)``\n- ``withFileHandle(forWritingAt:options:execute:)``\n- ``withFileHandle(forReadingAndWritingAt:options:execute:)``\n- ``withDirectoryHandle(atPath:options:execute:)``\n\n### Opening files\n\nOpen files and directories at paths relative to the directory handle. These methods return\nthe handle to the caller who is responsible for closing it.\n\n- ``openFile(forReadingAt:options:)``\n- ``openFile(forWritingAt:options:)``\n- ``openFile(forReadingAndWritingAt:options:)``\n- ``openDirectory(atPath:options:)``\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Docs.docc/Extensions/FileHandleProtocol.md",
    "content": "# ``_NIOFileSystem/FileHandleProtocol``\n\n## Topics\n\n### File Information\n\n- ``info()``\n\n### Permissions\n\n- ``replacePermissions(_:)``\n- ``addPermissions(_:)``\n- ``removePermissions(_:)``\n\n### Extended Attributes\n\n- ``attributeNames()``\n- ``valueForAttribute(_:)``\n- ``updateValueForAttribute(_:attribute:)``\n- ``removeValueForAttribute(_:)``\n\n### Descriptor Management\n\n- ``synchronize()``\n- ``withUnsafeDescriptor(_:)``\n- ``detachUnsafeFileDescriptor()``\n- ``close()``\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Docs.docc/Extensions/FileSystemProtocol.md",
    "content": "# ``_NIOFileSystem/FileSystemProtocol``\n\n## Topics\n\n### Opening files with managed lifecycles\n\nFiles and directories can be opened and have their lifecycles managed by using the\nfollowing methods:\n\n- ``withFileHandle(forReadingAt:options:execute:)``\n- ``withFileHandle(forWritingAt:options:execute:)``\n- ``withFileHandle(forReadingAndWritingAt:options:execute:)``\n- ``withDirectoryHandle(atPath:options:execute:)``\n\n### Opening files\n\nFiles and directories can be opened using the following methods. The caller is responsible for\nclosing it to avoid leaking resources.\n\n- ``openFile(forReadingAt:)``\n- ``openFile(forWritingAt:options:)``\n- ``openFile(forReadingAndWritingAt:options:)``\n- ``openDirectory(atPath:options:)``\n\n### File information\n\n- ``info(forFileAt:infoAboutSymbolicLink:)``\n\n### Symbolic links\n\n- ``createSymbolicLink(at:withDestination:)``\n- ``destinationOfSymbolicLink(at:)``\n\n### Managing files\n\n- ``copyItem(at:to:strategy:shouldProceedAfterError:shouldCopyItem:)``\n- ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n- ``removeItem(at:)``\n- ``moveItem(at:to:)``\n- ``replaceItem(at:withItemAt:)``\n- ``createDirectory(at:withIntermediateDirectories:permissions:)``\n\n### System directories\n\n- ``currentWorkingDirectory``\n- ``temporaryDirectory``\n- ``withTemporaryDirectory(prefix:options:execute:)``\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Docs.docc/Extensions/ReadableFileHandleProtocol.md",
    "content": "# ``_NIOFileSystem/ReadableFileHandleProtocol``\n\n## Topics\n\n### Read the contents of a file\n\n- ``bufferedReader(startingAtAbsoluteOffset:capacity:)``\n- ``readChunks(chunkLength:)``\n- ``readChunks(in:chunkLength:)``\n- ``readChunks(in:chunkLength:)``\n- ``readChunks(in:chunkLength:)``\n- ``readChunks(in:chunkLength:)``\n- ``readChunks(in:chunkLength:)``\n- ``readChunks(in:chunkLength:)``\n- ``readToEnd(fromAbsoluteOffset:maximumSizeAllowed:)``\n\n### Read part of a file\n\n- ``readChunk(fromAbsoluteOffset:length:)``\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Docs.docc/Extensions/WritableFileHandleProtocol.md",
    "content": "# ``_NIOFileSystem/WritableFileHandleProtocol``\n\n## Topics\n\n### Write bytes to a file\n\n- ``write(contentsOf:toAbsoluteOffset:)``\n- ``write(contentsOf:toAbsoluteOffset:)``\n- ``bufferedWriter(startingAtAbsoluteOffset:capacity:)``\n\n### Resize a file\n- ``resize(to:)``\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Docs.docc/index.md",
    "content": "# ``_NIOFileSystem``\n\nA file system library for Swift.\n\n## Overview\n\nThis module implements a file system library for Swift, providing ways to interact with and manage\nfiles. It provides a concrete ``FileSystem`` for interacting with the local file system in addition\nto a set of protocols for creating other file system implementations.\n\n`_NIOFileSystem` is cross-platform with the following caveats:\n- _Platforms don't have feature parity or system-level API parity._ Where this is the case these\n  implementation details are documented. One example is copying files, on Apple platforms files are\n  cloned if possible.\n- _Features may be disabled on some systems._ One example is extended attributes.\n- _Some types have platform specific representations._ These include the following:\n  - File paths on Apple platforms and Linux (e.g. `\"/Users/hal9000/\"`) are different to paths on\n    Windows (`\"C:\\Users\\hal9000\"`).\n  - Information about files is different on different platforms. See ``FileInfo`` for further\n    details.\n\n## A Brief Tour\n\nThe following sample code demonstrates a number of the APIs offered by this module:\n\n@Snippet(path: \"swift-nio/Snippets/NIOFileSystemTour\")\n\nIn depth documentation can be found in the following sections.\n\n## Topics\n\n### Interacting with the Local File System\n\n- ``FileSystem``\n- ``FileHandle``\n- ``ReadFileHandle``\n- ``WriteFileHandle``\n- ``ReadWriteFileHandle``\n- ``DirectoryFileHandle``\n- ``withFileSystem(numberOfThreads:_:)``\n\n### File and Directory Information\n\n- ``FileInfo``\n- ``FileType``\n\n### Reading Files\n\n- ``FileChunks``\n- ``BufferedReader``\n\n### Writing Files\n\n- ``BufferedWriter``\n\n### Listing Directories\n\n- ``DirectoryEntry``\n- ``DirectoryEntries``\n\n### Errors\n\n``FileSystemError`` is the only top-level error type thrown by the package (apart from Swift's\n`CancellationError`).\n\n- ``FileSystemError``\n- ``FileSystemError/SystemCallError``\n\n### Creating a File System\n\nCustom file system's can be created by implementing ``FileSystemProtocol`` which depends on a number\nof other protocols. These include the following:\n\n- ``FileSystemProtocol``\n- ``FileHandleProtocol``\n- ``ReadableFileHandleProtocol``\n- ``WritableFileHandleProtocol``\n- ``ReadableAndWritableFileHandleProtocol``\n- ``DirectoryFileHandleProtocol``\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Exports.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// These types are used in our public API; expose them to make\n// life easier for users.\n@_exported import enum SystemPackage.CInterop\n@_exported import struct SystemPackage.Errno\n@_exported import struct SystemPackage.FileDescriptor\n@_exported import struct SystemPackage.FilePath\n@_exported import struct SystemPackage.FilePermissions\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileChunks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n/// An `AsyncSequence` of ordered chunks read from a file.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct FileChunks: AsyncSequence, Sendable {\n    enum ChunkRange {\n        case entireFile\n        case partial(Range<Int64>)\n    }\n\n    public typealias Element = ByteBuffer\n\n    /// The buffered stream.\n    private let stream: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>\n\n    /// Create a ``FileChunks`` sequence backed by wrapping an `AsyncSequence`.\n    @preconcurrency\n    public init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n    where S.Element == ByteBuffer, S.AsyncIterator: _NIOFileSystemSendableMetatype {\n        self.stream = BufferedOrAnyStream(wrapping: sequence)\n    }\n\n    internal init(\n        handle: SystemFileHandle,\n        chunkLength: ByteCount,\n        range: Range<Int64>\n    ) {\n        let chunkRange: ChunkRange\n        if range.lowerBound == 0, range.upperBound == .max {\n            chunkRange = .entireFile\n        } else {\n            chunkRange = .partial(range)\n        }\n\n        // TODO: choose reasonable watermarks; this should likely be at least somewhat dependent\n        // on the chunk size.\n        let stream = NIOThrowingAsyncSequenceProducer.makeFileChunksStream(\n            of: ByteBuffer.self,\n            handle: handle,\n            chunkLength: chunkLength.bytes,\n            range: chunkRange,\n            lowWatermark: 4,\n            highWatermark: 8\n        )\n\n        self.stream = BufferedOrAnyStream(wrapping: stream)\n    }\n\n    public func makeAsyncIterator() -> FileChunkIterator {\n        FileChunkIterator(wrapping: self.stream.makeAsyncIterator())\n    }\n\n    public struct FileChunkIterator: AsyncIteratorProtocol {\n        private var iterator: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>.AsyncIterator\n\n        fileprivate init(wrapping iterator: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>.AsyncIterator) {\n            self.iterator = iterator\n        }\n\n        public mutating func next() async throws -> ByteBuffer? {\n            try await self.iterator.next()\n        }\n    }\n}\n\n@available(*, unavailable)\nextension FileChunks.FileChunkIterator: Sendable {}\n\n// MARK: - Internal\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate typealias FileChunkSequenceProducer = NIOThrowingAsyncSequenceProducer<\n    ByteBuffer, Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, FileChunkProducer\n>\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOThrowingAsyncSequenceProducer\nwhere\n    Element == ByteBuffer,\n    Failure == Error,\n    Strategy == NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,\n    Delegate == FileChunkProducer\n{\n    static func makeFileChunksStream(\n        of: Element.Type = Element.self,\n        handle: SystemFileHandle,\n        chunkLength: Int64,\n        range: FileChunks.ChunkRange,\n        lowWatermark: Int,\n        highWatermark: Int\n    ) -> FileChunkSequenceProducer {\n\n        let producer = FileChunkProducer(\n            range: range,\n            handle: handle,\n            chunkLength: chunkLength\n        )\n\n        let nioThrowingAsyncSequence = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: ByteBuffer.self,\n            backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark(\n                lowWatermark: lowWatermark,\n                highWatermark: highWatermark\n            ),\n            finishOnDeinit: false,\n            delegate: producer\n        )\n\n        producer.setSource(nioThrowingAsyncSequence.source)\n\n        return nioThrowingAsyncSequence.sequence\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate final class FileChunkProducer: NIOAsyncSequenceProducerDelegate, Sendable {\n    let state: NIOLockedValueBox<ProducerState>\n\n    let path: FilePath\n    let chunkLength: Int64\n\n    init(range: FileChunks.ChunkRange, handle: SystemFileHandle, chunkLength: Int64) {\n        let state: ProducerState\n        switch range {\n        case .entireFile:\n            state = .init(handle: handle, range: nil)\n        case .partial(let partialRange):\n            state = .init(handle: handle, range: partialRange)\n        }\n\n        self.state = NIOLockedValueBox(state)\n        self.path = handle.path\n        self.chunkLength = chunkLength\n    }\n\n    /// sets the source within the producer state\n    func setSource(_ source: FileChunkSequenceProducer.Source) {\n        self.state.withLockedValue { state in\n            switch state.state {\n            case .producing, .pausedProducing:\n                state.source = source\n            case .done(let emptyRange):\n                if emptyRange {\n                    source.finish()\n                }\n            }\n        }\n    }\n\n    func clearSource() {\n        self.state.withLockedValue { state in\n            state.source = nil\n        }\n    }\n\n    /// The 'entry point' for producing elements.\n    ///\n    /// Calling this function will start producing file chunks asynchronously by dispatching work\n    /// to the IO executor and feeding the result back to the stream source. On yielding to the\n    /// source it will either produce more or be scheduled to produce more. Stopping production\n    /// is signaled via the stream's 'onTermination' handler.\n    func produceMore() {\n        let threadPool = self.state.withLockedValue { state in\n            state.activeThreadPool()\n        }\n        // No thread pool means we're done.\n        guard let threadPool = threadPool else { return }\n\n        threadPool.submit { workItemState in\n            // update state to reflect that we have been requested to perform a read\n            // the read may be performed immediately, queued to be performed later or ignored\n            let requestedReadAction = self.state.withLockedValue { state in\n                state.requestedProduceMore()\n            }\n\n            switch requestedReadAction {\n            case .performRead:\n                let result: Result<ByteBuffer, Error>\n                switch workItemState {\n                case .active:\n                    result = Result { try self.readNextChunk() }\n                case .cancelled:\n                    result = .failure(CancellationError())\n                }\n\n                switch result {\n                case let .success(bytes):\n                    self.didReadNextChunk(bytes)\n                case let .failure(error):\n                    // Failed to read: update our state then notify the stream so consumers receive the\n                    // error.\n                    let source = self.state.withLockedValue { state in\n                        state.done()\n                        return state.source\n                    }\n                    source?.finish(error)\n                    self.clearSource()\n                }\n\n            case .stop:\n                return\n            }\n\n            let performedReadAction = self.state.withLockedValue { state in\n                state.performedProduceMore()\n            }\n\n            switch performedReadAction {\n            case .readMore:\n                self.produceMore()\n            case .stop:\n                return\n            }\n\n        }\n    }\n\n    private func readNextChunk() throws -> ByteBuffer {\n        try self.state.withLockedValue { state in\n            state.fileReadingState()\n        }.flatMap {\n            if let (descriptor, range) = $0 {\n                if let range {\n                    let remainingBytes = range.upperBound - range.lowerBound\n                    let clampedLength = min(self.chunkLength, remainingBytes)\n                    return descriptor.readChunk(\n                        fromAbsoluteOffset: range.lowerBound,\n                        length: clampedLength\n                    ).mapError { error in\n                        .read(usingSyscall: .pread, error: error, path: self.path, location: .here())\n                    }\n                } else {\n                    return descriptor.readChunk(length: self.chunkLength).mapError { error in\n                        .read(usingSyscall: .read, error: error, path: self.path, location: .here())\n                    }\n                }\n            } else {\n                // nil means done: return empty to indicate the stream should finish.\n                return .success(ByteBuffer())\n            }\n        }.get()\n    }\n\n    private func didReadNextChunk(_ buffer: ByteBuffer) {\n        let chunkLength = self.chunkLength\n        assert(buffer.readableBytes <= chunkLength)\n\n        let (source, initialState): (FileChunkSequenceProducer.Source?, ProducerState.State) = self.state\n            .withLockedValue { state in\n                state.didReadBytes(buffer.readableBytes)\n\n                // finishing short indicates the file is done\n                if buffer.readableBytes < chunkLength {\n                    state.state = .done(emptyRange: false)\n                }\n                return (state.source, state.state)\n            }\n\n        guard let source else {\n            return\n        }\n\n        // No bytes were produced, nothing more to do.\n        if buffer.readableBytes == 0 {\n            source.finish()\n            self.clearSource()\n        }\n\n        // Yield bytes and maybe produce more.\n        let yieldResult = source.yield(contentsOf: CollectionOfOne(buffer))\n\n        switch initialState {\n        case .done:\n            source.finish()\n            self.clearSource()\n            return\n        case .producing, .pausedProducing:\n            ()\n        }\n\n        switch yieldResult {\n        case .produceMore:\n            ()\n        case .stopProducing:\n            self.state.withLockedValue { state in state.pauseProducing() }\n        case .dropped:\n            // The source is finished; mark ourselves as done.\n            self.state.withLockedValue { state in state.done() }\n        }\n    }\n\n    func didTerminate() {\n        self.state.withLockedValue { state in\n            state.done()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate struct ProducerState: Sendable {\n    fileprivate struct Producing {\n        /// Possible states for activity relating to performing a read from disk\n        internal enum ActivityState {\n            /// The producer is not currently performing a read from disk\n            case inactive\n            /// The producer is in the critical section for reading from disk\n            case active\n            /// The producer is in the critical section for reading from disk and a further read has been requested.\n            /// This can happen e.g. if a sequence indicates that production should be paused then unpauses and calls\n            /// back into the code before the initial read block has exited.\n            case activeAndQueued\n        }\n\n        /// The handle to read from.\n        var handle: SystemFileHandle.SendableView\n\n        /// An optional range containing the offsets to read from and up to (exclusive)\n        /// The lower bound should be updated after each successful read.\n        /// The upper bound should be used to check if producer should stop.\n        /// If no range is present, then read entire file.\n        var range: Range<Int64>?\n\n        /// Keep track of whether or not we are currently actively engaged in a read\n        /// to protect against re-entrant behavior.\n        var activityState: ActivityState = .inactive\n    }\n\n    internal enum State {\n        /// Can potentially produce values (if the handle is not closed).\n        case producing(Producing)\n        /// Backpressure policy means that we should stop producing new values for now\n        case pausedProducing(Producing)\n        /// Done producing values either by reaching EOF, some error or the stream terminating.\n        case done(emptyRange: Bool)\n    }\n\n    internal var state: State\n\n    /// The route via which file chunks are yielded,\n    /// the sourcing end of the `FileChunkSequenceProducer`\n    internal var source: FileChunkSequenceProducer.Source?\n\n    init(handle: SystemFileHandle, range: Range<Int64>?) {\n        if let range, range.isEmpty {\n            self.state = .done(emptyRange: true)\n        } else {\n            self.state = .producing(.init(handle: handle.sendableView, range: range))\n        }\n    }\n\n    /// Actions which may be taken after 'produce more' is requested.\n    ///\n    /// Either perform the read immediately or (optionally queue the read then) stop.\n    internal enum RequestedProduceMoreAction {\n        case performRead\n        case stop\n    }\n\n    /// Update state to reflect that 'produce more' has been requested.\n    mutating func requestedProduceMore() -> RequestedProduceMoreAction {\n        switch self.state {\n        case .producing(var producingState):\n            switch producingState.activityState {\n            case .inactive:\n                producingState.activityState = .active\n                self.state = .producing(producingState)\n                return .performRead\n            case .active:\n                producingState.activityState = .activeAndQueued\n                self.state = .producing(producingState)\n                return .stop\n            case .activeAndQueued:\n                return .stop\n            }\n\n        case .pausedProducing(var producingState):\n            switch producingState.activityState {\n            case .inactive:\n                producingState.activityState = .active\n                self.state = .producing(producingState)\n                return .performRead\n            case .active:\n                producingState.activityState = .activeAndQueued\n                self.state = .pausedProducing(producingState)\n                return .stop\n            case .activeAndQueued:\n                return .stop\n            }\n\n        case .done:\n            return .stop\n        }\n    }\n\n    /// Actions which may be taken after a more data is produced.\n    ///\n    /// Either go on to read more or stop.\n    internal enum PerformedProduceMoreAction {\n        case readMore\n        case stop\n    }\n\n    /// Update state to reflect that a more data has been produced.\n    mutating func performedProduceMore() -> PerformedProduceMoreAction {\n        switch self.state {\n        case .producing(var producingState):\n            let oldActivityState = producingState.activityState\n\n            producingState.activityState = .inactive\n            self.state = .producing(producingState)\n\n            switch oldActivityState {\n            case .inactive:\n                preconditionFailure()\n            case .active, .activeAndQueued:\n                return .readMore\n            }\n\n        case .pausedProducing(var producingState):\n            let oldActivityState = producingState.activityState\n\n            producingState.activityState = .inactive\n            self.state = .pausedProducing(producingState)\n\n            switch oldActivityState {\n            case .inactive:\n                preconditionFailure()\n            case .active:\n                return .stop\n            case .activeAndQueued:\n                return .readMore\n            }\n\n        case .done:\n            return .stop\n        }\n    }\n\n    mutating func activeThreadPool() -> NIOThreadPool? {\n        switch self.state {\n        case .producing(let producingState), .pausedProducing(let producingState):\n            return producingState.handle.threadPool\n        case .done:\n            return nil\n        }\n    }\n\n    mutating func fileReadingState() -> Result<(FileDescriptor, Range<Int64>?)?, FileSystemError> {\n        switch self.state {\n        case .producing(let producingState), .pausedProducing(let producingState):\n            if let descriptor = producingState.handle.descriptorIfAvailable() {\n                return .success((descriptor, producingState.range))\n            } else {\n                let error = FileSystemError(\n                    code: .closed,\n                    message: \"Cannot read from closed file ('\\(producingState.handle.path)').\",\n                    cause: nil,\n                    location: .here()\n                )\n                return .failure(error)\n            }\n        case .done:\n            return .success(nil)\n        }\n    }\n\n    mutating func didReadBytes(_ count: Int) {\n        switch self.state {\n        case var .producing(state):\n            switch state.updateRangeWithReadBytes(count) {\n            case .moreToRead:\n                self.state = .producing(state)\n            case .cannotReadMore:\n                self.state = .done(emptyRange: false)\n            }\n        case var .pausedProducing(state):\n            switch state.updateRangeWithReadBytes(count) {\n            case .moreToRead:\n                self.state = .pausedProducing(state)\n            case .cannotReadMore:\n                self.state = .done(emptyRange: false)\n            }\n        case .done:\n            ()\n        }\n    }\n\n    mutating func pauseProducing() {\n        switch self.state {\n        case .producing(let state):\n            self.state = .pausedProducing(state)\n        case .pausedProducing, .done:\n            ()\n        }\n    }\n\n    mutating func done() {\n        self.state = .done(emptyRange: false)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ProducerState.Producing {\n    internal enum RangeUpdateOutcome {\n        case moreToRead\n        case cannotReadMore\n    }\n\n    /// Updates the range (the offsets to read from and up to) to reflect the number of bytes which have been read.\n    /// - Parameter count: The number of bytes which have been read.\n    /// - Returns: Returns `.moreToRead` if there are no remaining bytes to read, `.cannotReadMore` otherwise.\n    mutating func updateRangeWithReadBytes(_ count: Int) -> RangeUpdateOutcome {\n        guard let currentRange = self.range else {\n            // we are reading the whole file, just keep going\n            return .moreToRead\n        }\n\n        let newLowerBound = currentRange.lowerBound + Int64(count)\n\n        // we have run out of bytes to read, we are done\n        if newLowerBound >= currentRange.upperBound {\n            self.range = currentRange.upperBound..<currentRange.upperBound\n            return .cannotReadMore\n        }\n\n        // update range, we are not done\n        self.range = newLowerBound..<currentRange.upperBound\n        return .moreToRead\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileHandle.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Provides a ``FileHandle``.\n///\n/// Users should not implement or rely on this protocol; its purpose is to reduce boilerplate\n/// by providing a default implementation of ``FileHandleProtocol`` for types which hold\n/// a ``FileHandle``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol _HasFileHandle: FileHandleProtocol {\n    var fileHandle: FileHandle { get }\n}\n\n// Provides an implementation of `FileHandleProtocol` by calling through to `FileHandle`.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension _HasFileHandle {\n    public func info() async throws -> FileInfo {\n        try await self.fileHandle.info()\n    }\n\n    public func replacePermissions(_ permissions: FilePermissions) async throws {\n        try await self.fileHandle.replacePermissions(permissions)\n    }\n\n    public func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.fileHandle.addPermissions(permissions)\n    }\n\n    public func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.fileHandle.removePermissions(permissions)\n    }\n\n    public func attributeNames() async throws -> [String] {\n        try await self.fileHandle.attributeNames()\n    }\n\n    public func valueForAttribute(_ name: String) async throws -> [UInt8] {\n        try await self.fileHandle.valueForAttribute(name)\n    }\n\n    public func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws {\n        try await self.fileHandle.updateValueForAttribute(bytes, attribute: name)\n    }\n\n    public func removeValueForAttribute(_ name: String) async throws {\n        try await self.fileHandle.removeValueForAttribute(name)\n    }\n\n    public func synchronize() async throws {\n        try await self.fileHandle.synchronize()\n    }\n\n    public func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R {\n        try await self.fileHandle.withUnsafeDescriptor {\n            try execute($0)\n        }\n    }\n\n    public func detachUnsafeFileDescriptor() throws -> FileDescriptor {\n        try self.fileHandle.detachUnsafeFileDescriptor()\n    }\n\n    public func close() async throws {\n        try await self.fileHandle.close()\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``FileHandleProtocol`` by making system calls to interact with the local file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct FileHandle: FileHandleProtocol, Sendable {\n    internal let systemFileHandle: SystemFileHandle\n\n    internal init(wrapping handle: SystemFileHandle) {\n        self.systemFileHandle = handle\n    }\n\n    public func info() async throws -> FileInfo {\n        try await self.systemFileHandle.info()\n    }\n\n    public func replacePermissions(_ permissions: FilePermissions) async throws {\n        try await self.systemFileHandle.replacePermissions(permissions)\n    }\n\n    public func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.systemFileHandle.addPermissions(permissions)\n    }\n\n    public func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.systemFileHandle.removePermissions(permissions)\n    }\n\n    public func attributeNames() async throws -> [String] {\n        try await self.systemFileHandle.attributeNames()\n    }\n\n    public func valueForAttribute(_ name: String) async throws -> [UInt8] {\n        try await self.systemFileHandle.valueForAttribute(name)\n    }\n\n    public func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws {\n        try await self.systemFileHandle.updateValueForAttribute(bytes, attribute: name)\n    }\n\n    public func removeValueForAttribute(_ name: String) async throws {\n        try await self.systemFileHandle.removeValueForAttribute(name)\n    }\n\n    public func synchronize() async throws {\n        try await self.systemFileHandle.synchronize()\n    }\n\n    public func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R {\n        try await self.systemFileHandle.withUnsafeDescriptor {\n            try execute($0)\n        }\n    }\n\n    public func detachUnsafeFileDescriptor() throws -> FileDescriptor {\n        try self.systemFileHandle.detachUnsafeFileDescriptor()\n    }\n\n    public func close() async throws {\n        try await self.systemFileHandle.close()\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``ReadableFileHandleProtocol`` by making system calls to interact with the local\n/// file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct ReadFileHandle: ReadableFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    public func readChunk(\n        fromAbsoluteOffset offset: Int64,\n        length: ByteCount\n    ) async throws -> ByteBuffer {\n        try await self.fileHandle.systemFileHandle.readChunk(\n            fromAbsoluteOffset: offset,\n            length: length\n        )\n    }\n\n    public func readChunks(in range: Range<Int64>, chunkLength: ByteCount) -> FileChunks {\n        self.fileHandle.systemFileHandle.readChunks(in: range, chunkLength: chunkLength)\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``WritableFileHandleProtocol`` by making system calls to interact with the local\n/// file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct WriteFileHandle: WritableFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    @discardableResult\n    public func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.fileHandle.systemFileHandle.write(\n            contentsOf: bytes,\n            toAbsoluteOffset: offset\n        )\n    }\n\n    public func resize(to size: ByteCount) async throws {\n        try await self.fileHandle.systemFileHandle.resize(to: size)\n    }\n\n    public func close(makeChangesVisible: Bool) async throws {\n        try await self.fileHandle.systemFileHandle.close(makeChangesVisible: makeChangesVisible)\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``ReadableAndWritableFileHandleProtocol`` by making system calls to interact with the\n/// local file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct ReadWriteFileHandle: ReadableAndWritableFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    public func readChunk(\n        fromAbsoluteOffset offset: Int64,\n        length: ByteCount\n    ) async throws -> ByteBuffer {\n        try await self.fileHandle.systemFileHandle.readChunk(\n            fromAbsoluteOffset: offset,\n            length: length\n        )\n    }\n\n    public func readChunks(in offset: Range<Int64>, chunkLength: ByteCount) -> FileChunks {\n        self.fileHandle.systemFileHandle.readChunks(in: offset, chunkLength: chunkLength)\n    }\n\n    @discardableResult\n    public func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.fileHandle.systemFileHandle.write(\n            contentsOf: bytes,\n            toAbsoluteOffset: offset\n        )\n    }\n\n    public func resize(to size: ByteCount) async throws {\n        try await self.fileHandle.systemFileHandle.resize(to: size)\n    }\n\n    public func close(makeChangesVisible: Bool) async throws {\n        try await self.fileHandle.systemFileHandle.close(makeChangesVisible: makeChangesVisible)\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.fileHandle.systemFileHandle.setTimes(\n            lastAccess: lastAccess,\n            lastDataModification: lastDataModification\n        )\n    }\n}\n\n/// Implements ``DirectoryFileHandleProtocol`` by making system calls to interact with the local\n/// file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct DirectoryFileHandle: DirectoryFileHandleProtocol, _HasFileHandle, Sendable {\n    public let fileHandle: FileHandle\n\n    internal init(wrapping systemFileHandle: SystemFileHandle) {\n        self.fileHandle = FileHandle(wrapping: systemFileHandle)\n    }\n\n    public func listContents(recursive: Bool) -> DirectoryEntries {\n        self.fileHandle.systemFileHandle.listContents(recursive: recursive)\n    }\n\n    public func openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openFile(\n            forReadingAt: path,\n            options: options\n        )\n        return ReadFileHandle(wrapping: systemFileHandle)\n    }\n\n    public func openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openFile(\n            forWritingAt: path,\n            options: options\n        )\n        return WriteFileHandle(wrapping: systemFileHandle)\n    }\n\n    public func openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openFile(\n            forReadingAndWritingAt: path,\n            options: options\n        )\n        return ReadWriteFileHandle(wrapping: systemFileHandle)\n    }\n\n    public func openDirectory(\n        atPath path: FilePath,\n        options: OpenOptions.Directory\n    ) async throws -> DirectoryFileHandle {\n        let systemFileHandle = try await self.fileHandle.systemFileHandle.openDirectory(\n            atPath: path,\n            options: options\n        )\n        return DirectoryFileHandle(wrapping: systemFileHandle)\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileHandleProtocol.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport SystemPackage\n\n/// A handle for a file system object.\n///\n/// There is a hierarchy of file handle protocols which allow for different functionality. All\n/// file handle protocols refine the base ``FileHandleProtocol`` protocol.\n///\n/// ```\n///                                      ┌────────────────────┐\n///                                      │ FileHandleProtocol │\n///                                      │     [Protocol]     │\n///                                      └────────────────────┘\n///                                                ▲\n///                 ┌──────────────────────────────┼────────────────────────────────┐\n///                 │                              │                                │\n/// ┌────────────────────────────┐   ┌────────────────────────────┐  ┌─────────────────────────────┐\n/// │ ReadableFileHandleProtocol │   │ WritableFileHandleProtocol │  │ DirectoryFileHandleProtocol │\n/// │          [Protocol]        │   │         [Protocol]         │  │          [Protocol]         │\n/// └────────────────────────────┘   └────────────────────────────┘  └─────────────────────────────┘\n/// ```\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol FileHandleProtocol {\n    /// Returns information about the file.\n    ///\n    /// Information is typically gathered by calling `fstat(2)` on the file.\n    ///\n    /// - Returns: Information about the open file.\n    func info() async throws -> FileInfo\n\n    /// Replaces the permissions set on the file.\n    ///\n    /// Permissions are typically set using `fchmod(2)`.\n    ///\n    /// - Parameters:\n    ///   - permissions: The permissions to set on the file.\n    func replacePermissions(_ permissions: FilePermissions) async throws\n\n    /// Adds permissions to the existing permissions set for the file.\n    ///\n    /// This is equivalent to retrieving the permissions, merging them with the provided\n    /// permissions and then replacing the permissions on the file.\n    ///\n    /// - Parameters:\n    ///   - permissions: The permissions to add to the file.\n    /// - Returns: The updated permissions.\n    @discardableResult\n    func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions\n\n    /// Remove permissions from the existing permissions set for the file.\n    ///\n    /// This is equivalent to retrieving the permissions, subtracting any of the provided\n    /// permissions and then replacing the permissions on the file.\n    ///\n    /// - Parameters:\n    ///   - permissions: The permissions to remove from the file.\n    /// - Returns: The updated permissions.\n    @discardableResult\n    func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions\n\n    /// Returns an array containing the names of all extended attributes set on the file.\n    ///\n    /// Attributes names are typically fetched using `flistxattr(2)`.\n    func attributeNames() async throws -> [String]\n\n    /// Returns the value for the named attribute if it exists; `nil` otherwise.\n    ///\n    /// Attribute values are typically fetched using `fgetxattr(2)`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the attribute.\n    /// - Returns: The bytes of the value set for the attribute. If no value is set an empty array\n    ///     is returned.\n    func valueForAttribute(_ name: String) async throws -> [UInt8]\n\n    /// Replaces the value for the named attribute, creating it if it didn't already exist.\n    ///\n    /// Attribute values are typically replaced using `fsetxattr(2)`.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to set as the value for the attribute.\n    ///   - name: The name of the attribute.\n    func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws\n\n    /// Removes the value for the named attribute if it exists.\n    ///\n    /// Attribute values are typically removed using `fremovexattr(2)`.\n    ///\n    /// - Parameter name: The name of the attribute to remove.\n    func removeValueForAttribute(_ name: String) async throws\n\n    /// Synchronize modified data and metadata to a permanent storage device.\n    ///\n    /// This is typically achieved using `fsync(2)`.\n    func synchronize() async throws\n\n    /// Runs the provided callback with the file descriptor for this handle.\n    ///\n    /// This function should be used with caution: the `FileDescriptor` must not be escaped from\n    /// the closure nor should it be closed. Where possible make use of the methods defined\n    /// on ``FileHandleProtocol`` instead; this function is intended as an escape hatch.\n    ///\n    /// Note that `execute` is not run if the handle has already been closed.\n    ///\n    /// - Parameter execute: A closure to run.\n    /// - Returns: The result of the closure.\n    func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R\n\n    /// Detaches and returns the file descriptor from the handle.\n    ///\n    /// After detaching the file descriptor the handle is rendered invalid. All methods will throw\n    /// an appropriate error if called. Detaching the descriptor yields ownerships to the caller.\n    ///\n    /// - Returns: The detached `FileDescriptor`\n    func detachUnsafeFileDescriptor() throws -> FileDescriptor\n\n    /// Closes the file handle.\n    ///\n    /// It is important to close a handle once it has been finished with to avoid leaking\n    /// resources. Prefer using APIs which provided scoped access to a file handle which\n    /// manage lifecycles on your behalf. Note that if the handle has been detached via\n    /// ``detachUnsafeFileDescriptor()`` then it is not necessary to close the handle.\n    ///\n    /// After closing the handle calls to other functions will throw an appropriate error.\n    func close() async throws\n\n    /// Sets the file's last access and last data modification times to the given values.\n    ///\n    /// If **either** time is `nil`, the current value will not be changed.\n    /// If **both** times are `nil`, then both times will be set to the current time.\n    ///\n    /// > Important: Times are only considered valid if their nanoseconds components are one of the following:\n    /// > - `UTIME_NOW` (you can use ``FileInfo/Timespec/now`` to get a Timespec set to this value),\n    /// > - `UTIME_OMIT` (you can use ``FileInfo/Timespec/omit`` to get a Timespec set to this value),\n    /// > - Greater than zero and no larger than 1000 million: if outside of this range, the value will be clamped to the closest valid value.\n    /// > The seconds component must also be positive: if it's not, zero will be used as the value instead.\n    ///\n    /// - Parameters:\n    ///   - lastAccess: The new value of the file's last access time, as time elapsed since the Epoch.\n    ///   - lastDataModification: The new value of the file's last data modification time, as time elapsed since the Epoch.\n    ///\n    /// - Throws: If there's an error updating the times. If this happens, the original values won't be modified.\n    func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws\n}\n\n// MARK: - Readable\n\n/// A handle for reading data from an open file.\n///\n/// ``ReadableFileHandleProtocol`` refines ``FileHandleProtocol`` to add requirements for reading data from a file.\n///\n/// There are two requirements for implementing this protocol:\n/// 1. ``readChunk(fromAbsoluteOffset:length:)``, and\n/// 2. ``readChunks(chunkLength:)\n///\n/// A number of overloads are provided which provide sensible defaults.\n///\n/// Conformance to ``ReadableFileHandleProtocol`` also provides\n/// ``readToEnd(fromAbsoluteOffset:maximumSizeAllowed:)`` (and various overloads with sensible\n/// defaults) for reading the contents of a file into memory.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol ReadableFileHandleProtocol: FileHandleProtocol {\n    /// Returns a slice of bytes read from the file.\n    ///\n    /// The length of the slice to read indicates the largest size in bytes that the returned slice\n    /// may be. The slice may be shorter than the given `length` if there are fewer bytes from the\n    /// `offset` to the end of the file.\n    ///\n    /// - Parameters:\n    ///   - offset: The absolute offset into the file to read from.\n    ///   - length: The maximum number of bytes to read as a ``ByteCount``.\n    /// - Returns: The bytes read from the file.\n    func readChunk(fromAbsoluteOffset offset: Int64, length: ByteCount) async throws -> ByteBuffer\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: The absolute offsets into the file to read.\n    ///   - chunkLength: The maximum length of the chunk to read as a ``ByteCount``.\n    /// - Returns: A sequence of chunks read from the file.\n    func readChunks(in range: Range<Int64>, chunkLength: ByteCount) -> FileChunks\n}\n\n// MARK: - Read chunks with default chunk length\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ReadableFileHandleProtocol {\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: ClosedRange<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: Range(range), chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: Range<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: range, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: PartialRangeFrom<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        let newRange = range.lowerBound..<Int64.max\n        return self.readChunks(in: newRange, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: PartialRangeThrough<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        let newRange = 0...range.upperBound\n        return self.readChunks(in: newRange, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: PartialRangeUpTo<Int64>,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        let newRange = 0..<range.upperBound\n        return self.readChunks(in: newRange, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - range: A range of offsets in the file to read.\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        in range: UnboundedRange,\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: 0..<Int64.max, chunkLength: chunkLength)\n    }\n\n    /// Returns an asynchronous sequence of chunks read from the file.\n    ///\n    /// - Parameters:\n    ///   - chunkLength: The length of chunks to read, defaults to 128 KiB.\n    /// - SeeAlso: ``ReadableFileHandleProtocol/readChunks(in:chunkLength:)-2dz6``.\n    /// - Returns: An `AsyncSequence` of chunks read from the file.\n    public func readChunks(\n        chunkLength: ByteCount = .kibibytes(128)\n    ) -> FileChunks {\n        self.readChunks(in: ..., chunkLength: chunkLength)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension ReadableFileHandleProtocol {\n    /// Returns the contents of a file by loading it into memory.\n    ///\n    /// - Important: This method checks whether the file is seekable or not (i.e., whether it's a socket,\n    /// pipe or FIFO), and will throw ``FileSystemError/Code-swift.struct/unsupported`` if\n    /// an offset other than zero is passed.\n    ///\n    /// - Parameters:\n    ///   - offset: The absolute offset into the file to read from. Defaults to zero.\n    ///   - maximumSizeAllowed: The maximum size of file to read, as a ``ByteCount``.\n    /// - Returns: The bytes read from the file.\n    /// - Throws: ``FileSystemError`` with code ``FileSystemError/Code-swift.struct/resourceExhausted``\n    /// if `maximumSizeAllowed` is more than can be written to `ByteBuffer`. Or if there are more bytes to read than\n    /// `maximumBytesAllowed`.\n    public func readToEnd(\n        fromAbsoluteOffset offset: Int64 = 0,\n        maximumSizeAllowed: ByteCount\n    ) async throws -> ByteBuffer {\n        let maximumSizeAllowed = maximumSizeAllowed == .unlimited ? .byteBufferCapacity : maximumSizeAllowed\n        let info = try await self.info()\n        let fileSize = Int64(info.size)\n        let readSize = max(Int(fileSize - offset), 0)\n\n        if maximumSizeAllowed > .byteBufferCapacity {\n            throw FileSystemError(\n                code: .resourceExhausted,\n                message: \"\"\"\n                    The maximum size allowed (\\(maximumSizeAllowed)) is more than the maximum \\\n                    amount of bytes that can be written to ByteBuffer \\\n                    (\\(ByteCount.byteBufferCapacity)). You can read the file in smaller chunks by \\\n                    calling readChunks().\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n        }\n\n        if readSize > maximumSizeAllowed.bytes {\n            throw FileSystemError(\n                code: .resourceExhausted,\n                message: \"\"\"\n                    There are more bytes to read (\\(readSize)) than the maximum size allowed \\\n                    (\\(maximumSizeAllowed)). Read the file in chunks or increase the maximum size \\\n                    allowed.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n        }\n\n        let isSeekable = !(info.type == .fifo || info.type == .socket)\n        if isSeekable {\n            // Limit the size of single shot reads. If the system is busy then avoid slowing down other\n            // work by blocking an I/O executor thread while doing a large read. The limit is somewhat\n            // arbitrary.\n            let singleShotReadLimit = 64 * 1024 * 1024\n\n            // If the file size isn't 0 but the read size is, then it means that\n            // we are intending to read an empty fragment: we can just return\n            // fast and skip any reads.\n            // If the file size is 0, we can't conclude anything about the size\n            // of the file, as `stat` will return 0 for unbounded files.\n            // If this happens, just read in chunks to make sure the whole file\n            // is read (up to `maximumSizeAllowed` bytes).\n            var forceChunkedRead = false\n            if fileSize > 0 {\n                if readSize == 0 {\n                    return ByteBuffer()\n                }\n            } else {\n                forceChunkedRead = true\n            }\n\n            if !forceChunkedRead, readSize <= singleShotReadLimit {\n                return try await self.readChunk(\n                    fromAbsoluteOffset: offset,\n                    length: .bytes(Int64(readSize))\n                )\n            } else {\n                var accumulator = ByteBuffer()\n                accumulator.reserveCapacity(readSize)\n\n                for try await chunk in self.readChunks(in: offset..., chunkLength: .mebibytes(8)) {\n                    accumulator.writeImmutableBuffer(chunk)\n                    if accumulator.readableBytes > maximumSizeAllowed.bytes {\n                        throw FileSystemError(\n                            code: .resourceExhausted,\n                            message: \"\"\"\n                                There are more bytes to read than the maximum size allowed \\\n                                (\\(maximumSizeAllowed)). Read the file in chunks or increase the maximum size \\\n                                allowed.\n                                \"\"\",\n                            cause: nil,\n                            location: .here()\n                        )\n                    }\n                }\n\n                return accumulator\n            }\n        } else {\n            guard offset == 0 else {\n                throw FileSystemError(\n                    code: .unsupported,\n                    message: \"File is unseekable.\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n            var accumulator = ByteBuffer()\n            accumulator.reserveCapacity(readSize)\n\n            for try await chunk in self.readChunks(in: ..., chunkLength: .mebibytes(8)) {\n                accumulator.writeImmutableBuffer(chunk)\n                if accumulator.readableBytes > maximumSizeAllowed.bytes {\n                    throw FileSystemError(\n                        code: .resourceExhausted,\n                        message: \"\"\"\n                            There are more bytes to read than the maximum size allowed \\\n                            (\\(maximumSizeAllowed)). Read the file in chunks or increase the maximum size \\\n                            allowed.\n                            \"\"\",\n                        cause: nil,\n                        location: .here()\n                    )\n                }\n            }\n\n            return accumulator\n        }\n    }\n}\n\n// MARK: - Writable\n\n/// A file handle suitable for writing.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol WritableFileHandleProtocol: FileHandleProtocol {\n    /// Write the given bytes to the open file.\n    ///\n    /// - Important: This method checks whether the file is seekable or not (i.e., whether it's a socket,\n    /// pipe or FIFO), and will throw ``FileSystemError/Code-swift.struct/unsupported``\n    /// if an offset other than zero is passed.\n    ///\n    /// - Parameters:\n    ///   - bytes: The bytes to write.\n    ///   - offset: The absolute offset into the file to write the bytes.\n    /// - Returns: The number of bytes written.\n    /// - Throws: ``FileSystemError/Code-swift.struct/unsupported`` if file is\n    /// unseekable and `offset` is not 0.\n    @discardableResult\n    func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64\n\n    /// Resizes a file to the given size.\n    ///\n    /// - Parameters:\n    ///   - size: The number of bytes to resize the file to as a ``ByteCount``.\n    func resize(\n        to size: ByteCount\n    ) async throws\n\n    /// Closes the file handle.\n    ///\n    /// It is important to close a handle once it has been finished with to avoid leaking\n    /// resources. Prefer using APIs which provided scoped access to a file handle which\n    /// manage lifecycles on your behalf. Note that if the handle has been detached via\n    /// ``FileHandleProtocol/detachUnsafeFileDescriptor()`` then it is not necessary to close\n    /// the handle.\n    ///\n    /// After closing the handle calls to other functions will throw an appropriate error.\n    ///\n    /// - Parameters:\n    ///   - makeChangesVisible: Whether the changes made to the file will be made visibile. This\n    ///       parameter is ignored unless ``OpenOptions/NewFile/transactionalCreation`` was\n    ///       set to `true`. When `makeChangesVisible` is `true`, the file will be created on the\n    ///       filesystem with the expected name, otherwise no file will be created or the original\n    ///       file won't be modified (if one existed).\n    func close(makeChangesVisible: Bool) async throws\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension WritableFileHandleProtocol {\n    /// Write the readable bytes of the `ByteBuffer` to the open file.\n    ///\n    /// - Important: This method checks whether the file is seekable or not (i.e., whether it's a socket,\n    /// pipe or FIFO), and will throw ``FileSystemError/Code-swift.struct/unsupported``\n    /// if an offset other than zero is passed.\n    ///\n    /// - Parameters:\n    ///   - buffer: The bytes to write.\n    ///   - offset: The absolute offset into the file to write the bytes.\n    /// - Returns: The number of bytes written.\n    /// - Throws: ``FileSystemError/Code-swift.struct/unsupported`` if file is\n    /// unseekable and `offset` is not 0.\n    @discardableResult\n    public func write(\n        contentsOf buffer: ByteBuffer,\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.write(contentsOf: buffer.readableBytesView, toAbsoluteOffset: offset)\n    }\n}\n\n// MARK: - File times modifiers\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileHandleProtocol {\n    /// Sets the file's last access time to the given time.\n    ///\n    /// - Parameter time: The time to which the file's last access time should be set.\n    ///\n    /// - Throws: If there's an error updating the time. If this happens, the original value won't be modified.\n    public func setLastAccessTime(to time: FileInfo.Timespec) async throws {\n        try await self.setTimes(lastAccess: time, lastDataModification: nil)\n    }\n\n    /// Sets the file's last data modification time to the given time.\n    ///\n    /// - Parameter time: The time to which the file's last data modification time should be set.\n    ///\n    /// - Throws: If there's an error updating the time. If this happens, the original value won't be modified.\n    public func setLastDataModificationTime(to time: FileInfo.Timespec) async throws {\n        try await self.setTimes(lastAccess: nil, lastDataModification: time)\n    }\n\n    /// Sets the file's last access and last data modification times to the current time.\n    ///\n    /// - Throws: If there's an error updating the times. If this happens, the original values won't be modified.\n    public func touch() async throws {\n        try await self.setTimes(lastAccess: nil, lastDataModification: nil)\n    }\n}\n\n/// A file handle which is suitable for reading and writing.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic typealias ReadableAndWritableFileHandleProtocol = ReadableFileHandleProtocol\n    & WritableFileHandleProtocol\n\n// MARK: - Directory\n\n/// A handle suitable for directories.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol DirectoryFileHandleProtocol: FileHandleProtocol {\n    /// The type of ``ReadableFileHandleProtocol`` to return when opening files for reading.\n    associatedtype ReadFileHandle: ReadableFileHandleProtocol\n\n    /// The type of ``WritableFileHandleProtocol`` to return when opening files for writing.\n    associatedtype WriteFileHandle: WritableFileHandleProtocol\n\n    /// The type of ``ReadableAndWritableFileHandleProtocol`` to return when opening files for reading and writing.\n    associatedtype ReadWriteFileHandle: ReadableAndWritableFileHandleProtocol\n\n    /// Returns an `AsyncSequence` of entries in the open directory.\n    ///\n    /// You can recurse into and list the contents of any subdirectories by setting `recursive`\n    /// to `true`. The current (\".\") and parent (\"..\") directory entries are not included. The order\n    /// of entries is arbitrary and shouldn't be relied upon.\n    ///\n    /// - Parameter recursive: Whether subdirectories should be recursively visited.\n    /// - Returns: An `AsyncSequence` of directory entries.\n    func listContents(recursive: Bool) -> DirectoryEntries\n\n    /// Opens the file at `path` for reading and returns a handle to it.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle. The file being\n    /// opened must already exist otherwise this function will throw a ``FileSystemError`` with\n    /// code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open relative to the open file.\n    ///   - options: How the file should be opened.\n    /// - Returns: A read-only handle to the opened file.\n    func openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle\n\n    /// Opens the file at `path` for writing and returns a handle to it.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    /// - Returns: A write-only handle to the opened file.\n    func openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle\n\n    /// Opens the file at `path` for reading and writing and returns a handle to it.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    func openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle\n\n    /// Opens the directory at `path` and returns a handle to it.\n    ///\n    /// The directory being opened must already exist otherwise this function will throw an error.\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A handle to the opened directory.\n    func openDirectory(\n        atPath path: FilePath,\n        options: OpenOptions.Directory\n    ) async throws -> Self\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension DirectoryFileHandleProtocol {\n    /// Returns an `AsyncSequence` of entries in the open directory.\n    ///\n    /// The current (\".\") and parent (\"..\") directory entries are not included. The order of entries\n    /// is arbitrary and should not be relied upon.\n    public func listContents() -> DirectoryEntries {\n        self.listContents(recursive: false)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension DirectoryFileHandleProtocol {\n    /// Opens the file at the given path and provides scoped read access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns.\n    /// Files may also be opened in write-only and read-write\n    /// mode by calling ``DirectoryFileHandleProtocol/withFileHandle(forWritingAt:options:execute:)``\n    /// and ``DirectoryFileHandleProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)``,\n    /// respectively.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle. The file being\n    /// opened must already exist otherwise this function will throw a ``FileSystemError`` with\n    /// code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - body: A closure which provides read-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read = OpenOptions.Read(),\n        execute body: (_ read: ReadFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAt: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped write access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns.\n    /// Files may also be opened in read-only or read-write\n    /// mode by calling ``DirectoryFileHandleProtocol/withFileHandle(forReadingAt:options:execute:)`` and\n    /// ``DirectoryFileHandleProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)``,\n    /// respectively.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - body: A closure which provides write-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute body: (_ write: WriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forWritingAt: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { result in\n            switch result {\n            case .success:\n                try await handle.close(makeChangesVisible: true)\n            case .failure:\n                try await handle.close(makeChangesVisible: false)\n            }\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped read-write access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns.\n    /// Files may also be opened in read-only or write-only\n    /// mode by calling ``DirectoryFileHandleProtocol/withFileHandle(forReadingAt:options:execute:)`` and\n    /// ``DirectoryFileHandleProtocol/withFileHandle(forWritingAt:options:execute:)``, respectively.\n    ///\n    /// If `path` is a relative path then it is opened relative to the handle.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading and writing.\n    ///   - options: How the file should be opened.\n    ///   - body: A closure which provides access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute body: (_ readWrite: ReadWriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAndWritingAt: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { result in\n            switch result {\n            case .success:\n                try await handle.close(makeChangesVisible: true)\n            case .failure:\n                try await handle.close(makeChangesVisible: false)\n            }\n        }\n    }\n\n    /// Opens the directory at the given path and provides scoped access to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the directory should be opened.\n    ///   - body: A closure which provides access to the directory.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withDirectoryHandle<Result>(\n        atPath path: FilePath,\n        options: OpenOptions.Directory = OpenOptions.Directory(),\n        execute body: (_ directory: Self) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openDirectory(atPath: path, options: options)\n\n        return try await withUncancellableTearDown {\n            try await body(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileInfo.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n/// Information about a file system object.\n///\n/// The information available for a file depends on the platform, ``FileInfo`` provides\n/// convenient access to a common subset of properties. Using these properties ensures that\n/// code is portable. If available, the platform specific information is made available via\n/// ``FileInfo/platformSpecificStatus``. However users should take care to ensure their\n/// code uses the correct platform checks when using it to ensure their code is portable.\npublic struct FileInfo: Hashable, Sendable {\n    /// Wraps `CInterop.Stat` providing `Hashable` and `Equatable` conformance.\n    private var _platformSpecificStatus: Stat?\n\n    /// The information about the file returned from the filesystem, if available.\n    ///\n    /// This value is platform specific: you should be careful when using\n    /// it as some of its fields vary across platforms. In most cases prefer\n    /// using other properties on this type instead.\n    ///\n    /// See also: the manual pages for 'stat' (`man 2 stat`)\n    public var platformSpecificStatus: CInterop.Stat? {\n        get { self._platformSpecificStatus?.stat }\n        set { self._platformSpecificStatus = newValue.map { Stat($0) } }\n    }\n\n    /// The type of the file.\n    public var type: FileType\n\n    /// Permissions currently set on the file.\n    public var permissions: FilePermissions\n\n    /// The size of the file in bytes.\n    public var size: Int64\n\n    /// User ID of the file.\n    public var userID: UserID\n\n    /// Group ID of the file.\n    public var groupID: GroupID\n\n    /// The last time the file was accessed.\n    public var lastAccessTime: Timespec\n\n    /// The last time the files data was last changed.\n    public var lastDataModificationTime: Timespec\n\n    /// The last time the status of the file was changed.\n    public var lastStatusChangeTime: Timespec\n\n    /// Creates a ``FileInfo`` by deriving values from a platform-specific value.\n    public init(platformSpecificStatus: CInterop.Stat) {\n        self._platformSpecificStatus = Stat(platformSpecificStatus)\n        self.type = FileType(platformSpecificMode: CInterop.Mode(platformSpecificStatus.st_mode))\n        self.permissions = FilePermissions(masking: CInterop.Mode(platformSpecificStatus.st_mode))\n        self.size = Int64(platformSpecificStatus.st_size)\n        self.userID = UserID(rawValue: platformSpecificStatus.st_uid)\n        self.groupID = GroupID(rawValue: platformSpecificStatus.st_gid)\n\n        #if canImport(Darwin)\n        self.lastAccessTime = Timespec(platformSpecificStatus.st_atimespec)\n        self.lastDataModificationTime = Timespec(platformSpecificStatus.st_mtimespec)\n        self.lastStatusChangeTime = Timespec(platformSpecificStatus.st_ctimespec)\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        self.lastAccessTime = Timespec(platformSpecificStatus.st_atim)\n        self.lastDataModificationTime = Timespec(platformSpecificStatus.st_mtim)\n        self.lastStatusChangeTime = Timespec(platformSpecificStatus.st_ctim)\n        #endif\n    }\n\n    /// Creates a ``FileInfo`` from the provided values.\n    ///\n    /// If you have a platform specific status value prefer calling\n    /// ``init(platformSpecificStatus:)``.\n    public init(\n        type: FileType,\n        permissions: FilePermissions,\n        size: Int64,\n        userID: UserID,\n        groupID: GroupID,\n        lastAccessTime: Timespec,\n        lastDataModificationTime: Timespec,\n        lastStatusChangeTime: Timespec\n    ) {\n        self._platformSpecificStatus = nil\n        self.type = type\n        self.permissions = permissions\n        self.size = size\n        self.userID = userID\n        self.groupID = groupID\n        self.lastAccessTime = lastAccessTime\n        self.lastDataModificationTime = lastDataModificationTime\n        self.lastStatusChangeTime = lastStatusChangeTime\n    }\n}\n\nextension FileInfo {\n    /// The numeric ID of a user.\n    public struct UserID: Hashable, Sendable, CustomStringConvertible {\n        public var rawValue: UInt32\n\n        public init(rawValue: UInt32) {\n            self.rawValue = rawValue\n        }\n\n        public var description: String {\n            String(describing: self.rawValue)\n        }\n    }\n\n    /// The numeric ID of a group.\n    public struct GroupID: Hashable, Sendable, CustomStringConvertible {\n        public var rawValue: UInt32\n\n        public init(rawValue: UInt32) {\n            self.rawValue = rawValue\n        }\n\n        public var description: String {\n            String(describing: self.rawValue)\n        }\n    }\n\n    /// A time interval consisting of whole seconds and nanoseconds.\n    public struct Timespec: Hashable, Sendable {\n        #if canImport(Darwin)\n        private static let utimeOmit = Int(UTIME_OMIT)\n        private static let utimeNow = Int(UTIME_NOW)\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        private static let utimeOmit = Int(CNIOLinux_UTIME_OMIT)\n        private static let utimeNow = Int(CNIOLinux_UTIME_NOW)\n        #endif\n\n        /// A timespec where the seconds are set to zero and the nanoseconds set to `UTIME_OMIT`.\n        /// In syscalls such as `futimens`, this means the time component set to this value will be ignored.\n        public static let omit = Self(\n            seconds: 0,\n            nanoseconds: Self.utimeOmit\n        )\n\n        /// A timespec where the seconds are set to zero and the nanoseconds set to `UTIME_NOW`.\n        /// In syscalls such as `futimens`, this means the time component set to this value will be\n        /// be set to the current time or the largest value supported by the platform, whichever is smaller.\n        public static let now = Self(\n            seconds: 0,\n            nanoseconds: Self.utimeNow\n        )\n\n        /// The number of seconds.\n        public var seconds: Int\n\n        /// The number of nanoseconds.\n        public var nanoseconds: Int\n\n        init(_ timespec: timespec) {\n            self.seconds = timespec.tv_sec\n            self.nanoseconds = timespec.tv_nsec\n        }\n\n        public init(seconds: Int, nanoseconds: Int) {\n            self.seconds = seconds\n            self.nanoseconds = nanoseconds\n        }\n    }\n}\n\n/// A wrapper providing `Hashable` and `Equatable` conformance for `CInterop.Stat`.\nprivate struct Stat: Hashable {\n    var stat: CInterop.Stat\n\n    init(_ stat: CInterop.Stat) {\n        self.stat = stat\n    }\n\n    func hash(into hasher: inout Hasher) {\n        let stat = self.stat\n        // Different platforms have different values; these are\n        // common between Darwin and Glibc.\n        hasher.combine(stat.st_dev)\n        hasher.combine(stat.st_mode)\n        hasher.combine(stat.st_nlink)\n        hasher.combine(stat.st_ino)\n        hasher.combine(stat.st_uid)\n        hasher.combine(stat.st_gid)\n        hasher.combine(stat.st_rdev)\n        hasher.combine(stat.st_size)\n        hasher.combine(stat.st_blocks)\n        hasher.combine(stat.st_blksize)\n\n        #if canImport(Darwin)\n        hasher.combine(FileInfo.Timespec(stat.st_atimespec))\n        hasher.combine(FileInfo.Timespec(stat.st_mtimespec))\n        hasher.combine(FileInfo.Timespec(stat.st_ctimespec))\n        hasher.combine(FileInfo.Timespec(stat.st_birthtimespec))\n        hasher.combine(stat.st_flags)\n        hasher.combine(stat.st_gen)\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        hasher.combine(FileInfo.Timespec(stat.st_atim))\n        hasher.combine(FileInfo.Timespec(stat.st_mtim))\n        hasher.combine(FileInfo.Timespec(stat.st_ctim))\n        #endif\n\n    }\n\n    static func == (lhs: Stat, rhs: Stat) -> Bool {\n        let lStat = lhs.stat\n        let rStat = rhs.stat\n\n        // Different platforms have different values; these are\n        // common between Darwin and Glibc.\n        var isEqual = lStat.st_dev == rStat.st_dev\n        isEqual = isEqual && lStat.st_mode == rStat.st_mode\n        isEqual = isEqual && lStat.st_nlink == rStat.st_nlink\n        isEqual = isEqual && lStat.st_ino == rStat.st_ino\n        isEqual = isEqual && lStat.st_uid == rStat.st_uid\n        isEqual = isEqual && lStat.st_gid == rStat.st_gid\n        isEqual = isEqual && lStat.st_rdev == rStat.st_rdev\n        isEqual = isEqual && lStat.st_size == rStat.st_size\n        isEqual = isEqual && lStat.st_blocks == rStat.st_blocks\n        isEqual = isEqual && lStat.st_blksize == rStat.st_blksize\n\n        #if canImport(Darwin)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_atimespec) == FileInfo.Timespec(rStat.st_atimespec)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_mtimespec) == FileInfo.Timespec(rStat.st_mtimespec)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_ctimespec) == FileInfo.Timespec(rStat.st_ctimespec)\n        isEqual =\n            isEqual\n            && FileInfo.Timespec(lStat.st_birthtimespec)\n                == FileInfo.Timespec(rStat.st_birthtimespec)\n        isEqual = isEqual && lStat.st_flags == rStat.st_flags\n        isEqual = isEqual && lStat.st_gen == rStat.st_gen\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n        isEqual = isEqual && FileInfo.Timespec(lStat.st_atim) == FileInfo.Timespec(rStat.st_atim)\n        isEqual = isEqual && FileInfo.Timespec(lStat.st_mtim) == FileInfo.Timespec(rStat.st_mtim)\n        isEqual = isEqual && FileInfo.Timespec(lStat.st_ctim) == FileInfo.Timespec(rStat.st_ctim)\n        #endif\n\n        return isEqual\n    }\n}\n\nextension FilePermissions {\n    internal init(masking rawValue: CInterop.Mode) {\n        self = .init(rawValue: rawValue & ~S_IFMT)\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#endif\n\n/// A file system which interacts with the local system. The file system uses a thread pool to\n/// perform system calls.\n///\n/// ### Creating a `FileSystem`\n///\n/// You should prefer using the `shared` instance of the file system. The `shared` instance uses two\n/// threads unless the `SWIFT_FILE_SYSTEM_THREAD_COUNT` environment variable is set.\n///\n/// If you require more granular control you can create a ``FileSystem`` with the required number of\n/// threads by calling ``withFileSystem(numberOfThreads:_:)`` or by using ``init(threadPool:)``.\n///\n/// ### Errors\n///\n/// Errors thrown by ``FileSystem`` will be of type:\n/// - ``FileSystemError`` if it wasn't possible to complete the operation, or\n/// - `CancellationError` if the `Task` was cancelled.\n///\n/// ``FileSystemError`` implements `CustomStringConvertible`. The output from the `description`\n/// contains basic information including the error code, message and error. You can get\n/// more information about the error by calling ``FileSystemError/detailedDescription()`` which\n/// returns a structured multi-line string containing information about the error.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct FileSystem: Sendable, FileSystemProtocol {\n    /// Returns a shared global instance of the ``FileSystem``.\n    ///\n    /// The file system executes blocking work in a thread pool which defaults to having two\n    /// threads. This can be modified by `blockingPoolThreadCountSuggestion` or by setting the\n    /// `NIO_SINGLETON_BLOCKING_POOL_THREAD_COUNT` environment variable.\n    public static var shared: FileSystem { globalFileSystem }\n\n    private let threadPool: NIOThreadPool\n    private let ownsThreadPool: Bool\n\n    fileprivate func shutdown() async {\n        if self.ownsThreadPool {\n            try? await self.threadPool.shutdownGracefully()\n        }\n    }\n\n    /// Creates a new ``FileSystem`` using the provided thread pool.\n    ///\n    /// - Parameter threadPool: A started thread pool to execute blocking system calls on. The\n    ///     ``FileSystem`` doesn't take ownership of the thread pool and you remain responsible for\n    ///     shutting it down when necessary.\n    public init(threadPool: NIOThreadPool) {\n        self.init(threadPool: threadPool, ownsThreadPool: false)\n    }\n\n    fileprivate init(threadPool: NIOThreadPool, ownsThreadPool: Bool) {\n        self.threadPool = threadPool\n        self.ownsThreadPool = ownsThreadPool\n    }\n\n    fileprivate init(numberOfThreads: Int) async {\n        let threadPool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        threadPool.start()\n        // Wait for the thread pool to start.\n        try? await threadPool.runIfActive {}\n        self.init(threadPool: threadPool, ownsThreadPool: true)\n    }\n\n    /// Open the file at `path` for reading.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A readable handle to the opened file.\n    public func openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openFile(forReadingAt: path, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Open the file at `path` for writing.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/permissionDenied`` if you have insufficient\n    ///   permissions to create the file.\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist and `options`\n    ///   weren't set to create a file.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A writable handle to the opened file.\n    public func openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openFile(forWritingAt: path, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Open the file at `path` for reading and writing.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/permissionDenied`` if you have insufficient\n    ///   permissions to create the file.\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist and `options`\n    ///   weren't set to create a file.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A readable and writable handle to the opened file.\n    public func openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openFile(forReadingAndWritingAt: path, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Open the directory at `path`.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` doesn't exist.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `open(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the directory should be opened.\n    /// - Returns: A handle to the opened directory.\n    public func openDirectory(\n        atPath path: FilePath,\n        options: OpenOptions.Directory\n    ) async throws -> DirectoryFileHandle {\n        let handle = try await self.threadPool.runIfActive {\n            let handle = try self._openDirectory(at: path, options: options).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    /// Create a directory at the given path.\n    ///\n    /// If a directory (or file) already exists at `path` a ``FileSystemError`` with code\n    /// ``FileSystemError/Code-swift.struct/fileAlreadyExists`` is thrown.\n    ///\n    /// If the parent directory of the directory to created does not exist a ``FileSystemError``\n    /// with ``FileSystemError/Code-swift.struct/invalidArgument`` is thrown. Missing directories\n    /// can be created by passing `true` to `createIntermediateDirectories`.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if a file or directory already\n    ///   exists .\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if a component in the `path` prefix\n    ///   does not exist and `createIntermediateDirectories` is `false`.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `mkdir(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The directory to create.\n    ///   - createIntermediateDirectories: Whether intermediate directories should be created.\n    ///   - permissions: The permissions to set on the new directory; default permissions will be\n    ///       used if not specified.\n    public func createDirectory(\n        at path: FilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions?\n    ) async throws {\n        try await self.createDirectory(\n            at: path,\n            withIntermediateDirectories: createIntermediateDirectories,\n            permissions: permissions,\n            idempotent: true\n        )\n    }\n\n    private func createDirectory(\n        at path: FilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions?,\n        idempotent: Bool\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._createDirectory(\n                at: path,\n                withIntermediateDirectories: createIntermediateDirectories,\n                permissions: permissions ?? .defaultsForDirectory,\n                idempotent: idempotent\n            ).get()\n        }\n    }\n\n    /// Create a temporary directory at the given path, using a template.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if the template doesn't end in at\n    ///   least 3 'X's.\n    /// - ``FileSystemError/Code-swift.struct/permissionDenied`` if the user doesn't have permission\n    ///  to create a directory at the path specified in the template.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `mkdir(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - template: The template for the path of the temporary directory.\n    /// - Returns:\n    ///   - The path to the new temporary directory.\n    public func createTemporaryDirectory(\n        template: FilePath\n    ) async throws -> FilePath {\n        try await self.threadPool.runIfActive {\n            try self._createTemporaryDirectory(template: template).get()\n        }\n    }\n\n    /// Returns information about the file at `path` if it exists; nil otherwise.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses `lstat(2)` if `infoAboutSymbolicLink` is `true`, `stat(2)` otherwise.\n    ///\n    /// - Parameters:\n    ///    - path: The path of the file.\n    ///    - infoAboutSymbolicLink: If the file is a symbolic link and this parameter is `true`,\n    ///        then information about the link will be returned. Otherwise, information about the\n    ///        destination of the symbolic link is returned.\n    /// - Returns: Information about the file at the given path or `nil` if no file exists.\n    public func info(\n        forFileAt path: FilePath,\n        infoAboutSymbolicLink: Bool\n    ) async throws -> FileInfo? {\n        try await self.threadPool.runIfActive {\n            try self._info(forFileAt: path, infoAboutSymbolicLink: infoAboutSymbolicLink).get()\n        }\n    }\n\n    // MARK: - File copying, removal, and moving\n\n    /// See ``FileSystemProtocol/copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    ///\n    /// The item to be copied must be a:\n    /// - regular file,\n    /// - symbolic link, or\n    /// - directory.\n    ///\n    /// `shouldCopyItem` can be used to ignore objects not part of this set.\n    ///\n    /// #### Errors\n    ///\n    /// In addition to the already documented errors these may be thrown\n    /// - ``FileSystemError/Code-swift.struct/unsupported`` if an item to be copied is not a regular\n    ///   file, symbolic link or directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// This function is platform dependent. On Darwin the `copyfile(2)` system call is used and\n    /// items are cloned where possible. On Linux the `sendfile(2)` system call is used.\n    ///\n    /// When `replaceExisting` is `true`, regular files are atomically replaced using `COPYFILE_UNLINK`\n    /// on Darwin or a temporary file followed by `renameat2(2)` on Linux. Symbolic links are\n    /// atomically replaced using a temporary symlink followed by `renamex_np(2)` on Darwin or\n    /// `renameat2(2)` on Linux.\n    ///\n    /// Note that `replaceExisting` is ignored for directories and implemented only for regular\n    /// files and symbolic links.\n    public func copyItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath,\n        strategy copyStrategy: CopyStrategy,\n        replaceExisting: Bool,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        guard let info = try await self.info(forFileAt: sourcePath, infoAboutSymbolicLink: true)\n        else {\n            throw FileSystemError(\n                code: .notFound,\n                message: \"Unable to copy '\\(sourcePath)', it does not exist.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n\n        // By doing this before looking at the type, we allow callers to decide whether\n        // unanticipated kinds of entries can be safely ignored without needing changes upstream.\n        if await shouldCopyItem(.init(path: sourcePath, type: info.type)!, destinationPath) {\n            switch info.type {\n            case .regular:\n                try await self.copyRegularFile(from: sourcePath, to: destinationPath, replaceExisting: replaceExisting)\n\n            case .symlink:\n                try await self.copySymbolicLink(from: sourcePath, to: destinationPath, replaceExisting: replaceExisting)\n\n            case .directory:\n                try await self.copyDirectory(\n                    from: sourcePath,\n                    to: destinationPath,\n                    strategy: copyStrategy,\n                    shouldProceedAfterError: shouldProceedAfterError\n                ) { source, destination in\n                    await shouldCopyItem(source, destination)\n                }\n\n            default:\n                throw FileSystemError(\n                    code: .unsupported,\n                    message: \"\"\"\n                        Can't copy '\\(sourcePath)' of type '\\(info.type)'; only regular files, \\\n                        symbolic links and directories can be copied.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    /// See ``FileSystemProtocol/removeItem(at:strategy:recursively:)``\n    ///\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// Only regular files, symbolic links and directories may be removed. If the file at `path` is\n    /// a directory then its contents and all of its subdirectories will be removed recursively.\n    /// Symbolic links are also removed (but their targets are not deleted). If no file exists at\n    /// `path` this function returns zero.\n    ///\n    /// #### Errors\n    ///\n    /// Errors codes thrown by this function include:\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if the item is not a regular file,\n    ///   symbolic link or directory. This also applies to items within the directory being removed.\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item being removed is a directory\n    ///   which isn't empty and `removeItemRecursively` is false.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `remove(3)` system call.\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removalStrategy: Whether to delete files sequentially (one-by-one), or perform a\n    ///       concurrent scan of the tree at `path` and delete files when they are found.\n    ///   - removeItemRecursively: Whether or not to remove items recursively.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: FilePath,\n        strategy removalStrategy: RemovalStrategy,\n        recursively removeItemRecursively: Bool\n    ) async throws -> Int {\n        // Try to remove the item: we might just get lucky.\n        let result = try await self.threadPool.runIfActive { Libc.remove(path) }\n\n        switch result {\n        case .success:\n            // Great; we removed an entire item.\n            return 1\n\n        case .failure(.noSuchFileOrDirectory):\n            // Nothing to delete.\n            return 0\n\n        case .failure(.directoryNotEmpty):\n            guard removeItemRecursively else {\n                throw FileSystemError(\n                    code: .notEmpty,\n                    message: \"\"\"\n                        Can't remove directory at path '\\(path)', it isn't empty and \\\n                        'removeItemRecursively' is false. Remove items from the directory first or \\\n                        set 'removeItemRecursively' to true when calling \\\n                        'removeItem(at:recursively:)'.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n\n            switch removalStrategy.wrapped {\n            case .sequential:\n                return try await self.removeItemSequentially(at: path)\n            case let .parallel(maxDescriptors):\n                return try await self.removeConcurrently(at: path, maxDescriptors)\n            }\n\n        case let .failure(errno):\n            throw FileSystemError.remove(errno: errno, path: path, location: .here())\n        }\n    }\n\n    @discardableResult\n    private func removeItemSequentially(\n        at path: FilePath\n    ) async throws -> Int {\n        var (subdirectories, filesRemoved) = try await self.withDirectoryHandle(\n            atPath: path\n        ) { directory in\n            var subdirectories = [FilePath]()\n            var filesRemoved = 0\n\n            for try await batch in directory.listContents().batched() {\n                for entry in batch {\n                    switch entry.type {\n                    case .directory:\n                        subdirectories.append(entry.path)\n\n                    default:\n                        filesRemoved += try await self.removeOneItem(at: entry.path)\n                    }\n                }\n            }\n\n            return (subdirectories, filesRemoved)\n        }\n\n        for subdirectory in subdirectories {\n            filesRemoved += try await self.removeItemSequentially(at: subdirectory)\n        }\n\n        // The directory should be empty now. Remove ourself.\n        filesRemoved += try await self.removeOneItem(at: path)\n\n        return filesRemoved\n\n    }\n\n    private func removeConcurrently(\n        at path: FilePath,\n        _ maxDescriptors: Int\n    ) async throws -> Int {\n        let bucket: TokenBucket = .init(tokens: maxDescriptors)\n        return try await self.discoverAndRemoveItemsInTree(at: path, bucket)\n    }\n\n    /// Moves the named file or directory to a new location.\n    ///\n    /// Only regular files, symbolic links and directories may be moved. If the item to be is a\n    /// symbolic link then only the link is moved; the target of the link is not moved.\n    ///\n    /// If the file is moved within to a different logical partition then the file is copied to the\n    /// new partition before being removed from old partition. If removing the item fails the copied\n    /// file will not be removed.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if an item at `destinationPath`\n    ///   already exists.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `rename(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to move.\n    ///   - destinationPath: The path at which to place the item.\n    public func moveItem(at sourcePath: FilePath, to destinationPath: FilePath) async throws {\n        let result = try await self.threadPool.runIfActive {\n            try self._moveItem(at: sourcePath, to: destinationPath).get()\n        }\n\n        switch result {\n        case .moved:\n            ()\n        case .differentLogicalDevices:\n            // Fall back to copy and remove.\n            try await self.copyItem(at: sourcePath, to: destinationPath)\n            try await self.removeItem(at: sourcePath, strategy: .platformDefault)\n        }\n    }\n\n    /// Replaces the item at `destinationPath` with the item at `existingPath`.\n    ///\n    /// Only regular files, symbolic links and directories may replace the item at the existing\n    /// path. The file at the destination path isn't required to exist. If it does exist it does not\n    /// have to match the type of the file it is being replaced with.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `existingPath` does not\n    ///   exist.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `rename(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - destinationPath: The path of the file or directory to replace.\n    ///   - existingPath: The path of the existing file or directory.\n    public func replaceItem(\n        at destinationPath: FilePath,\n        withItemAt existingPath: FilePath\n    ) async throws {\n        do {\n            try await self.removeItem(at: destinationPath, strategy: .platformDefault)\n            try await self.moveItem(at: existingPath, to: destinationPath)\n            try await self.removeItem(at: existingPath, strategy: .platformDefault)\n        } catch let error as FileSystemError {\n            throw FileSystemError(\n                message: \"Can't replace '\\(destinationPath)' with '\\(existingPath)'.\",\n                wrapping: error\n            )\n        }\n    }\n\n    // MARK: - Symbolic links\n\n    /// Creates a symbolic link between two files.\n    ///\n    /// A link is created at `linkPath` which points to `destinationPath`. The destination of a\n    /// symbolic link can be read with ``destinationOfSymbolicLink(at:)``.\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if a file exists at\n    ///   `destinationPath`.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `link(2)` system call.\n    ///\n    /// - Parameters:\n    ///   - linkPath: The path at which to create the symbolic link.\n    ///   - destinationPath: The path that contains the item that the symbolic link points to.`\n    public func createSymbolicLink(\n        at linkPath: FilePath,\n        withDestination destinationPath: FilePath\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._createSymbolicLink(at: linkPath, withDestination: destinationPath).get()\n        }\n    }\n\n    /// Returns the path of the item pointed to by a symbolic link.\n    ///\n    /// The destination of the symbolic link is not guaranteed to be a valid path, nor is it\n    /// guaranteed to be an absolute path. If you need to open a file which is the destination of a\n    /// symbolic link then the appropriate `open` function:\n    /// - ``openFile(forReadingAt:options:)\n    /// - ``openFile(forWritingAt:options:)``\n    /// - ``openFile(forReadingAndWritingAt:options:)``\n    /// - ``openDirectory(atPath:options:)``\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `path` does not exist.\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if the file at `path` is not a\n    ///   symbolic link.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `readlink(2)` system call.\n    ///\n    /// - Parameter path: The path of a file or directory.\n    /// - Returns: The path of the file or directory to which the symbolic link points to.\n    public func destinationOfSymbolicLink(\n        at path: FilePath\n    ) async throws -> FilePath {\n        try await self.threadPool.runIfActive {\n            try self._destinationOfSymbolicLink(at: path).get()\n        }\n    }\n\n    /// Returns the path of the current working directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// Uses the `getcwd(2)` system call.\n    ///\n    /// - Returns: The path to the current working directory.\n    public var currentWorkingDirectory: FilePath {\n        get async throws {\n            let result = try await self.threadPool.runIfActive {\n                try Libc.getcwd().mapError { errno in\n                    FileSystemError.getcwd(errno: errno, location: .here())\n                }.get()\n            }\n            return result\n        }\n    }\n\n    /// Returns the path of the current user's home directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// This function first checks the `HOME` environment variable (and `USERPROFILE` on Windows).\n    /// If not set, on Darwin/Linux/Android it uses `getpwuid_r(3)` to query the password database.\n    ///\n    /// Note: `getpwuid_r` can potentially block on I/O (e.g., when using NIS or LDAP),\n    /// which is why this property is async when falling back to the password database.\n    ///\n    /// - Returns: The path to the current user's home directory.\n    public var homeDirectory: FilePath {\n        get async throws {\n            if let path = Libc.homeDirectoryFromEnvironment() {\n                return path\n            }\n\n            #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Android)\n            return try await self.threadPool.runIfActive {\n                try Libc.homeDirectoryFromPasswd().mapError { errno in\n                    FileSystemError.getpwuid_r(errno: errno, location: .here())\n                }.get()\n            }\n            #else\n            throw FileSystemError.getpwuid_r(errno: .noSuchFileOrDirectory, location: .here())\n            #endif\n        }\n    }\n\n    /// Returns a path to a temporary directory.\n    ///\n    /// #### Implementation details\n    ///\n    /// On all platforms, this function first attempts to read the `TMPDIR` environment variable and returns that path, omitting trailing slashes.\n    /// If that fails:\n    /// - On Darwin this function uses `confstr(3)` and gets the value of `_CS_DARWIN_USER_TEMP_DIR`;\n    ///   the users temporary directory. Typically items are removed after three days if they are not\n    ///   accessed.\n    /// - On Android this returns \"/data/local/tmp\".\n    /// - On other platforms this returns \"/tmp\".\n    ///\n    /// - Returns: The path to a temporary directory.\n    public var temporaryDirectory: FilePath {\n        get async throws {\n            if let tmpdir = getenv(\"TMPDIR\") {\n                return FilePath(String(cString: tmpdir))\n            }\n\n            #if canImport(Darwin)\n            return try await self.threadPool.runIfActive {\n                let result = Libc.constr(_CS_DARWIN_USER_TEMP_DIR)\n                switch result {\n                case .success(let path):\n                    return FilePath(path)\n                case .failure(_):\n                    return FilePath(\"/tmp\")\n                }\n            }\n            #elseif os(Android)\n            return FilePath(\"/data/local/tmp\")\n            #else\n            return FilePath(\"/tmp\")\n            #endif\n        }\n    }\n}\n\n// MARK: - Creating FileSystems\n\nextension NIOSingletons {\n    /// A suggestion of how many threads the global singleton ``FileSystem`` uses for blocking I/O.\n    ///\n    /// The thread count is the system's available core count unless the environment variable\n    /// `NIO_SINGLETON_FILESYSTEM_THREAD_COUNT` is set or this value was set manually by the user.\n    ///\n    /// - Note: This value must be set _before_ any singletons are used and must only be set once.\n    @available(*, deprecated, renamed: \"blockingPoolThreadCountSuggestion\")\n    public static var fileSystemThreadCountSuggestion: Int {\n        set { Self.blockingPoolThreadCountSuggestion = newValue }\n        get { Self.blockingPoolThreadCountSuggestion }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate let globalFileSystem: FileSystem = {\n    guard NIOSingletons.singletonsEnabledSuggestion else {\n        fatalError(\n            \"\"\"\n            Cannot create global singleton FileSystem thread pool because the global singletons \\\n            have been disabled by setting `NIOSingletons.singletonsEnabledSuggestion = false`\n            \"\"\"\n        )\n    }\n    return FileSystem(threadPool: NIOSingletons.posixBlockingThreadPool, ownsThreadPool: false)\n}()\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension NIOSingletons {\n    /// Returns a shared global instance of the ``FileSystem``.\n    ///\n    /// The file system executes blocking work in a thread pool. See\n    /// `blockingPoolThreadCountSuggestion` for the default behaviour and ways to control it.\n    public static var fileSystem: FileSystem { globalFileSystem }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemProtocol where Self == FileSystem {\n    /// A global shared instance of ``FileSystem``.\n    public static var shared: FileSystem {\n        FileSystem.shared\n    }\n}\n\n/// Provides temporary scoped access to a ``FileSystem`` with the given number of threads.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic func withFileSystem<Result>(\n    numberOfThreads: Int,\n    _ body: (FileSystem) async throws -> Result\n) async throws -> Result {\n    let fileSystem = await FileSystem(numberOfThreads: numberOfThreads)\n    return try await withUncancellableTearDown {\n        try await body(fileSystem)\n    } tearDown: { _ in\n        await fileSystem.shutdown()\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    /// Opens `path` for reading and returns ``ReadFileHandle`` or ``FileSystemError``.\n    private func _openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) -> Result<ReadFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .readOnly,\n            options: options.descriptorOptions,\n            permissions: nil,\n            transactionalIfPossible: false,\n            threadPool: self.threadPool\n        ).map {\n            ReadFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Opens `path` for writing and returns ``WriteFileHandle`` or ``FileSystemError``.\n    private func _openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) -> Result<WriteFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .writeOnly,\n            options: options.descriptorOptions,\n            permissions: options.permissionsForRegularFile,\n            transactionalIfPossible: options.newFile?.transactionalCreation ?? false,\n            threadPool: self.threadPool\n        ).map {\n            WriteFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Opens `path` for reading and writing and returns ``ReadWriteFileHandle`` or\n    /// ``FileSystemError``.\n    private func _openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) -> Result<ReadWriteFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .readWrite,\n            options: options.descriptorOptions,\n            permissions: options.permissionsForRegularFile,\n            transactionalIfPossible: options.newFile?.transactionalCreation ?? false,\n            threadPool: self.threadPool\n        ).map {\n            ReadWriteFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Opens the directory at `path` and returns ``DirectoryFileHandle`` or ``FileSystemError``.\n    private func _openDirectory(\n        at path: FilePath,\n        options: OpenOptions.Directory\n    ) -> Result<DirectoryFileHandle, FileSystemError> {\n        SystemFileHandle.syncOpen(\n            atPath: path,\n            mode: .readOnly,\n            options: options.descriptorOptions,\n            permissions: nil,\n            transactionalIfPossible: false,\n            threadPool: self.threadPool\n        ).map {\n            DirectoryFileHandle(wrapping: $0)\n        }\n    }\n\n    /// Creates a directory at `fullPath`, potentially creating other directories along the way.\n    private func _createDirectory(\n        at fullPath: FilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions,\n        idempotent: Bool = true\n    ) -> Result<Void, FileSystemError> {\n        // We assume that we will be creating intermediate directories:\n        // - Try creating the directory. If it fails with ENOENT (no such file or directory), then\n        //   drop the last component and append it to a buffer.\n        // - Repeat until the path is empty. This means we cannot create the directory or we\n        //   succeed, in which case we can build up our original path and create directories one at\n        //   a time.\n        var droppedComponents: [FilePath.Component] = []\n        var path = fullPath\n\n        // Normalize the path to remove any superflous '..'.\n        path.lexicallyNormalize()\n\n        if path.isEmpty {\n            let error = FileSystemError(\n                code: .invalidArgument,\n                message: \"Path of directory to create must not be empty.\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        loop: while true {\n            switch Syscall.mkdir(at: path, permissions: permissions) {\n            case .success:\n                break loop\n\n            case let .failure(errno):\n                if errno == .fileExists {\n                    if idempotent {\n                        switch self._info(forFileAt: path, infoAboutSymbolicLink: false) {\n                        case let .success(maybeInfo):\n                            if let info = maybeInfo, info.type == .directory {\n                                break loop\n                            } else {\n                                // A file exists at this path.\n                                return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                            }\n                        case .failure:\n                            // Unable to determine what exists at this path.\n                            return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                        }\n                    } else {\n                        return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                    }\n                }\n                guard createIntermediateDirectories, errno == .noSuchFileOrDirectory else {\n                    return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                }\n\n                // Drop the last component and loop around.\n                if let component = path.lastComponent {\n                    path.removeLastComponent()\n                    droppedComponents.append(component)\n                } else {\n                    // Should only happen if the path is empty or contains just the root.\n                    return .failure(.mkdir(errno: errno, path: path, location: .here()))\n                }\n            }\n        }\n\n        // Successfully made a directory, construct its children.\n        while let subdirectory = droppedComponents.popLast() {\n            path.append(subdirectory)\n            switch Syscall.mkdir(at: path, permissions: permissions) {\n            case .success:\n                continue\n            case let .failure(errno):\n                return .failure(.mkdir(errno: errno, path: path, location: .here()))\n            }\n        }\n\n        return .success(())\n    }\n\n    /// Returns info about the file at `path`.\n    private func _info(\n        forFileAt path: FilePath,\n        infoAboutSymbolicLink: Bool\n    ) -> Result<FileInfo?, FileSystemError> {\n        let result: Result<CInterop.Stat, Errno>\n        if infoAboutSymbolicLink {\n            result = Syscall.lstat(path: path)\n        } else {\n            result = Syscall.stat(path: path)\n        }\n\n        return result.map {\n            FileInfo(platformSpecificStatus: $0)\n        }.flatMapError { errno in\n            if errno == .noSuchFileOrDirectory {\n                return .success(nil)\n            } else {\n                let name = infoAboutSymbolicLink ? \"lstat\" : \"stat\"\n                return .failure(.stat(name, errno: errno, path: path, location: .here()))\n            }\n        }\n    }\n\n    /// Represents an item in a directory that needs copying, or an explicit indication of the end\n    /// of items. The provision of the ``endOfDir`` case significantly simplifies the parallel code\n    enum DirCopyItem: Hashable, Sendable {\n        case endOfDir\n        case toCopy(from: DirectoryEntry, to: FilePath)\n    }\n\n    /// Creates the directory ``destinationPath`` based on the directory at ``sourcePath`` including\n    /// any permissions/attributes. It does not copy the contents but indicates the items within\n    /// ``sourcePath`` which should be copied.\n    ///\n    /// This is a little cumbersome, because it is used by ``copyDirectorySequential`` and\n    /// ``copyDirectoryParallel``. It is desirable to use the directories' file descriptor for as\n    /// little time as possible, and certainly not across asynchronous invocations. The downstream\n    /// paths in the parallel and sequential paths are very different\n    /// - Returns: An array of `DirCopyItem` which have passed the ``shouldCopyItem``` filter. The\n    ///     target file paths will all be in ``destinationPath``. The array will always finish with\n    ///     an ``DirCopyItem.endOfDir``.\n    private func prepareDirectoryForRecusiveCopy(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws -> [DirCopyItem] {\n        try await self.withDirectoryHandle(atPath: sourcePath) { dir in\n            // Grab the directory info to copy permissions.\n            let info = try await dir.info()\n            try await self.createDirectory(\n                at: destinationPath,\n                withIntermediateDirectories: false,\n                permissions: info.permissions,\n                idempotent: false  // Fail if the destination dir already exists.\n            )\n\n            #if !os(Android)\n            // Copy over extended attributes, if any exist.\n            do {\n                let attributes = try await dir.attributeNames()\n\n                if !attributes.isEmpty {\n                    try await self.withDirectoryHandle(\n                        atPath: destinationPath\n                    ) { destinationDir in\n                        for attribute in attributes {\n                            let value = try await dir.valueForAttribute(attribute)\n                            try await destinationDir.updateValueForAttribute(\n                                value,\n                                attribute: attribute\n                            )\n                        }\n                    }\n                }\n            } catch let error as FileSystemError where error.code == .unsupported {\n                // Not all file systems support extended attributes. Swallow errors indicating this.\n                ()\n            }\n            #endif\n            // Build a list of items the caller needs to deal with, then do any further work after\n            // closing the current directory.\n            var contentsToCopy = [DirCopyItem]()\n\n            for try await batch in dir.listContents().batched() {\n                for entry in batch {\n                    // Any further work is pointless. We are under no obligation to cleanup. Exit as\n                    // fast and cleanly as possible.\n                    try Task.checkCancellation()\n                    let entryDestination = destinationPath.appending(entry.name)\n\n                    if await shouldCopyItem(entry, entryDestination) {\n                        // Assume there's a good chance of everything in the batch being included in\n                        // the common case. Let geometric growth go from this point though.\n                        if contentsToCopy.isEmpty {\n                            // Reserve space for the endOfDir entry too.\n                            contentsToCopy.reserveCapacity(batch.count + 1)\n                        }\n                        switch entry.type {\n                        case .regular, .symlink, .directory:\n                            contentsToCopy.append(.toCopy(from: entry, to: entryDestination))\n\n                        default:\n                            let error = FileSystemError(\n                                code: .unsupported,\n                                message: \"\"\"\n                                    Can't copy '\\(entry.path)' of type '\\(entry.type)'; only regular \\\n                                    files, symbolic links and directories can be copied.\n                                    \"\"\",\n                                cause: nil,\n                                location: .here()\n                            )\n\n                            try await shouldProceedAfterError(entry, error)\n                        }\n                    }\n                }\n            }\n\n            contentsToCopy.append(.endOfDir)\n            return contentsToCopy\n        }\n    }\n\n    /// This could be achieved through quite complicated special casing of the parallel copy. The\n    /// resulting code is far harder to read and debug, so this is kept as a special case.\n    private func copyDirectorySequential(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        // Strategy: find all needed items to copy/recurse into while the directory is open; defer\n        // actual copying and recursion until after the source directory has been closed to avoid\n        // consuming too many file descriptors.\n        let toCopy = try await self.prepareDirectoryForRecusiveCopy(\n            from: sourcePath,\n            to: destinationPath,\n            shouldProceedAfterError: shouldProceedAfterError,\n            shouldCopyItem: shouldCopyItem\n        )\n\n        for entry in toCopy {\n            switch entry {\n            case .endOfDir:\n                // Sequential cases doesn't need to worry about this, it uses simple recursion.\n                continue\n            case let .toCopy(source, destination):\n                // Note: The entry type could have changed between finding it and acting on it. This\n                // is inherent in file systems, just more likely in an asynchronous environment. We\n                // just accept those coming through as regular errors.\n                switch source.type {\n                case .regular:\n                    do {\n                        try await self.copyRegularFile(\n                            from: source.path,\n                            to: destination,\n                            replaceExisting: false\n                        )\n                    } catch {\n                        try await shouldProceedAfterError(source, error)\n                    }\n\n                case .symlink:\n                    do {\n                        try await self.copySymbolicLink(\n                            from: source.path,\n                            to: destination,\n                            replaceExisting: false\n                        )\n                    } catch {\n                        try await shouldProceedAfterError(source, error)\n                    }\n\n                case .directory:\n                    try await self.copyDirectorySequential(\n                        from: source.path,\n                        to: destination,\n                        shouldProceedAfterError: shouldProceedAfterError,\n                        shouldCopyItem: shouldCopyItem\n                    )\n\n                default:\n                    let error = FileSystemError(\n                        code: .unsupported,\n                        message: \"\"\"\n                            Can't copy '\\(source.path)' of type '\\(source.type)'; only regular \\\n                            files, symbolic links and directories can be copied.\n                            \"\"\",\n                        cause: nil,\n                        location: .here()\n                    )\n\n                    try await shouldProceedAfterError(source, error)\n                }\n            }\n        }\n    }\n\n    /// Copies the directory from `sourcePath` to `destinationPath`.\n    private func copyDirectory(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        strategy copyStrategy: CopyStrategy,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        switch copyStrategy.wrapped {\n        case .sequential:\n            return try await self.copyDirectorySequential(\n                from: sourcePath,\n                to: destinationPath,\n                shouldProceedAfterError: shouldProceedAfterError,\n                shouldCopyItem: shouldCopyItem\n            )\n        case let .parallel(maxDescriptors):\n            // Note that maxDescriptors was validated on construction of CopyStrategy. See notes on\n            // CopyStrategy about assumptions on descriptor use. For now, we take the worst case\n            // peak for every operation, which is two file descriptors. This keeps the downstream\n            // limiting code simple.\n            //\n            // We do not preclude the use of more granular limiting in the future (e.g. a directory\n            // scan requires only a single file descriptor). For now we just drop any excess\n            // remainder entirely.\n            let limitValue = maxDescriptors / 2\n            return try await self.copyDirectoryParallel(\n                from: sourcePath,\n                to: destinationPath,\n                maxConcurrentOperations: limitValue,\n                shouldProceedAfterError: shouldProceedAfterError,\n                shouldCopyItem: shouldCopyItem\n            )\n        }\n    }\n\n    /// Building block of the parallel directory copy implementation. Each invocation of this is\n    /// allowed to consume two file descriptors. Any further work (if any) should be sent to `yield`\n    /// for future processing.\n    func copySelfAndEnqueueChildren(\n        from: DirectoryEntry,\n        to: FilePath,\n        yield: @Sendable ([DirCopyItem]) -> Void,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        switch from.type {\n        case .regular:\n            do {\n                try await self.copyRegularFile(\n                    from: from.path,\n                    to: to,\n                    replaceExisting: false\n                )\n            } catch {\n                try await shouldProceedAfterError(from, error)\n            }\n\n        case .symlink:\n            do {\n                try await self.copySymbolicLink(\n                    from: from.path,\n                    to: to,\n                    replaceExisting: false\n                )\n            } catch {\n                try await shouldProceedAfterError(from, error)\n            }\n\n        case .directory:\n            do {\n                let addToQueue = try await self.prepareDirectoryForRecusiveCopy(\n                    from: from.path,\n                    to: to,\n                    shouldProceedAfterError: shouldProceedAfterError,\n                    shouldCopyItem: shouldCopyItem\n                )\n                yield(addToQueue)\n            } catch {\n                // The caller expects an end-of-dir regardless of whether there was an error or not.\n                yield([.endOfDir])\n                try await shouldProceedAfterError(from, error)\n            }\n\n        default:\n            let error = FileSystemError(\n                code: .unsupported,\n                message: \"\"\"\n                    Can't copy '\\(from.path)' of type '\\(from.type)'; only regular \\\n                    files, symbolic links and directories can be copied.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n\n            try await shouldProceedAfterError(from, error)\n        }\n    }\n\n    private func copyRegularFile(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._copyRegularFile(from: sourcePath, to: destinationPath, replaceExisting: replaceExisting).get()\n        }\n    }\n\n    private func _copyRegularFile(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool = false\n    ) -> Result<Void, FileSystemError> {\n        #if canImport(Darwin)\n        // COPYFILE_CLONE clones the file if possible and will fallback to doing a copy.\n        // COPYFILE_ALL is shorthand for:\n        //    COPYFILE_STAT | COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA\n        var flags = copyfile_flags_t(COPYFILE_CLONE) | copyfile_flags_t(COPYFILE_ALL)\n        if replaceExisting {\n            flags |= copyfile_flags_t(COPYFILE_UNLINK)\n        }\n        return Libc.copyfile(\n            from: sourcePath,\n            to: destinationPath,\n            state: nil,\n            flags: flags\n        ).mapError { errno in\n            FileSystemError.copyfile(\n                errno: errno,\n                from: sourcePath,\n                to: destinationPath,\n                location: .here()\n            )\n        }\n\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        if replaceExisting {\n            return self._copyRegularFileReplacing(from: sourcePath, to: destinationPath)\n        } else {\n            return self._copyFileContents(\n                from: sourcePath,\n                to: destinationPath\n            ) { destinationPath, writeOptions in\n                self._openFile(\n                    forWritingAt: destinationPath,\n                    options: writeOptions\n                ).mapError {\n                    FileSystemError(\n                        message: \"Can't copy '\\(sourcePath)' as '\\(destinationPath)' couldn't be opened.\",\n                        wrapping: $0\n                    )\n                }\n            }\n        }\n        #endif\n    }\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    private func _copyRegularFileReplacing(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath\n    ) -> Result<Void, FileSystemError> {\n        // on Linux platforms we implement replaceExisting by copying the source file into\n        // a temporary destination and then atomically renaming it, using the renameat2(2) system call.\n        let parentDirectory = destinationPath.removingLastComponent()\n        let destinationDirectoryHandle: DirectoryFileHandle\n        switch self._openDirectory(\n            at: parentDirectory.isEmpty ? FilePath(\".\") : parentDirectory,\n            // not following symlinks here to prevent TOCTOU attacks where the parent directory\n            // is replaced with a symlink pointing to an attacker-controlled location\n            options: OpenOptions.Directory(followSymbolicLinks: false)\n        ) {\n        case let .success(handle):\n            destinationDirectoryHandle = handle\n        case let .failure(error):\n            return .failure(\n                FileSystemError(\n                    message: \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory couldn't be opened.\",\n                    wrapping: error\n                )\n            )\n        }\n        defer {\n            _ = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                ._close(materialize: true)\n        }\n\n        guard\n            let destinationDirectoryFD = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                .descriptorIfAvailable()\n        else {\n            let error = FileSystemError(\n                code: .closed,\n                message:\n                    \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory descriptor unavailable.\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        let temporaryFilepath = FilePath(\".tmp-\" + String(randomAlphaNumericOfLength: 6))\n        let copyResult = self._copyFileContents(\n            from: sourcePath,\n            to: temporaryFilepath\n        ) { destinationPath, writeOptions in\n            destinationDirectoryFD.open(\n                atPath: destinationPath,\n                mode: .writeOnly,\n                options: writeOptions.descriptorOptions,\n                permissions: writeOptions.permissionsForRegularFile\n            )\n            .mapError { errno in\n                let openError = FileSystemError.open(\n                    \"openat\",\n                    error: errno,\n                    path: destinationPath,\n                    location: .here()\n                )\n                return FileSystemError(\n                    message: \"Can't copy '\\(sourcePath)' as '\\(destinationPath)' couldn't be opened.\",\n                    wrapping: openError\n                )\n            }\n            .map { fd in\n                let handle = SystemFileHandle(\n                    takingOwnershipOf: fd,\n                    path: destinationPath,\n                    threadPool: self.threadPool\n                )\n                return WriteFileHandle(wrapping: handle)\n            }\n        }\n        guard case .success = copyResult else {\n            _ = Syscall.unlinkat(path: temporaryFilepath, relativeTo: destinationDirectoryFD)\n            return copyResult\n        }\n\n        guard let destinationFilename = destinationPath.lastComponent else {\n            return .failure(\n                FileSystemError(\n                    code: .invalidArgument,\n                    message: \"Can't copy to '\\(destinationPath)', path has no filename component.\",\n                    cause: nil,\n                    location: .here()\n                )\n            )\n        }\n        let destinationFilepath = FilePath(root: nil, components: destinationFilename)\n\n        switch Syscall.rename(\n            from: temporaryFilepath,\n            relativeTo: destinationDirectoryFD,\n            to: destinationFilepath,\n            relativeTo: destinationDirectoryFD,\n            flags: []\n        ) {\n        case .failure(let errno):\n            _ = Syscall.unlinkat(path: temporaryFilepath, relativeTo: destinationDirectoryFD)\n            return .failure(\n                FileSystemError.rename(\n                    \"renameat2\",\n                    errno: errno,\n                    oldName: temporaryFilepath,\n                    newName: destinationFilepath,\n                    location: .here()\n                )\n            )\n        case .success:\n            return .success(())\n        }\n    }\n\n    private func _copyFileContents(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        openDestination: (FilePath, OpenOptions.Write) -> Result<WriteFileHandle, FileSystemError>\n    ) -> Result<Void, FileSystemError> {\n        func makeOnUnavailableError(\n            path: FilePath,\n            location: FileSystemError.SourceLocation\n        ) -> FileSystemError {\n            FileSystemError(\n                code: .closed,\n                message: \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', '\\(path)' is closed.\",\n                cause: nil,\n                location: location\n            )\n        }\n\n        let openSourceResult = self._openFile(\n            forReadingAt: sourcePath,\n            options: OpenOptions.Read(followSymbolicLinks: true)\n        ).mapError {\n            FileSystemError(\n                message: \"Can't copy '\\(sourcePath)', it couldn't be opened.\",\n                wrapping: $0\n            )\n        }\n\n        let source: ReadFileHandle\n        switch openSourceResult {\n        case let .success(handle):\n            source = handle\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        defer {\n            _ = source.fileHandle.systemFileHandle.sendableView._close(materialize: true)\n        }\n\n        let sourceInfo: FileInfo\n        switch source.fileHandle.systemFileHandle.sendableView._info() {\n        case let .success(info):\n            sourceInfo = info\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        let options = OpenOptions.Write(\n            existingFile: .none,\n            newFile: OpenOptions.NewFile(\n                permissions: sourceInfo.permissions,\n                transactionalCreation: false\n            )\n        )\n\n        let destination: WriteFileHandle\n        switch openDestination(destinationPath, options) {\n        case let .success(handle):\n            destination = handle\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        let copyResult: Result<Void, FileSystemError>\n        copyResult = source.fileHandle.systemFileHandle.sendableView._withUnsafeDescriptorResult { sourceFD in\n            destination.fileHandle.systemFileHandle.sendableView._withUnsafeDescriptorResult { destinationFD in\n                var offset = 0\n\n                while offset < sourceInfo.size {\n                    // sendfile(2) limits writes to 0x7ffff000 in size\n                    let size = min(Int(sourceInfo.size) - offset, 0x7fff_f000)\n                    let result = Syscall.sendfile(\n                        to: destinationFD,\n                        from: sourceFD,\n                        offset: offset,\n                        size: size\n                    ).mapError { errno in\n                        FileSystemError.sendfile(\n                            errno: errno,\n                            from: sourcePath,\n                            to: destinationPath,\n                            location: .here()\n                        )\n                    }\n\n                    switch result {\n                    case let .success(bytesCopied):\n                        offset += bytesCopied\n                    case let .failure(error):\n                        return .failure(error)\n                    }\n                }\n                return .success(())\n            } onUnavailable: {\n                makeOnUnavailableError(path: destinationPath, location: .here())\n            }\n        } onUnavailable: {\n            makeOnUnavailableError(path: sourcePath, location: .here())\n        }\n\n        let closeResult = destination.fileHandle.systemFileHandle.sendableView._close(materialize: true)\n        return copyResult.flatMap { closeResult }\n    }\n    #endif\n\n    private func copySymbolicLink(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool\n    ) async throws {\n        try await self.threadPool.runIfActive {\n            try self._copySymbolicLink(from: sourcePath, to: destinationPath, replaceExisting: replaceExisting).get()\n        }\n    }\n\n    private func _copySymbolicLink(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        replaceExisting: Bool\n    ) -> Result<Void, FileSystemError> {\n        if replaceExisting {\n            return self._copySymbolicLinkReplacing(from: sourcePath, to: destinationPath)\n        } else {\n            return self._destinationOfSymbolicLink(at: sourcePath).flatMap { linkDestination in\n                self._createSymbolicLink(at: destinationPath, withDestination: linkDestination)\n            }\n        }\n    }\n\n    private func _copySymbolicLinkReplacing(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath\n    ) -> Result<Void, FileSystemError> {\n        // There is no atomic symlink replace copy on either Darwin or Linux platforms\n        // so we copy the source symlink into a temporary symlink using `symlinkat` system call and then\n        // rename it into the destination symlink using the `renameatx_np(2)` on Darwin and\n        // `renameat2(2)` on Linux.\n        let parentDirectory = destinationPath.removingLastComponent()\n        let destinationDirectoryHandle: DirectoryFileHandle\n        switch self._openDirectory(\n            at: parentDirectory.isEmpty ? FilePath(\".\") : parentDirectory,\n            // not following symlinks here to prevent TOCTOU attacks where the parent directory\n            // is replaced with a symlink pointing to an attacker-controlled location\n            options: OpenOptions.Directory(followSymbolicLinks: false)\n        ) {\n        case let .success(handle):\n            destinationDirectoryHandle = handle\n        case let .failure(error):\n            return .failure(\n                FileSystemError(\n                    message: \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory couldn't be opened.\",\n                    wrapping: error\n                )\n            )\n        }\n        defer {\n            _ = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                ._close(materialize: true)\n        }\n\n        guard\n            let destinationDirectoryFD = destinationDirectoryHandle\n                .fileHandle\n                .systemFileHandle\n                .sendableView\n                .descriptorIfAvailable()\n        else {\n            let error = FileSystemError(\n                code: .closed,\n                message:\n                    \"Can't copy '\\(sourcePath)' to '\\(destinationPath)', directory descriptor unavailable.\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        let sourceSymlinkTarget: FilePath\n        switch self._destinationOfSymbolicLink(at: sourcePath) {\n        case let .success(target):\n            sourceSymlinkTarget = target\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        let temporarySymlinkPath = FilePath(\".tmp-link-\" + String(randomAlphaNumericOfLength: 6))\n        if case let .failure(errno) = Syscall.symlinkat(\n            to: sourceSymlinkTarget,\n            in: destinationDirectoryFD,\n            from: temporarySymlinkPath\n        ) {\n            let error = FileSystemError.symlink(\n                \"symlinkat\",\n                errno: errno,\n                link: temporarySymlinkPath,\n                target: sourceSymlinkTarget,\n                location: .here()\n            )\n            return .failure(error)\n        }\n\n        guard let destinationFilename = destinationPath.lastComponent else {\n            return .failure(\n                FileSystemError(\n                    code: .invalidArgument,\n                    message: \"Can't copy to '\\(destinationPath)', path has no filename component.\",\n                    cause: nil,\n                    location: .here()\n                )\n            )\n        }\n\n        let destinationFilePath = FilePath(root: nil, components: destinationFilename)\n        #if canImport(Darwin)\n        switch Syscall.rename(\n            from: temporarySymlinkPath,\n            relativeTo: destinationDirectoryFD,\n            to: destinationFilePath,\n            relativeTo: destinationDirectoryFD,\n            options: []\n        ) {\n        case .success:\n            return .success(())\n        case .failure(let errno):\n            _ = Syscall.unlinkat(path: temporarySymlinkPath, relativeTo: destinationDirectoryFD)\n            let error = FileSystemError.rename(\n                \"renameatx_np\",\n                errno: errno,\n                oldName: temporarySymlinkPath,\n                newName: destinationFilePath,\n                location: .here()\n            )\n            return .failure(error)\n        }\n        #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        switch Syscall.rename(\n            from: temporarySymlinkPath,\n            relativeTo: destinationDirectoryFD,\n            to: destinationFilePath,\n            relativeTo: destinationDirectoryFD,\n            flags: []\n        ) {\n        case .success:\n            return .success(())\n        case .failure(let errno):\n            _ = Syscall.unlinkat(path: temporarySymlinkPath, relativeTo: destinationDirectoryFD)\n            let error = FileSystemError.rename(\n                \"renameat2\",\n                errno: errno,\n                oldName: temporarySymlinkPath,\n                newName: destinationFilePath,\n                location: .here()\n            )\n            return .failure(error)\n        }\n        #endif\n    }\n\n    @_spi(Testing)\n    public func removeOneItem(\n        at path: FilePath,\n        function: String = #function,\n        file: String = #fileID,\n        line: Int = #line\n    ) async throws -> Int {\n        try await self.threadPool.runIfActive {\n            switch Libc.remove(path) {\n            case .success:\n                return 1\n            case .failure(.noSuchFileOrDirectory):\n                return 0\n            case .failure(let errno):\n                throw FileSystemError.remove(\n                    errno: errno,\n                    path: path,\n                    location: .init(function: function, file: file, line: line)\n                )\n            }\n        }\n    }\n\n    private enum MoveResult {\n        case moved\n        case differentLogicalDevices\n    }\n\n    private func _moveItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath\n    ) -> Result<MoveResult, FileSystemError> {\n        // Check that the destination doesn't exist. 'rename' will remove it otherwise!\n        switch self._info(forFileAt: destinationPath, infoAboutSymbolicLink: true) {\n        case .success(.none):\n            // Doesn't exist: continue\n            ()\n\n        case .success(.some):\n            let fileSystemError = FileSystemError(\n                code: .fileAlreadyExists,\n                message: \"\"\"\n                    Unable to move '\\(sourcePath)' to '\\(destinationPath)', the destination path \\\n                    already exists.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n\n        case let .failure(error):\n            let fileSystemError = FileSystemError(\n                message: \"\"\"\n                    Unable to move '\\(sourcePath)' to '\\(destinationPath)', could not determine \\\n                    whether the destination path exists or not.\n                    \"\"\",\n                wrapping: error\n            )\n            return .failure(fileSystemError)\n        }\n\n        switch Syscall.rename(from: sourcePath, to: destinationPath) {\n        case .success:\n            return .success(.moved)\n\n        case .failure(.improperLink):\n            // The two paths are on different logical devices; copy and then remove the original.\n            return .success(.differentLogicalDevices)\n\n        case let .failure(errno):\n            let error = FileSystemError.rename(\n                \"rename\",\n                errno: errno,\n                oldName: sourcePath,\n                newName: destinationPath,\n                location: .here()\n            )\n            return .failure(error)\n        }\n    }\n\n    private func parseTemporaryDirectoryTemplate(\n        _ template: FilePath\n    ) -> Result<(FilePath, String, Int), FileSystemError> {\n        // Check whether template is valid (i.e. has a `lastComponent`).\n        guard let lastComponentPath = template.lastComponent else {\n            let fileSystemError = FileSystemError(\n                code: .invalidArgument,\n                message: \"\"\"\n                    Can't create temporary directory, the template ('\\(template)') is invalid. \\\n                    The template should be a file path ending in at least three 'X's.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n        }\n\n        let lastComponent = lastComponentPath.string\n\n        // Finding the index of the last non-'X' character in `lastComponent.string` and advancing\n        // it by one.\n        let prefix: String\n        var index = lastComponent.lastIndex(where: { $0 != \"X\" })\n        if index != nil {\n            lastComponent.formIndex(after: &(index!))\n            prefix = String(lastComponent[..<index!])\n        } else if lastComponent.first == \"X\" {\n            // The directory name from the template contains only 'X's.\n            prefix = \"\"\n            index = lastComponent.startIndex\n        } else {\n            let fileSystemError = FileSystemError(\n                code: .invalidArgument,\n                message: \"\"\"\n                    Can't create temporary directory, the template ('\\(template)') is invalid. \\\n                    The template must end in at least three 'X's.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n        }\n\n        // Computing the number of 'X's.\n        let suffixLength = lastComponent.distance(from: index!, to: lastComponent.endIndex)\n        guard suffixLength >= 3 else {\n            let fileSystemError = FileSystemError(\n                code: .invalidArgument,\n                message: \"\"\"\n                    Can't create temporary directory, the template ('\\(template)') is invalid. \\\n                    The template must end in at least three 'X's.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n            return .failure(fileSystemError)\n        }\n\n        return .success((template.removingLastComponent(), prefix, suffixLength))\n    }\n\n    private func _createTemporaryDirectory(\n        template: FilePath\n    ) -> Result<FilePath, FileSystemError> {\n        let prefix: String\n        let root: FilePath\n        let suffixLength: Int\n\n        let parseResult = self.parseTemporaryDirectoryTemplate(template)\n        switch parseResult {\n        case let .success((parseRoot, parsePrefix, parseSuffixLength)):\n            root = parseRoot\n            prefix = parsePrefix\n            suffixLength = parseSuffixLength\n        case let .failure(error):\n            return .failure(error)\n        }\n\n        for _ in 1...16 {\n            let name = prefix + String(randomAlphaNumericOfLength: suffixLength)\n\n            // Trying to create the directory.\n            let finalPath = root.appending(name)\n            let createDirectoriesResult = self._createDirectory(\n                at: finalPath,\n                withIntermediateDirectories: true,\n                permissions: FilePermissions.defaultsForDirectory\n            )\n            switch createDirectoriesResult {\n            case .success:\n                return .success(finalPath)\n            case let .failure(error):\n                if let systemCallError = error.cause as? FileSystemError.SystemCallError {\n                    switch systemCallError.errno {\n                    // If the file at the generated path already exists, we generate a new file\n                    // path.\n                    case .fileExists, .isDirectory:\n                        break\n                    default:\n                        let fileSystemError = FileSystemError(\n                            message: \"Unable to create temporary directory '\\(template)'.\",\n                            wrapping: error\n                        )\n                        return .failure(fileSystemError)\n                    }\n                } else {\n                    let fileSystemError = FileSystemError(\n                        message: \"Unable to create temporary directory '\\(template)'.\",\n                        wrapping: error\n                    )\n                    return .failure(fileSystemError)\n                }\n            }\n        }\n        let fileSystemError = FileSystemError(\n            code: .unknown,\n            message: \"\"\"\n                Could not create a temporary directory from the provided template ('\\(template)'). \\\n                Try adding more 'X's at the end of the template.\n                \"\"\",\n            cause: nil,\n            location: .here()\n        )\n        return .failure(fileSystemError)\n    }\n\n    func _createSymbolicLink(\n        at linkPath: FilePath,\n        withDestination destinationPath: FilePath\n    ) -> Result<Void, FileSystemError> {\n        Syscall.symlink(to: destinationPath, from: linkPath).mapError { errno in\n            FileSystemError.symlink(\n                \"symlink\",\n                errno: errno,\n                link: linkPath,\n                target: destinationPath,\n                location: .here()\n            )\n        }\n    }\n\n    func _destinationOfSymbolicLink(at path: FilePath) -> Result<FilePath, FileSystemError> {\n        Syscall.readlink(at: path).mapError { errno in\n            FileSystemError.readlink(\n                errno: errno,\n                path: path,\n                location: .here()\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileSystemError+Syscall.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#endif\n\nextension FileSystemError {\n    /// Creates a ``FileSystemError`` by constructing a ``SystemCallError`` as the cause.\n    internal init(\n        code: Code,\n        message: String,\n        systemCall: String,\n        errno: Errno,\n        location: SourceLocation\n    ) {\n        self.init(\n            code: code,\n            message: message,\n            cause: SystemCallError(systemCall: systemCall, errno: errno),\n            location: location\n        )\n    }\n}\n\nextension FileSystemError {\n    /// Create a file system error appropriate for the `stat`/`lstat`/`fstat` system calls.\n    @_spi(Testing)\n    public static func stat(\n        _ name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 fstat'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Unable to get information about '\\(path)', the file is closed.\"\n        default:\n            code = .unknown\n            message = \"Unable to get information about '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public static func fchmod(\n        operation: SystemFileHandle.UpdatePermissionsOperation,\n        operand: FilePermissions,\n        permissions: FilePermissions,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let message: String\n        let code: FileSystemError.Code\n\n        // See: 'man 2 fchmod'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not \\(operation) permissions '\\(operand)', '\\(path)' is closed.\"\n\n        case .invalidArgument:\n            // Permissions are invalid so display the raw value in octal.\n            let rawPermissions = String(permissions.rawValue, radix: 0o10)\n            let op: String\n            switch operation {\n            case .set:\n                op = \"set\"\n            case .add:\n                op = \"added\"\n            case .remove:\n                op = \"removed\"\n            }\n            code = .invalidArgument\n            message = \"\"\"\n                Invalid permissions ('\\(rawPermissions)') could not be \\(op) for file '\\(path)'.\n                \"\"\"\n\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"\"\"\n                Not permitted to \\(operation) permissions '\\(operand)' for file '\\(path)', \\\n                the effective user ID does not match the owner of the file and the effective \\\n                user ID is not the super-user.\n                \"\"\"\n\n        default:\n            code = .unknown\n            message = \"Could not \\(operation) permissions '\\(operand)' to '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fchmod\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func flistxattr(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not list extended attributes, '\\(path)' is closed.\"\n\n        case .notSupported:\n            code = .unsupported\n            message = \"Extended attributes are disabled or not supported by the filesystem.\"\n\n        case .notPermitted:\n            code = .unsupported\n            message = \"Extended attributes are not supported by '\\(path)'.\"\n\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"Not permitted to list extended attributes for '\\(path)'.\"\n\n        default:\n            code = .unknown\n            message = \"Could not to list extended attributes for '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"flistxattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fgetxattr(\n        attribute name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"\"\"\n                Could not get value for extended attribute ('\\(name)'), '\\(path)' is closed.\n                \"\"\"\n        case .notSupported:\n            code = .unsupported\n            message = \"Extended attributes are disabled or not supported by the filesystem.\"\n        #if canImport(Darwin)\n        case .fileNameTooLong:\n            code = .invalidArgument\n            message = \"\"\"\n                Length of UTF-8 extended attribute name (\\(name.utf8.count)) is greater \\\n                than the limit (\\(XATTR_MAXNAMELEN)). Use a shorter attribute name.\n                \"\"\"\n        #endif\n        default:\n            code = .unknown\n            message = \"Could not get value for extended attribute ('\\(name)') for '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fgetxattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fsetxattr(\n        attribute name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 fsetxattr'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"\"\"\n                Could not set value for extended attribute ('\\(name)'), '\\(path)' is closed.\n                \"\"\"\n\n        case .notSupported:\n            code = .unsupported\n            message = \"\"\"\n                Extended attributes are disabled or not supported by the filesystem.\n                \"\"\"\n\n        #if canImport(Darwin)\n        case .fileNameTooLong:\n            code = .invalidArgument\n            message = \"\"\"\n                Length of UTF-8 extended attribute name (\\(name.utf8.count)) is greater \\\n                than the limit limit (\\(XATTR_MAXNAMELEN)). Use a shorter attribute \\\n                name.\n                \"\"\"\n        #endif\n\n        case .invalidArgument:\n            code = .invalidArgument\n            message = \"\"\"\n                Extended attribute name ('\\(name)') must be a valid UTF-8 string.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"\"\"\n                Could not set value for extended attribute ('\\(name)') for '\\(path)'.\n                \"\"\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fsetxattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fremovexattr(\n        attribute name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 fremovexattr'\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not remove extended attribute ('\\(name)'), '\\(path)' is closed.\"\n\n        case .notSupported:\n            code = .unsupported\n            message = \"Extended attributes are disabled or not supported by the filesystem.\"\n\n        #if canImport(Darwin)\n        case .fileNameTooLong:\n            code = .invalidArgument\n            message = \"\"\"\n                Length of UTF-8 extended attribute name (\\(name.utf8.count)) is greater \\\n                than the limit (\\(XATTR_MAXNAMELEN)). Use a shorter attribute name.\n                \"\"\"\n        #endif\n\n        default:\n            code = .unknown\n            message = \"Could not remove extended attribute ('\\(name)') from '\\(path)'\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fremovexattr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fsync(\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not synchronize file, '\\(path)' is closed.\"\n        case .ioError:\n            code = .io\n            message = \"An I/O error occurred while synchronizing '\\(path)'.\"\n        default:\n            code = .unknown\n            message = \"Could not synchronize file '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"fsync\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func dup(error: Error, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Unable to duplicate descriptor of closed handle for '\\(path)'.\"\n            default:\n                code = .unknown\n                message = \"Unable to duplicate descriptor of handle for '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: \"dup\", errno: errno)\n        } else {\n            code = .unknown\n            message = \"Unable to duplicate descriptor of handle for '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func ftruncate(error: Error, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Can't resize '\\(path)', it's closed.\"\n            case .fileTooLarge:\n                code = .invalidArgument\n                message = \"The requested size for '\\(path)' is too large.\"\n            case .invalidArgument:\n                code = .invalidArgument\n                message = \"The requested size for '\\(path)' is negative, therefore invalid.\"\n            default:\n                code = .unknown\n                message = \"Unable to resize '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: \"ftruncate\", errno: errno)\n        } else {\n            code = .unknown\n            message = \"Unable to resize '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func close(error: Error, path: FilePath, location: SourceLocation) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        // See: 'man 2 close'\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"File already closed or file descriptor was invalid ('\\(path)').\"\n            case .ioError:\n                code = .io\n                message = \"I/O error during close, some writes to '\\(path)' may have failed.\"\n            default:\n                code = .unknown\n                message = \"Error closing file '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: \"close\", errno: errno)\n        } else {\n            code = .unknown\n            message = \"Error closing file '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public enum ReadSyscall: String, Sendable {\n        case read\n        case pread\n    }\n\n    @_spi(Testing)\n    public static func read(\n        usingSyscall syscall: ReadSyscall,\n        error: Error,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        // We expect an Errno as 'swift-system' uses result types under-the-hood,\n        // but don't require that in case something changes.\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Could not read from closed file '\\(path)'.\"\n            case .ioError:\n                code = .io\n                message = \"\"\"\n                    Could not read from file ('\\(path)'); an I/O error occurred while reading \\\n                    from the file system.\n                    \"\"\"\n            case .illegalSeek:\n                code = .unsupported\n                message = \"File is not seekable: '\\(path)'.\"\n            default:\n                code = .unknown\n                message = \"Could not read from file '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: syscall.rawValue, errno: errno)\n        } else {\n            code = .unknown\n            message = \"Could not read from file '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public enum WriteSyscall: String, Sendable {\n        case write\n        case pwrite\n    }\n\n    @_spi(Testing)\n    public static func write(\n        usingSyscall syscall: WriteSyscall,\n        error: Error,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        // We expect an Errno as 'swift-system' uses result types under-the-hood,\n        // but don't require that in case something changes.\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Could not write to closed file '\\(path)'.\"\n            case .ioError:\n                code = .io\n                message = \"\"\"\n                    Could not write to file ('\\(path)'); an I/O error occurred while writing to \\\n                    the file system.\n                    \"\"\"\n            case .illegalSeek:\n                code = .unsupported\n                message = \"File is not seekable: '\\(path)'.\"\n            default:\n                code = .unknown\n                message = \"Could not write to file.\"\n            }\n            cause = SystemCallError(systemCall: syscall.rawValue, errno: errno)\n        } else {\n            code = .unknown\n            message = \"Could not write to file.\"\n            cause = error\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: cause,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fdopendir(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unknown,\n            message: \"Unable to open directory stream for '\\(path)'.\",\n            systemCall: \"fdopendir\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func readdir(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unknown,\n            message: \"Unable to read directory stream for '\\(path)'.\",\n            systemCall: \"readdir\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func ftsRead(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unknown,\n            message: \"Unable to read FTS stream for '\\(path)'.\",\n            systemCall: \"fts_read\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func open(\n        _ name: String,\n        error: Error,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n        let cause: Error\n\n        if let errno = error as? Errno {\n            switch errno {\n            case .badFileDescriptor:\n                code = .closed\n                message = \"Unable to open file at path '\\(path)', the descriptor is closed.\"\n            case .permissionDenied:\n                code = .permissionDenied\n                message = \"Unable to open file at path '\\(path)', permissions denied.\"\n            case .fileExists:\n                code = .fileAlreadyExists\n                message = \"\"\"\n                    Unable to create file at path '\\(path)', no existing file options were set \\\n                    which implies that no file should exist but a file already exists at the \\\n                    specified path.\n                    \"\"\"\n            case .ioError:\n                code = .io\n                message = \"\"\"\n                    Unable to create file at path '\\(path)', an I/O error occurred while \\\n                    creating the file.\n                    \"\"\"\n            case .tooManyOpenFiles:\n                code = .unavailable\n                message = \"\"\"\n                    Unable to open file at path '\\(path)', too many file descriptors are open.\n                    \"\"\"\n            case .noSuchFileOrDirectory:\n                code = .notFound\n                message = \"\"\"\n                    Unable to open or create file at path '\\(path)', either a component of the \\\n                    path did not exist or the named file to be opened did not exist.\n                    \"\"\"\n            case .notDirectory:\n                code = .notFound\n                message = \"\"\"\n                    Unable to open or create file at path '\\(path)', an intermediate component of \\\n                    the path was not a directory.\n                    \"\"\"\n            case .tooManySymbolicLinkLevels:\n                code = .invalidArgument\n                message = \"\"\"\n                    Can't open file at path '\\(path)', the target is a symbolic link and \\\n                    'followSymbolicLinks' was set to 'false'.\n                    \"\"\"\n            default:\n                code = .unknown\n                message = \"Unable to open file at path '\\(path)'.\"\n            }\n            cause = SystemCallError(systemCall: name, errno: errno)\n        } else {\n            code = .unknown\n            message = \"Unable to open file at path '\\(path)'.\"\n            cause = error\n        }\n\n        return FileSystemError(code: code, message: message, cause: cause, location: location)\n    }\n\n    @_spi(Testing)\n    public static func mkdir(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permissions to create a directory at '\\(path)'. Search permissions \\\n                denied for a component of the path or write permission denied for the parent \\\n                directory.\n                \"\"\"\n        case .isDirectory:\n            code = .invalidArgument\n            message = \"Can't create directory, '\\(path)' is the root directory.\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"Can't create directory, the pathname '\\(path)' already exists.\"\n        case .notDirectory:\n            code = .invalidArgument\n            message = \"Can't create directory, a component of '\\(path)' is not a directory.\"\n        case .noSuchFileOrDirectory:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't create directory, a component of '\\(path)' does not exist. Ensure all \\\n                parent directories exist or set 'withIntermediateDirectories' to 'true' when \\\n                calling 'createDirectory(at:withIntermediateDirectories:permissions)'.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"An I/O error occurred when the directory at '\\(path)'.\"\n        default:\n            code = .unknown\n            message = \"\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"mkdir\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func rename(\n        _ name: String,\n        errno: Errno,\n        oldName: FilePath,\n        newName: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permissions to rename '\\(oldName)' to '\\(newName)'. Search \\\n                permissions were denied on a component of either path, or write permissions were \\\n                denied on the parent directory of either path.\n                \"\"\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"Can't rename '\\(oldName)' to '\\(newName)' as it already exists.\"\n        case .invalidArgument:\n            code = .invalidArgument\n            if oldName == \".\" || oldName == \"..\" {\n                message = \"\"\"\n                    Can't rename '\\(oldName)' to '\\(newName)', '.' and '..' can't be renamed.\n                    \"\"\"\n            } else {\n                message = \"\"\"\n                    Can't rename '\\(oldName)', it may be a parent directory of '\\(newName)'.\n                    \"\"\"\n            }\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"\"\"\n                Can't rename '\\(oldName)' to '\\(newName)', a component of '\\(oldName)' does \\\n                not exist.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't rename '\\(oldName)' to '\\(newName)', an I/O error occurred while making \\\n                or updating a directory entry.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't rename '\\(oldName)' to '\\(newName)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func remove(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permissions to remove '\\(path)'. Search permissions denied \\\n                on a component of the path or write permission denied on the directory \\\n                containing the item to be removed.\n                \"\"\"\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"\"\"\n                Insufficient permission to remove '\\(path)', the effective user ID of the \\\n                process is not permitted to remove the file.\n                \"\"\"\n        case .resourceBusy:\n            code = .unavailable\n            message = \"\"\"\n                Can't remove '\\(path)', it may be being used by another process or is the mount \\\n                point for a mounted file system.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't remove '\\(path)', an I/O error occurred while deleting its directory entry.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't remove '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"remove\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func symlink(\n        _ name: String,\n        errno: Errno,\n        link: FilePath,\n        target: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', write access to the \\\n                directory containing the link was denied or one of the directories in its path \\\n                denied search permissions.\n                \"\"\"\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', the file system \\\n                containing '\\(link)' doesn't support the creation of symbolic links.\n                \"\"\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', '\\(link)' already exists.\n                \"\"\"\n        case .noSuchFileOrDirectory:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', a component of '\\(link)' \\\n                does not exist or is a dangling symbolic link.\n                \"\"\"\n        case .notDirectory:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', a component of '\\(link)' \\\n                is not a directory.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't create symbolic link '\\(link)' to '\\(target)', an I/O error occurred.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't create symbolic link '\\(link)' to '\\(target)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func readlink(errno: Errno, path: FilePath, location: SourceLocation) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't read symbolic link at '\\(path)'; search permission was denied for a \\\n                component in its prefix.\n                \"\"\"\n        case .invalidArgument:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't read '\\(path)'; it is not a symbolic link.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                Can't read symbolic link at '\\(path)'; an I/O error occurred.\n                \"\"\"\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"\"\"\n                Can't read symbolic link, no file exists at '\\(path)'.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't read symbolic link at '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"readlink\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func link(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 link'\n        switch errno {\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"\"\"\n                Can't link '\\(sourcePath)' to '\\(destinationPath)', a file already exists \\\n                at '\\(destinationPath)'.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"I/O error while linking '\\(sourcePath)' to '\\(destinationPath)'.\"\n        default:\n            code = .unknown\n            message = \"Error linking '\\(sourcePath)' to '\\(destinationPath)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: SystemCallError(systemCall: \"linkat\", errno: errno),\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func unlink(\n        _ name: String,\n        errno: Errno,\n        path: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: FileSystemError.Code\n        let message: String\n\n        // See: 'man 2 unlink'\n        switch errno {\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Search permission denied for a component of the path ('\\(path)') or write \\\n                permission denied on the directory containing the link to be removed.\n                \"\"\"\n        case .ioError:\n            code = .io\n            message = \"I/O error while unlinking '\\(path)'.\"\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"The named file ('\\(path)') doesn't exist.\"\n        case .notPermitted:\n            code = .permissionDenied\n            message = \"Insufficient permissions to unlink '\\(path)'.\"\n        default:\n            code = .unknown\n            message = \"Error unlinking '\\(path)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            cause: SystemCallError(systemCall: name, errno: errno),\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func getcwd(errno: Errno, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unavailable,\n            message: \"Can't get current working directory.\",\n            systemCall: \"getcwd\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func confstr(name: String, errno: Errno, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unavailable,\n            message: \"Can't get configuration value for '\\(name)'.\",\n            systemCall: \"confstr\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func getpwuid_r(errno: Errno, location: SourceLocation) -> Self {\n        FileSystemError(\n            code: .unavailable,\n            message: \"Can't get home directory for current user.\",\n            systemCall: \"getpwuid_r\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func fcopyfile(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        Self._copyfile(\n            \"fcopyfile\",\n            errno: errno,\n            from: sourcePath,\n            to: destinationPath,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func copyfile(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        Self._copyfile(\n            \"copyfile\",\n            errno: errno,\n            from: sourcePath,\n            to: destinationPath,\n            location: location\n        )\n    }\n\n    private static func _copyfile(\n        _ name: String,\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> Self {\n        let code: Code\n        let message: String\n\n        switch errno {\n        case .notSupported:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't copy file from '\\(sourcePath)' to '\\(destinationPath)', the item to copy is \\\n                not a directory, symbolic link or regular file.\n                \"\"\"\n        case .permissionDenied:\n            code = .permissionDenied\n            message = \"\"\"\n                Can't copy file, search permission was denied for a component of the path \\\n                prefix for the source ('\\(sourcePath)') or destination ('\\(destinationPath)'), \\\n                or write permission was denied for a component of the path prefix for the source.\n                \"\"\"\n        case .invalidArgument:\n            code = .invalidArgument\n            message = \"\"\"\n                Can't copy file from '\\(sourcePath)' to '\\(destinationPath)', the destination \\\n                path already exists.\n                \"\"\"\n        case .fileExists:\n            code = .fileAlreadyExists\n            message = \"\"\"\n                Unable to create file at path '\\(destinationPath)', no existing file options were set \\\n                which implies that no file should exist but a file already exists at the \\\n                specified path.\n                \"\"\"\n        case .tooManyOpenFiles:\n            code = .unavailable\n            message = \"\"\"\n                Unable to open the source ('\\(sourcePath)') or destination ('\\(destinationPath)') files, \\\n                too many file descriptors are open.\n                \"\"\"\n        case .noSuchFileOrDirectory:\n            code = .notFound\n            message = \"\"\"\n                Unable to open or create file at path '\\(sourcePath)', either a component of the \\\n                path did not exist or the named file to be opened did not exist.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't copy file from '\\(sourcePath)' to '\\(destinationPath)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: name,\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func sendfile(\n        errno: Errno,\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        location: SourceLocation\n    ) -> FileSystemError {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .ioError:\n            code = .io\n            message = \"\"\"\n                An I/O error occurred while reading from '\\(sourcePath)', can't copy to \\\n                '\\(destinationPath)'.\n                \"\"\"\n        case .noMemory:\n            code = .io\n            message = \"\"\"\n                Insufficient memory to read from '\\(sourcePath)', can't copy to \\\n                '\\(destinationPath)'.\n                \"\"\"\n        default:\n            code = .unknown\n            message = \"Can't copy file from '\\(sourcePath)' to '\\(destinationPath)'.\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"sendfile\",\n            errno: errno,\n            location: location\n        )\n    }\n\n    @_spi(Testing)\n    public static func futimens(\n        errno: Errno,\n        path: FilePath,\n        lastAccessTime: FileInfo.Timespec?,\n        lastDataModificationTime: FileInfo.Timespec?,\n        location: SourceLocation\n    ) -> FileSystemError {\n        let code: FileSystemError.Code\n        let message: String\n\n        switch errno {\n        case .permissionDenied, .notPermitted:\n            code = .permissionDenied\n            message = \"Not permitted to change last access or last data modification times for \\(path).\"\n\n        case .readOnlyFileSystem:\n            code = .unsupported\n            message =\n                \"Not permitted to change last access or last data modification times for \\(path): this is a read-only file system.\"\n\n        case .badFileDescriptor:\n            code = .closed\n            message = \"Could not change last access or last data modification dates for \\(path): file is closed.\"\n\n        default:\n            code = .unknown\n            message = \"Could not change last access or last data modification dates for \\(path).\"\n        }\n\n        return FileSystemError(\n            code: code,\n            message: message,\n            systemCall: \"futimens\",\n            errno: errno,\n            location: location\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileSystemError.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// An error thrown as a result of interaction with the file system.\n///\n/// All errors have a high-level ``FileSystemError/Code-swift.struct`` which identifies the domain\n/// of the error. For example an operation performed on a ``FileHandleProtocol`` which has already been\n/// closed will result in a ``FileSystemError/Code-swift.struct/closed`` error code. Errors also\n/// include a message describing what went wrong and how to remedy it (if applicable). The\n/// ``FileSystemError/message`` is not static and may include dynamic information such as the path\n/// of the file for which the operation failed, for example.\n///\n/// Errors may have a ``FileSystemError/cause``, an error which caused the operation to\n/// fail which may be platform specific.\npublic struct FileSystemError: Error, Sendable {\n    /// A high-level error code to provide broad a classification.\n    public var code: Code\n\n    /// A message describing what went wrong and how it may be remedied.\n    public var message: String\n\n    /// An error which caused the operation to fail. This may include additional details\n    /// about the root cause of the failure.\n    public var cause: Error?\n\n    /// The location from which this error was thrown.\n    public var location: SourceLocation\n\n    public init(\n        code: Code,\n        message: String,\n        cause: Error?,\n        location: SourceLocation\n    ) {\n        self.code = code\n        self.message = message\n        self.cause = cause\n        self.location = location\n    }\n\n    /// Creates a ``FileSystemError`` by wrapping the given `cause` and its location and code.\n    internal init(message: String, wrapping cause: FileSystemError) {\n        self.init(code: cause.code, message: message, cause: cause, location: cause.location)\n    }\n}\n\nextension FileSystemError: CustomStringConvertible {\n    public var description: String {\n        if let cause = self.cause {\n            return \"\\(self.code): \\(self.message) (\\(cause))\"\n        } else {\n            return \"\\(self.code): \\(self.message)\"\n        }\n    }\n}\n\nextension FileSystemError: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        if let cause = self.cause {\n            return \"\"\"\n                \\(String(reflecting: self.code)): \\(String(reflecting: self.message)) \\\n                (\\(String(reflecting: cause)))\n                \"\"\"\n        } else {\n            return \"\\(String(reflecting: self.code)): \\(String(reflecting: self.message))\"\n        }\n    }\n}\n\nextension FileSystemError {\n    private func detailedDescriptionLines() -> [String] {\n        // Build up a tree-like description of the error. This allows nested causes to be formatted\n        // correctly, especially when they are also FileSystemErrors.\n        //\n        // An example is:\n        //\n        //  FileSystemError: Closed\n        //  ├─ Reason: Unable to open file at path 'foo.swift', the descriptor is closed.\n        //  ├─ Cause: 'openat' system call failed with '(9) Bad file descriptor'.\n        //  └─ Source location: openFile(forReadingAt:_:) (FileSystem.swift:314)\n        var lines = [\n            \"FileSystemError: \\(self.code)\",\n            \"├─ Reason: \\(self.message)\",\n        ]\n\n        if let error = self.cause as? FileSystemError {\n            lines.append(\"├─ Cause:\")\n            let causeLines = error.detailedDescriptionLines()\n            // We know this will never be empty.\n            lines.append(\"│  └─ \\(causeLines.first!)\")\n            lines.append(contentsOf: causeLines.dropFirst().map { \"│     \\($0)\" })\n        } else if let error = self.cause {\n            lines.append(\"├─ Cause: \\(String(reflecting: error))\")\n        }\n\n        lines.append(\n            \"└─ Source location: \\(self.location.function) (\\(self.location.file):\\(self.location.line))\"\n        )\n\n        return lines\n    }\n\n    /// A detailed multi-line description of the error.\n    ///\n    /// - Returns: A multi-line description of the error.\n    public func detailedDescription() -> String {\n        self.detailedDescriptionLines().joined(separator: \"\\n\")\n    }\n}\n\nextension FileSystemError {\n    /// A high level indication of the kind of error being thrown.\n    public struct Code: Hashable, Sendable, CustomStringConvertible {\n        private enum Wrapped: Hashable, Sendable, CustomStringConvertible {\n            case closed\n            case invalidArgument\n            case io\n            case permissionDenied\n            case notEmpty\n            case notFound\n            case resourceExhausted\n            case unavailable\n            case unknown\n            case unsupported\n            case fileAlreadyExists\n\n            var description: String {\n                switch self {\n                case .closed:\n                    return \"Closed\"\n                case .invalidArgument:\n                    return \"Invalid argument\"\n                case .io:\n                    return \"I/O error\"\n                case .permissionDenied:\n                    return \"Permission denied\"\n                case .resourceExhausted:\n                    return \"Resource exhausted\"\n                case .notEmpty:\n                    return \"Not empty\"\n                case .notFound:\n                    return \"Not found\"\n                case .unavailable:\n                    return \"Unavailable\"\n                case .unknown:\n                    return \"Unknown\"\n                case .unsupported:\n                    return \"Unsupported\"\n                case .fileAlreadyExists:\n                    return \"File already exists\"\n                }\n            }\n        }\n\n        public var description: String {\n            String(describing: self.code)\n        }\n\n        private var code: Wrapped\n        private init(_ code: Wrapped) {\n            self.code = code\n        }\n\n        /// An operation on the file could not be performed because the file is closed\n        /// (or detached).\n        public static var closed: Self {\n            Self(.closed)\n        }\n\n        /// A provided argument was not valid for the operation.\n        public static var invalidArgument: Self {\n            Self(.invalidArgument)\n        }\n\n        /// An I/O error occurred.\n        public static var io: Self {\n            Self(.io)\n        }\n\n        /// The caller did not have sufficient permission to perform the operation.\n        public static var permissionDenied: Self {\n            Self(.permissionDenied)\n        }\n\n        /// A required resource was exhausted.\n        public static var resourceExhausted: Self {\n            Self(.resourceExhausted)\n        }\n\n        /// The directory wasn't empty.\n        public static var notEmpty: Self {\n            Self(.notEmpty)\n        }\n\n        /// The file could not be found.\n        public static var notFound: Self {\n            Self(.notFound)\n        }\n\n        /// The file system is not currently available, for example if the executor\n        /// is not running.\n        public static var unavailable: Self {\n            Self(.unavailable)\n        }\n\n        /// The error is not known or may not have an appropriate classification. See\n        /// ``FileSystemError/cause`` for more information about the error.\n        public static var unknown: Self {\n            Self(.unknown)\n        }\n\n        /// The operation is not supported or is not enabled.\n        public static var unsupported: Self {\n            Self(.unsupported)\n        }\n\n        /// The file already exists.\n        public static var fileAlreadyExists: Self {\n            Self(.fileAlreadyExists)\n        }\n    }\n\n    /// A location within source code.\n    public struct SourceLocation: Sendable, Hashable {\n        /// The function in which the error was thrown.\n        public var function: String\n\n        /// The file in which the error was thrown.\n        public var file: String\n\n        /// The line on which the error was thrown.\n        public var line: Int\n\n        public init(function: String, file: String, line: Int) {\n            self.function = function\n            self.file = file\n            self.line = line\n        }\n\n        internal static func here(\n            function: String = #function,\n            file: String = #fileID,\n            line: Int = #line\n        ) -> Self {\n            SourceLocation(function: function, file: file, line: line)\n        }\n    }\n}\n\nextension FileSystemError {\n    /// An error resulting from a system call.\n    public struct SystemCallError: Error, Hashable, CustomStringConvertible {\n        /// The name of the system call which produced the error.\n        public var systemCall: String\n        /// The errno set by the system call.\n        public var errno: Errno\n\n        public init(systemCall: String, errno: Errno) {\n            self.systemCall = systemCall\n            self.errno = errno\n        }\n\n        public var description: String {\n            \"'\\(self.systemCall)' system call failed with '(\\(self.errno.rawValue)) \\(self.errno)'.\"\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileSystemProtocol.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// The interface for interacting with a file system.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic protocol FileSystemProtocol: Sendable {\n    /// The type of ``ReadableFileHandleProtocol`` to return when opening files for reading.\n    associatedtype ReadFileHandle: ReadableFileHandleProtocol\n\n    /// The type of ``WritableFileHandleProtocol`` to return when opening files for writing.\n    associatedtype WriteFileHandle: WritableFileHandleProtocol\n\n    /// The type of ``ReadableAndWritableFileHandleProtocol`` to return when opening files for reading and writing.\n    associatedtype ReadWriteFileHandle: ReadableAndWritableFileHandleProtocol\n\n    /// The type of ``DirectoryFileHandleProtocol`` to return when opening directories.\n    associatedtype DirectoryFileHandle: DirectoryFileHandleProtocol\n    where\n        DirectoryFileHandle.ReadFileHandle == ReadFileHandle,\n        DirectoryFileHandle.ReadWriteFileHandle == ReadWriteFileHandle,\n        DirectoryFileHandle.WriteFileHandle == WriteFileHandle\n\n    // MARK: - File access\n\n    /// Opens the file at `path` for reading and returns a handle to it.\n    ///\n    /// The file being opened must exist otherwise this function will throw a ``FileSystemError``\n    /// with code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    ///   - options: How the file should be opened.\n    /// - Returns: A readable handle to the opened file.\n    func openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) async throws -> ReadFileHandle\n\n    /// Opens the file at `path` for writing and returns a handle to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    /// - Returns: A writable handle to the opened file.\n    func openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> WriteFileHandle\n\n    /// Opens the file at `path` for reading and writing and returns a handle to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open relative to the open file.\n    ///   - options: How the file should be opened.\n    func openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> ReadWriteFileHandle\n\n    /// Opens the directory at `path` and returns a handle to it.\n    ///\n    /// The directory being opened must already exist otherwise this function will throw an error.\n    /// Use ``createDirectory(at:withIntermediateDirectories:permissions:)`` to create directories.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the directory should be opened.\n    /// - Returns: A handle to the opened directory.\n    func openDirectory(\n        atPath path: FilePath,\n        options: OpenOptions.Directory\n    ) async throws -> DirectoryFileHandle\n\n    /// Create a directory at the given path.\n    ///\n    /// If a directory (or file) already exists at `path` then an error will be thrown. If\n    /// `createIntermediateDirectories` is `false` then the full prefix of `path` must already\n    /// exist. If set to `true` then all intermediate directories will be created.\n    ///\n    /// Related system calls: `mkdir(2)`.\n    ///\n    /// - Parameters:\n    ///   - path: The directory to create.\n    ///   - createIntermediateDirectories: Whether intermediate directories should be created.\n    ///   - permissions: The permissions to set on the new directory; default permissions will be\n    ///       used if not specified.\n    func createDirectory(\n        at path: FilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool,\n        permissions: FilePermissions?\n    ) async throws\n\n    // MARK: - Common directories\n\n    /// Returns the current working directory.\n    var currentWorkingDirectory: FilePath { get async throws }\n\n    /// Returns the current user's home directory.\n    var homeDirectory: FilePath { get async throws }\n\n    /// Returns the path of the temporary directory.\n    var temporaryDirectory: FilePath { get async throws }\n\n    /// Create a temporary directory at the given path, from a template.\n    ///\n    /// The template for the path of the temporary directory must end in at least\n    /// three 'X's, which will be replaced with a unique alphanumeric combination.\n    /// The template can contain intermediary directories which will be created\n    /// if they do not exist already.\n    ///\n    /// Related system calls: `mkdir(2)`.\n    ///\n    /// - Parameters:\n    ///   - template: The template for the path of the temporary directory.\n    /// - Returns:\n    ///   - The path to the new temporary directory.\n    func createTemporaryDirectory(\n        template: FilePath\n    ) async throws -> FilePath\n\n    // MARK: - File information\n\n    /// Returns information about the file at the given path, if it exists; nil otherwise.\n    ///\n    /// - Parameters:\n    ///    - path: The path to get information about.\n    ///    - infoAboutSymbolicLink: If the file is a symbolic link and this parameter is `true` then\n    ///        information about the link will be returned, otherwise information about the\n    ///        destination of the symbolic link is returned.\n    /// - Returns: Information about the file at the given path or `nil` if no file exists.\n    func info(\n        forFileAt path: FilePath,\n        infoAboutSymbolicLink: Bool\n    ) async throws -> FileInfo?\n\n    // MARK: - Symbolic links\n\n    /// Creates a symbolic link that points to the destination.\n    ///\n    /// If a file or directory exists at `path` then an error is thrown.\n    ///\n    /// - Parameters:\n    ///   - path: The path at which to create the symbolic link.\n    ///   - destinationPath: The path that contains the item that the symbolic link points to.`\n    func createSymbolicLink(\n        at path: FilePath,\n        withDestination destinationPath: FilePath\n    ) async throws\n\n    /// Returns the path of the item pointed to by a symbolic link.\n    ///\n    /// - Parameter path: The path of a file or directory.\n    /// - Returns: The path of the file or directory to which the symbolic link points to.\n    func destinationOfSymbolicLink(\n        at path: FilePath\n    ) async throws -> FilePath\n\n    // MARK: - File copying, removal, and moving\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy (when `replaceExisting` is `false`) or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// If `sourcePath` is a symbolic link then only the link is copied. The copied file will\n    /// preserve permissions and any extended attributes (if supported by the file system).\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - copyStrategy: How to deal with concurrent aspects of the copy, only relevant to directories.\n    ///   - replaceExisting: If `true`, atomically replace any existing file at `destinationPath`.\n    ///   - shouldProceedAfterError: A closure which is executed to determine whether to continue\n    ///       copying files if an error is encountered during the operation. See Errors section for full details.\n    ///   - shouldCopyItem: A closure which is executed before each copy to determine whether each\n    ///       item should be copied. See Filtering section for full details\n    ///\n    /// #### Errors\n    ///\n    /// No errors should be throw by implementors without first calling `shouldProceedAfterError`,\n    /// if that returns without throwing this is taken as permission to continue and the error is swallowed.\n    /// If instead the closure throws then ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    ///  will throw and copying will stop, though the precise semantics of this can depend on the `strategy`.\n    ///\n    /// if using ``CopyStrategy/parallel(maxDescriptors:)``\n    /// Already started work may continue for an indefinite period of time. In particular, after throwing an error\n    /// it is possible that invocations of `shouldCopyItem` may continue to occur!\n    ///\n    /// If using ``CopyStrategy/sequential`` only one invocation of any of the `should*` closures will occur at a time,\n    /// and an error will immediately stop further activity.\n    ///\n    /// The specific error thrown from copyItem is undefined, it does not have to be the same error thrown from\n    /// `shouldProceedAfterError`.\n    /// In the event of any errors (ignored or otherwise) implementations are under no obbligation to\n    /// attempt to 'tidy up' after themselves. The state of the file system within `destinationPath`\n    /// after an aborted copy should is undefined.\n    ///\n    /// When calling `shouldProceedAfterError` implementations of this method\n    /// MUST:\n    ///  - Do so once and only once per item.\n    ///  - Not hold any locks when doing so.\n    /// MAY:\n    ///  - invoke the function multiple times concurrently (except when using ``CopyStrategy/sequential``)\n    ///\n    /// #### Filtering\n    ///\n    /// When invoking `shouldCopyItem` implementations of this method\n    /// MUST:\n    ///  - Do so once and only once per item.\n    ///  - Do so before attempting any operations related to the copy (including determining if they can do so).\n    ///  - Not hold any locks when doing so.\n    ///  - Check parent directories *before* items within them,\n    ///     * if a parent is ignored no items within it should be considered or checked\n    ///  - Skip all contents of a directory which is filtered out.\n    ///  - Invoke it for the `sourcePath` itself.\n    /// MAY:\n    ///  - invoke the function multiple times concurrently (except when using ``CopyStrategy/sequential``)\n    ///  - invoke the function an arbitrary point before actually trying to copy the file\n    func copyItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath,\n        strategy copyStrategy: CopyStrategy,\n        replaceExisting: Bool,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory and `removeItemRecursively` is `true` then the\n    /// contents of all of its subdirectories will be removed recursively before the directory at\n    /// `path`. Symbolic links are removed (but their targets are not deleted).\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removalStrategy: Whether to delete files sequentially (one-by-one), or perform a\n    ///       concurrent scan of the tree at `path` and delete files when they are found. Ignored if\n    ///       the item being removed isn't a directory.\n    ///   - removeItemRecursively: If the item being removed is a directory, remove it by\n    ///       recursively removing its children. Setting this to `true` is synonymous with calling\n    ///       `rm -r`, setting this false is synonymous to calling `rmdir`. Ignored if the item\n    ///       being removed isn't a directory.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    func removeItem(\n        at path: FilePath,\n        strategy removalStrategy: RemovalStrategy,\n        recursively removeItemRecursively: Bool\n    ) async throws -> Int\n\n    /// Moves the file or directory at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// If the file at `sourcePath` is a symbolic link then only the link is moved to the new path.\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to move.\n    ///   - destinationPath: The path at which to place the item.\n    func moveItem(at sourcePath: FilePath, to destinationPath: FilePath) async throws\n\n    /// Replaces the item at `destinationPath` with the item at `existingPath`.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `existingPath` does\n    ///    not exist,\n    /// - ``FileSystemError/Code-swift.struct/io`` if the file at `existingPath` was successfully\n    ///    copied to `destinationPath` but an error occurred while removing it from `existingPath.`\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// The item at `destinationPath` is not required to exist. Note that it is possible to replace\n    /// a file with a directory and vice versa. After the file or directory at `destinationPath`\n    /// has been replaced, the item at `existingPath` will be removed.\n    ///\n    /// - Parameters:\n    ///   - destinationPath: The path of the file or directory to replace.\n    ///   - existingPath: The path of the existing file or directory.\n    func replaceItem(at destinationPath: FilePath, withItemAt existingPath: FilePath) async throws\n}\n\n// MARK: - Open existing files/directories\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemProtocol {\n    /// Opens the file at the given path and provides scoped read-only access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns.\n    /// Files may also be opened in read-write or write-only mode by calling\n    /// ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)`` and\n    /// ``FileSystemProtocol/withFileHandle(forWritingAt:options:execute:)``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides read-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read = OpenOptions.Read(),\n        execute: (_ read: ReadFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAt: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped write-only access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the call returns.\n    /// Files may also be opened in read-write or write-only mode by calling\n    /// ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)`` and\n    /// ``FileSystemProtocol/withFileHandle(forWritingAt:options:execute:)``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides write-only access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute: (_ write: WriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forWritingAt: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { result in\n            switch result {\n            case .success:\n                try await handle.close()\n            case .failure:\n                try await handle.close(makeChangesVisible: false)\n            }\n        }\n    }\n\n    /// Opens the file at the given path and provides scoped read-write access to it.\n    ///\n    /// The file remains open during lifetime of the `execute` block and will be closed\n    /// automatically before the function returns.\n    /// Files may also be opened in read-only or\n    /// write-only mode by with ``FileSystemProtocol/withFileHandle(forReadingAt:options:execute:)`` and\n    /// ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open for reading and writing.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides access to the open file. The file is closed\n    ///       automatically after the closure exits.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withFileHandle<Result>(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write = .newFile(replaceExisting: false),\n        execute: (_ readWrite: ReadWriteFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openFile(forReadingAndWritingAt: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n\n    /// Opens the directory at the given path and provides scoped access to it.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    ///   - options: How the file should be opened.\n    ///   - execute: A closure which provides access to the directory.\n    /// - Important: The handle passed to `execute` must not escape the closure.\n    /// - Returns: The result of the `execute` closure.\n    public func withDirectoryHandle<Result>(\n        atPath path: FilePath,\n        options: OpenOptions.Directory = OpenOptions.Directory(),\n        execute: (_ directory: DirectoryFileHandle) async throws -> Result\n    ) async throws -> Result {\n        let handle = try await self.openDirectory(atPath: path, options: options)\n        return try await withUncancellableTearDown {\n            try await execute(handle)\n        } tearDown: { _ in\n            try await handle.close()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemProtocol {\n    /// Opens the file at `path` for reading and returns a handle to it.\n    ///\n    /// The file being opened must exist otherwise this function will throw a ``FileSystemError``\n    /// with code ``FileSystemError/Code-swift.struct/notFound``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to open.\n    /// - Returns: A readable handle to the opened file.\n    public func openFile(\n        forReadingAt path: FilePath\n    ) async throws -> ReadFileHandle {\n        try await self.openFile(forReadingAt: path, options: OpenOptions.Read())\n    }\n\n    /// Opens the directory at `path` and returns a handle to it.\n    ///\n    /// The directory being opened must already exist otherwise this function will throw an error.\n    /// Use ``createDirectory(at:withIntermediateDirectories:permissions:)`` to create directories.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the directory to open.\n    /// - Returns: A handle to the opened directory.\n    public func openDirectory(\n        atPath path: FilePath\n    ) async throws -> DirectoryFileHandle {\n        try await self.openDirectory(atPath: path, options: OpenOptions.Directory())\n    }\n\n    /// Returns information about the file at the given path, if it exists; nil otherwise.\n    ///\n    /// Calls ``info(forFileAt:infoAboutSymbolicLink:)`` setting `infoAboutSymbolicLink` to `false`.\n    ///\n    /// - Parameters:\n    ///    - path: The path to get information about.\n    /// - Returns: Information about the file at the given path or `nil` if no file exists.\n    public func info(forFileAt path: FilePath) async throws -> FileInfo? {\n        try await self.info(forFileAt: path, infoAboutSymbolicLink: false)\n    }\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// Calls through to\n    /// ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    /// with `replaceExisting` set to `false`.\n    public func copyItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath,\n        strategy copyStrategy: CopyStrategy,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        try await self.copyItem(\n            at: sourcePath,\n            to: destinationPath,\n            strategy: copyStrategy,\n            replaceExisting: false,\n            shouldProceedAfterError: shouldProceedAfterError,\n            shouldCopyItem: shouldCopyItem\n        )\n    }\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown. If any error is encountered during the copy\n    /// then the copy is aborted. You can modify the behaviour with the `shouldProceedAfterError`\n    /// parameter of ``FileSystemProtocol/copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``.\n    ///\n    /// If the file at `sourcePath` is a symbolic link then only the link is copied to the new path.\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - copyStrategy: This controls the concurrency used if the file at `sourcePath` is a directory.\n    public func copyItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath,\n        strategy copyStrategy: CopyStrategy = .platformDefault\n    ) async throws {\n        try await self.copyItem(\n            at: sourcePath,\n            to: destinationPath,\n            strategy: copyStrategy,\n            replaceExisting: false,\n            shouldProceedAfterError: { _, error in\n                throw error\n            },\n            shouldCopyItem: { _, _ in\n                true\n            }\n        )\n    }\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The item to be copied must be a:\n    /// - regular file,\n    /// - symbolic link, or\n    /// - directory.\n    ///\n    /// If `sourcePath` is a symbolic link then only the link is copied. The copied file will\n    /// preserve permissions and any extended attributes (if supported by the file system).\n    ///\n    /// #### Errors\n    ///\n    /// Error codes thrown include:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if `sourcePath` doesn't exist.\n    /// - ``FileSystemError/Code-swift.struct/fileAlreadyExists`` if `destinationPath` exists.\n    ///\n    /// #### Backward Compatibility details\n    ///\n    /// This is implemented in terms of ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    /// using ``CopyStrategy/sequential`` to avoid changing the concurrency semantics of the should callbacks\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - shouldProceedAfterError: Determines whether to continue copying files if an error is\n    ///       thrown during the operation. This error does not have to match the error passed\n    ///       to the closure.\n    ///   - shouldCopyFile: A closure which is executed before each file to determine whether the\n    ///       file should be copied.\n    @available(*, deprecated, message: \"please use copyItem overload taking CopyStrategy\")\n    public func copyItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyFile:\n            @escaping @Sendable (\n                _ source: FilePath,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        try await self.copyItem(\n            at: sourcePath,\n            to: destinationPath,\n            strategy: .sequential,\n            replaceExisting: false,\n            shouldProceedAfterError: shouldProceedAfterError,\n            shouldCopyItem: { (source, destination) in\n                await shouldCopyFile(source.path, destination)\n            }\n        )\n    }\n\n    /// Copies the item at the specified path to a new location.\n    ///\n    /// The following error codes may be thrown:\n    /// - ``FileSystemError/Code-swift.struct/notFound`` if the item at `sourcePath` does not exist,\n    /// - ``FileSystemError/Code-swift.struct/invalidArgument`` if an item at `destinationPath`\n    ///   exists prior to the copy or its parent directory does not exist.\n    ///\n    /// Note that other errors may also be thrown.\n    ///\n    /// If `sourcePath` is a symbolic link then only the link is copied. The copied file will\n    /// preserve permissions and any extended attributes (if supported by the file system).\n    ///\n    /// - Parameters:\n    ///   - sourcePath: The path to the item to copy.\n    ///   - destinationPath: The path at which to place the copy.\n    ///   - shouldProceedAfterError: A closure which is executed to determine whether to continue\n    ///       copying files if an error is encountered during the operation. See Errors section for full details.\n    ///   - shouldCopyItem: A closure which is executed before each copy to determine whether each\n    ///       item should be copied. See Filtering section for full details\n    ///\n    /// #### Parallelism\n    ///\n    /// This overload uses ``CopyStrategy/platformDefault`` which is likely to result in multiple concurrency domains being used\n    /// in the event of copying a directory.\n    /// See the detailed description on ``copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)``\n    /// for the implications of this with respect to the `shouldProceedAfterError` and `shouldCopyItem` callbacks\n    public func copyItem(\n        at sourcePath: FilePath,\n        to destinationPath: FilePath,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        try await self.copyItem(\n            at: sourcePath,\n            to: destinationPath,\n            strategy: .platformDefault,\n            replaceExisting: false,\n            shouldProceedAfterError: shouldProceedAfterError,\n            shouldCopyItem: shouldCopyItem\n        )\n    }\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory then the contents of all of its subdirectories will\n    /// be removed recursively before the directory at `path`. Symbolic links are removed (but their\n    /// targets are not deleted).\n    ///\n    /// The strategy for deletion will be determined automatically depending on the discovered\n    /// platform.\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: FilePath\n    ) async throws -> Int {\n        try await self.removeItem(at: path, strategy: .platformDefault, recursively: true)\n    }\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory then the contents of all of its subdirectories will\n    /// be removed recursively before the directory at `path`. Symbolic links are removed (but their\n    /// targets are not deleted).\n    ///\n    /// The strategy for deletion will be determined automatically depending on the discovered\n    /// platform.\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removeItemRecursively: If the item being removed is a directory, remove it by\n    ///       recursively removing its children. Setting this to `true` is synonymous with calling\n    ///       `rm -r`, setting this false is synonymous to calling `rmdir`. Ignored if the item\n    ///       being removed isn't a directory.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: FilePath,\n        recursively removeItemRecursively: Bool\n    ) async throws -> Int {\n        try await self.removeItem(at: path, strategy: .platformDefault, recursively: removeItemRecursively)\n    }\n\n    /// Deletes the file or directory (and its contents) at `path`.\n    ///\n    /// The item to be removed must be a regular file, symbolic link or directory. If no file exists\n    /// at the given path then this function returns zero.\n    ///\n    /// If the item at the `path` is a directory then the contents of all of its subdirectories will\n    /// be removed recursively before the directory at `path`. Symbolic links are removed (but their\n    /// targets are not deleted).\n    ///\n    /// - Parameters:\n    ///   - path: The path to delete.\n    ///   - removalStrategy: Whether to delete files sequentially (one-by-one), or perform a\n    ///       concurrent scan of the tree at `path` and delete files when they are found.\n    /// - Returns: The number of deleted items which may be zero if `path` did not exist.\n    @discardableResult\n    public func removeItem(\n        at path: FilePath,\n        strategy removalStrategy: RemovalStrategy\n    ) async throws -> Int {\n        try await self.removeItem(at: path, strategy: removalStrategy, recursively: true)\n    }\n\n    /// Create a directory at the given path.\n    ///\n    /// If a directory (or file) already exists at `path` then an error will be thrown. If\n    /// `createIntermediateDirectories` is `false` then the full prefix of `path` must already\n    /// exist. If set to `true` then all intermediate directories will be created.\n    ///\n    /// New directories will be given read-write-execute owner permissions and read-execute group\n    /// and other permissions.\n    ///\n    /// Related system calls: `mkdir(2)`.\n    ///\n    /// - Parameters:\n    ///   - path: The directory to create.\n    ///   - createIntermediateDirectories: Whether intermediate directories should be created.\n    public func createDirectory(\n        at path: FilePath,\n        withIntermediateDirectories createIntermediateDirectories: Bool\n    ) async throws {\n        try await self.createDirectory(\n            at: path,\n            withIntermediateDirectories: createIntermediateDirectories,\n            permissions: .defaultsForDirectory\n        )\n    }\n\n    /// Create a temporary directory and removes it once the function returns.\n    ///\n    /// You can use `prefix` to specify the directory in which the temporary directory should\n    /// be created. If `prefix` is `nil` then the value of ``temporaryDirectory`` is used as\n    /// the prefix.\n    ///\n    /// The temporary directory, and all of its contents, is removed once `execute` returns.\n    ///\n    /// - Parameters:\n    ///   - prefix: The prefix to use for the path of the temporary directory.\n    ///   - options: Options used to create the directory.\n    ///   - execute: A closure which provides access to the directory and its path.\n    /// - Returns: The result of `execute`.\n    public func withTemporaryDirectory<Result>(\n        prefix: FilePath? = nil,\n        options: OpenOptions.Directory = OpenOptions.Directory(),\n        execute: (_ directory: DirectoryFileHandle, _ path: FilePath) async throws -> Result\n    ) async throws -> Result {\n        let template: FilePath\n\n        if let prefix = prefix {\n            template = prefix.appending(\"XXXXXXXX\")\n        } else {\n            template = try await self.temporaryDirectory.appending(\"XXXXXXXX\")\n        }\n\n        let directory = try await self.createTemporaryDirectory(template: template)\n        return try await withUncancellableTearDown {\n            try await withDirectoryHandle(atPath: directory, options: options) { handle in\n                try await execute(handle, directory)\n            }\n        } tearDown: { _ in\n            try await self.removeItem(at: directory, strategy: .platformDefault, recursively: true)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/FileType.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\n\n/// The type of a file system object.\npublic struct FileType: Hashable, Sendable {\n    internal enum Wrapped: Hashable, Sendable, CaseIterable {\n        case regular\n        case block\n        case character\n        case fifo\n        case directory\n        case symlink\n        case socket\n        case whiteout\n        case unknown\n    }\n\n    internal let wrapped: Wrapped\n    private init(_ wrapped: Wrapped) {\n        self.wrapped = wrapped\n    }\n}\n\nextension FileType {\n    /// Regular file.\n    public static var regular: Self { Self(.regular) }\n\n    /// Directory.\n    public static var directory: Self { Self(.directory) }\n\n    /// Symbolic link.\n    public static var symlink: Self { Self(.symlink) }\n\n    /// Hardware block device.\n    public static var block: Self { Self(.block) }\n\n    /// Hardware character device.\n    public static var character: Self { Self(.character) }\n\n    /// FIFO (or named pipe).\n    public static var fifo: Self { Self(.fifo) }\n\n    /// Socket.\n    public static var socket: Self { Self(.socket) }\n\n    /// Whiteout file.\n    public static var whiteout: Self { Self(.whiteout) }\n\n    /// A file of unknown type.\n    public static var unknown: Self { Self(.unknown) }\n}\n\nextension FileType: CustomStringConvertible {\n    public var description: String {\n        switch self.wrapped {\n        case .regular:\n            return \"regular\"\n        case .block:\n            return \"block\"\n        case .character:\n            return \"character\"\n        case .fifo:\n            return \"fifo\"\n        case .directory:\n            return \"directory\"\n        case .symlink:\n            return \"symlink\"\n        case .socket:\n            return \"socket\"\n        case .whiteout:\n            return \"whiteout\"\n        case .unknown:\n            return \"unknown\"\n        }\n    }\n}\n\nextension FileType: CaseIterable {\n    public static var allCases: [FileType] {\n        Self.Wrapped.allCases.map { FileType($0) }\n    }\n}\n\nextension FileType {\n    /// Initializes a file type from a `CInterop.Mode`.\n    ///\n    /// Note: an appropriate mask is applied to `mode`.\n    public init(platformSpecificMode: CInterop.Mode) {\n        // See: `man 2 stat`\n        switch platformSpecificMode & S_IFMT {\n        case S_IFIFO:\n            self = .fifo\n        case S_IFCHR:\n            self = .character\n        case S_IFDIR:\n            self = .directory\n        case S_IFBLK:\n            self = .block\n        case S_IFREG:\n            self = .regular\n        case S_IFLNK:\n            self = .symlink\n        case S_IFSOCK:\n            self = .socket\n        #if canImport(Darwin)\n        case S_IFWHT:\n            self = .whiteout\n        #endif\n        default:\n            self = .unknown\n        }\n    }\n\n    /// Initializes a file type from the `d_type` from `dirent`.\n    @_spi(Testing)\n    public init(direntType: UInt8) {\n        #if canImport(Darwin) || canImport(Musl) || os(Android)\n        let value = Int32(direntType)\n        #elseif canImport(Glibc)\n        let value = Int(direntType)\n        #endif\n\n        switch value {\n        case DT_FIFO:\n            self = .fifo\n        case DT_CHR:\n            self = .character\n        case DT_DIR:\n            self = .directory\n        case DT_BLK:\n            self = .block\n        case DT_REG:\n            self = .regular\n        case DT_LNK:\n            self = .symlink\n        case DT_SOCK:\n            self = .socket\n        #if canImport(Darwin)\n        case DT_WHT:\n            self = .whiteout\n        #endif\n        case DT_UNKNOWN:\n            self = .unknown\n        default:\n            self = .unknown\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/IOStrategy.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// How many file descriptors to open when performing I/O operations.\nenum IOStrategy: Hashable, Sendable {\n    // platformDefault is reified into one of the concrete options below:\n    case sequential\n    case parallel(_ maxDescriptors: Int)\n\n    // These selections are relatively arbitrary but the rationale is as follows:\n    //\n    // - Never exceed the default OS limits even if 4 such operations were happening at once.\n    // - Sufficient to enable significant speed up from parallelism\n    // - Not wasting effort by pushing contention to the storage device. Further we\n    //   assume an SSD or similar storage tech. Users on spinning rust need to account\n    //   for that themselves anyway.\n    //\n    // That said, empirical testing for this has not been performed, suggestions welcome.\n    //\n    // Note: The directory scan is modelled after a copy strategy needing two handles: during the\n    // creation of the destination directory we hold the handle while copying attributes. A much\n    // more complex internal state machine could allow doing two of these if desired. This may not\n    // result in a faster copy though so things are left simple.\n    internal static func determinePlatformDefault() -> Self {\n        #if os(macOS) || os(Linux) || os(Windows)\n        // Eight file descriptors allow for four concurrent file copies/directory scans. Avoiding\n        // storage system contention is of utmost importance.\n        //\n        // Testing was performed on an SSD, while copying objects (a dense directory of small files\n        // and subdirectories of similar shape) to the same volume, totalling 12GB. Results showed\n        // improvements in elapsed time for (expected) increases in CPU time up to parallel(8).\n        // Beyond this, the increases in CPU led to only moderate gains.\n        //\n        // Anyone tuning this is encouraged to cover worst case scenarios.\n        return .parallel(8)\n        #elseif (canImport(Darwin) && !os(macOS)) || os(Android)\n        // Reduced maximum descriptors in embedded world. This is chosen based on biasing towards\n        // safety, not empirical testing.\n        return .parallel(4)\n        #else\n        // Safety first. If we do not know what system we run on, we keep it simple.\n        return .sequential\n        #endif\n    }\n}\n\n/// How to perform copies. Currently only relevant to directory level copies when using\n/// ``FileSystemProtocol/copyItem(at:to:strategy:replaceExisting:shouldProceedAfterError:shouldCopyItem:)`` or other\n/// overloads that use the default behaviour.\npublic struct CopyStrategy: Hashable, Sendable {\n    internal let wrapped: IOStrategy\n    private init(_ strategy: IOStrategy) {\n        switch strategy {\n        case .sequential:\n            self.wrapped = .sequential\n        case let .parallel(maxDescriptors):\n            self.wrapped = .parallel(maxDescriptors)\n        }\n    }\n\n    // A copy fundamentally can't work without two descriptors unless you copy everything into\n    // memory which is infeasible/inefficient for large copies.\n    private static let minDescriptorsAllowed = 2\n\n    /// Operate in whatever manner is deemed a reasonable default for the platform. This will limit\n    /// the maximum file descriptors usage based on reasonable defaults.\n    ///\n    /// Current assumptions (which are subject to change):\n    /// - Only one copy operation would be performed at once\n    /// - The copy operation is not intended to be the primary activity on the device\n    public static let platformDefault: Self = Self(IOStrategy.determinePlatformDefault())\n\n    /// The copy is done asynchronously, but only one operation will occur at a time. This is the\n    /// only way to guarantee only one callback to the `shouldCopyItem` will happen at a time.\n    public static let sequential: Self = Self(.sequential)\n\n    /// Allow multiple I/O operations to run concurrently, including file copies/directory creation\n    /// and scanning.\n    ///\n    /// - Parameter maxDescriptors: a conservative limit on the number of concurrently open file\n    ///     descriptors involved in the copy. This number must be >= 2 though, if you are using a\n    ///     value that low you should use ``sequential``\n    ///\n    /// - Throws: ``FileSystemError/Code-swift.struct/invalidArgument`` if `maxDescriptors` is less\n    ///     than 2.\n    ///\n    public static func parallel(maxDescriptors: Int) throws -> Self {\n        guard maxDescriptors >= Self.minDescriptorsAllowed else {\n            // 2 is not quite the same as sequential, you could have two concurrent directory\n            // listings for example less than 2 and you can't actually do a _copy_ though so it's\n            // non-sensical.\n            throw FileSystemError(\n                code: .invalidArgument,\n                message: \"Can't do a copy operation without at least 2 file descriptors '\\(maxDescriptors)' is illegal\",\n                cause: nil,\n                location: .here()\n            )\n        }\n        return .init(.parallel(maxDescriptors))\n    }\n}\n\nextension CopyStrategy: CustomStringConvertible {\n    public var description: String {\n        switch self.wrapped {\n        case .sequential:\n            return \"sequential\"\n        case let .parallel(maxDescriptors):\n            return \"parallel with max \\(maxDescriptors) descriptors\"\n        }\n    }\n}\n\n/// How to perform file deletions. Currently only relevant to directory level deletions when using\n/// ``FileSystemProtocol/removeItem(at:strategy:recursively:)`` or other overloads that use the\n/// default behaviour.\npublic struct RemovalStrategy: Hashable, Sendable {\n    internal let wrapped: IOStrategy\n    private init(_ strategy: IOStrategy) {\n        switch strategy {\n        case .sequential:\n            self.wrapped = .sequential\n        case let .parallel(maxDescriptors):\n            self.wrapped = .parallel(maxDescriptors)\n        }\n    }\n\n    // A deletion requires no file descriptors. We only consume a file descriptor while scanning the\n    // contents of a directory, so the minimum is 1.\n    private static let minRequiredDescriptors = 1\n\n    /// Operate in whatever manner is deemed a reasonable default for the platform. This will limit\n    /// the maximum file descriptors usage based on reasonable defaults.\n    ///\n    /// Current assumptions (which are subject to change):\n    /// - Only one delete operation would be performed at once\n    /// - The delete operation is not intended to be the primary activity on the device\n    public static let platformDefault: Self = Self(IOStrategy.determinePlatformDefault())\n\n    /// Traversal of directories and removal of files will be done sequentially without any\n    /// parallelization.\n    public static let sequential: Self = Self(.sequential)\n\n    /// Allow for one or more directory scans to run at the same time. Removal of files will happen\n    /// on asynchronous tasks in parallel.\n    ///\n    /// Setting `maxDescriptors` to 1, will limit the speed of directory discovery. Deletion of\n    /// files within that directory will run in parallel, but discovery of subdirectories will be\n    /// limited to one at a time.\n    public static func parallel(maxDescriptors: Int) throws -> Self {\n        guard maxDescriptors >= Self.minRequiredDescriptors else {\n            throw FileSystemError(\n                code: .invalidArgument,\n                message:\n                    \"Can't do a remove operation without at least one file descriptor '\\(maxDescriptors)' is illegal\",\n                cause: nil,\n                location: .here()\n            )\n        }\n        return .init(.parallel(maxDescriptors))\n    }\n}\n\nextension RemovalStrategy: CustomStringConvertible {\n    public var description: String {\n        switch self.wrapped {\n        case .sequential:\n            return \"sequential\"\n        case let .parallel(maxDescriptors):\n            return \"parallel with max \\(maxDescriptors) descriptors\"\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/BufferedOrAnyStream.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Wraps a ``NIOThrowingAsyncSequenceProducer<Element>`` or ``AnyAsyncSequence<Element>``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal enum BufferedOrAnyStream<Element: Sendable, Delegate: NIOAsyncSequenceProducerDelegate>: Sendable {\n    typealias AsyncSequenceProducer = NIOThrowingAsyncSequenceProducer<\n        Element, Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, Delegate\n    >\n\n    case nioThrowingAsyncSequenceProducer(AsyncSequenceProducer)\n    case anyAsyncSequence(AnyAsyncSequence<Element>)\n\n    internal init(wrapping stream: AsyncSequenceProducer) {\n        self = .nioThrowingAsyncSequenceProducer(stream)\n    }\n\n    internal init<S: AsyncSequence & Sendable>(wrapping stream: S)\n    where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {\n        self = .anyAsyncSequence(AnyAsyncSequence(wrapping: stream))\n    }\n\n    internal func makeAsyncIterator() -> AsyncIterator {\n        switch self {\n        case let .nioThrowingAsyncSequenceProducer(stream):\n            return AsyncIterator(wrapping: stream.makeAsyncIterator())\n        case let .anyAsyncSequence(stream):\n            return AsyncIterator(wrapping: stream.makeAsyncIterator())\n        }\n    }\n\n    internal enum AsyncIterator: AsyncIteratorProtocol {\n        case bufferedStream(AsyncSequenceProducer.AsyncIterator)\n        case anyAsyncSequence(AnyAsyncSequence<Element>.AsyncIterator)\n\n        internal mutating func next() async throws -> Element? {\n            let element: Element?\n            switch self {\n            case let .bufferedStream(iterator):\n                defer { self = .bufferedStream(iterator) }\n                element = try await iterator.next()\n            case var .anyAsyncSequence(iterator):\n                defer { self = .anyAsyncSequence(iterator) }\n                element = try await iterator.next()\n            }\n            return element\n        }\n\n        internal init(wrapping iterator: AsyncSequenceProducer.AsyncIterator) {\n            self = .bufferedStream(iterator)\n        }\n\n        internal init(wrapping iterator: AnyAsyncSequence<Element>.AsyncIterator) {\n            self = .anyAsyncSequence(iterator)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal struct AnyAsyncSequence<Element>: AsyncSequence, Sendable {\n    private let _makeAsyncIterator: @Sendable () -> AsyncIterator\n\n    internal init<S: AsyncSequence & Sendable>(wrapping sequence: S)\n    where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {\n        self._makeAsyncIterator = {\n            AsyncIterator(wrapping: sequence.makeAsyncIterator())\n        }\n    }\n\n    internal func makeAsyncIterator() -> AsyncIterator {\n        self._makeAsyncIterator()\n    }\n\n    internal struct AsyncIterator: AsyncIteratorProtocol, _NIOFileSystemSendableMetatype {\n        private var iterator: any AsyncIteratorProtocol\n\n        init<I: AsyncIteratorProtocol>(wrapping iterator: I) where I.Element == Element {\n            self.iterator = iterator\n        }\n\n        internal mutating func next() async throws -> Element? {\n            try await self.iterator.next() as? Element\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/BufferedStream.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\n\n/// An asynchronous sequence generated from an error-throwing closure that\n/// calls a continuation to produce new elements.\n///\n/// `BufferedStream` conforms to `AsyncSequence`, providing a convenient\n/// way to create an asynchronous sequence without manually implementing an\n/// asynchronous iterator. In particular, an asynchronous stream is well-suited\n/// to adapt callback- or delegation-based APIs to participate with\n/// `async`-`await`.\n///\n/// In contrast to `AsyncStream`, this type can throw an error from the awaited\n/// `next()`, which terminates the stream with the thrown error.\n///\n/// You initialize an `BufferedStream` with a closure that receives an\n/// `BufferedStream.Continuation`. Produce elements in this closure, then\n/// provide them to the stream by calling the continuation's `yield(_:)` method.\n/// When there are no further elements to produce, call the continuation's\n/// `finish()` method. This causes the sequence iterator to produce a `nil`,\n/// which terminates the sequence. If an error occurs, call the continuation's\n/// `finish(throwing:)` method, which causes the iterator's `next()` method to\n/// throw the error to the awaiting call point. The continuation is `Sendable`,\n/// which permits calling it from concurrent contexts external to the iteration\n/// of the `BufferedStream`.\n///\n/// An arbitrary source of elements can produce elements faster than they are\n/// consumed by a caller iterating over them. Because of this, `BufferedStream`\n/// defines a buffering behavior, allowing the stream to buffer a specific\n/// number of oldest or newest elements. By default, the buffer limit is\n/// `Int.max`, which means it's unbounded.\n///\n/// ### Adapting Existing Code to Use Streams\n///\n/// To adapt existing callback code to use `async`-`await`, use the callbacks\n/// to provide values to the stream, by using the continuation's `yield(_:)`\n/// method.\n///\n/// Consider a hypothetical `QuakeMonitor` type that provides callers with\n/// `Quake` instances every time it detects an earthquake. To receive callbacks,\n/// callers set a custom closure as the value of the monitor's\n/// `quakeHandler` property, which the monitor calls back as necessary. Callers\n/// can also set an `errorHandler` to receive asynchronous error notifications,\n/// such as the monitor service suddenly becoming unavailable.\n///\n///     class QuakeMonitor {\n///         var quakeHandler: ((Quake) -> Void)?\n///         var errorHandler: ((Error) -> Void)?\n///\n///         func startMonitoring() {…}\n///         func stopMonitoring() {…}\n///     }\n///\n/// To adapt this to use `async`-`await`, extend the `QuakeMonitor` to add a\n/// `quakes` property, of type `BufferedStream<Quake>`. In the getter for\n/// this property, return an `BufferedStream`, whose `build` closure --\n/// called at runtime to create the stream -- uses the continuation to\n/// perform the following steps:\n///\n/// 1. Creates a `QuakeMonitor` instance.\n/// 2. Sets the monitor's `quakeHandler` property to a closure that receives\n/// each `Quake` instance and forwards it to the stream by calling the\n/// continuation's `yield(_:)` method.\n/// 3. Sets the monitor's `errorHandler` property to a closure that receives\n/// any error from the monitor and forwards it to the stream by calling the\n/// continuation's `finish(throwing:)` method. This causes the stream's\n/// iterator to throw the error and terminate the stream.\n/// 4. Sets the continuation's `onTermination` property to a closure that\n/// calls `stopMonitoring()` on the monitor.\n/// 5. Calls `startMonitoring` on the `QuakeMonitor`.\n///\n/// ```\n/// extension QuakeMonitor {\n///\n///     static var throwingQuakes: BufferedStream<Quake, Error> {\n///         BufferedStream { continuation in\n///             let monitor = QuakeMonitor()\n///             monitor.quakeHandler = { quake in\n///                  continuation.yield(quake)\n///             }\n///             monitor.errorHandler = { error in\n///                 continuation.finish(throwing: error)\n///             }\n///             continuation.onTermination = { @Sendable _ in\n///                 monitor.stopMonitoring()\n///             }\n///             monitor.startMonitoring()\n///         }\n///     }\n/// }\n/// ```\n///\n///\n/// Because the stream is an `AsyncSequence`, the call point uses the\n/// `for`-`await`-`in` syntax to process each `Quake` instance as produced by the stream:\n///\n///     do {\n///         for try await quake in quakeStream {\n///             print(\"Quake: \\(quake.date)\")\n///         }\n///         print(\"Stream done.\")\n///     } catch {\n///         print(\"Error: \\(error)\")\n///     }\n///\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal struct BufferedStream<Element: Sendable> {\n    final class _Backing: Sendable {\n        let storage: _BackPressuredStorage\n\n        init(storage: _BackPressuredStorage) {\n            self.storage = storage\n        }\n\n        deinit {\n            self.storage.sequenceDeinitialized()\n        }\n    }\n\n    enum _Implementation: Sendable {\n        /// This is the implementation with backpressure based on the Source\n        case backpressured(_Backing)\n    }\n\n    let implementation: _Implementation\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream: AsyncSequence {\n    /// The asynchronous iterator for iterating an asynchronous stream.\n    ///\n    /// This type is not `Sendable`. Don't use it from multiple\n    /// concurrent contexts. It is a programmer error to invoke `next()` from a\n    /// concurrent context that contends with another such call, which\n    /// results in a call to `fatalError()`.\n    internal struct Iterator: AsyncIteratorProtocol {\n        final class _Backing {\n            let storage: _BackPressuredStorage\n\n            init(storage: _BackPressuredStorage) {\n                self.storage = storage\n                self.storage.iteratorInitialized()\n            }\n\n            deinit {\n                self.storage.iteratorDeinitialized()\n            }\n        }\n        enum _Implementation {\n            /// This is the implementation with backpressure based on the Source\n            case backpressured(_Backing)\n        }\n\n        var implementation: _Implementation\n\n        /// The next value from the asynchronous stream.\n        ///\n        /// When `next()` returns `nil`, this signifies the end of the\n        /// `BufferedStream`.\n        ///\n        /// It is a programmer error to invoke `next()` from a concurrent context\n        /// that contends with another such call, which results in a call to\n        ///  `fatalError()`.\n        ///\n        /// If you cancel the task this iterator is running in while `next()` is\n        /// awaiting a value, the `BufferedStream` terminates. In this case,\n        /// `next()` may return `nil` immediately, or else return `nil` on\n        /// subsequent calls.\n        internal mutating func next() async throws -> Element? {\n            switch self.implementation {\n            case .backpressured(let backing):\n                return try await backing.storage.next()\n            }\n        }\n    }\n\n    /// Creates the asynchronous iterator that produces elements of this\n    /// asynchronous sequence.\n    internal func makeAsyncIterator() -> Iterator {\n        switch self.implementation {\n        case .backpressured(let backing):\n            return Iterator(implementation: .backpressured(.init(storage: backing.storage)))\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream: Sendable {}\n\ninternal struct _ManagedCriticalState<State>: @unchecked Sendable {\n    let lock: NIOLockedValueBox<State>\n\n    internal init(_ initial: State) {\n        self.lock = .init(initial)\n    }\n\n    internal func withCriticalRegion<R>(\n        _ critical: (inout State) throws -> R\n    ) rethrows -> R {\n        try self.lock.withLockedValue(critical)\n    }\n}\n\ninternal struct AlreadyFinishedError: Error {}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    /// A mechanism to interface between producer code and an asynchronous stream.\n    ///\n    /// Use this source to provide elements to the stream by calling one of the `write` methods, then terminate the stream normally\n    /// by calling the `finish()` method. You can also use the source's `finish(throwing:)` method to terminate the stream by\n    /// throwing an error.\n    internal struct Source: Sendable {\n        /// A strategy that handles the backpressure of the asynchronous stream.\n        internal struct BackPressureStrategy: Sendable {\n            /// When the high watermark is reached producers will be suspended. All producers will be resumed again once\n            /// the low watermark is reached.\n            internal static func watermark(low: Int, high: Int) -> BackPressureStrategy {\n                BackPressureStrategy(\n                    internalBackPressureStrategy: .watermark(.init(low: low, high: high))\n                )\n            }\n\n            private init(internalBackPressureStrategy: _InternalBackPressureStrategy) {\n                self._internalBackPressureStrategy = internalBackPressureStrategy\n            }\n\n            fileprivate let _internalBackPressureStrategy: _InternalBackPressureStrategy\n        }\n\n        /// A type that indicates the result of writing elements to the source.\n        internal enum WriteResult: Sendable {\n            /// A token that is returned when the asynchronous stream's backpressure strategy indicated that production should\n            /// be suspended. Use this token to enqueue a callback by  calling the ``enqueueCallback(_:)`` method.\n            internal struct CallbackToken: Sendable {\n                let id: UInt\n            }\n\n            /// Indicates that more elements should be produced and written to the source.\n            case produceMore\n\n            /// Indicates that a callback should be enqueued.\n            ///\n            /// The associated token should be passed to the ``enqueueCallback(_:)`` method.\n            case enqueueCallback(CallbackToken)\n        }\n\n        /// Backing class for the source used to hook a deinit.\n        final class _Backing: Sendable {\n            let storage: _BackPressuredStorage\n\n            init(storage: _BackPressuredStorage) {\n                self.storage = storage\n            }\n\n            deinit {\n                self.storage.sourceDeinitialized()\n            }\n        }\n\n        /// A callback to invoke when the stream finished.\n        ///\n        /// The stream finishes and calls this closure in the following cases:\n        /// - No iterator was created and the sequence was deinited\n        /// - An iterator was created and deinited\n        /// - After ``finish(throwing:)`` was called and all elements have been consumed\n        /// - The consuming task got cancelled\n        internal var onTermination: (@Sendable () -> Void)? {\n            set {\n                self._backing.storage.onTermination = newValue\n            }\n            get {\n                self._backing.storage.onTermination\n            }\n        }\n\n        private var _backing: _Backing\n\n        internal init(storage: _BackPressuredStorage) {\n            self._backing = .init(storage: storage)\n        }\n\n        /// Writes new elements to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// first element of the provided sequence. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// - Parameter sequence: The elements to write to the asynchronous stream.\n        /// - Returns: The result that indicates if more elements should be produced at this time.\n        internal func write<S>(contentsOf sequence: S) throws -> WriteResult\n        where Element == S.Element, S: Sequence, Element: Sendable {\n            try self._backing.storage.write(contentsOf: sequence)\n        }\n\n        /// Write the element to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// provided element. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// - Parameter element: The element to write to the asynchronous stream.\n        /// - Returns: The result that indicates if more elements should be produced at this time.\n        internal func write(_ element: Element) throws -> WriteResult {\n            try self._backing.storage.write(contentsOf: CollectionOfOne(element))\n        }\n\n        /// Enqueues a callback that will be invoked once more elements should be produced.\n        ///\n        /// Call this method after ``write(contentsOf:)`` or ``write(:)`` returned ``WriteResult/enqueueCallback(_:)``.\n        ///\n        /// - Important: Enqueueing the same token multiple times is not allowed.\n        ///\n        /// - Parameters:\n        ///   - callbackToken: The callback token.\n        ///   - onProduceMore: The callback which gets invoked once more elements should be produced.\n        internal func enqueueCallback(\n            callbackToken: WriteResult.CallbackToken,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) {\n            self._backing.storage.enqueueProducer(\n                callbackToken: callbackToken,\n                onProduceMore: onProduceMore\n            )\n        }\n\n        /// Cancel an enqueued callback.\n        ///\n        /// Call this method to cancel a callback enqueued by the ``enqueueCallback(callbackToken:onProduceMore:)`` method.\n        ///\n        /// - Note: This methods supports being called before ``enqueueCallback(callbackToken:onProduceMore:)`` is called and\n        /// will mark the passed `callbackToken` as cancelled.\n        ///\n        /// - Parameter callbackToken: The callback token.\n        internal func cancelCallback(callbackToken: WriteResult.CallbackToken) {\n            self._backing.storage.cancelProducer(callbackToken: callbackToken)\n        }\n\n        /// Write new elements to the asynchronous stream and provide a callback which will be invoked once more elements should be produced.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// first element of the provided sequence. If the asynchronous stream already terminated then `onProduceMore` will be invoked with\n        /// a `Result.failure`.\n        ///\n        /// - Parameters:\n        ///   - sequence: The elements to write to the asynchronous stream.\n        ///   - onProduceMore: The callback which gets invoked once more elements should be produced. This callback might be\n        ///   invoked during the call to ``write(contentsOf:onProduceMore:)``.\n        internal func write<S>(\n            contentsOf sequence: S,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) where Element == S.Element, S: Sequence, Element: Sendable {\n            do {\n                let writeResult = try self.write(contentsOf: sequence)\n\n                switch writeResult {\n                case .produceMore:\n                    onProduceMore(Result<Void, Error>.success(()))\n\n                case .enqueueCallback(let callbackToken):\n                    self.enqueueCallback(callbackToken: callbackToken, onProduceMore: onProduceMore)\n                }\n            } catch {\n                onProduceMore(.failure(error))\n            }\n        }\n\n        /// Writes the element to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// provided element. If the asynchronous stream already terminated then `onProduceMore` will be invoked with\n        /// a `Result.failure`.\n        ///\n        /// - Parameters:\n        ///   - sequence: The element to write to the asynchronous stream.\n        ///   - onProduceMore: The callback which gets invoked once more elements should be produced. This callback might be\n        ///   invoked during the call to ``write(_:onProduceMore:)``.\n        internal func write(\n            _ element: Element,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) {\n            self.write(contentsOf: CollectionOfOne(element), onProduceMore: onProduceMore)\n        }\n\n        /// Write new elements to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// first element of the provided sequence. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// This method returns once more elements should be produced.\n        ///\n        /// - Parameters:\n        ///   - sequence: The elements to write to the asynchronous stream.\n        internal func write<S>(contentsOf sequence: S) async throws\n        where Element == S.Element, S: Sequence, Element: Sendable {\n            let writeResult = try { try self.write(contentsOf: sequence) }()\n\n            switch writeResult {\n            case .produceMore:\n                return\n\n            case .enqueueCallback(let callbackToken):\n                try await withTaskCancellationHandler {\n                    try await withCheckedThrowingContinuation { continuation in\n                        self.enqueueCallback(\n                            callbackToken: callbackToken,\n                            onProduceMore: { result in\n                                switch result {\n                                case .success():\n                                    continuation.resume(returning: ())\n                                case .failure(let error):\n                                    continuation.resume(throwing: error)\n                                }\n                            }\n                        )\n                    }\n                } onCancel: {\n                    self.cancelCallback(callbackToken: callbackToken)\n                }\n            }\n        }\n\n        /// Write new element to the asynchronous stream.\n        ///\n        /// If there is a task consuming the stream and awaiting the next element then the task will get resumed with the\n        /// provided element. If the asynchronous stream already terminated then this method will throw an error\n        /// indicating the failure.\n        ///\n        /// This method returns once more elements should be produced.\n        ///\n        /// - Parameters:\n        ///   - sequence: The element to write to the asynchronous stream.\n        internal func write(_ element: Element) async throws {\n            try await self.write(contentsOf: CollectionOfOne(element))\n        }\n\n        /// Write the elements of the asynchronous sequence to the asynchronous stream.\n        ///\n        /// This method returns once the provided asynchronous sequence or the  the asynchronous stream finished.\n        ///\n        /// - Important: This method does not finish the source if consuming the upstream sequence terminated.\n        ///\n        /// - Parameters:\n        ///   - sequence: The elements to write to the asynchronous stream.\n        internal func write<S>(contentsOf sequence: S) async throws\n        where Element == S.Element, S: AsyncSequence, Element: Sendable {\n            for try await element in sequence {\n                try await self.write(contentsOf: CollectionOfOne(element))\n            }\n        }\n\n        /// Indicates that the production terminated.\n        ///\n        /// After all buffered elements are consumed the next iteration point will return `nil` or throw an error.\n        ///\n        /// Calling this function more than once has no effect. After calling finish, the stream enters a terminal state and doesn't accept\n        /// new elements.\n        ///\n        /// - Parameters:\n        ///   - error: The error to throw, or `nil`, to finish normally.\n        internal func finish(throwing error: Error?) {\n            self._backing.storage.finish(error)\n        }\n    }\n\n    /// Initializes a new ``BufferedStream`` and an ``BufferedStream/Source``.\n    ///\n    /// - Parameters:\n    ///   - elementType: The element type of the stream.\n    ///   - failureType: The failure type of the stream.\n    ///   - backPressureStrategy: The backpressure strategy that the stream should use.\n    /// - Returns: A tuple containing the stream and its source. The source should be passed to the\n    ///   producer while the stream should be passed to the consumer.\n    internal static func makeStream(\n        of elementType: Element.Type = Element.self,\n        throwing failureType: Error.Type = Error.self,\n        backPressureStrategy: Source.BackPressureStrategy\n    ) -> (`Self`, Source) where Error == Error {\n        let storage = _BackPressuredStorage(\n            backPressureStrategy: backPressureStrategy._internalBackPressureStrategy\n        )\n        let source = Source(storage: storage)\n\n        return (.init(storage: storage), source)\n    }\n\n    init(storage: _BackPressuredStorage) {\n        self.implementation = .backpressured(.init(storage: storage))\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    struct _WatermarkBackPressureStrategy {\n        /// The low watermark where demand should start.\n        private let _low: Int\n        /// The high watermark where demand should be stopped.\n        private let _high: Int\n\n        /// Initializes a new ``_WatermarkBackPressureStrategy``.\n        ///\n        /// - Parameters:\n        ///   - low: The low watermark where demand should start.\n        ///   - high: The high watermark where demand should be stopped.\n        init(low: Int, high: Int) {\n            precondition(low <= high)\n            self._low = low\n            self._high = high\n        }\n\n        func didYield(bufferDepth: Int) -> Bool {\n            // We are demanding more until we reach the high watermark\n            bufferDepth < self._high\n        }\n\n        func didConsume(bufferDepth: Int) -> Bool {\n            // We start demanding again once we are below the low watermark\n            bufferDepth < self._low\n        }\n    }\n\n    enum _InternalBackPressureStrategy {\n        case watermark(_WatermarkBackPressureStrategy)\n\n        mutating func didYield(bufferDepth: Int) -> Bool {\n            switch self {\n            case .watermark(let strategy):\n                return strategy.didYield(bufferDepth: bufferDepth)\n            }\n        }\n\n        mutating func didConsume(bufferDepth: Int) -> Bool {\n            switch self {\n            case .watermark(let strategy):\n                return strategy.didConsume(bufferDepth: bufferDepth)\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    // We are unchecked Sendable since we are protecting our state with a lock.\n    final class _BackPressuredStorage: Sendable {\n        /// The state machine\n        let _stateMachine: _ManagedCriticalState<_StateMachine>\n\n        var onTermination: (@Sendable () -> Void)? {\n            set {\n                self._stateMachine.withCriticalRegion {\n                    $0._onTermination = newValue\n                }\n            }\n            get {\n                self._stateMachine.withCriticalRegion {\n                    $0._onTermination\n                }\n            }\n        }\n\n        init(\n            backPressureStrategy: _InternalBackPressureStrategy\n        ) {\n            self._stateMachine = .init(.init(backPressureStrategy: backPressureStrategy))\n        }\n\n        func sequenceDeinitialized() {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.sequenceDeinitialized()\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .failProducersAndCallOnTermination(let producerContinuations, let onTermination):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n                onTermination?()\n\n            case .none:\n                break\n            }\n        }\n\n        func iteratorInitialized() {\n            self._stateMachine.withCriticalRegion {\n                $0.iteratorInitialized()\n            }\n        }\n\n        func iteratorDeinitialized() {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.iteratorDeinitialized()\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .failProducersAndCallOnTermination(let producerContinuations, let onTermination):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n                onTermination?()\n\n            case .none:\n                break\n            }\n        }\n\n        func sourceDeinitialized() {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.sourceDeinitialized()\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .failProducersAndCallOnTermination(let producerContinuations, let onTermination):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n                onTermination?()\n\n            case .failProducers(let producerContinuations):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n\n            case .none:\n                break\n            }\n        }\n\n        func write(\n            contentsOf sequence: some Sequence<Element>\n        ) throws -> Source.WriteResult {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.write(sequence)\n            }\n\n            switch action {\n            case .returnProduceMore:\n                return .produceMore\n\n            case .returnEnqueue(let callbackToken):\n                return .enqueueCallback(callbackToken)\n\n            case .resumeConsumerAndReturnProduceMore(let continuation, let element):\n                continuation.resume(returning: element)\n                return .produceMore\n\n            case .resumeConsumerAndReturnEnqueue(let continuation, let element, let callbackToken):\n                continuation.resume(returning: element)\n                return .enqueueCallback(callbackToken)\n\n            case .throwFinishedError:\n                throw AlreadyFinishedError()\n            }\n        }\n\n        func enqueueProducer(\n            callbackToken: Source.WriteResult.CallbackToken,\n            onProduceMore: @escaping @Sendable (Result<Void, Error>) -> Void\n        ) {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.enqueueProducer(callbackToken: callbackToken, onProduceMore: onProduceMore)\n            }\n\n            switch action {\n            case .resumeProducer(let onProduceMore):\n                onProduceMore(Result<Void, Error>.success(()))\n\n            case .resumeProducerWithError(let onProduceMore, let error):\n                onProduceMore(Result<Void, Error>.failure(error))\n\n            case .none:\n                break\n            }\n        }\n\n        func cancelProducer(callbackToken: Source.WriteResult.CallbackToken) {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.cancelProducer(callbackToken: callbackToken)\n            }\n\n            switch action {\n            case .resumeProducerWithCancellationError(let onProduceMore):\n                onProduceMore(Result<Void, Error>.failure(CancellationError()))\n\n            case .none:\n                break\n            }\n        }\n\n        func finish(_ failure: Error?) {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.finish(failure)\n            }\n\n            switch action {\n            case .callOnTermination(let onTermination):\n                onTermination?()\n\n            case .resumeConsumerAndCallOnTermination(\n                let consumerContinuation,\n                let failure,\n                let onTermination\n            ):\n                switch failure {\n                case .some(let error):\n                    consumerContinuation.resume(throwing: error)\n                case .none:\n                    consumerContinuation.resume(returning: nil)\n                }\n\n                onTermination?()\n\n            case .resumeProducers(let producerContinuations):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(.failure(AlreadyFinishedError()))\n                }\n\n            case .none:\n                break\n            }\n        }\n\n        func next() async throws -> Element? {\n            let action = self._stateMachine.withCriticalRegion {\n                $0.next()\n            }\n\n            switch action {\n            case .returnElement(let element):\n                return element\n\n            case .returnElementAndResumeProducers(let element, let producerContinuations):\n                for producerContinuation in producerContinuations {\n                    producerContinuation(Result<Void, Error>.success(()))\n                }\n\n                return element\n\n            case .returnErrorAndCallOnTermination(let failure, let onTermination):\n                onTermination?()\n                switch failure {\n                case .some(let error):\n                    throw error\n\n                case .none:\n                    return nil\n                }\n\n            case .returnNil:\n                return nil\n\n            case .suspendTask:\n                return try await self.suspendNext()\n            }\n        }\n\n        func suspendNext() async throws -> Element? {\n            try await withTaskCancellationHandler {\n                try await withCheckedThrowingContinuation { continuation in\n                    let action = self._stateMachine.withCriticalRegion {\n                        $0.suspendNext(continuation: continuation)\n                    }\n\n                    switch action {\n                    case .resumeConsumerWithElement(let continuation, let element):\n                        continuation.resume(returning: element)\n\n                    case .resumeConsumerWithElementAndProducers(\n                        let continuation,\n                        let element,\n                        let producerContinuations\n                    ):\n                        continuation.resume(returning: element)\n                        for producerContinuation in producerContinuations {\n                            producerContinuation(Result<Void, Error>.success(()))\n                        }\n\n                    case .resumeConsumerWithErrorAndCallOnTermination(\n                        let continuation,\n                        let failure,\n                        let onTermination\n                    ):\n                        switch failure {\n                        case .some(let error):\n                            continuation.resume(throwing: error)\n\n                        case .none:\n                            continuation.resume(returning: nil)\n                        }\n                        onTermination?()\n\n                    case .resumeConsumerWithNil(let continuation):\n                        continuation.resume(returning: nil)\n\n                    case .none:\n                        break\n                    }\n                }\n            } onCancel: {\n                let action = self._stateMachine.withCriticalRegion {\n                    $0.cancelNext()\n                }\n\n                switch action {\n                case .resumeConsumerWithCancellationErrorAndCallOnTermination(\n                    let continuation,\n                    let onTermination\n                ):\n                    continuation.resume(throwing: CancellationError())\n                    onTermination?()\n\n                case .failProducersAndCallOnTermination(\n                    let producerContinuations,\n                    let onTermination\n                ):\n                    for producerContinuation in producerContinuations {\n                        producerContinuation(.failure(AlreadyFinishedError()))\n                    }\n                    onTermination?()\n\n                case .none:\n                    break\n                }\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream {\n    /// The state machine of the backpressured async stream.\n    struct _StateMachine {\n        enum _State {\n            struct Initial {\n                /// The backpressure strategy.\n                var backPressureStrategy: _InternalBackPressureStrategy\n                /// Indicates if the iterator was initialized.\n                var iteratorInitialized: Bool\n                /// The onTermination callback.\n                var onTermination: (@Sendable () -> Void)?\n            }\n\n            struct Streaming {\n                /// The backpressure strategy.\n                var backPressureStrategy: _InternalBackPressureStrategy\n                /// Indicates if the iterator was initialized.\n                var iteratorInitialized: Bool\n                /// The onTermination callback.\n                var onTermination: (@Sendable () -> Void)?\n                /// The buffer of elements.\n                var buffer: Deque<Element>\n                /// The optional consumer continuation.\n                var consumerContinuation: CheckedContinuation<Element?, Error>?\n                /// The producer continuations.\n                var producerContinuations: Deque<(UInt, (Result<Void, Error>) -> Void)>\n                /// The producers that have been cancelled.\n                var cancelledAsyncProducers: Deque<UInt>\n                /// Indicates if we currently have outstanding demand.\n                var hasOutstandingDemand: Bool\n            }\n\n            struct SourceFinished {\n                /// Indicates if the iterator was initialized.\n                var iteratorInitialized: Bool\n                /// The buffer of elements.\n                var buffer: Deque<Element>\n                /// The failure that should be thrown after the last element has been consumed.\n                var failure: Error?\n                /// The onTermination callback.\n                var onTermination: (@Sendable () -> Void)?\n            }\n\n            case initial(Initial)\n            /// The state once either any element was yielded or `next()` was called.\n            case streaming(Streaming)\n            /// The state once the source signalled that it is finished.\n            case sourceFinished(SourceFinished)\n\n            /// The state once there can be no outstanding demand. This can happen if:\n            /// 1. The iterator was deinited\n            /// 2. The source finished and all buffered elements have been consumed\n            case finished(iteratorInitialized: Bool)\n\n            /// An intermediate state to avoid CoWs.\n            case modify\n        }\n\n        /// The state machine's current state.\n        var _state: _State\n\n        // The ID used for the next CallbackToken.\n        var nextCallbackTokenID: UInt = 0\n\n        var _onTermination: (@Sendable () -> Void)? {\n            set {\n                switch self._state {\n                case .initial(var initial):\n                    initial.onTermination = newValue\n                    self._state = .initial(initial)\n\n                case .streaming(var streaming):\n                    streaming.onTermination = newValue\n                    self._state = .streaming(streaming)\n\n                case .sourceFinished(var sourceFinished):\n                    sourceFinished.onTermination = newValue\n                    self._state = .sourceFinished(sourceFinished)\n\n                case .finished:\n                    break\n\n                case .modify:\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n            }\n            get {\n                switch self._state {\n                case .initial(let initial):\n                    return initial.onTermination\n\n                case .streaming(let streaming):\n                    return streaming.onTermination\n\n                case .sourceFinished(let sourceFinished):\n                    return sourceFinished.onTermination\n\n                case .finished:\n                    return nil\n\n                case .modify:\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n            }\n        }\n\n        /// Initializes a new `StateMachine`.\n        ///\n        /// We are passing and holding the back-pressure strategy here because\n        /// it is a customizable extension of the state machine.\n        ///\n        /// - Parameter backPressureStrategy: The back-pressure strategy.\n        init(\n            backPressureStrategy: _InternalBackPressureStrategy\n        ) {\n            self._state = .initial(\n                .init(\n                    backPressureStrategy: backPressureStrategy,\n                    iteratorInitialized: false,\n                    onTermination: nil\n                )\n            )\n        }\n\n        /// Generates the next callback token.\n        mutating func nextCallbackToken() -> Source.WriteResult.CallbackToken {\n            let id = self.nextCallbackTokenID\n            self.nextCallbackTokenID += 1\n            return .init(id: id)\n        }\n\n        /// Actions returned by `sequenceDeinitialized()`.\n        enum SequenceDeinitializedAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((@Sendable () -> Void)?)\n            /// Indicates that  all producers should be failed and `onTermination` should be called.\n            case failProducersAndCallOnTermination(\n                [(Result<Void, Error>) -> Void],\n                (@Sendable () -> Void)?\n            )\n        }\n\n        mutating func sequenceDeinitialized() -> SequenceDeinitializedAction? {\n            switch self._state {\n            case .initial(let initial):\n                if initial.iteratorInitialized {\n                    // An iterator was created and we deinited the sequence.\n                    // This is an expected pattern and we just continue on normal.\n                    return .none\n                } else {\n                    // No iterator was created so we can transition to finished right away.\n                    self._state = .finished(iteratorInitialized: false)\n\n                    return .callOnTermination(initial.onTermination)\n                }\n\n            case .streaming(let streaming):\n                if streaming.iteratorInitialized {\n                    // An iterator was created and we deinited the sequence.\n                    // This is an expected pattern and we just continue on normal.\n                    return .none\n                } else {\n                    // No iterator was created so we can transition to finished right away.\n                    self._state = .finished(iteratorInitialized: false)\n\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                }\n\n            case .sourceFinished(let sourceFinished):\n                if sourceFinished.iteratorInitialized {\n                    // An iterator was created and we deinited the sequence.\n                    // This is an expected pattern and we just continue on normal.\n                    return .none\n                } else {\n                    // No iterator was created so we can transition to finished right away.\n                    self._state = .finished(iteratorInitialized: false)\n\n                    return .callOnTermination(sourceFinished.onTermination)\n                }\n\n            case .finished:\n                // We are already finished so there is nothing left to clean up.\n                // This is just the references dropping afterwards.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        mutating func iteratorInitialized() {\n            switch self._state {\n            case .initial(var initial):\n                if initial.iteratorInitialized {\n                    // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                    fatalError(\"Only a single AsyncIterator can be created\")\n                } else {\n                    // The first and only iterator was initialized.\n                    initial.iteratorInitialized = true\n                    self._state = .initial(initial)\n                }\n\n            case .streaming(var streaming):\n                if streaming.iteratorInitialized {\n                    // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                    fatalError(\"Only a single AsyncIterator can be created\")\n                } else {\n                    // The first and only iterator was initialized.\n                    streaming.iteratorInitialized = true\n                    self._state = .streaming(streaming)\n                }\n\n            case .sourceFinished(var sourceFinished):\n                if sourceFinished.iteratorInitialized {\n                    // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                    fatalError(\"Only a single AsyncIterator can be created\")\n                } else {\n                    // The first and only iterator was initialized.\n                    sourceFinished.iteratorInitialized = true\n                    self._state = .sourceFinished(sourceFinished)\n                }\n\n            case .finished(iteratorInitialized: true):\n                // Our sequence is a unicast sequence and does not support multiple AsyncIterator's\n                fatalError(\"Only a single AsyncIterator can be created\")\n\n            case .finished(iteratorInitialized: false):\n                // It is strange that an iterator is created after we are finished\n                // but it can definitely happen, e.g.\n                // Sequence.init -> source.finish -> sequence.makeAsyncIterator\n                self._state = .finished(iteratorInitialized: true)\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `iteratorDeinitialized()`.\n        enum IteratorDeinitializedAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((@Sendable () -> Void)?)\n            /// Indicates that  all producers should be failed and `onTermination` should be called.\n            case failProducersAndCallOnTermination(\n                [(Result<Void, Error>) -> Void],\n                (@Sendable () -> Void)?\n            )\n        }\n\n        mutating func iteratorDeinitialized() -> IteratorDeinitializedAction? {\n            switch self._state {\n            case .initial(let initial):\n                if initial.iteratorInitialized {\n                    // An iterator was created and deinited. Since we only support\n                    // a single iterator we can now transition to finish.\n                    self._state = .finished(iteratorInitialized: true)\n                    return .callOnTermination(initial.onTermination)\n                } else {\n                    // An iterator needs to be initialized before it can be deinitialized.\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n            case .streaming(let streaming):\n                if streaming.iteratorInitialized {\n                    // An iterator was created and deinited. Since we only support\n                    // a single iterator we can now transition to finish.\n                    self._state = .finished(iteratorInitialized: true)\n\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                } else {\n                    // An iterator needs to be initialized before it can be deinitialized.\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n            case .sourceFinished(let sourceFinished):\n                if sourceFinished.iteratorInitialized {\n                    // An iterator was created and deinited. Since we only support\n                    // a single iterator we can now transition to finish.\n                    self._state = .finished(iteratorInitialized: true)\n                    return .callOnTermination(sourceFinished.onTermination)\n                } else {\n                    // An iterator needs to be initialized before it can be deinitialized.\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n            case .finished:\n                // We are already finished so there is nothing left to clean up.\n                // This is just the references dropping afterwards.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `sourceDeinitialized()`.\n        enum SourceDeinitializedAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((() -> Void)?)\n            /// Indicates that  all producers should be failed and `onTermination` should be called.\n            case failProducersAndCallOnTermination(\n                [(Result<Void, Error>) -> Void],\n                (@Sendable () -> Void)?\n            )\n            /// Indicates that all producers should be failed.\n            case failProducers([(Result<Void, Error>) -> Void])\n        }\n\n        mutating func sourceDeinitialized() -> SourceDeinitializedAction? {\n            switch self._state {\n            case .initial(let initial):\n                // The source got deinited before anything was written\n                self._state = .finished(iteratorInitialized: initial.iteratorInitialized)\n                return .callOnTermination(initial.onTermination)\n\n            case .streaming(let streaming):\n                if streaming.buffer.isEmpty {\n                    // We can transition to finished right away since the buffer is empty now\n                    self._state = .finished(iteratorInitialized: streaming.iteratorInitialized)\n\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                } else {\n                    // The continuation must be `nil` if the buffer has elements\n                    precondition(streaming.consumerContinuation == nil)\n\n                    self._state = .sourceFinished(\n                        .init(\n                            iteratorInitialized: streaming.iteratorInitialized,\n                            buffer: streaming.buffer,\n                            failure: nil,\n                            onTermination: streaming.onTermination\n                        )\n                    )\n\n                    return .failProducers(\n                        Array(streaming.producerContinuations.map { $0.1 })\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                // This is normal and we just have to tolerate it\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `write()`.\n        enum WriteAction {\n            /// Indicates that the producer should be notified to produce more.\n            case returnProduceMore\n            /// Indicates that the producer should be suspended to stop producing.\n            case returnEnqueue(\n                callbackToken: Source.WriteResult.CallbackToken\n            )\n            /// Indicates that the consumer should be resumed and the producer should be notified to produce more.\n            case resumeConsumerAndReturnProduceMore(\n                continuation: CheckedContinuation<Element?, Error>,\n                element: Element\n            )\n            /// Indicates that the consumer should be resumed and the producer should be suspended.\n            case resumeConsumerAndReturnEnqueue(\n                continuation: CheckedContinuation<Element?, Error>,\n                element: Element,\n                callbackToken: Source.WriteResult.CallbackToken\n            )\n            /// Indicates that the producer has been finished.\n            case throwFinishedError\n\n            init(\n                callbackToken: Source.WriteResult.CallbackToken?,\n                continuationAndElement: (CheckedContinuation<Element?, Error>, Element)? = nil\n            ) {\n                switch (callbackToken, continuationAndElement) {\n                case (.none, .none):\n                    self = .returnProduceMore\n\n                case (.some(let callbackToken), .none):\n                    self = .returnEnqueue(callbackToken: callbackToken)\n\n                case (.none, .some((let continuation, let element))):\n                    self = .resumeConsumerAndReturnProduceMore(\n                        continuation: continuation,\n                        element: element\n                    )\n\n                case (.some(let callbackToken), .some((let continuation, let element))):\n                    self = .resumeConsumerAndReturnEnqueue(\n                        continuation: continuation,\n                        element: element,\n                        callbackToken: callbackToken\n                    )\n                }\n            }\n        }\n\n        mutating func write(_ sequence: some Sequence<Element>) -> WriteAction {\n            switch self._state {\n            case .initial(var initial):\n                var buffer = Deque<Element>()\n                buffer.append(contentsOf: sequence)\n\n                let shouldProduceMore = initial.backPressureStrategy.didYield(\n                    bufferDepth: buffer.count\n                )\n                let callbackToken = shouldProduceMore ? nil : self.nextCallbackToken()\n\n                self._state = .streaming(\n                    .init(\n                        backPressureStrategy: initial.backPressureStrategy,\n                        iteratorInitialized: initial.iteratorInitialized,\n                        onTermination: initial.onTermination,\n                        buffer: buffer,\n                        consumerContinuation: nil,\n                        producerContinuations: .init(),\n                        cancelledAsyncProducers: .init(),\n                        hasOutstandingDemand: shouldProduceMore\n                    )\n                )\n\n                return .init(callbackToken: callbackToken)\n\n            case .streaming(var streaming):\n                self._state = .modify\n\n                streaming.buffer.append(contentsOf: sequence)\n\n                // We have an element and can resume the continuation\n                let shouldProduceMore = streaming.backPressureStrategy.didYield(\n                    bufferDepth: streaming.buffer.count\n                )\n                streaming.hasOutstandingDemand = shouldProduceMore\n                let callbackToken = shouldProduceMore ? nil : self.nextCallbackToken()\n\n                if let consumerContinuation = streaming.consumerContinuation {\n                    guard let element = streaming.buffer.popFirst() else {\n                        // We got a yield of an empty sequence. We just tolerate this.\n                        self._state = .streaming(streaming)\n\n                        return .init(callbackToken: callbackToken)\n                    }\n\n                    // We got a consumer continuation and an element. We can resume the consumer now\n                    streaming.consumerContinuation = nil\n                    self._state = .streaming(streaming)\n                    return .init(\n                        callbackToken: callbackToken,\n                        continuationAndElement: (consumerContinuation, element)\n                    )\n                } else {\n                    // We don't have a suspended consumer so we just buffer the elements\n                    self._state = .streaming(streaming)\n                    return .init(\n                        callbackToken: callbackToken\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                // If the source has finished we are dropping the elements.\n                return .throwFinishedError\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `enqueueProducer()`.\n        enum EnqueueProducerAction {\n            /// Indicates that the producer should be notified to produce more.\n            case resumeProducer((Result<Void, Error>) -> Void)\n            /// Indicates that the producer should be notified about an error.\n            case resumeProducerWithError((Result<Void, Error>) -> Void, Error)\n        }\n\n        mutating func enqueueProducer(\n            callbackToken: Source.WriteResult.CallbackToken,\n            onProduceMore: @Sendable @escaping (Result<Void, Error>) -> Void\n        ) -> EnqueueProducerAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                // This is enforced because the CallbackToken has no internal init so\n                // one must create it by calling `write` first.\n                fatalError(\"AsyncStream internal inconsistency\")\n\n            case .streaming(var streaming):\n                if let index = streaming.cancelledAsyncProducers.firstIndex(of: callbackToken.id) {\n                    // Our producer got marked as cancelled.\n                    self._state = .modify\n                    streaming.cancelledAsyncProducers.remove(at: index)\n                    self._state = .streaming(streaming)\n\n                    return .resumeProducerWithError(onProduceMore, CancellationError())\n                } else if streaming.hasOutstandingDemand {\n                    // We hit an edge case here where we wrote but the consuming thread got interleaved\n                    return .resumeProducer(onProduceMore)\n                } else {\n                    self._state = .modify\n                    streaming.producerContinuations.append((callbackToken.id, onProduceMore))\n\n                    self._state = .streaming(streaming)\n                    return .none\n                }\n\n            case .sourceFinished, .finished:\n                // Since we are unlocking between yielding and suspending the yield\n                // It can happen that the source got finished or the consumption fully finishes.\n                return .resumeProducerWithError(onProduceMore, AlreadyFinishedError())\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `cancelProducer()`.\n        enum CancelProducerAction {\n            /// Indicates that the producer should be notified about cancellation.\n            case resumeProducerWithCancellationError((Result<Void, Error>) -> Void)\n        }\n\n        mutating func cancelProducer(\n            callbackToken: Source.WriteResult.CallbackToken\n        ) -> CancelProducerAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                fatalError(\"AsyncStream internal inconsistency\")\n\n            case .streaming(var streaming):\n                if let index = streaming.producerContinuations.firstIndex(where: {\n                    $0.0 == callbackToken.id\n                }) {\n                    // We have an enqueued producer that we need to resume now\n                    self._state = .modify\n                    let continuation = streaming.producerContinuations.remove(at: index).1\n                    self._state = .streaming(streaming)\n\n                    return .resumeProducerWithCancellationError(continuation)\n                } else {\n                    // The task that yields was cancelled before yielding so the cancellation handler\n                    // got invoked right away\n                    self._state = .modify\n                    streaming.cancelledAsyncProducers.append(callbackToken.id)\n                    self._state = .streaming(streaming)\n\n                    return .none\n                }\n\n            case .sourceFinished, .finished:\n                // Since we are unlocking between yielding and suspending the yield\n                // It can happen that the source got finished or the consumption fully finishes.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `finish()`.\n        enum FinishAction {\n            /// Indicates that `onTermination` should be called.\n            case callOnTermination((() -> Void)?)\n            /// Indicates that the consumer  should be resumed with the failure, the producers\n            /// should be resumed with an error and `onTermination` should be called.\n            case resumeConsumerAndCallOnTermination(\n                consumerContinuation: CheckedContinuation<Element?, Error>,\n                failure: Error?,\n                onTermination: (() -> Void)?\n            )\n            /// Indicates that the producers should be resumed with an error.\n            case resumeProducers(\n                producerContinuations: [(Result<Void, Error>) -> Void]\n            )\n        }\n\n        @inlinable\n        mutating func finish(_ failure: Error?) -> FinishAction? {\n            switch self._state {\n            case .initial(let initial):\n                // Nothing was yielded nor did anybody call next\n                // This means we can transition to sourceFinished and store the failure\n                self._state = .sourceFinished(\n                    .init(\n                        iteratorInitialized: initial.iteratorInitialized,\n                        buffer: .init(),\n                        failure: failure,\n                        onTermination: initial.onTermination\n                    )\n                )\n\n                return .callOnTermination(initial.onTermination)\n\n            case .streaming(let streaming):\n                if let consumerContinuation = streaming.consumerContinuation {\n                    // We have a continuation, this means our buffer must be empty\n                    // Furthermore, we can now transition to finished\n                    // and resume the continuation with the failure\n                    precondition(streaming.buffer.isEmpty, \"Expected an empty buffer\")\n                    precondition(\n                        streaming.producerContinuations.isEmpty,\n                        \"Expected no suspended producers\"\n                    )\n\n                    self._state = .finished(iteratorInitialized: streaming.iteratorInitialized)\n\n                    return .resumeConsumerAndCallOnTermination(\n                        consumerContinuation: consumerContinuation,\n                        failure: failure,\n                        onTermination: streaming.onTermination\n                    )\n                } else {\n                    self._state = .sourceFinished(\n                        .init(\n                            iteratorInitialized: streaming.iteratorInitialized,\n                            buffer: streaming.buffer,\n                            failure: failure,\n                            onTermination: streaming.onTermination\n                        )\n                    )\n\n                    return .resumeProducers(\n                        producerContinuations: Array(streaming.producerContinuations.map { $0.1 })\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                // If the source has finished, finishing again has no effect.\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `next()`.\n        enum NextAction {\n            /// Indicates that the element should be returned to the caller.\n            case returnElement(Element)\n            /// Indicates that the element should be returned to the caller and that all producers should be called.\n            case returnElementAndResumeProducers(Element, [(Result<Void, Error>) -> Void])\n            /// Indicates that the `Error` should be returned to the caller and that `onTermination` should be called.\n            case returnErrorAndCallOnTermination(Error?, (() -> Void)?)\n            /// Indicates that the `nil` should be returned to the caller.\n            case returnNil\n            /// Indicates that the `Task` of the caller should be suspended.\n            case suspendTask\n        }\n\n        mutating func next() -> NextAction {\n            switch self._state {\n            case .initial(let initial):\n                // We are not interacting with the back-pressure strategy here because\n                // we are doing this inside `next(:)`\n                self._state = .streaming(\n                    .init(\n                        backPressureStrategy: initial.backPressureStrategy,\n                        iteratorInitialized: initial.iteratorInitialized,\n                        onTermination: initial.onTermination,\n                        buffer: Deque<Element>(),\n                        consumerContinuation: nil,\n                        producerContinuations: .init(),\n                        cancelledAsyncProducers: .init(),\n                        hasOutstandingDemand: false\n                    )\n                )\n\n                return .suspendTask\n            case .streaming(var streaming):\n                guard streaming.consumerContinuation == nil else {\n                    // We have multiple AsyncIterators iterating the sequence\n                    fatalError(\"AsyncStream internal inconsistency\")\n                }\n\n                self._state = .modify\n\n                if let element = streaming.buffer.popFirst() {\n                    // We have an element to fulfil the demand right away.\n                    let shouldProduceMore = streaming.backPressureStrategy.didConsume(\n                        bufferDepth: streaming.buffer.count\n                    )\n                    streaming.hasOutstandingDemand = shouldProduceMore\n\n                    if shouldProduceMore {\n                        // There is demand and we have to resume our producers\n                        let producers = Array(streaming.producerContinuations.map { $0.1 })\n                        streaming.producerContinuations.removeAll()\n                        self._state = .streaming(streaming)\n                        return .returnElementAndResumeProducers(element, producers)\n                    } else {\n                        // We don't have any new demand, so we can just return the element.\n                        self._state = .streaming(streaming)\n                        return .returnElement(element)\n                    }\n                } else {\n                    // There is nothing in the buffer to fulfil the demand so we need to suspend.\n                    // We are not interacting with the back-pressure strategy here because\n                    // we are doing this inside `suspendNext`\n                    self._state = .streaming(streaming)\n\n                    return .suspendTask\n                }\n\n            case .sourceFinished(var sourceFinished):\n                // Check if we have an element left in the buffer and return it\n                self._state = .modify\n\n                if let element = sourceFinished.buffer.popFirst() {\n                    self._state = .sourceFinished(sourceFinished)\n\n                    return .returnElement(element)\n                } else {\n                    // We are returning the queued failure now and can transition to finished\n                    self._state = .finished(iteratorInitialized: sourceFinished.iteratorInitialized)\n\n                    return .returnErrorAndCallOnTermination(\n                        sourceFinished.failure,\n                        sourceFinished.onTermination\n                    )\n                }\n\n            case .finished:\n                return .returnNil\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `suspendNext()`.\n        enum SuspendNextAction {\n            /// Indicates that the consumer should be resumed.\n            case resumeConsumerWithElement(CheckedContinuation<Element?, Error>, Element)\n            /// Indicates that the consumer and all producers should be resumed.\n            case resumeConsumerWithElementAndProducers(\n                CheckedContinuation<Element?, Error>,\n                Element,\n                [(Result<Void, Error>) -> Void]\n            )\n            /// Indicates that the consumer should be resumed with the failure and that `onTermination` should be called.\n            case resumeConsumerWithErrorAndCallOnTermination(\n                CheckedContinuation<Element?, Error>,\n                Error?,\n                (() -> Void)?\n            )\n            /// Indicates that the consumer should be resumed with `nil`.\n            case resumeConsumerWithNil(CheckedContinuation<Element?, Error>)\n        }\n\n        mutating func suspendNext(\n            continuation: CheckedContinuation<Element?, Error>\n        ) -> SuspendNextAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                preconditionFailure(\"AsyncStream internal inconsistency\")\n\n            case .streaming(var streaming):\n                guard streaming.consumerContinuation == nil else {\n                    // We have multiple AsyncIterators iterating the sequence\n                    fatalError(\n                        \"This should never happen since we only allow a single Iterator to be created\"\n                    )\n                }\n\n                self._state = .modify\n\n                // We have to check here again since we might have a producer interleave next and suspendNext\n                if let element = streaming.buffer.popFirst() {\n                    // We have an element to fulfil the demand right away.\n\n                    let shouldProduceMore = streaming.backPressureStrategy.didConsume(\n                        bufferDepth: streaming.buffer.count\n                    )\n                    streaming.hasOutstandingDemand = shouldProduceMore\n\n                    if shouldProduceMore {\n                        // There is demand and we have to resume our producers\n                        let producers = Array(streaming.producerContinuations.map { $0.1 })\n                        streaming.producerContinuations.removeAll()\n                        self._state = .streaming(streaming)\n                        return .resumeConsumerWithElementAndProducers(\n                            continuation,\n                            element,\n                            producers\n                        )\n                    } else {\n                        // We don't have any new demand, so we can just return the element.\n                        self._state = .streaming(streaming)\n                        return .resumeConsumerWithElement(continuation, element)\n                    }\n                } else {\n                    // There is nothing in the buffer to fulfil the demand so we to store the continuation.\n                    streaming.consumerContinuation = continuation\n                    self._state = .streaming(streaming)\n\n                    return .none\n                }\n\n            case .sourceFinished(var sourceFinished):\n                // Check if we have an element left in the buffer and return it\n                self._state = .modify\n\n                if let element = sourceFinished.buffer.popFirst() {\n                    self._state = .sourceFinished(sourceFinished)\n\n                    return .resumeConsumerWithElement(continuation, element)\n                } else {\n                    // We are returning the queued failure now and can transition to finished\n                    self._state = .finished(iteratorInitialized: sourceFinished.iteratorInitialized)\n\n                    return .resumeConsumerWithErrorAndCallOnTermination(\n                        continuation,\n                        sourceFinished.failure,\n                        sourceFinished.onTermination\n                    )\n                }\n\n            case .finished:\n                return .resumeConsumerWithNil(continuation)\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n\n        /// Actions returned by `cancelNext()`.\n        enum CancelNextAction {\n            /// Indicates that the continuation should be resumed with a cancellation error, the producers should be finished and call onTermination.\n            case resumeConsumerWithCancellationErrorAndCallOnTermination(\n                CheckedContinuation<Element?, Error>,\n                (() -> Void)?\n            )\n            /// Indicates that the producers should be finished and call onTermination.\n            case failProducersAndCallOnTermination([(Result<Void, Error>) -> Void], (() -> Void)?)\n        }\n\n        mutating func cancelNext() -> CancelNextAction? {\n            switch self._state {\n            case .initial:\n                // We need to transition to streaming before we can suspend\n                fatalError(\"AsyncStream internal inconsistency\")\n\n            case .streaming(let streaming):\n                self._state = .finished(iteratorInitialized: streaming.iteratorInitialized)\n\n                if let consumerContinuation = streaming.consumerContinuation {\n                    precondition(\n                        streaming.producerContinuations.isEmpty,\n                        \"Internal inconsistency. Unexpected producer continuations.\"\n                    )\n                    return .resumeConsumerWithCancellationErrorAndCallOnTermination(\n                        consumerContinuation,\n                        streaming.onTermination\n                    )\n                } else {\n                    return .failProducersAndCallOnTermination(\n                        Array(streaming.producerContinuations.map { $0.1 }),\n                        streaming.onTermination\n                    )\n                }\n\n            case .sourceFinished, .finished:\n                return .none\n\n            case .modify:\n                fatalError(\"AsyncStream internal inconsistency\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/Cancellation.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n/// Executes the closure and masks cancellation.\n@_spi(Testing)\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic func withoutCancellation<R: Sendable>(\n    _ execute: @escaping () async throws -> R\n) async throws -> R {\n    // Okay as we immediately wait for the result of the task.\n    let unsafeExecute = UnsafeTransfer(execute)\n    let t = Task {\n        try await unsafeExecute.wrappedValue()\n    }\n    return try await t.value\n}\n\n/// Executes `fn` and then `tearDown`, which cannot be cancelled.\n@_spi(Testing)\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic func withUncancellableTearDown<R>(\n    _ fn: () async throws -> R,\n    tearDown: @escaping (Result<Void, Error>) async throws -> Void\n) async throws -> R {\n    let result: Result<R, Error>\n    do {\n        result = .success(try await fn())\n    } catch {\n        result = .failure(error)\n    }\n\n    let errorOnlyResult: Result<Void, Error> = result.map { _ in () }\n    let tearDownResult: Result<Void, Error> = try await withoutCancellation {\n        do {\n            return .success(try await tearDown(errorOnlyResult))\n        } catch {\n            return .failure(error)\n        }\n    }\n\n    try tearDownResult.get()\n    return try result.get()\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/Concurrency Primitives/TokenBucket.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the Swift open source project\n//\n// Copyright (c) 2023 Apple Inc. and the Swift project authors\n// Licensed under Apache License v2.0 with Runtime Library Exception\n//\n// See http://swift.org/LICENSE.txt for license information\n// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\n\n/// Type modeled after a \"token bucket\" pattern, which is similar to a semaphore, but is built with\n/// Swift Concurrency primitives.\n///\n/// This is an adaptation of the TokenBucket found in Swift Package Manager.\n/// Instead of using an ``actor``, we define a class and limit access through\n/// ``NIOLock``.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class TokenBucket: @unchecked Sendable {\n    private struct State {\n        var tokens: Int\n        var waiters: Deque<CheckedContinuation<Void, Never>>\n\n        enum TakeTokenResult {\n            /// A token is available to use.\n            case tookToken\n            /// No token is available, call back with a continuation.\n            case tryAgainWithContinuation\n            /// No token is available, the continuation will be resumed with one later.\n            case storedContinuation\n        }\n\n        mutating func takeToken(continuation: CheckedContinuation<Void, Never>?) -> TakeTokenResult {\n            if self.tokens > 0 {\n                self.tokens &-= 1\n                return .tookToken\n            } else if let continuation = continuation {\n                self.waiters.append(continuation)\n                return .storedContinuation\n            } else {\n                return .tryAgainWithContinuation\n            }\n        }\n\n        mutating func returnToken() -> CheckedContinuation<Void, Never>? {\n            if let next = self.waiters.popFirst() {\n                return next\n            } else {\n                self.tokens &+= 1\n                return nil\n            }\n        }\n    }\n\n    private let lock: NIOLockedValueBox<State>\n\n    init(tokens: Int) {\n        precondition(tokens >= 1, \"Need at least one token!\")\n        self.lock = NIOLockedValueBox(State(tokens: tokens, waiters: []))\n    }\n\n    /// Executes an `async` closure immediately when a token is available.\n    /// Only the same number of closures will be executed concurrently as the number\n    /// of `tokens` passed to ``TokenBucket/init(tokens:)``, all subsequent\n    /// invocations of `withToken` will suspend until a \"free\" token is available.\n    /// - Parameter body: The closure to invoke when a token is available.\n    /// - Returns: Resulting value returned by `body`.\n    func withToken<ReturnType>(\n        _ body: @Sendable () async throws -> ReturnType\n    ) async rethrows -> ReturnType {\n        await self.getToken()\n        defer { self.returnToken() }\n        return try await body()\n    }\n\n    private func getToken() async {\n        switch self.lock.withLockedValue({ $0.takeToken(continuation: nil) }) {\n        case .tookToken:\n            ()\n\n        case .tryAgainWithContinuation:\n            // Holding the lock here *should* be safe but because of a bug in the runtime\n            // it isn't, so drop the lock, create the continuation and try again.\n            //\n            // See also: https://github.com/swiftlang/swift/issues/85668\n            await withCheckedContinuation { continuation in\n                switch self.lock.withLockedValue({ $0.takeToken(continuation: continuation) }) {\n                case .tookToken:\n                    continuation.resume()\n                case .storedContinuation:\n                    ()\n                case .tryAgainWithContinuation:\n                    // Only possible when 'takeToken(continuation:)' is called with no continuation.\n                    fatalError()\n                }\n            }\n\n        case .storedContinuation:\n            // Only possible when 'takeToken(continuation:)' is called with a continuation.\n            fatalError()\n        }\n    }\n\n    private func returnToken() {\n        let continuation = self.lock.withLockedValue { $0.returnToken() }\n        continuation?.resume()\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/ParallelDirCopy.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    /// Iterative implementation of a recursive parallel copy of the directory from `sourcePath` to\n    /// `destinationPath`.\n    ///\n    /// The parallelism is solely at the level of individual items (files, symbolic links and\n    /// directories). A larger file is not 'split' into concurrent reads or writes.\n    ///\n    /// If a symbolic link is encountered, then only the link is copied. If supported by the file\n    /// system, the copied items will preserve permissions and any extended attributes.\n    ///\n    /// Note: `maxConcurrentOperations` is used as a hard (conservative) limit on the number of open\n    /// file descriptors at any point. Operations are assumed to consume 2 descriptors, so the\n    /// maximum open descriptors are `maxConcurrentOperations * 2`\n    @usableFromInline\n    func copyDirectoryParallel(\n        from sourcePath: FilePath,\n        to destinationPath: FilePath,\n        maxConcurrentOperations: Int,\n        shouldProceedAfterError:\n            @escaping @Sendable (\n                _ entry: DirectoryEntry,\n                _ error: Error\n            ) async throws -> Void,\n        shouldCopyItem:\n            @escaping @Sendable (\n                _ source: DirectoryEntry,\n                _ destination: FilePath\n            ) async -> Bool\n    ) async throws {\n        // Implemented with NIOAsyncSequenceProducer rather than AsyncStream. It is approximately\n        // the same speed in the best case, but has significantly less variance.\n        // NIOAsyncSequenceProducer also enforces a multi-producer, single-consumer access pattern.\n        let copyRequiredQueue = NIOAsyncSequenceProducer.makeSequence(\n            elementType: DirCopyItem.self,\n            backPressureStrategy: NoBackPressureStrategy(),\n            finishOnDeinit: false,\n            delegate: DirCopyDelegate()\n        )\n\n        // We ignore the result of yield in all cases, because we are not implementing back\n        // pressure, and cancellation is dealt with separately.\n        @Sendable func yield(_ contentsOf: [DirCopyItem]) {\n            _ = copyRequiredQueue.source.yield(contentsOf: contentsOf)\n        }\n\n        // Kick-start the procees by enqueuing the root entry. The calling function already\n        // validated the root needed copying, so it is safe to force unwrap the value.\n        _ = copyRequiredQueue.source.yield(\n            .toCopy(from: .init(path: sourcePath, type: .directory)!, to: destinationPath)\n        )\n\n        // The processing of the very first item (the root) will increment this counter. Processing\n        // will finish when the counter hits zero again.\n        //\n        // This does not need to be a ManagedAtomic or similar because:\n        // - All state maintenance is done within the withThrowingTaskGroup closure\n        // - All actual file system work is done by tasks created on the `taskGroup`\n        var activeDirCount = 0\n\n        // Despite there being no 'result' for each operation, we cannot use a discarding task group,\n        // because we use the 'drain results' queue as a concurrency limiting side effect.\n        try await withThrowingTaskGroup(of: Void.self) { taskGroup in\n            // Process each item in the current task.\n            //\n            // Side Effects:\n            // - Updates activeDirCount and finishes the stream if required.\n            // - Might add a task to `taskGroup`.\n            //\n            // Returns true if it added a task, false otherwise.\n            func onNextItem(_ item: DirCopyItem) -> Bool {\n                switch item {\n                case .endOfDir:\n                    activeDirCount -= 1\n                    if activeDirCount == 0 {\n                        copyRequiredQueue.source.finish()\n                    }\n                    return false\n                case let .toCopy(from: from, to: to):\n                    if from.type == .directory {\n                        activeDirCount += 1\n                    }\n                    taskGroup.addTask {\n                        try await copySelfAndEnqueueChildren(\n                            from: from,\n                            to: to,\n                            yield: yield,\n                            shouldProceedAfterError: shouldProceedAfterError,\n                            shouldCopyItem: shouldCopyItem\n                        )\n                    }\n                    return true\n                }\n            }\n\n            let iter = copyRequiredQueue.sequence.makeAsyncIterator()\n\n            // inProgress counts the number of tasks we have added to the task group.\n            // Get up to the maximum concurrency first.\n            // We haven't started monitoring for task completion, so inProgress is 'worst case'.\n            var inProgress = 0\n            while inProgress <= maxConcurrentOperations {\n                let item = await iter.next()\n                if let item = item {\n                    if onNextItem(item) {\n                        inProgress += 1\n                    }\n                } else {\n                    // Either we completed things before we hit the limit or we were cancelled. In\n                    // the latter case we choose to propagate the cancellation clearly. This makes\n                    // testing for it more reliable.\n                    try Task.checkCancellation()\n\n                    // If any child tasks failed throw up an error.\n                    try await taskGroup.waitForAll()\n\n                    return\n                }\n            }\n\n            // One in (finish) -> one out (start another), but only for items that trigger a task.\n            while let _ = try await taskGroup.next() {\n                var keepConsuming = true\n                while keepConsuming {\n                    let item = await iter.next()\n                    if let item = item {\n                        keepConsuming = !onNextItem(item)\n                    } else {\n                        // We must check here, to accurately propagate the cancellation.\n                        try Task.checkCancellation()\n                        keepConsuming = false\n                    }\n                }\n            }\n        }\n    }\n}\n\n/// An 'always ask for more' no back-pressure strategy for a ``NIOAsyncSequenceProducer``.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate struct NoBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategy {\n    mutating func didYield(bufferDepth: Int) -> Bool { true }\n\n    mutating func didConsume(bufferDepth: Int) -> Bool { true }\n}\n\n/// We ignore back pressure, the inherent handle limiting in copyDirectoryParallel means it is unnecessary.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nprivate struct DirCopyDelegate: NIOAsyncSequenceProducerDelegate, Sendable {\n    @inlinable\n    func produceMore() {}\n\n    @inlinable\n    func didTerminate() {}\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/ParallelRemoval.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    /// Recursively walk all objects found in `path`. Call ourselves recursively\n    /// on each directory that we find, as soon as the file descriptor for\n    /// `path` has been closed; also delete all files that we come across.\n    func discoverAndRemoveItemsInTree(\n        at path: FilePath,\n        _ bucket: TokenBucket\n    ) async throws -> Int {\n        // Discover current directory and find all files/directories. Free up\n        // the handle as fast as possible.\n        let (directoriesToRecurseInto, itemsToDelete) = try await bucket.withToken {\n            try await self.withDirectoryHandle(atPath: path) { directory in\n                var subdirectories: [FilePath] = []\n                var itemsInDirectory: [FilePath] = []\n\n                for try await batch in directory.listContents().batched() {\n                    for entry in batch {\n                        switch entry.type {\n                        case .directory:\n                            subdirectories.append(entry.path)\n                        default:\n                            itemsInDirectory.append(entry.path)\n                        }\n                    }\n                }\n\n                return (subdirectories, itemsInDirectory)\n            }\n        }\n\n        return try await withThrowingTaskGroup(of: Int.self) { group in\n            // Delete all items we found in the current directory.\n            for item in itemsToDelete {\n                group.addTask {\n                    try await self.removeOneItem(at: item)\n                }\n            }\n\n            // Recurse into all newly found subdirectories.\n            for directory in directoriesToRecurseInto {\n                group.addTask {\n                    try await self.discoverAndRemoveItemsInTree(at: directory, bucket)\n                }\n            }\n\n            // Await task groups to finish and sum all items deleted so far.\n            var numberOfDeletedItems = try await group.reduce(0, +)\n\n            // Remove top level directory.\n            numberOfDeletedItems += try await self.removeOneItem(at: path)\n\n            return numberOfDeletedItems\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/String+UnsafeUnititializedCapacity.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nextension String {\n    @inlinable\n    init(\n        backportUnsafeUninitializedCapacity capacity: Int,\n        initializingUTF8With initializer: (_ buffer: UnsafeMutableBufferPointer<UInt8>) throws -> Int\n    ) rethrows {\n        // The buffer will store zero terminated C string\n        let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: capacity + 1)\n        defer {\n            buffer.deallocate()\n        }\n\n        let initializedCount = try initializer(buffer)\n        precondition(initializedCount <= capacity, \"Overran buffer in initializer!\")\n\n        // add zero termination\n        buffer[initializedCount] = 0\n\n        self = String(cString: buffer.baseAddress!)\n    }\n}\n\n// Frustratingly, Swift 5.3 shipped before the macOS 11 SDK did, so we cannot gate the availability of\n// this declaration on having the 5.3 compiler. This has caused a number of build issues. While updating\n// to newer Xcodes does work, we can save ourselves some hassle and just wait until 5.4 to get this\n// enhancement on Apple platforms.\nextension String {\n    @inlinable\n    init(\n        customUnsafeUninitializedCapacity capacity: Int,\n        initializingUTF8With initializer: (\n            _ buffer: UnsafeMutableBufferPointer<UInt8>\n        ) throws -> Int\n    ) rethrows {\n        if #available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) {\n            try self.init(\n                unsafeUninitializedCapacity: capacity,\n                initializingUTF8With: initializer\n            )\n        } else {\n            try self.init(\n                backportUnsafeUninitializedCapacity: capacity,\n                initializingUTF8With: initializer\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/System Calls/CInterop.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\nimport CNIODarwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n/// Aliases for platform-dependent types used for system calls.\nextension CInterop {\n    #if canImport(Darwin)\n    public typealias Stat = Darwin.stat\n    #elseif canImport(Glibc)\n    public typealias Stat = Glibc.stat\n    #elseif canImport(Musl)\n    public typealias Stat = Musl.stat\n    #elseif canImport(Android)\n    public typealias Stat = Android.stat\n    #endif\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static let maxPathLength = Darwin.PATH_MAX\n    #elseif canImport(Glibc)\n    @_spi(Testing)\n    public static let maxPathLength = Glibc.PATH_MAX\n    #elseif canImport(Musl)\n    @_spi(Testing)\n    public static let maxPathLength = Musl.PATH_MAX\n    #elseif canImport(Android)\n    @_spi(Testing)\n    public static let maxPathLength = Android.PATH_MAX\n    #endif\n\n    #if canImport(Darwin)\n    typealias DirPointer = UnsafeMutablePointer<Darwin.DIR>\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    typealias DirPointer = OpaquePointer\n    #endif\n\n    #if canImport(Darwin)\n    typealias DirEnt = Darwin.dirent\n    #elseif canImport(Glibc)\n    typealias DirEnt = Glibc.dirent\n    #elseif canImport(Musl)\n    typealias DirEnt = Musl.dirent\n    #elseif canImport(Android)\n    typealias DirEnt = Android.dirent\n    #endif\n\n    #if canImport(Darwin)\n    typealias FTS = CNIODarwin.FTS\n    typealias FTSEnt = CNIODarwin.FTSENT\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    typealias FTS = CNIOLinux.FTS\n    typealias FTSEnt = CNIOLinux.FTSENT\n    #endif\n\n    typealias FTSPointer = UnsafeMutablePointer<FTS>\n    typealias FTSEntPointer = UnsafeMutablePointer<CInterop.FTSEnt>\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/System Calls/Errno.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\n#elseif canImport(Musl)\n@preconcurrency import Musl\n#elseif canImport(Android)\n@preconcurrency import Android\n#endif\n\nextension Errno {\n    @_spi(Testing)\n    public static var _current: Errno {\n        get {\n            #if canImport(Darwin)\n            return Errno(rawValue: Darwin.errno)\n            #elseif canImport(Glibc)\n            return Errno(rawValue: Glibc.errno)\n            #elseif canImport(Musl)\n            return Errno(rawValue: Musl.errno)\n            #elseif canImport(Android)\n            return Errno(rawValue: Android.errno)\n            #endif\n        }\n        set {\n            #if canImport(Darwin)\n            Darwin.errno = newValue.rawValue\n            #elseif canImport(Glibc)\n            Glibc.errno = newValue.rawValue\n            #elseif canImport(Musl)\n            Musl.errno = newValue.rawValue\n            #elseif canImport(Android)\n            Android.errno = newValue.rawValue\n            #endif\n        }\n    }\n\n    fileprivate static func clear() {\n        #if canImport(Darwin)\n        Darwin.errno = 0\n        #elseif canImport(Glibc)\n        Glibc.errno = 0\n        #elseif canImport(Musl)\n        Musl.errno = 0\n        #elseif canImport(Android)\n        Android.errno = 0\n        #endif\n    }\n}\n\n/// Returns a `Result` representing the value returned from the given closure\n/// or an `Errno` if that value was -1.\n///\n/// If desired this function can call the closure in a loop until it does not\n/// result in `Errno` being `.interrupted`.\n@_spi(Testing)\npublic func valueOrErrno<I: FixedWidthInteger>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> I\n) -> Result<I, Errno> {\n    while true {\n        Errno.clear()\n        let result = fn()\n        if result == -1 {\n            let errno = Errno._current\n            if errno == .interrupted, retryOnInterrupt {\n                continue\n            } else {\n                return .failure(errno)\n            }\n        } else {\n            return .success(result)\n        }\n    }\n}\n\n/// As `valueOrErrno` but discards the success value.\n@_spi(Testing)\npublic func nothingOrErrno<I: FixedWidthInteger>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> I\n) -> Result<Void, Errno> {\n    valueOrErrno(retryOnInterrupt: retryOnInterrupt, fn).map { _ in }\n}\n\n/// Returns a `Result` representing the value returned from the given closure\n/// or an `Errno` if that value was `nil`.\n///\n/// If desired this function can call the closure in a loop until it does not\n/// result in `Errno` being `.interrupted`. `Errno` is only checked if the\n/// closure returns `nil`.\n@_spi(Testing)\npublic func optionalValueOrErrno<R>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> R?\n) -> Result<R?, Errno> {\n    while true {\n        Errno.clear()\n        if let result = fn() {\n            return .success(result)\n        } else {\n            let errno = Errno._current\n            if errno == .interrupted, retryOnInterrupt {\n                continue\n            } else if errno.rawValue == 0 {\n                return .success(nil)\n            } else {\n                return .failure(errno)\n            }\n        }\n    }\n}\n\n/// As `valueOrErrno` but unconditionally checks the current `Errno`.\n@_spi(Testing)\npublic func valueOrErrno<R>(\n    retryOnInterrupt: Bool = true,\n    _ fn: () -> R\n) -> Result<R, Errno> {\n    while true {\n        Errno.clear()\n        let value = fn()\n        let errno = Errno._current\n        if errno.rawValue == 0 {\n            return .success(value)\n        } else if errno == .interrupted, retryOnInterrupt {\n            continue\n        } else {\n            return .failure(errno)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/System Calls/FileDescriptor+Syscalls.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\nimport CNIOLinux\n#endif\n\nextension FileDescriptor {\n    /// Opens or creates a file for reading or writing.\n    ///\n    /// The corresponding C function is `fdopenat`.\n    ///\n    /// - Parameters:\n    ///   - path: The location of the file to open. If the path is relative then the file is opened\n    ///       relative to the descriptor.\n    ///   - mode: The read and write access to use.\n    ///   - options: The behavior for opening the file.\n    ///   - permissions: The file permissions to use for created files.\n    ///   - retryOnInterrupt: Whether to retry the operation if it throws `Errno.interrupted`. The\n    ///       default is true. Pass false to try only once and throw an error upon interruption.\n    /// - Returns: A file descriptor for the open file.\n    @_spi(Testing)\n    public func `open`(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        retryOnInterrupt: Bool = true\n    ) -> Result<FileDescriptor, Errno> {\n        let oFlag = mode.rawValue | options.rawValue\n        let rawValue = valueOrErrno(retryOnInterrupt: retryOnInterrupt) {\n            path.withPlatformString {\n                if let permissions = permissions {\n                    return system_fdopenat(self.rawValue, $0, oFlag, permissions.rawValue)\n                } else {\n                    precondition(!options.contains(.create), \"Create must be given permissions\")\n                    return system_fdopenat(self.rawValue, $0, oFlag)\n                }\n            }\n        }\n\n        return rawValue.map { FileDescriptor(rawValue: $0) }\n    }\n\n    /// Returns information about the status of the open file.\n    ///\n    /// The corresponding C function is `fstat`.\n    ///\n    /// - Returns: Information about the open file.\n    @_spi(Testing)\n    public func status() -> Result<CInterop.Stat, Errno> {\n        var status = CInterop.Stat()\n        return nothingOrErrno(retryOnInterrupt: false) {\n            system_fstat(self.rawValue, &status)\n        }.map { status }\n    }\n\n    /// Sets the permission bits of the open file.\n    ///\n    /// The corresponding C function is `fchmod`.\n    ///\n    /// - Parameters:\n    ///   - mode: The permissions to set on the file.\n    ///   - retryOnInterrupt: Whether to retry the operation if it throws `Errno.interrupted`. The\n    ///       default is true. Pass false to try only once and throw an error upon interruption.\n    @_spi(Testing)\n    public func changeMode(\n        _ mode: FilePermissions,\n        retryOnInterrupt: Bool = true\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: retryOnInterrupt) {\n            system_fchmod(self.rawValue, mode.rawValue)\n        }\n    }\n\n    /// List the names of extended attributes.\n    ///\n    /// The corresponding C function is `flistxattr`.\n    ///\n    /// - Parameter buffer: The buffer into which names are written. Names are written are NULL\n    ///     terminated UTF-8 strings and are returned in an arbitrary order. There is no padding\n    ///     between strings. If `buffer` is `nil` then the return value is the size of the buffer\n    ///     required to list all extended attributes. If there is not enough space in the `buffer`\n    ///     then `Errno.outOfRange` is returned.\n    /// - Returns: The size of the extended attribute list.\n    @_spi(Testing)\n    public func listExtendedAttributes(\n        _ buffer: UnsafeMutableBufferPointer<CChar>?\n    ) -> Result<Int, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            system_flistxattr(self.rawValue, buffer?.baseAddress, buffer?.count ?? 0)\n        }\n    }\n\n    /// Get the value of the named extended attribute.\n    ///\n    /// The corresponding C function is `fgetxattr`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the extended attribute.\n    ///   - buffer: The buffer into which the value is written. If `buffer` is `nil` then the return\n    ///       value is the size of the buffer required to read the value. If there is not enough\n    ///       space in the `buffer` then `Errno.outOfRange` is returned.\n    /// - Returns: The size of the extended attribute value.\n    @_spi(Testing)\n    public func getExtendedAttribute(\n        named name: String,\n        buffer: UnsafeMutableRawBufferPointer?\n    ) -> Result<Int, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            name.withPlatformString {\n                system_fgetxattr(self.rawValue, $0, buffer?.baseAddress, buffer?.count ?? 0)\n            }\n        }\n    }\n\n    /// Set the value of the named extended attribute.\n    ///\n    /// The corresponding C function is `fsetxattr`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the extended attribute.\n    ///   - value: The data to set for the attribute.\n    @_spi(Testing)\n    public func setExtendedAttribute(\n        named name: String,\n        to value: UnsafeRawBufferPointer?\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            name.withPlatformString { namePointer in\n                system_fsetxattr(self.rawValue, namePointer, value?.baseAddress, value?.count ?? 0)\n            }\n        }\n    }\n\n    /// Remove the value for the named extended attribute.\n    ///\n    /// The corresponding C function is `fremovexattr`.\n    ///\n    /// - Parameters:\n    ///   - name: The name of the extended attribute.\n    @_spi(Testing)\n    public func removeExtendedAttribute(_ name: String) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            name.withPlatformString {\n                system_fremovexattr(self.rawValue, $0)\n            }\n        }\n    }\n\n    /// Synchronize modified data and metadata to a permanent storage device.\n    ///\n    /// The corresponding C functions is `fsync`.\n    ///\n    /// - Parameter retryOnInterrupt: Whether the call should be retried on `Errno.interrupted`.\n    @_spi(Testing)\n    public func synchronize(retryOnInterrupt: Bool = true) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: retryOnInterrupt) {\n            system_fsync(self.rawValue)\n        }\n    }\n\n    /// Returns a pointer to a directory structure.\n    ///\n    /// The corresponding C function is `fdopendir`\n    ///\n    /// - Important: Calling this function cedes ownership of the file descriptor to the system. The\n    ///     caller should not modify the descriptor or close the descriptor via `close()`. Once\n    ///     directory iteration has been completed then `Libc.closdir(_:)` must be called.\n    internal func opendir() -> Result<CInterop.DirPointer, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            libc_fdopendir(self.rawValue)\n        }\n    }\n}\n\nextension FileDescriptor {\n    func listExtendedAttributes() -> Result<[String], Errno> {\n        // Required capacity is returned if a no buffer is passed to flistxattr.\n        self.listExtendedAttributes(nil).flatMap { capacity in\n            guard capacity > 0 else {\n                // Required capacity is zero: no attributes to read.\n                return .success([])\n            }\n\n            // Read and decode.\n            var buffer = [UInt8](repeating: 0, count: capacity)\n            return buffer.withUnsafeMutableBufferPointer { pointer in\n                pointer.withMemoryRebound(to: CChar.self) { buffer in\n                    self.listExtendedAttributes(buffer)\n                }\n            }.map { size in\n                // The buffer contains null terminated C-strings.\n                var attributes = [String]()\n                var slice = buffer.prefix(size)\n                while let index = slice.firstIndex(of: 0) {\n                    // TODO: can we do this more cheaply?\n                    let prefix = slice[..<index]\n                    attributes.append(String(decoding: Array(prefix), as: UTF8.self))\n                    slice = slice.dropFirst(prefix.count + 1)\n                }\n\n                return attributes\n            }\n        }\n    }\n\n    func readExtendedAttribute(named name: String) -> Result<[UInt8], Errno> {\n        // Required capacity is returned if a no buffer is passed to fgetxattr.\n        self.getExtendedAttribute(named: name, buffer: nil).flatMap { capacity in\n            guard capacity > 0 else {\n                // Required capacity is zero: no values to read.\n                return .success([])\n            }\n\n            // Read and decode.\n            var buffer = [UInt8](repeating: 0, count: capacity)\n            return buffer.withUnsafeMutableBytes { bytes in\n                self.getExtendedAttribute(named: name, buffer: bytes)\n            }.map { size in\n                // Remove any trailing zeros.\n                buffer.removeLast(buffer.count - size)\n                return buffer\n            }\n        }\n    }\n}\n\nextension FileDescriptor {\n    func readChunk(fromAbsoluteOffset offset: Int64, length: Int64) -> Result<ByteBuffer, Error> {\n        self._readChunk(fromAbsoluteOffset: offset, length: length)\n    }\n\n    func readChunk(length: Int64) -> Result<ByteBuffer, Error> {\n        self._readChunk(fromAbsoluteOffset: nil, length: length)\n    }\n\n    private func _readChunk(\n        fromAbsoluteOffset offset: Int64?,\n        length: Int64\n    ) -> Result<ByteBuffer, Error> {\n        // This is used by the `FileChunks` and means we allocate for every chunk that we read for\n        // the file. That's fine for now because the syscall cost is likely to be the dominant\n        // factor here. However we should investigate whether it's possible to have a pool of\n        // buffers which we can reuse. This would need to be at least as large as the high watermark\n        // of the chunked file for it to be useful.\n        Result {\n            var buffer = ByteBuffer()\n            try buffer.writeWithUnsafeMutableBytes(minimumWritableBytes: Int(length)) { buffer in\n                let bufferPointer: UnsafeMutableRawBufferPointer\n\n                // Don't vend a buffer which is larger than `length`; we can read less but we must\n                // not read more.\n                if length < buffer.count {\n                    bufferPointer = UnsafeMutableRawBufferPointer(\n                        start: buffer.baseAddress,\n                        count: Int(length)\n                    )\n                } else {\n                    bufferPointer = buffer\n                }\n\n                if let offset {\n                    return try self.read(fromAbsoluteOffset: offset, into: bufferPointer)\n                } else {\n                    return try self.read(into: bufferPointer)\n                }\n            }\n            return buffer\n        }\n    }\n}\n\nextension FileDescriptor {\n    func write(\n        contentsOf bytes: some Sequence<UInt8>,\n        toAbsoluteOffset offset: Int64\n    ) -> Result<Int64, Error> {\n        Result {\n            Int64(try self.writeAll(toAbsoluteOffset: offset, bytes))\n        }\n    }\n\n    func write(\n        contentsOf bytes: some Sequence<UInt8>\n    ) -> Result<Int64, Error> {\n        Result {\n            Int64(try self.writeAll(bytes))\n        }\n    }\n}\n\n#if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\nextension FileDescriptor.OpenOptions {\n    static var temporaryFile: Self {\n        Self(rawValue: CNIOLinux_O_TMPFILE)\n    }\n}\n\nextension FileDescriptor {\n    static var currentWorkingDirectory: Self {\n        Self(rawValue: AT_FDCWD)\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/System Calls/Mocking.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// This source file is part of the Swift System open source project//\n// Copyright (c) 2020 Apple Inc. and the Swift System project authors\n// Licensed under Apache License v2.0 with Runtime Library Exception//\n// See https://swift.org/LICENSE.txt for license information\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n// Syscall mocking support.\n//\n// NOTE: This is currently the bare minimum needed for System's testing purposes, though we do\n// eventually want to expose some solution to users.\n//\n// Mocking is contextual, accessible through MockingDriver.withMockingEnabled. Mocking\n// state, including whether it is enabled, is stored in thread-local storage. Mocking is only\n// enabled in testing builds of System currently, to minimize runtime overhead of release builds.\n//\n\n#if ENABLE_MOCKING\n@_spi(Testing)\npublic struct Trace {\n    @_spi(Testing)\n    public struct Entry {\n        @_spi(Testing)\n        public var name: String\n        @_spi(Testing)\n        public var arguments: [AnyHashable]\n\n        @_spi(Testing)\n        public init(name: String, _ arguments: [AnyHashable]) {\n            self.name = name\n            self.arguments = arguments\n        }\n    }\n\n    private var entries: [Entry] = []\n    private var firstEntry: Int = 0\n\n    @_spi(Testing)\n    public var isEmpty: Bool { firstEntry >= entries.count }\n\n    @_spi(Testing)\n    public mutating func dequeue() -> Entry? {\n        guard !self.isEmpty else { return nil }\n        defer { firstEntry += 1 }\n        return entries[firstEntry]\n    }\n\n    fileprivate mutating func add(_ e: Entry) {\n        entries.append(e)\n    }\n}\n\n@available(*, unavailable)\nextension Trace: Sendable {}\n\n@available(*, unavailable)\nextension Trace.Entry: Sendable {}\n\n@_spi(Testing)\npublic enum ForceErrno: Equatable, Sendable {\n    case none\n    case always(errno: CInt)\n\n    case counted(errno: CInt, count: Int)\n}\n\n// Provide access to the driver, context, and trace stack of mocking\n@_spi(Testing)\npublic final class MockingDriver {\n    // Record syscalls and their arguments\n    @_spi(Testing)\n    public var trace = Trace()\n\n    // Mock errors inside syscalls\n    @_spi(Testing)\n    public var forceErrno = ForceErrno.none\n\n    // Whether we should pretend to be Windows for syntactic operations\n    // inside FilePath\n    fileprivate var forceWindowsSyntaxForPaths = false\n}\n\n@available(*, unavailable)\nextension MockingDriver: Sendable {}\n\nprivate let driverKey: _PlatformTLSKey = { makeTLSKey() }()\n\ninternal var currentMockingDriver: MockingDriver? {\n    #if !ENABLE_MOCKING\n    fatalError(\"Contextual mocking in non-mocking build\")\n    #endif\n    guard let rawPtr = getTLS(driverKey) else { return nil }\n\n    return Unmanaged<MockingDriver>.fromOpaque(rawPtr).takeUnretainedValue()\n}\n\nextension MockingDriver {\n    /// Enables mocking for the duration of `f` with a clean trace queue\n    /// Restores prior mocking status and trace queue after execution\n    @_spi(Testing)\n    public static func withMockingEnabled(\n        _ f: (MockingDriver) throws -> Void\n    ) rethrows {\n        let priorMocking = currentMockingDriver\n        let driver = MockingDriver()\n\n        defer {\n            if let object = priorMocking {\n                setTLS(driverKey, Unmanaged.passUnretained(object).toOpaque())\n            } else {\n                setTLS(driverKey, nil)\n            }\n            _fixLifetime(driver)\n        }\n\n        setTLS(driverKey, Unmanaged.passUnretained(driver).toOpaque())\n        return try f(driver)\n    }\n}\n\n// Check TLS for mocking\n@inline(never)\nprivate var contextualMockingEnabled: Bool {\n    currentMockingDriver != nil\n}\n\nextension MockingDriver {\n    @_spi(Testing)\n    public static var enabled: Bool { mockingEnabled }\n\n    @_spi(Testing)\n    public static var forceWindowsPaths: Bool {\n        currentMockingDriver?.forceWindowsSyntaxForPaths ?? false\n    }\n}\n\n#endif  // ENABLE_MOCKING\n\n@inline(__always)\ninternal var mockingEnabled: Bool {\n    // Fast constant-foldable check for release builds\n    #if ENABLE_MOCKING\n    return contextualMockingEnabled\n    #else\n    return false\n    #endif\n}\n\n@inline(__always)\ninternal var forceWindowsPaths: Bool {\n    #if !ENABLE_MOCKING\n    return false\n    #else\n    return MockingDriver.forceWindowsPaths\n    #endif\n}\n\n#if ENABLE_MOCKING\n// Strip the mock_system prefix and the arg list suffix\nprivate func originalSyscallName(_ function: String) -> String {\n    // `function` must be of format `system_<name>(<parameters>)`\n    for `prefix` in [\"system_\", \"libc_\"] {\n        if function.starts(with: `prefix`) {\n            return String(function.dropFirst(`prefix`.count).prefix { $0 != \"(\" })\n        }\n    }\n    preconditionFailure(\"\\(function) must start with 'system_' or 'libc_'\")\n}\n\nprivate func mockImpl(syscall name: String, args: [AnyHashable]) -> CInt {\n    precondition(mockingEnabled)\n    let origName = originalSyscallName(name)\n    guard let driver = currentMockingDriver else {\n        fatalError(\"Mocking requested from non-mocking context\")\n    }\n\n    driver.trace.add(Trace.Entry(name: origName, args))\n\n    switch driver.forceErrno {\n    case .none: break\n    case .always(let e):\n        system_errno = e\n        return -1\n    case .counted(let e, let count):\n        assert(count >= 1)\n        system_errno = e\n        driver.forceErrno = count > 1 ? .counted(errno: e, count: count - 1) : .none\n        return -1\n    }\n\n    return 0\n}\n\nprivate func reinterpret(_ args: [AnyHashable?]) -> [AnyHashable] {\n    args.map { arg in\n        switch arg {\n        case let charPointer as UnsafePointer<CInterop.PlatformChar>:\n            return String(_errorCorrectingPlatformString: charPointer)\n        case is UnsafeMutablePointer<CInterop.PlatformChar>:\n            return \"<buffer>\"\n        case is UnsafeMutableRawPointer:\n            return \"<buffer>\"\n        case is UnsafeRawPointer:\n            return \"<buffer>\"\n        case .none:\n            return \"nil\"\n        case let .some(arg):\n            return arg\n        }\n    }\n}\n\nfunc mock(\n    syscall name: String = #function,\n    _ args: AnyHashable?...\n) -> CInt {\n    mockImpl(syscall: name, args: reinterpret(args))\n}\n\nfunc mockInt(\n    syscall name: String = #function,\n    _ args: AnyHashable?...\n) -> Int {\n    Int(mockImpl(syscall: name, args: reinterpret(args)))\n}\n\n#endif  // ENABLE_MOCKING\n\n// Force paths to be treated as Windows syntactically if `enabled` is\n// true.\n@_spi(Testing)\npublic func _withWindowsPaths(enabled: Bool, _ body: () -> Void) {\n    #if ENABLE_MOCKING\n    guard enabled else {\n        body()\n        return\n    }\n    MockingDriver.withMockingEnabled { driver in\n        driver.forceWindowsSyntaxForPaths = true\n        body()\n    }\n    #else\n    body()\n    #endif\n}\n\n// Internal wrappers and typedefs which help reduce #if littering in System's\n// code base.\n\n// TODO: Should CSystem just include all the header files we need?\n\ninternal typealias _COffT = off_t\n\n// MARK: syscalls and variables\n\n#if canImport(Darwin)\ninternal var system_errno: CInt {\n    get { Darwin.errno }\n    set { Darwin.errno = newValue }\n}\n#elseif canImport(Glibc)\ninternal var system_errno: CInt {\n    get { Glibc.errno }\n    set { Glibc.errno = newValue }\n}\n#elseif canImport(Musl)\ninternal var system_errno: CInt {\n    get { Musl.errno }\n    set { Musl.errno = newValue }\n}\n#elseif canImport(Android)\ninternal var system_errno: CInt {\n    get { Android.errno }\n    set { Android.errno = newValue }\n}\n#endif\n\n// MARK: C stdlib decls\n\n// Convention: `system_foo` is system's wrapper for `foo`.\n\ninternal func system_strerror(_ __errnum: Int32) -> UnsafeMutablePointer<Int8>! {\n    strerror(__errnum)\n}\n\ninternal func system_strlen(_ s: UnsafePointer<CChar>) -> Int {\n    strlen(s)\n}\ninternal func system_strlen(_ s: UnsafeMutablePointer<CChar>) -> Int {\n    strlen(s)\n}\n\n// Convention: `system_platform_foo` is a\n// platform-representation-abstracted wrapper around `foo`-like functionality.\n// Type and layout differences such as the `char` vs `wchar` are abstracted.\n//\n\n// strlen for the platform string\ninternal func system_platform_strlen(_ s: UnsafePointer<CInterop.PlatformChar>) -> Int {\n    strlen(s)\n}\n\n// memset for raw buffers\n// FIXME: Do we really not have something like this in the stdlib already?\ninternal func system_memset(\n    _ buffer: UnsafeMutableRawBufferPointer,\n    to byte: UInt8\n) {\n    guard buffer.count > 0 else { return }\n    memset(buffer.baseAddress!, CInt(byte), buffer.count)\n}\n\n// Interop between String and platfrom string\nextension String {\n    internal func _withPlatformString<Result>(\n        _ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result\n    ) rethrows -> Result {\n        // Need to #if because CChar may be signed\n        try withCString(body)\n    }\n\n    internal init?(_platformString platformString: UnsafePointer<CInterop.PlatformChar>) {\n        // Need to #if because CChar may be signed\n        self.init(validatingCString: platformString)\n    }\n\n    internal init(\n        _errorCorrectingPlatformString platformString: UnsafePointer<CInterop.PlatformChar>\n    ) {\n        // Need to #if because CChar may be signed\n        self.init(cString: platformString)\n    }\n}\n\ninternal typealias _PlatformTLSKey = pthread_key_t\n\ninternal func makeTLSKey() -> _PlatformTLSKey {\n    var raw = pthread_key_t()\n    guard 0 == pthread_key_create(&raw, nil) else {\n        fatalError(\"Unable to create key\")\n    }\n    return raw\n}\n\ninternal func setTLS(_ key: _PlatformTLSKey, _ p: UnsafeMutableRawPointer?) {\n    guard 0 == pthread_setspecific(key, p) else {\n        fatalError(\"Unable to set TLS\")\n    }\n}\n\ninternal func getTLS(_ key: _PlatformTLSKey) -> UnsafeMutableRawPointer? {\n    pthread_getspecific(key)\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/System Calls/Syscall.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\nimport CNIODarwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\nimport CNIOLinux\n#endif\n\n@_spi(Testing)\npublic enum Syscall: Sendable {\n    @_spi(Testing)\n    public static func stat(path: FilePath) -> Result<CInterop.Stat, Errno> {\n        path.withPlatformString { platformPath in\n            var status = CInterop.Stat()\n            return valueOrErrno(retryOnInterrupt: false) {\n                system_stat(platformPath, &status)\n            }.map { _ in\n                status\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func lstat(path: FilePath) -> Result<CInterop.Stat, Errno> {\n        path.withPlatformString { platformPath in\n            var status = CInterop.Stat()\n            return valueOrErrno(retryOnInterrupt: false) {\n                system_lstat(platformPath, &status)\n            }.map { _ in\n                status\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func mkdir(at path: FilePath, permissions: FilePermissions) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString { p in\n                system_mkdir(p, permissions.rawValue)\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func rename(from old: FilePath, to new: FilePath) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_rename(oldPath, newPath)\n                }\n            }\n        }\n    }\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static func rename(\n        from old: FilePath,\n        to new: FilePath,\n        options: RenameOptions\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_renamex_np(oldPath, newPath, options.rawValue)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func rename(\n        from old: FilePath,\n        relativeTo oldFD: FileDescriptor,\n        to new: FilePath,\n        relativeTo newFD: FileDescriptor,\n        options: RenameOptions\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_renameatx_np(\n                        oldFD.rawValue,\n                        oldPath,\n                        newFD.rawValue,\n                        newPath,\n                        options.rawValue\n                    )\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public struct RenameOptions: OptionSet, Sendable {\n        public var rawValue: CUnsignedInt\n\n        public init(rawValue: CUnsignedInt) {\n            self.rawValue = rawValue\n        }\n\n        public static var exclusive: Self {\n            Self(rawValue: UInt32(bitPattern: RENAME_EXCL))\n        }\n\n        public static var swap: Self {\n            Self(rawValue: UInt32(bitPattern: RENAME_SWAP))\n        }\n    }\n    #endif\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func rename(\n        from old: FilePath,\n        relativeTo oldFD: FileDescriptor,\n        to new: FilePath,\n        relativeTo newFD: FileDescriptor,\n        flags: RenameAtFlags\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            old.withPlatformString { oldPath in\n                new.withPlatformString { newPath in\n                    system_renameat2(\n                        oldFD.rawValue,\n                        oldPath,\n                        newFD.rawValue,\n                        newPath,\n                        flags.rawValue\n                    )\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public struct RenameAtFlags: OptionSet {\n        public var rawValue: CUnsignedInt\n\n        public init(rawValue: CUnsignedInt) {\n            self.rawValue = rawValue\n        }\n\n        public static var exclusive: Self {\n            Self(rawValue: CNIOLinux_RENAME_NOREPLACE)\n        }\n\n        public static var swap: Self {\n            Self(rawValue: CNIOLinux_RENAME_EXCHANGE)\n        }\n    }\n    #endif\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public struct LinkAtFlags: OptionSet {\n        @_spi(Testing)\n        public var rawValue: CInt\n\n        @_spi(Testing)\n        public init(rawValue: CInt) {\n            self.rawValue = rawValue\n        }\n\n        @_spi(Testing)\n        public static var emptyPath: Self {\n            Self(rawValue: CNIOLinux_AT_EMPTY_PATH)\n        }\n\n        @_spi(Testing)\n        public static var followSymbolicLinks: Self {\n            Self(rawValue: AT_SYMLINK_FOLLOW)\n        }\n    }\n\n    @_spi(Testing)\n    public static func linkAt(\n        from source: FilePath,\n        relativeTo sourceFD: FileDescriptor,\n        to destination: FilePath,\n        relativeTo destinationFD: FileDescriptor,\n        flags: LinkAtFlags\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_linkat(\n                        sourceFD.rawValue,\n                        src,\n                        destinationFD.rawValue,\n                        dst,\n                        flags.rawValue\n                    )\n                }\n            }\n        }\n    }\n    #endif\n\n    @_spi(Testing)\n    public static func link(\n        from source: FilePath,\n        to destination: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_link(src, dst)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func unlink(path: FilePath) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString { ptr in\n                system_unlink(ptr)\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func unlinkat(\n        path: FilePath,\n        relativeTo directoryDescriptor: FileDescriptor,\n        flags: CInt = 0\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString { ptr in\n                system_unlinkat(directoryDescriptor.rawValue, ptr, flags)\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func symlink(\n        to destination: FilePath,\n        from source: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_symlink(dst, src)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func symlinkat(\n        to destination: FilePath,\n        in directoryDescriptor: FileDescriptor,\n        from source: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            source.withPlatformString { src in\n                destination.withPlatformString { dst in\n                    system_symlinkat(dst, directoryDescriptor.rawValue, src)\n                }\n            }\n        }\n    }\n\n    @_spi(Testing)\n    public static func readlink(at path: FilePath) -> Result<FilePath, Errno> {\n        do {\n            let resolved = try path.withPlatformString { p in\n                try String(customUnsafeUninitializedCapacity: Int(CInterop.maxPathLength)) { pointer in\n                    let result = pointer.withMemoryRebound(to: CInterop.PlatformChar.self) { ptr in\n                        valueOrErrno(retryOnInterrupt: false) {\n                            system_readlink(p, ptr.baseAddress!, ptr.count)\n                        }\n                    }\n                    return try result.get()\n                }\n            }\n            return .success(FilePath(resolved))\n        } catch let error as Errno {\n            return .failure(error)\n        } catch {\n            // Shouldn't happen: we deal in Result types and only ever with Errno.\n            fatalError(\"Unexpected error '\\(error)' caught\")\n        }\n    }\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func sendfile(\n        to output: FileDescriptor,\n        from input: FileDescriptor,\n        offset: Int,\n        size: Int\n    ) -> Result<Int, Errno> {\n        valueOrErrno(retryOnInterrupt: false) {\n            system_sendfile(output.rawValue, input.rawValue, off_t(offset), size)\n        }\n    }\n    #endif\n\n    @_spi(Testing)\n    public static func futimens(\n        fileDescriptor fd: FileDescriptor,\n        times: UnsafePointer<timespec>?\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            system_futimens(fd.rawValue, times)\n        }\n    }\n\n    #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func getuid() -> uid_t {\n        system_getuid()\n    }\n    #endif\n}\n\n@_spi(Testing)\npublic enum Libc: Sendable {\n    static func readdir(\n        _ dir: CInterop.DirPointer\n    ) -> Result<UnsafeMutablePointer<CInterop.DirEnt>?, Errno> {\n        optionalValueOrErrno(retryOnInterrupt: false) {\n            libc_readdir(dir)\n        }\n    }\n\n    static func closedir(\n        _ dir: CInterop.DirPointer\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            libc_closedir(dir)\n        }\n    }\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static func fcopyfile(\n        from source: FileDescriptor,\n        to destination: FileDescriptor,\n        state: copyfile_state_t?,\n        flags: copyfile_flags_t\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            libc_fcopyfile(source.rawValue, destination.rawValue, state, flags)\n        }\n    }\n    #endif\n\n    #if canImport(Darwin)\n    @_spi(Testing)\n    public static func copyfile(\n        from source: FilePath,\n        to destination: FilePath,\n        state: copyfile_state_t?,\n        flags: copyfile_flags_t\n    ) -> Result<Void, Errno> {\n        source.withPlatformString { sourcePath in\n            destination.withPlatformString { destinationPath in\n                nothingOrErrno(retryOnInterrupt: false) {\n                    libc_copyfile(sourcePath, destinationPath, state, flags)\n                }\n            }\n        }\n    }\n    #endif\n\n    @_spi(Testing)\n    public static func remove(\n        _ path: FilePath\n    ) -> Result<Void, Errno> {\n        nothingOrErrno(retryOnInterrupt: false) {\n            path.withPlatformString {\n                libc_remove($0)\n            }\n        }\n    }\n\n    static func getcwd() -> Result<FilePath, Errno> {\n        var buffer = [CInterop.PlatformChar](\n            repeating: 0,\n            count: Int(CInterop.maxPathLength)\n        )\n\n        return optionalValueOrErrno(retryOnInterrupt: false) {\n            buffer.withUnsafeMutableBufferPointer { pointer in\n                libc_getcwd(pointer.baseAddress!, pointer.count)\n            }\n        }.map { ptr in\n            // 'ptr' is just the input pointer, we should ignore it and just rely on the bytes\n            // in buffer.\n            //\n            // At this point 'ptr' must be non-nil, because if it were 'nil' we should be on the\n            // error path.\n            precondition(ptr != nil)\n            return FilePath(platformString: buffer)\n        }\n    }\n\n    #if !os(Android)\n    static func constr(_ name: CInt) -> Result<String, Errno> {\n        var buffer = [UInt8](repeating: 0, count: 128)\n\n        repeat {\n            let result = valueOrErrno(retryOnInterrupt: false) {\n                buffer.withUnsafeMutableBufferPointer { pointer in\n                    pointer.withMemoryRebound(to: CInterop.PlatformChar.self) { pointer in\n                        libc_confstr(name, pointer.baseAddress!, pointer.count)\n                    }\n                }\n            }\n\n            switch result {\n            case let .success(length):\n                let nullTerminationIndex = buffer.firstIndex(of: 0) ?? buffer.endIndex\n                if length <= buffer.count {\n                    return .success(String(decoding: buffer[..<nullTerminationIndex], as: UTF8.self))\n                } else {\n                    // The buffer wasn't long enough. Double and try again.\n                    buffer.append(contentsOf: repeatElement(0, count: buffer.capacity))\n                }\n            case let .failure(errno):\n                return .failure(errno)\n            }\n        } while true\n    }\n    #endif\n\n    static func ftsOpen(_ path: FilePath, options: FTSOpenOptions) -> Result<CInterop.FTSPointer, Errno> {\n        // 'fts_open' needs an unsafe mutable pointer to the C-string, `FilePath` doesn't offer this\n        // so copy out its bytes.\n        var pathBytes = path.withPlatformString { pointer in\n            // Length excludes the null terminator, so add it back.\n            let bufferPointer = UnsafeBufferPointer(start: pointer, count: path.length + 1)\n            return Array(bufferPointer)\n        }\n\n        return valueOrErrno {\n            pathBytes.withUnsafeMutableBufferPointer { pointer in\n                // The array must be terminated with a nil.\n                libc_fts_open([pointer.baseAddress, nil], options.rawValue)\n            }\n        }\n    }\n\n    /// Options passed to 'fts_open'.\n    struct FTSOpenOptions: OptionSet {\n        var rawValue: CInt\n\n        /// Don't change directory while walking the filesystem hierarchy.\n        static var noChangeDir: Self { Self(rawValue: FTS_NOCHDIR) }\n\n        /// Return FTS entries for symbolic links rather than their targets.\n        static var physical: Self { Self(rawValue: FTS_PHYSICAL) }\n\n        /// Return FTS entries for the targets of symbolic links.\n        static var logical: Self { Self(rawValue: FTS_LOGICAL) }\n    }\n\n    static func ftsRead(\n        _ pointer: CInterop.FTSPointer\n    ) -> Result<UnsafeMutablePointer<CInterop.FTSEnt>?, Errno> {\n        optionalValueOrErrno {\n            libc_fts_read(pointer)\n        }\n    }\n\n    static func ftsClose(\n        _ pointer: CInterop.FTSPointer\n    ) -> Result<Void, Errno> {\n        nothingOrErrno {\n            libc_fts_close(pointer)\n        }\n    }\n\n    @_spi(Testing)\n    public static func homeDirectoryFromEnvironment() -> FilePath? {\n        if let home = getenv(\"HOME\"), home.pointee != 0 {\n            return FilePath(String(cString: home))\n        }\n        #if os(Windows)\n        if let profile = getenv(\"USERPROFILE\"), profile.pointee != 0 {\n            return FilePath(String(cString: profile))\n        }\n        #endif\n        return nil\n    }\n\n    #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    @_spi(Testing)\n    public static func homeDirectoryFromPasswd() -> Result<FilePath, Errno> {\n        let uid = Syscall.getuid()\n        var pwd = passwd()\n        var result: UnsafeMutablePointer<passwd>? = nil\n\n        return withUnsafeTemporaryAllocation(of: CChar.self, capacity: 1024) { buffer in\n            let callResult = nothingOrErrno(retryOnInterrupt: true) {\n                libc_getpwuid_r(\n                    uid,\n                    &pwd,\n                    buffer.baseAddress!,\n                    buffer.count,\n                    &result\n                )\n            }\n            switch callResult {\n            case .success:\n                guard result != nil, let directoryPointer = pwd.pw_dir else {\n                    return .failure(.noSuchFileOrDirectory)\n                }\n                return .success(FilePath(String(cString: directoryPointer)))\n            case .failure(let errno):\n                return .failure(errno)\n            }\n        }\n    }\n    #endif\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/System Calls/Syscalls.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\nimport CNIODarwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Android)\n@preconcurrency import Android\nimport CNIOLinux\n#endif\n\n// MARK: - system\n\n/// openat(2): Open or create a file for reading or writing\nfunc system_fdopenat(\n    _ fd: FileDescriptor.RawValue,\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ oflag: Int32\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, path, oflag)\n    }\n    #endif\n    return openat(fd, path, oflag)\n}\n\n/// openat(2): Open or create a file for reading or writing\nfunc system_fdopenat(\n    _ fd: FileDescriptor.RawValue,\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ oflag: Int32,\n    _ mode: CInterop.Mode\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, path, oflag, mode)\n    }\n    #endif\n    return openat(fd, path, oflag, mode)\n}\n\n/// stat(2): Get file status\nfunc system_stat(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ info: inout CInterop.Stat\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return stat(path, &info)\n}\n\n/// lstat(2): Get file status\ninternal func system_lstat(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ info: inout CInterop.Stat\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return lstat(path, &info)\n}\n\n/// fstat(2): Get file status\ninternal func system_fstat(\n    _ fd: FileDescriptor.RawValue,\n    _ info: inout CInterop.Stat\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd)\n    }\n    #endif\n    return fstat(fd, &info)\n}\n\n/// fchmod(2): Change mode of file\ninternal func system_fchmod(\n    _ fd: FileDescriptor.RawValue,\n    _ mode: CInterop.Mode\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, mode)\n    }\n    #endif\n    return fchmod(fd, mode)\n}\n\n/// fsync(2): Synchronize modifications to a file to permanent storage\ninternal func system_fsync(\n    _ fd: FileDescriptor.RawValue\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd)\n    }\n    #endif\n    return fsync(fd)\n}\n\n/// mkdir(2): Make a directory file\ninternal func system_mkdir(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ mode: CInterop.Mode\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path, mode)\n    }\n    #endif\n    return mkdir(path, mode)\n}\n\n/// symlink(2): Make symolic link to a file\ninternal func system_symlink(\n    _ destination: UnsafePointer<CInterop.PlatformChar>,\n    _ source: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(destination, source)\n    }\n    #endif\n    return symlink(destination, source)\n}\n\n/// symlinkat(2): Make symbolic link to a file relative to directory file descriptor\ninternal func system_symlinkat(\n    _ destination: UnsafePointer<CInterop.PlatformChar>,\n    _ dirfd: FileDescriptor.RawValue,\n    _ source: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(destination, dirfd, source)\n    }\n    #endif\n    return symlinkat(destination, dirfd, source)\n}\n\n/// readlink(2): Read value of a symolic link\ninternal func system_readlink(\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ buffer: UnsafeMutablePointer<CInterop.PlatformChar>,\n    _ bufferSize: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(path, buffer, bufferSize)\n    }\n    #endif\n    return readlink(path, buffer, bufferSize)\n}\n\n/// flistxattr(2): List extended attribute names\ninternal func system_flistxattr(\n    _ fd: FileDescriptor.RawValue,\n    _ namebuf: UnsafeMutablePointer<CChar>?,\n    _ size: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(fd, namebuf, size)\n    }\n    #endif\n    #if canImport(Darwin)\n    // The final parameter is 'options'; there is no equivalent on Linux.\n    return flistxattr(fd, namebuf, size, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return flistxattr(fd, namebuf, size)\n    #endif\n}\n\n/// fgetxattr(2): Get an extended attribute value\ninternal func system_fgetxattr(\n    _ fd: FileDescriptor.RawValue,\n    _ name: UnsafePointer<CChar>,\n    _ value: UnsafeMutableRawPointer?,\n    _ size: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(fd, name, value, size)\n    }\n    #endif\n\n    #if canImport(Darwin)\n    // Penultimate parameter is position which is reserved and should be zero.\n    // The final parameter is 'options'; there is no equivalent on Linux.\n    return fgetxattr(fd, name, value, size, 0, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return fgetxattr(fd, name, value, size)\n    #endif\n}\n\n/// fsetxattr(2): Set an extended attribute value\ninternal func system_fsetxattr(\n    _ fd: FileDescriptor.RawValue,\n    _ name: UnsafePointer<CChar>,\n    _ value: UnsafeRawPointer?,\n    _ size: Int\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, name, value, size)\n    }\n    #endif\n\n    // The final parameter is 'options'/'flags' on Darwin/Linux respectively.\n    #if canImport(Darwin)\n    // Penultimate parameter is position which is reserved and should be zero.\n    return fsetxattr(fd, name, value, size, 0, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return fsetxattr(fd, name, value, size, 0)\n    #endif\n}\n\n/// fremovexattr(2): Remove an extended attribute value\ninternal func system_fremovexattr(\n    _ fd: FileDescriptor.RawValue,\n    _ name: UnsafePointer<CChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, name)\n    }\n    #endif\n\n    #if canImport(Darwin)\n    // The final parameter is 'options'; there is no equivalent on Linux.\n    return fremovexattr(fd, name, 0)\n    #elseif canImport(Glibc) || canImport(Musl) || canImport(Android)\n    return fremovexattr(fd, name)\n    #endif\n}\n\n/// rename(2): Change the name of a file\ninternal func system_rename(\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ new: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(old, new)\n    }\n    #endif\n    return rename(old, new)\n}\n\n#if canImport(Darwin)\ninternal func system_renamex_np(\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CUnsignedInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(old, new, flags)\n    }\n    #endif\n    return renamex_np(old, new, flags)\n}\n\n/// renameatx_np(2): Rename a file relative to directory file descriptors\ninternal func system_renameatx_np(\n    _ oldFD: FileDescriptor.RawValue,\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ newFD: FileDescriptor.RawValue,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CUnsignedInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(oldFD, old, newFD, new, flags)\n    }\n    #endif\n    return renameatx_np(oldFD, old, newFD, new, flags)\n}\n#endif\n\n#if canImport(Glibc) || canImport(Musl) || canImport(Android)\ninternal func system_renameat2(\n    _ oldFD: FileDescriptor.RawValue,\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ newFD: FileDescriptor.RawValue,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CUnsignedInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(oldFD, old, newFD, new, flags)\n    }\n    #endif\n    return CNIOLinux_renameat2(oldFD, old, newFD, new, flags)\n}\n#endif\n\n/// link(2): Creates a new link for a file.\n#if canImport(Glibc) || canImport(Musl) || canImport(Android)\ninternal func system_linkat(\n    _ oldFD: FileDescriptor.RawValue,\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ newFD: FileDescriptor.RawValue,\n    _ new: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(oldFD, old, newFD, new, flags)\n    }\n    #endif\n    return linkat(oldFD, old, newFD, new, flags)\n}\n#endif\n\n/// link(2): Creates a new link for a file.\ninternal func system_link(\n    _ old: UnsafePointer<CInterop.PlatformChar>,\n    _ new: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(old, new)\n    }\n    #endif\n    return link(old, new)\n}\n\n/// unlink(2): Remove a directory entry.\ninternal func system_unlink(\n    _ path: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return unlink(path)\n}\n\n/// unlinkat(2): Remove a directory entry relative to a directory file descriptor\ninternal func system_unlinkat(\n    _ fd: FileDescriptor.RawValue,\n    _ path: UnsafePointer<CInterop.PlatformChar>,\n    _ flags: CInt\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, path, flags)\n    }\n    #endif\n    return unlinkat(fd, path, flags)\n}\n\n#if canImport(Glibc) || canImport(Musl) || canImport(Android)\n/// sendfile(2): Transfer data between descriptors\ninternal func system_sendfile(\n    _ outFD: CInt,\n    _ inFD: CInt,\n    _ offset: off_t,\n    _ count: Int\n) -> Int {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mockInt(outFD, inFD, offset, count)\n    }\n    #endif\n    var offset = offset\n    return sendfile(outFD, inFD, &offset, count)\n}\n#endif\n\ninternal func system_futimens(\n    _ fd: CInt,\n    _ times: UnsafePointer<timespec>?\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(fd, times)\n    }\n    #endif\n    return futimens(fd, times)\n}\n\n// MARK: - libc\n\n/// fdopendir(3): Opens a directory stream for the file descriptor\ninternal func libc_fdopendir(\n    _ fd: FileDescriptor.RawValue\n) -> CInterop.DirPointer {\n    fdopendir(fd)!\n}\n\n/// readdir(3): Returns a pointer to the next directory entry\ninternal func libc_readdir(\n    _ dir: CInterop.DirPointer\n) -> UnsafeMutablePointer<CInterop.DirEnt>? {\n    readdir(dir)\n}\n\n/// readdir(3): Closes the directory stream and frees associated structures\ninternal func libc_closedir(\n    _ dir: CInterop.DirPointer\n) -> CInt {\n    closedir(dir)\n}\n\n/// remove(3): Remove directory entry\ninternal func libc_remove(\n    _ path: UnsafePointer<CInterop.PlatformChar>\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(path)\n    }\n    #endif\n    return remove(path)\n}\n\n#if canImport(Darwin)\n/// fcopyfile(3): Copy a file from one file to another.\ninternal func libc_fcopyfile(\n    _ from: CInt,\n    _ to: CInt,\n    _ state: copyfile_state_t?,\n    _ flags: copyfile_flags_t\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(from, to, state, flags)\n    }\n    #endif\n    return fcopyfile(from, to, state, flags)\n}\n#endif\n\n#if canImport(Darwin)\n/// copyfile(3): Copy a file from one file to another.\ninternal func libc_copyfile(\n    _ from: UnsafePointer<CInterop.PlatformChar>,\n    _ to: UnsafePointer<CInterop.PlatformChar>,\n    _ state: copyfile_state_t?,\n    _ flags: copyfile_flags_t\n) -> CInt {\n    #if ENABLE_MOCKING\n    if mockingEnabled {\n        return mock(from, to, state, flags)\n    }\n    #endif\n    return copyfile(from, to, state, flags)\n}\n#endif\n\n/// getcwd(3): Get working directory pathname\ninternal func libc_getcwd(\n    _ buffer: UnsafeMutablePointer<CInterop.PlatformChar>,\n    _ size: Int\n) -> UnsafeMutablePointer<CInterop.PlatformChar>? {\n    getcwd(buffer, size)\n}\n\n/// confstr(3)\n#if !os(Android)\ninternal func libc_confstr(\n    _ name: CInt,\n    _ buffer: UnsafeMutablePointer<CInterop.PlatformChar>,\n    _ size: Int\n) -> Int {\n    confstr(name, buffer, size)\n}\n#endif\n\n/// fts(3)\ninternal func libc_fts_open(\n    _ path: [UnsafeMutablePointer<CInterop.PlatformChar>?],\n    _ options: CInt\n) -> UnsafeMutablePointer<CInterop.FTS> {\n    #if os(Android)\n    // This branch is a workaround for incorrect nullability annotations in the Android SDK.\n    // They were added in https://android.googlesource.com/platform/bionic/+/dec8efd72a6ad8b807a15a614ae1519487cfa456,\n    // and lasted for more than a year: https://android.googlesource.com/platform/bionic/+/da81ec4d1cbd0279014feb60535bf38defcd9346.\n    CNIOLinux_fts_open(path, options, nil)!\n    #else\n    fts_open(path, options, nil)!\n    #endif\n}\n\n/// fts(3)\ninternal func libc_fts_read(\n    _ fts: UnsafeMutablePointer<CInterop.FTS>\n) -> UnsafeMutablePointer<CInterop.FTSEnt>? {\n    fts_read(fts)\n}\n\n/// fts(3)\ninternal func libc_fts_close(\n    _ fts: UnsafeMutablePointer<CInterop.FTS>\n) -> CInt {\n    fts_close(fts)\n}\n\n#if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Android)\n/// getuid(2): Get user identification\ninternal func system_getuid() -> uid_t {\n    getuid()\n}\n\n/// getpwuid_r(3): Get password file entry\ninternal func libc_getpwuid_r(\n    _ uid: uid_t,\n    _ pwd: UnsafeMutablePointer<passwd>,\n    _ buffer: UnsafeMutablePointer<CChar>,\n    _ bufferSize: Int,\n    _ result: UnsafeMutablePointer<UnsafeMutablePointer<passwd>?>\n) -> CInt {\n    getpwuid_r(uid, pwd, buffer, bufferSize, result)\n}\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/SystemFileHandle.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOPosix\nimport SystemPackage\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\n@preconcurrency import Glibc\nimport CNIOLinux\n#elseif canImport(Musl)\n@preconcurrency import Musl\nimport CNIOLinux\n#elseif canImport(Bionic)\n@preconcurrency import Bionic\n#endif\n\n/// An implementation of ``FileHandleProtocol`` which is backed by system calls and a file\n/// descriptor.\n@_spi(Testing)\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic final class SystemFileHandle: Sendable {\n    /// The executor on which to execute system calls.\n    internal var threadPool: NIOThreadPool { self.sendableView.threadPool }\n\n    /// The path used to open this handle.\n    internal var path: FilePath { self.sendableView.path }\n\n    @_spi(Testing)\n    public struct Materialization: Sendable {\n        /// The path of the file which was created.\n        var created: FilePath\n        /// The desired path of the file.\n        var desired: FilePath\n        /// Whether the ``desired`` file must be created exclusively. If `true` then if a file\n        /// already exists at the ``desired`` path then an error is thrown, otherwise any existing\n        /// file will be replaced.`\n        var exclusive: Bool\n        /// The mode used to materialize the file.\n        var mode: Mode\n\n        enum Mode {\n            /// Rename the created file to become the desired file.\n            case rename\n            #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n            /// Link the unnamed file to the desired file using 'linkat(2)'.\n            case link\n            #endif\n        }\n    }\n\n    fileprivate enum Lifecycle {\n        case open(FileDescriptor)\n        case detached\n        case closed\n    }\n\n    @_spi(Testing)\n    public let sendableView: SendableView\n\n    /// The file handle may be for a non-seekable file, so it shouldn't be 'Sendable', however, most\n    /// of the work performed on behalf of the handle is executed in a thread pool which means that\n    /// its state must be 'Sendable'.\n    @_spi(Testing)\n    public struct SendableView: Sendable {\n        /// The lifecycle of the file handle.\n        fileprivate let lifecycle: NIOLockedValueBox<Lifecycle>\n\n        /// The executor on which to execute system calls.\n        internal let threadPool: NIOThreadPool\n\n        /// The path used to open this handle.\n        internal let path: FilePath\n\n        /// An action to take when closing the file handle.\n        fileprivate let materialization: Materialization?\n\n        fileprivate init(\n            lifecycle: Lifecycle,\n            threadPool: NIOThreadPool,\n            path: FilePath,\n            materialization: Materialization?\n        ) {\n            self.lifecycle = NIOLockedValueBox(lifecycle)\n            self.threadPool = threadPool\n            self.path = path\n            self.materialization = materialization\n        }\n    }\n\n    /// Creates a handle which takes ownership of the provided descriptor.\n    ///\n    /// - Precondition: The descriptor must be open.\n    /// - Parameters:\n    ///   - descriptor: The open file descriptor.\n    ///   - path: The path to the file used to open the descriptor.\n    ///   - executor: The executor which system calls will be performed on.\n    @_spi(Testing)\n    public init(\n        takingOwnershipOf descriptor: FileDescriptor,\n        path: FilePath,\n        materialization: Materialization? = nil,\n        threadPool: NIOThreadPool\n    ) {\n        self.sendableView = SendableView(\n            lifecycle: .open(descriptor),\n            threadPool: threadPool,\n            path: path,\n            materialization: materialization\n        )\n    }\n\n    deinit {\n        self.sendableView.lifecycle.withLockedValue { lifecycle -> Void in\n            switch lifecycle {\n            case .open:\n                fatalError(\n                    \"\"\"\n                    Leaking file descriptor: the handle for '\\(self.sendableView.path)' MUST be closed or \\\n                    detached with 'close()' or 'detachUnsafeFileDescriptor()' before the final \\\n                    reference to the handle is dropped.\n                    \"\"\"\n                )\n            case .detached, .closed:\n                ()\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    /// Returns the file descriptor if it's available; `nil` otherwise.\n    internal func descriptorIfAvailable() -> FileDescriptor? {\n        self.lifecycle.withLockedValue {\n            switch $0 {\n            case let .open(descriptor):\n                return descriptor\n            case .detached, .closed:\n                return nil\n            }\n        }\n    }\n\n    /// Executes a closure with the file descriptor if it's available otherwise throws the result\n    /// of `onUnavailable`.\n    internal func _withUnsafeDescriptor<R>(\n        _ execute: (FileDescriptor) throws -> R,\n        onUnavailable: () -> FileSystemError\n    ) throws -> R {\n        if let descriptor = self.descriptorIfAvailable() {\n            return try execute(descriptor)\n        } else {\n            throw onUnavailable()\n        }\n    }\n\n    /// Executes a closure with the file descriptor if it's available otherwise returns the result\n    /// of `onUnavailable` as a `Result` Error.\n    internal func _withUnsafeDescriptorResult<R>(\n        _ execute: (FileDescriptor) -> Result<R, FileSystemError>,\n        onUnavailable: () -> FileSystemError\n    ) -> Result<R, FileSystemError> {\n        if let descriptor = self.descriptorIfAvailable() {\n            return execute(descriptor)\n        } else {\n            return .failure(onUnavailable())\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: FileHandleProtocol {\n    // Notes which apply to the following block of functions:\n    //\n    // 1. Documentation is inherited from ``FileHandleProtocol`` and is not repeated here.\n    // 2. The functions should be annotated with @_spi(Testing); this is not possible with the\n    //    conformance to FileHandleProtocol which requires them to be only marked public. However\n    //    this is not an issue: the implementing type is annotated with @_spi(Testing) so the\n    //    functions are not actually public.\n    // 3. Most of these functions call through to a synchronous version prefixed with an underscore,\n    //    this is to make testing possible with the system call mocking infrastructure we are\n    //    currently using.\n\n    public func info() async throws -> FileInfo {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._info().get()\n        }\n    }\n\n    public func replacePermissions(_ permissions: FilePermissions) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._replacePermissions(permissions)\n        }\n    }\n\n    public func addPermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._addPermissions(permissions)\n        }\n    }\n\n    public func removePermissions(_ permissions: FilePermissions) async throws -> FilePermissions {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._removePermissions(permissions)\n        }\n    }\n\n    public func attributeNames() async throws -> [String] {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._attributeNames()\n        }\n    }\n\n    public func valueForAttribute(_ name: String) async throws -> [UInt8] {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._valueForAttribute(name)\n        }\n    }\n\n    public func updateValueForAttribute(\n        _ bytes: some (Sendable & RandomAccessCollection<UInt8>),\n        attribute name: String\n    ) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._updateValueForAttribute(bytes, attribute: name)\n        }\n    }\n\n    public func removeValueForAttribute(_ name: String) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._removeValueForAttribute(name)\n        }\n    }\n\n    public func synchronize() async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._synchronize()\n        }\n    }\n\n    public func withUnsafeDescriptor<R: Sendable>(\n        _ execute: @Sendable @escaping (FileDescriptor) throws -> R\n    ) async throws -> R {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._withUnsafeDescriptor {\n                try execute($0)\n            } onUnavailable: {\n                FileSystemError(\n                    code: .closed,\n                    message: \"File is closed ('\\(sendableView.path)').\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func detachUnsafeFileDescriptor() throws -> FileDescriptor {\n        try self.sendableView.lifecycle.withLockedValue { lifecycle in\n            switch lifecycle {\n            case let .open(descriptor):\n                lifecycle = .detached\n\n                // We need to be careful handling files which have delayed materialization to avoid\n                // leftover temporary files.\n                //\n                // Where we use the 'link' mode we simply call materialize and return the\n                // descriptor as it will be materialized when closed.\n                //\n                // For the 'rename' mode we create a hard link to the desired file and unlink the\n                // created file.\n                guard let materialization = self.sendableView.materialization else {\n                    // File opened 'normally', just detach and return.\n                    return descriptor\n                }\n\n                switch materialization.mode {\n                #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                case .link:\n                    let result = self.sendableView._materializeLink(\n                        descriptor: descriptor,\n                        from: materialization.created,\n                        to: materialization.desired,\n                        exclusive: materialization.exclusive\n                    )\n                    return try result.map { descriptor }.get()\n                #endif\n\n                case .rename:\n                    let result = Syscall.link(\n                        from: materialization.created,\n                        to: materialization.desired\n                    ).mapError { errno in\n                        FileSystemError.link(\n                            errno: errno,\n                            from: materialization.created,\n                            to: materialization.desired,\n                            location: .here()\n                        )\n                    }.flatMap {\n                        Syscall.unlink(path: materialization.created).mapError { errno in\n                            .unlink(\"unlink\", errno: errno, path: materialization.created, location: .here())\n                        }\n                    }\n\n                    return try result.map { descriptor }.get()\n                }\n\n            case .detached:\n                throw FileSystemError(\n                    code: .closed,\n                    message: \"\"\"\n                        File descriptor has already been detached ('\\(self.path)'). Handles may \\\n                        only be detached once.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n\n            case .closed:\n                throw FileSystemError(\n                    code: .closed,\n                    message: \"\"\"\n                        Cannot detach descriptor for closed file ('\\(self.path)'). Handles may \\\n                        only be detached while they are open.\n                        \"\"\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func close() async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._close(materialize: true).get()\n        }\n    }\n\n    public func close(makeChangesVisible: Bool) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._close(materialize: makeChangesVisible).get()\n        }\n    }\n\n    public func setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._setTimes(\n                lastAccess: lastAccess,\n                lastDataModification: lastDataModification\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public enum UpdatePermissionsOperation: Sendable { case set, add, remove }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    /// Returns a string in the format: \"{message}, the file '{path}' is closed.\"\n    private func fileIsClosed(_ message: String) -> String {\n        \"\\(message), the file '\\(self.path)' is closed.\"\n    }\n\n    /// Returns a string in the format: \"{message} for '{path}'.\"\n    private func unknown(_ message: String) -> String {\n        \"\\(message) for '\\(self.path)'.\"\n    }\n\n    @_spi(Testing)\n    public func _info() -> Result<FileInfo, FileSystemError> {\n        self._withUnsafeDescriptorResult { descriptor in\n            descriptor.status().map { stat in\n                FileInfo(platformSpecificStatus: stat)\n            }.mapError { errno in\n                .stat(\"fstat\", errno: errno, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to get information\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _replacePermissions(_ permissions: FilePermissions) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            try self.updatePermissions(\n                permissions,\n                operation: .set,\n                operand: permissions,\n                descriptor: descriptor\n            )\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to replace permissions\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _addPermissions(_ permissions: FilePermissions) throws -> FilePermissions {\n        try self._withUnsafeDescriptor { descriptor in\n            switch descriptor.status() {\n            case let .success(status):\n                let info = FileInfo(platformSpecificStatus: status)\n                let merged = info.permissions.union(permissions)\n\n                // Check if we need to make any changes.\n                if merged == info.permissions {\n                    return merged\n                }\n\n                // Apply the new permissions.\n                try self.updatePermissions(\n                    merged,\n                    operation: .add,\n                    operand: permissions,\n                    descriptor: descriptor\n                )\n\n                return merged\n\n            case let .failure(errno):\n                throw FileSystemError(\n                    message: \"Unable to add permissions.\",\n                    wrapping: .stat(\"fstat\", errno: errno, path: self.path, location: .here())\n                )\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to add permissions\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _removePermissions(_ permissions: FilePermissions) throws -> FilePermissions {\n        try self._withUnsafeDescriptor { descriptor in\n            switch descriptor.status() {\n            case let .success(status):\n                let info = FileInfo(platformSpecificStatus: status)\n                let merged = info.permissions.subtracting(permissions)\n\n                // Check if we need to make any changes.\n                if merged == info.permissions {\n                    return merged\n                }\n\n                // Apply the new permissions.\n                try self.updatePermissions(\n                    merged,\n                    operation: .remove,\n                    operand: permissions,\n                    descriptor: descriptor\n                )\n\n                return merged\n\n            case let .failure(errno):\n                throw FileSystemError(\n                    message: \"Unable to remove permissions.\",\n                    wrapping: .stat(\"fstat\", errno: errno, path: self.path, location: .here())\n                )\n\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Unable to remove permissions\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    private func updatePermissions(\n        _ permissions: FilePermissions,\n        operation: SystemFileHandle.UpdatePermissionsOperation,\n        operand: FilePermissions,\n        descriptor: FileDescriptor\n    ) throws {\n        try descriptor.changeMode(permissions).mapError { errno in\n            FileSystemError.fchmod(\n                operation: operation,\n                operand: operand,\n                permissions: permissions,\n                errno: errno,\n                path: self.path,\n                location: .here()\n            )\n        }.get()\n    }\n\n    @_spi(Testing)\n    public func _attributeNames() throws -> [String] {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.listExtendedAttributes().mapError { errno in\n                FileSystemError.flistxattr(errno: errno, path: self.path, location: .here())\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Could not list extended attributes\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _valueForAttribute(_ name: String) throws -> [UInt8] {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.readExtendedAttribute(\n                named: name\n            ).flatMapError { errno -> Result<[UInt8], FileSystemError> in\n                switch errno {\n                #if canImport(Darwin)\n                case .attributeNotFound:\n                    // Okay, return empty value.\n                    return .success([])\n                #endif\n                case .noData:\n                    // Okay, return empty value.\n                    return .success([])\n                default:\n                    let error = FileSystemError.fgetxattr(\n                        attribute: name,\n                        errno: errno,\n                        path: self.path,\n                        location: .here()\n                    )\n                    return .failure(error)\n                }\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\n                    \"Could not get value for extended attribute ('\\(name)')\"\n                ),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _updateValueForAttribute(\n        _ bytes: some RandomAccessCollection<UInt8>,\n        attribute name: String\n    ) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            func withUnsafeBufferPointer(_ body: (UnsafeBufferPointer<UInt8>) throws -> Void) throws {\n                try bytes.withContiguousStorageIfAvailable(body)\n                    ?? Array(bytes).withUnsafeBufferPointer(body)\n            }\n\n            try withUnsafeBufferPointer { pointer in\n                let rawBufferPointer = UnsafeRawBufferPointer(pointer)\n                return try descriptor.setExtendedAttribute(\n                    named: name,\n                    to: rawBufferPointer\n                ).mapError { errno in\n                    FileSystemError.fsetxattr(\n                        attribute: name,\n                        errno: errno,\n                        path: self.path,\n                        location: .here()\n                    )\n                }.get()\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\n                    \"Could not set value for extended attribute ('\\(name)')\"\n                ),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _removeValueForAttribute(_ name: String) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.removeExtendedAttribute(name).mapError { errno in\n                FileSystemError.fremovexattr(\n                    attribute: name,\n                    errno: errno,\n                    path: self.path,\n                    location: .here()\n                )\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Could not remove extended attribute ('\\(name)')\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _synchronize() throws {\n        try self._withUnsafeDescriptor { descriptor in\n            try descriptor.synchronize().mapError { errno in\n                FileSystemError.fsync(errno: errno, path: self.path, location: .here())\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: self.fileIsClosed(\"Could not synchronize\"),\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    internal func _duplicate() -> Result<FileDescriptor, FileSystemError> {\n        self._withUnsafeDescriptorResult { descriptor in\n            Result {\n                try descriptor.duplicate()\n            }.mapError { error in\n                FileSystemError.dup(error: error, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"Unable to duplicate descriptor of closed handle for '\\(self.path)'.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n\n    @_spi(Testing)\n    public func _close(materialize: Bool, failRenameat2WithEINVAL: Bool = false) -> Result<Void, FileSystemError> {\n        let descriptor: FileDescriptor? = self.lifecycle.withLockedValue { lifecycle in\n            switch lifecycle {\n            case let .open(descriptor):\n                lifecycle = .closed\n                return descriptor\n            case .detached, .closed:\n                return nil\n            }\n        }\n\n        guard let descriptor = descriptor else {\n            return .success(())\n        }\n\n        // Materialize then close.\n        let materializeResult = self._materialize(\n            materialize,\n            descriptor: descriptor,\n            failRenameat2WithEINVAL: failRenameat2WithEINVAL\n        )\n\n        return Result {\n            try descriptor.close()\n        }.mapError { error in\n            .close(error: error, path: self.path, location: .here())\n        }.flatMap {\n            materializeResult\n        }\n    }\n\n    #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n    fileprivate func _materializeLink(\n        descriptor: FileDescriptor,\n        from createdPath: FilePath,\n        to desiredPath: FilePath,\n        exclusive: Bool\n    ) -> Result<Void, FileSystemError> {\n        func linkAtEmptyPath() -> Result<Void, Errno> {\n            Syscall.linkAt(\n                from: \"\",\n                relativeTo: descriptor,\n                to: desiredPath,\n                relativeTo: .currentWorkingDirectory,\n                flags: [.emptyPath]\n            )\n        }\n\n        func linkAtProcFS() -> Result<Void, Errno> {\n            Syscall.linkAt(\n                from: FilePath(\"/proc/self/fd/\\(descriptor.rawValue)\"),\n                relativeTo: .currentWorkingDirectory,\n                to: desiredPath,\n                relativeTo: .currentWorkingDirectory,\n                flags: [.followSymbolicLinks]\n            )\n        }\n\n        let result: Result<Void, FileSystemError>\n\n        switch linkAtEmptyPath() {\n        case .success:\n            result = .success(())\n\n        case .failure(.fileExists) where !exclusive:\n            // File exists and materialization _isn't_ exclusive. Remove the existing\n            // file and try again.\n            let removeResult = Libc.remove(desiredPath).mapError { errno in\n                FileSystemError.remove(errno: errno, path: desiredPath, location: .here())\n            }\n\n            let linkAtResult = linkAtEmptyPath().flatMapError { errno in\n                // ENOENT means we likely didn't have the 'CAP_DAC_READ_SEARCH' capability\n                // so try again by linking to the descriptor via procfs.\n                if errno == .noSuchFileOrDirectory {\n                    return linkAtProcFS()\n                } else {\n                    return .failure(errno)\n                }\n            }.mapError { errno in\n                FileSystemError.link(\n                    errno: errno,\n                    from: createdPath,\n                    to: desiredPath,\n                    location: .here()\n                )\n            }\n\n            result = removeResult.flatMap { linkAtResult }\n\n        case .failure(.noSuchFileOrDirectory):\n            result = linkAtProcFS().flatMapError { errno in\n                if errno == .fileExists, !exclusive {\n                    return Libc.remove(desiredPath).mapError { errno in\n                        FileSystemError.remove(\n                            errno: errno,\n                            path: desiredPath,\n                            location: .here()\n                        )\n                    }.flatMap {\n                        linkAtProcFS().mapError { errno in\n                            FileSystemError.link(\n                                errno: errno,\n                                from: createdPath,\n                                to: desiredPath,\n                                location: .here()\n                            )\n                        }\n                    }\n                } else {\n                    let error = FileSystemError.link(\n                        errno: errno,\n                        from: createdPath,\n                        to: desiredPath,\n                        location: .here()\n                    )\n                    return .failure(error)\n                }\n            }\n\n        case .failure(let errno):\n            result = .failure(\n                .link(errno: errno, from: createdPath, to: desiredPath, location: .here())\n            )\n        }\n\n        return result\n    }\n    #endif\n\n    func _materialize(\n        _ materialize: Bool,\n        descriptor: FileDescriptor,\n        failRenameat2WithEINVAL: Bool\n    ) -> Result<Void, FileSystemError> {\n        guard let materialization = self.materialization else { return .success(()) }\n\n        let createdPath = materialization.created\n        let desiredPath = materialization.desired\n\n        let result: Result<Void, FileSystemError>\n        switch materialization.mode {\n        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        case .link:\n            if materialize {\n                result = self._materializeLink(\n                    descriptor: descriptor,\n                    from: createdPath,\n                    to: desiredPath,\n                    exclusive: materialization.exclusive\n                )\n            } else {\n                result = .success(())\n            }\n        #endif\n\n        case .rename:\n            if materialize {\n                var renameResult: Result<Void, Errno>\n                let renameFunction: String\n                #if canImport(Darwin)\n                renameFunction = \"renamex_np\"\n                renameResult = Syscall.rename(\n                    from: createdPath,\n                    to: desiredPath,\n                    options: materialization.exclusive ? [.exclusive] : []\n                )\n                #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                // The created and desired paths are absolute, so the relative descriptors are\n                // ignored. However, they must still be provided to 'rename' in order to pass\n                // flags.\n                renameFunction = \"renameat2\"\n                if materialization.exclusive, failRenameat2WithEINVAL {\n                    renameResult = .failure(.invalidArgument)\n                } else {\n                    renameResult = Syscall.rename(\n                        from: createdPath,\n                        relativeTo: .currentWorkingDirectory,\n                        to: desiredPath,\n                        relativeTo: .currentWorkingDirectory,\n                        flags: materialization.exclusive ? [.exclusive] : []\n                    )\n                }\n                #endif\n\n                if materialization.exclusive {\n                    switch renameResult {\n                    case .failure(.fileExists):\n                        // A file exists at the desired path and the user specified exclusive\n                        // creation, clear up by removing the file that we did create.\n                        _ = Libc.remove(createdPath)\n\n                    case .failure(.invalidArgument):\n                        // If 'renameat2' failed on Linux with EINVAL then in all likelihood the\n                        // 'RENAME_NOREPLACE' option isn't supported. As we're doing an exclusive\n                        // create, check the desired path doesn't exist then do a regular rename.\n                        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                        switch Syscall.stat(path: desiredPath) {\n                        case .failure(.noSuchFileOrDirectory):\n                            // File doesn't exist, do a 'regular' rename.\n                            renameResult = Syscall.rename(from: createdPath, to: desiredPath)\n\n                        case .success:\n                            // File exists so exclusive create isn't possible. Remove the file\n                            // we did create then throw.\n                            _ = Libc.remove(createdPath)\n                            let error = FileSystemError(\n                                code: .fileAlreadyExists,\n                                message: \"\"\"\n                                    Couldn't open '\\(desiredPath)', it already exists and the \\\n                                    file was opened with the 'existingFile' option set to 'none'.\n                                    \"\"\",\n                                cause: nil,\n                                location: .here()\n                            )\n                            return .failure(error)\n\n                        case .failure:\n                            // Failed to stat the desired file for reasons unknown. Remove the file\n                            // we did create then throw.\n                            _ = Libc.remove(createdPath)\n                            let error = FileSystemError(\n                                code: .unknown,\n                                message: \"Couldn't open '\\(desiredPath)'.\",\n                                cause: FileSystemError.rename(\n                                    \"renameat2\",\n                                    errno: .invalidArgument,\n                                    oldName: createdPath,\n                                    newName: desiredPath,\n                                    location: .here()\n                                ),\n                                location: .here()\n                            )\n                            return .failure(error)\n                        }\n                        #else\n                        ()  // Not Linux, use the normal error flow.\n                        #endif\n\n                    case .success, .failure:\n                        ()\n                    }\n                }\n\n                result = renameResult.mapError { errno in\n                    .rename(\n                        renameFunction,\n                        errno: errno,\n                        oldName: createdPath,\n                        newName: desiredPath,\n                        location: .here()\n                    )\n                }\n            } else {\n                // Don't materialize the source, remove it\n                result = Libc.remove(createdPath).mapError {\n                    .remove(errno: $0, path: createdPath, location: .here())\n                }\n            }\n        }\n\n        return result\n    }\n\n    func _setTimes(\n        lastAccess: FileInfo.Timespec?,\n        lastDataModification: FileInfo.Timespec?\n    ) throws {\n        try self._withUnsafeDescriptor { descriptor in\n            let syscallResult: Result<Void, Errno>\n            switch (lastAccess, lastDataModification) {\n            case (.none, .none):\n                // If the timespec array is nil, as per the `futimens` docs,\n                // both the last accessed and last modification times\n                // will be set to now.\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: nil\n                )\n\n            case (.some(let lastAccess), .none):\n                // Don't modify the last modification time.\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: [timespec(lastAccess), timespec(.omit)]\n                )\n\n            case (.none, .some(let lastDataModification)):\n                // Don't modify the last access time.\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: [timespec(.omit), timespec(lastDataModification)]\n                )\n\n            case (.some(let lastAccess), .some(let lastDataModification)):\n                syscallResult = Syscall.futimens(\n                    fileDescriptor: descriptor,\n                    times: [timespec(lastAccess), timespec(lastDataModification)]\n                )\n            }\n\n            try syscallResult.mapError { errno in\n                FileSystemError.futimens(\n                    errno: errno,\n                    path: self.path,\n                    lastAccessTime: lastAccess,\n                    lastDataModificationTime: lastDataModification,\n                    location: .here()\n                )\n            }.get()\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"Couldn't modify file dates, the file '\\(self.path)' is closed.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n}\n\nextension timespec {\n    fileprivate init(_ fileinfoTimespec: FileInfo.Timespec) {\n        // Clamp seconds to be positive\n        let seconds = max(0, fileinfoTimespec.seconds)\n\n        // If nanoseconds are not UTIME_NOW or UTIME_OMIT, clamp to be between\n        // 0 and 1,000 million.\n        let nanoseconds: Int\n        switch fileinfoTimespec {\n        case .now, .omit:\n            nanoseconds = fileinfoTimespec.nanoseconds\n        default:\n            nanoseconds = min(1_000_000_000, max(0, fileinfoTimespec.nanoseconds))\n        }\n\n        self.init(\n            tv_sec: seconds,\n            tv_nsec: nanoseconds\n        )\n    }\n}\n\n// MARK: - Readable File Handle\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: ReadableFileHandleProtocol {\n    // Notes which apply to the following block of functions:\n    //\n    // 1. Documentation is inherited from ``FileHandleProtocol`` and is not repeated here.\n    // 2. The functions should be annotated with @_spi(Testing); this is not possible with the\n    //    conformance to FileHandleProtocol which requires them to be only marked public. However\n    //    this is not an issue: the implementing type is annotated with @_spi(Testing) so the\n    //    functions are not actually public.\n\n    public func readChunk(\n        fromAbsoluteOffset offset: Int64,\n        length: ByteCount\n    ) async throws -> ByteBuffer {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._withUnsafeDescriptor { descriptor in\n                try descriptor.readChunk(\n                    fromAbsoluteOffset: offset,\n                    length: length.bytes\n                ).flatMapError { error in\n                    if let errno = error as? Errno, errno == .illegalSeek {\n                        guard offset == 0 else {\n                            return .failure(\n                                FileSystemError(\n                                    code: .unsupported,\n                                    message: \"File is unseekable.\",\n                                    cause: nil,\n                                    location: .here()\n                                )\n                            )\n                        }\n\n                        return descriptor.readChunk(length: length.bytes).mapError { error in\n                            FileSystemError.read(\n                                usingSyscall: .read,\n                                error: error,\n                                path: sendableView.path,\n                                location: .here()\n                            )\n                        }\n                    } else {\n                        return .failure(\n                            FileSystemError.read(\n                                usingSyscall: .pread,\n                                error: error,\n                                path: sendableView.path,\n                                location: .here()\n                            )\n                        )\n                    }\n                }\n                .get()\n            } onUnavailable: {\n                FileSystemError(\n                    code: .closed,\n                    message: \"Couldn't read chunk, the file '\\(sendableView.path)' is closed.\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func readChunks(\n        in range: Range<Int64>,\n        chunkLength size: ByteCount\n    ) -> FileChunks {\n        FileChunks(handle: self, chunkLength: size, range: range)\n    }\n}\n\n// MARK: - Writable File Handle\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: WritableFileHandleProtocol {\n    @discardableResult\n    public func write(\n        contentsOf bytes: some (Sequence<UInt8> & Sendable),\n        toAbsoluteOffset offset: Int64\n    ) async throws -> Int64 {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._withUnsafeDescriptor { descriptor in\n                try descriptor.write(contentsOf: bytes, toAbsoluteOffset: offset)\n                    .flatMapError { error in\n                        if let errno = error as? Errno, errno == .illegalSeek {\n                            guard offset == 0 else {\n                                return .failure(\n                                    FileSystemError(\n                                        code: .unsupported,\n                                        message: \"File is unseekable.\",\n                                        cause: nil,\n                                        location: .here()\n                                    )\n                                )\n                            }\n\n                            return descriptor.write(contentsOf: bytes)\n                                .mapError { error in\n                                    FileSystemError.write(\n                                        usingSyscall: .write,\n                                        error: error,\n                                        path: sendableView.path,\n                                        location: .here()\n                                    )\n                                }\n                        } else {\n                            return .failure(\n                                FileSystemError.write(\n                                    usingSyscall: .pwrite,\n                                    error: error,\n                                    path: sendableView.path,\n                                    location: .here()\n                                )\n                            )\n                        }\n                    }\n                    .get()\n            } onUnavailable: {\n                FileSystemError(\n                    code: .closed,\n                    message: \"Couldn't write bytes, the file '\\(sendableView.path)' is closed.\",\n                    cause: nil,\n                    location: .here()\n                )\n            }\n        }\n    }\n\n    public func resize(to size: ByteCount) async throws {\n        try await self.threadPool.runIfActive { [sendableView] in\n            try sendableView._resize(to: size).get()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    func _resize(to size: ByteCount) -> Result<(), FileSystemError> {\n        self._withUnsafeDescriptorResult { descriptor in\n            Result {\n                try descriptor.resize(to: size.bytes, retryOnInterrupt: true)\n            }.mapError { error in\n                FileSystemError.ftruncate(error: error, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"Unable to resize file '\\(self.path)'.\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n}\n\n// MARK: - Directory File Handle\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle: DirectoryFileHandleProtocol {\n    public typealias ReadFileHandle = SystemFileHandle\n    public typealias WriteFileHandle = SystemFileHandle\n    public typealias ReadWriteFileHandle = SystemFileHandle\n\n    public func listContents(recursive: Bool) -> DirectoryEntries {\n        DirectoryEntries(handle: self, recursive: recursive)\n    }\n\n    public func openFile(\n        forReadingAt path: FilePath,\n        options: OpenOptions.Read\n    ) async throws -> SystemFileHandle {\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path,\n                mode: .readOnly,\n                options: opts,\n                transactionalIfPossible: false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    public func openFile(\n        forReadingAndWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> SystemFileHandle {\n        let perms = options.permissionsForRegularFile\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path,\n                mode: .readWrite,\n                options: opts,\n                permissions: perms,\n                transactionalIfPossible: options.newFile?.transactionalCreation ?? false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    public func openFile(\n        forWritingAt path: FilePath,\n        options: OpenOptions.Write\n    ) async throws -> SystemFileHandle {\n        let perms = options.permissionsForRegularFile\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path,\n                mode: .writeOnly,\n                options: opts,\n                permissions: perms,\n                transactionalIfPossible: options.newFile?.transactionalCreation ?? false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n\n    public func openDirectory(\n        atPath path: FilePath,\n        options: OpenOptions.Directory\n    ) async throws -> SystemFileHandle {\n        let opts = options.descriptorOptions.union(.nonBlocking)\n        let handle = try await self.threadPool.runIfActive { [sendableView] in\n            let handle = try sendableView._open(\n                atPath: path,\n                mode: .readOnly,\n                options: opts,\n                transactionalIfPossible: false\n            ).get()\n            // Okay to transfer: we just created it and are now moving back to the callers task.\n            return UnsafeTransfer(handle)\n        }\n        return handle.wrappedValue\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle.SendableView {\n    func _open(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions? = nil,\n        transactionalIfPossible transactional: Bool\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        if transactional {\n            if path.isAbsolute {\n                // The provided path is absolute: just open the handle normally.\n                return SystemFileHandle.syncOpen(\n                    atPath: path,\n                    mode: mode,\n                    options: options,\n                    permissions: permissions,\n                    transactionalIfPossible: transactional,\n                    threadPool: self.threadPool\n                )\n            } else if self.path.isAbsolute {\n                // The parent path is absolute and the provided path is relative; combine them.\n                return SystemFileHandle.syncOpen(\n                    atPath: self.path.appending(path.components),\n                    mode: mode,\n                    options: options,\n                    permissions: permissions,\n                    transactionalIfPossible: transactional,\n                    threadPool: self.threadPool\n                )\n            }\n\n            // At this point transactional file creation isn't possible. Fallback to\n            // non-transactional.\n        }\n\n        // Provided and parent paths are relative. There's no way we can safely delay\n        // materialization as we don't know if the parent descriptor will be available when\n        // closing the opened file.\n        return self._withUnsafeDescriptorResult { descriptor in\n            descriptor.open(\n                atPath: path,\n                mode: mode,\n                options: options,\n                permissions: permissions\n            ).map { newDescriptor in\n                SystemFileHandle(\n                    takingOwnershipOf: newDescriptor,\n                    path: self.path.appending(path.components).lexicallyNormalized(),\n                    threadPool: self.threadPool\n                )\n            }.mapError { errno in\n                .open(\"openat\", error: errno, path: self.path, location: .here())\n            }\n        } onUnavailable: {\n            FileSystemError(\n                code: .closed,\n                message: \"\"\"\n                    Unable to open file at path '\\(path)' relative to '\\(self.path)', the file \\\n                    is closed.\n                    \"\"\",\n                cause: nil,\n                location: .here()\n            )\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension SystemFileHandle {\n    static func syncOpen(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        transactionalIfPossible transactional: Bool,\n        threadPool: NIOThreadPool\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        let isWritable = (mode == .writeOnly || mode == .readWrite)\n        let exclusiveCreate = options.contains(.exclusiveCreate)\n        let truncate = options.contains(.truncate)\n        let delayMaterialization = transactional && isWritable && (exclusiveCreate || truncate)\n\n        if delayMaterialization {\n            // When opening in this mode we can more \"atomically\" create the file, that is, by not\n            // leaving the user with a half written file should e.g. the system crash or throw an\n            // error while writing. On non-Android Linux we do this by opening the directory for\n            // the path with `O_TMPFILE` and creating a hard link when closing the file. On other\n            // platforms we generate a dot file with a randomised suffix name and rename it to the\n            // destination.\n            #if os(Android)\n            let temporaryHardLink = false\n            #else\n            let temporaryHardLink = true\n            #endif\n            return Self.syncOpenWithMaterialization(\n                atPath: path,\n                mode: mode,\n                options: options,\n                permissions: permissions,\n                threadPool: threadPool,\n                useTemporaryFileIfPossible: temporaryHardLink\n            )\n        } else {\n            return Self.syncOpen(\n                atPath: path,\n                mode: mode,\n                options: options,\n                permissions: permissions,\n                threadPool: threadPool\n            )\n        }\n    }\n\n    static func syncOpen(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        threadPool: NIOThreadPool\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        Result {\n            try FileDescriptor.open(\n                path,\n                mode,\n                options: options,\n                permissions: permissions\n            )\n        }.map { descriptor in\n            SystemFileHandle(\n                takingOwnershipOf: descriptor,\n                path: path,\n                threadPool: threadPool\n            )\n        }.mapError { errno in\n            FileSystemError.open(\"open\", error: errno, path: path, location: .here())\n        }\n    }\n\n    @_spi(Testing)\n    public static func syncOpenWithMaterialization(\n        atPath path: FilePath,\n        mode: FileDescriptor.AccessMode,\n        options originalOptions: FileDescriptor.OpenOptions,\n        permissions: FilePermissions?,\n        threadPool: NIOThreadPool,\n        useTemporaryFileIfPossible: Bool = true\n    ) -> Result<SystemFileHandle, FileSystemError> {\n        let openedPath: FilePath\n        let desiredPath: FilePath\n\n        // There are two different approaches to materializing the file. On Linux, and where\n        // supported, we can open the file with the 'O_TMPFILE' flag which creates a temporary\n        // unnamed file. If we later decide the make the file visible we use 'linkat(2)' with\n        // the appropriate flags to link the unnamed temporary file to the desired file path.\n        //\n        // On other platforms, and when not supported on Linux, we create a regular file as we\n        // normally would and when we decide to materialize it we simply rename it to the desired\n        // name (or remove it if we aren't materializing it).\n        //\n        // There are, however, some wrinkles.\n        //\n        // Normally when a file is opened the system will open files specified with relative paths\n        // relative to the current working directory. However, when we delay making a file visible\n        // the current working directory could change which introduces an awkward race. Consider\n        // the following sequence of events:\n        //\n        // 1. User opens a file with delay materialization using a relative path\n        // 2. A temporary file is opened relative to the current working directory\n        // 3. The current working directory is changed\n        // 4. The file is closed.\n        //\n        // Where is the file created? It *should* be relative to the working directory at the time\n        // the user opened the file. However, if materializing the file relative to the new\n        // working directory would be very surprising behaviour for the user.\n        //\n        // To work around this we will get the current working directory only if the provided path\n        // is relative. That way all operations can be done on a path relative to a fixed point\n        // (i.e. the current working directory at this point in time).\n        if path.isRelative {\n            let currentWorkingDirectory: FilePath\n\n            switch Libc.getcwd() {\n            case .success(let path):\n                currentWorkingDirectory = path\n            case .failure(let errno):\n                let error = FileSystemError(\n                    message: \"\"\"\n                        Can't open relative '\\(path)' as the current working directory couldn't \\\n                        be determined.\n                        \"\"\",\n                    wrapping: .getcwd(errno: errno, location: .here())\n                )\n                return .failure(error)\n            }\n\n            func makePath() -> FilePath {\n                #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                if useTemporaryFileIfPossible {\n                    return currentWorkingDirectory.appending(path.components.dropLast())\n                }\n                #endif\n                return currentWorkingDirectory.appending(path.components.dropLast())\n                    .appending(\".tmp-\" + String(randomAlphaNumericOfLength: 6))\n            }\n\n            openedPath = makePath()\n            desiredPath = currentWorkingDirectory.appending(path.components)\n        } else {\n            func makePath() -> FilePath {\n                #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n                if useTemporaryFileIfPossible {\n                    return path.removingLastComponent()\n                }\n                #endif\n                return path.removingLastComponent()\n                    .appending(\".tmp-\" + String(randomAlphaNumericOfLength: 6))\n            }\n\n            openedPath = makePath()\n            desiredPath = path\n        }\n\n        let materializationMode: Materialization.Mode\n        let options: FileDescriptor.OpenOptions\n\n        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        if useTemporaryFileIfPossible {\n            options = [.temporaryFile]\n            materializationMode = .link\n        } else {\n            options = originalOptions\n            materializationMode = .rename\n        }\n        #else\n        options = originalOptions\n        materializationMode = .rename\n        #endif\n\n        let materialization = Materialization(\n            created: openedPath,\n            desired: desiredPath,\n            exclusive: originalOptions.contains(.exclusiveCreate),\n            mode: materializationMode\n        )\n\n        do {\n            let descriptor = try FileDescriptor.open(\n                openedPath,\n                mode,\n                options: options,\n                permissions: permissions\n            )\n\n            let handle = SystemFileHandle(\n                takingOwnershipOf: descriptor,\n                path: openedPath,\n                materialization: materialization,\n                threadPool: threadPool\n            )\n\n            return .success(handle)\n        } catch {\n            #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n            // 'O_TMPFILE' isn't supported for the current file system, try again but using\n            // rename instead.\n            if useTemporaryFileIfPossible, let errno = error as? Errno, errno == .notSupported {\n                return Self.syncOpenWithMaterialization(\n                    atPath: path,\n                    mode: mode,\n                    options: originalOptions,\n                    permissions: permissions,\n                    threadPool: threadPool,\n                    useTemporaryFileIfPossible: false\n                )\n            }\n            #endif\n            return .failure(.open(\"open\", error: error, path: path, location: .here()))\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/Internal/Utilities.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n@usableFromInline\ninternal final class Ref<Value> {\n    @usableFromInline\n    var value: Value\n    @inlinable\n    init(_ value: Value) {\n        self.value = value\n    }\n}\n\n@available(*, unavailable)\nextension Ref: Sendable {}\n\nextension String {\n    init(randomAlphaNumericOfLength length: Int) {\n        precondition(length > 0)\n\n        let characters = (0..<length).lazy.map {\n            _ in Array.alphaNumericValues.randomElement()!\n        }\n        self = String(decoding: characters, as: UTF8.self)\n    }\n}\n\nextension Array where Element == UInt8 {\n    fileprivate static let alphaNumericValues: [UInt8] = {\n        var alphaNumericValues = Array(UInt8(ascii: \"a\")...UInt8(ascii: \"z\"))\n        alphaNumericValues.append(contentsOf: UInt8(ascii: \"A\")...UInt8(ascii: \"Z\"))\n        alphaNumericValues.append(contentsOf: UInt8(ascii: \"0\")...UInt8(ascii: \"9\"))\n        return alphaNumericValues\n    }()\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/NIOFilePath.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n#if canImport(System)\nimport System\n#endif\n\n/// `NIOFilePath` is a type for representing a file path. It is backed by `SystemPackage`'s `FilePath` type.\n///\n/// You can create a `NIOFilePath` from a string literal:\n///\n/// ```swift\n/// let path: NIOFilePath = \"/home/user/report.txt\"\n/// ```\n///\n/// To interact with the underlying filepath using `SystemPackage.FilePath`'s API, you can initialize a `SystemPackage.FilePath` instance from a\n/// `NIOFilePath` instance (and vice-versa).\npublic struct NIOFilePath: Equatable, Hashable, Sendable, ExpressibleByStringLiteral, CustomStringConvertible,\n    CustomDebugStringConvertible\n{\n    /// The underlying `SystemPackage.FilePath` instance that ``NIOFilePath`` uses.\n    var underlying: SystemPackage.FilePath\n\n    /// Creates a ``NIOFilePath`` given an underlying `SystemPackage.FilePath` instance.\n    ///\n    /// - Parameter underlying: The `SystemPackage.FilePath` to use as the underlying backing for ``NIOFilePath``.\n    public init(_ underlying: SystemPackage.FilePath) {\n        self.underlying = underlying\n    }\n\n    #if canImport(System)\n    /// Creates a ``NIOFilePath`` given an underlying `System.FilePath` instance.\n    ///\n    /// - Parameter underlying: The `System.FilePath` instance to use to create this ``NIOFilePath`` instance.\n    @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)\n    public init(_ underlying: System.FilePath) {\n        self.underlying = underlying.withPlatformString {\n            SystemPackage.FilePath(platformString: $0)\n        }\n    }\n    #endif\n\n    /// Creates an instance representing an empty and null-terminated filepath.\n    public init() {\n        self.underlying = .init()\n    }\n\n    /// Creates an instance corresponding to the file path represented by the provided string.\n    ///\n    /// - Parameter string: A string whose Unicode encoded contents to use as the contents of the path\n    public init(_ string: String) {\n        self.underlying = .init(string)\n    }\n\n    /// Creates an instance from a string literal.\n    ///\n    /// - Parameter stringLiteral: A string literal whose Unicode encoded contents to use as the contents of the path.\n    public init(stringLiteral: String) {\n        self.init(stringLiteral)\n    }\n\n    /// A textual representation of the file path.\n    ///\n    /// If the content of the path isn't a well-formed Unicode string, this replaces invalid bytes with U+FFFD. See `String.init(decoding:)`\n    public var description: String {\n        self.underlying.description\n    }\n\n    /// A textual representation of the file path, suitable for debugging.\n    ///\n    /// If the content of the path isn't a well-formed Unicode string, this replaces invalid bytes with U+FFFD. See `String.init(decoding:)`\n    public var debugDescription: String {\n        self.underlying.debugDescription\n    }\n}\n\nextension SystemPackage.FilePath {\n    /// Creates a `SystemPackage.FilePath` from a ``NIOFilePath`` instance.\n    public init(_ filePath: NIOFilePath) {\n        self = filePath.underlying\n    }\n}\n\n#if canImport(System)\n@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)\nextension System.FilePath {\n    /// Creates a `System.FilePath` from a ``NIOFilePath`` instance.\n    public init(_ filePath: NIOFilePath) {\n        self = filePath.underlying.withPlatformString {\n            System.FilePath(platformString: $0)\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystem/NIOFileSystemSendableMetatype.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if compiler(>=6.2)\npublic typealias _NIOFileSystemSendableMetatype = SendableMetatype\n#else\npublic typealias _NIOFileSystemSendableMetatype = Any\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystem/OpenOptions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport SystemPackage\n\n/// Options for opening file handles.\npublic enum OpenOptions: Sendable {\n    /// Options for opening a file for reading.\n    public struct Read: Hashable, Sendable {\n        /// If the last path component is a symbolic link then this flag determines whether the\n        /// link is followed. If `false` and the last path component is a symbolic link then an\n        /// error is thrown.\n        public var followSymbolicLinks: Bool\n\n        /// Marks the descriptor of the opened file as 'close-on-exec'.\n        public var closeOnExec: Bool\n\n        /// Creates a new set of options for opening a file for reading.\n        ///\n        /// - Parameters:\n        ///   - followSymbolicLinks: Whether symbolic links should be followed, defaults to `true`.\n        ///   - closeOnExec: Whether the descriptor should be marked as closed-on-exec, defaults\n        ///     to `false`.\n        public init(\n            followSymbolicLinks: Bool = true,\n            closeOnExec: Bool = false\n        ) {\n            self.followSymbolicLinks = followSymbolicLinks\n            self.closeOnExec = closeOnExec\n        }\n    }\n\n    /// Options for opening a directory.\n    public struct Directory: Hashable, Sendable {\n        /// If the last path component is a symbolic link then this flag determines whether the\n        /// link is followed. If `false` and the last path component is a symbolic link then an\n        /// error is thrown.\n        public var followSymbolicLinks: Bool\n\n        /// Marks the descriptor of the opened file as 'close-on-exec'.\n        public var closeOnExec: Bool\n\n        /// Creates a new set of options for opening a directory.\n        ///\n        /// - Parameters:\n        ///   - followSymbolicLinks: Whether symbolic links should be followed, defaults to `true`.\n        ///   - closeOnExec: Whether the descriptor should be marked as closed-on-exec, defaults\n        ///     to `false`.\n        public init(\n            followSymbolicLinks: Bool = true,\n            closeOnExec: Bool = false\n        ) {\n            self.followSymbolicLinks = followSymbolicLinks\n            self.closeOnExec = closeOnExec\n        }\n    }\n\n    /// Options for opening a file for writing (or reading and writing).\n    ///\n    /// You can use the following methods to create commonly used sets of options:\n    /// - ``newFile(replaceExisting:permissions:)`` to create a new file, optionally replacing\n    ///   one which already exists.\n    /// - ``modifyFile(createIfNecessary:permissions:)`` to modify an existing file, optionally\n    ///   creating it if it doesn't exist.\n    public struct Write: Hashable, Sendable {\n        /// The behavior for opening an existing file.\n        public var existingFile: OpenOptions.ExistingFile\n\n        /// The creation options for a new file, if one should be created. `nil` means that no\n        /// file should be created.\n        public var newFile: OpenOptions.NewFile?\n\n        /// If the last path component is a symbolic link then this flag determines whether the\n        /// link is followed. If `false` and the last path component is a symbolic link then an\n        /// error is thrown.\n        public var followSymbolicLinks: Bool\n\n        /// Marks the descriptor of the opened file as 'close-on-exec'.\n        public var closeOnExec: Bool\n\n        /// Creates a new set of options for opening a directory.\n        ///\n        /// - Parameters:\n        ///   - existingFile: Options for handling an existing file.\n        ///   - newFile: Options for creating a new file.\n        ///   - followSymbolicLinks: Whether symbolic links should be followed, defaults to `true`.\n        ///   - closeOnExec: Whether the descriptor should be marked as closed-on-exec, defaults\n        ///     to `false`.\n        public init(\n            existingFile: OpenOptions.ExistingFile,\n            newFile: OpenOptions.NewFile?,\n            followSymbolicLinks: Bool = true,\n            closeOnExec: Bool = false\n        ) {\n            self.existingFile = existingFile\n            self.newFile = newFile\n            self.followSymbolicLinks = followSymbolicLinks\n            self.closeOnExec = closeOnExec\n        }\n\n        /// Create a new file for writing to.\n        ///\n        /// - Parameters:\n        ///   - replaceExisting: Whether any existing file of the same name is replaced. If\n        ///       this is `true` then any existing file of the same name will be replaced with the\n        ///       new file. If this is `false` and a file already exists an error is thrown.\n        ///   - permissions: The permissions to apply to the newly created file. Default permissions\n        ///       (read-write owner permissions and read permissions for everyone else) are applied\n        ///       if `nil`.\n        /// - Returns: Options for creating a new file for writing.\n        public static func newFile(\n            replaceExisting: Bool,\n            permissions: FilePermissions? = nil\n        ) -> Self {\n            Write(\n                existingFile: replaceExisting ? .truncate : .none,\n                newFile: NewFile(permissions: permissions)\n            )\n        }\n\n        /// Opens a file for modifying.\n        ///\n        /// - Parameters:\n        ///   - createIfNecessary: Whether a file should be created if one doesn't exist. If\n        ///     `false` and a file doesn't exist then an error is thrown.\n        ///   - permissions: The permissions to apply to the newly created file. Default permissions\n        ///       (read-write owner permissions and read permissions for everyone else) are applied\n        ///       if `nil`. Ignored if `createIfNonExistent` is `false`.\n        /// - Returns: Options for modifying an existing file for writing.\n        public static func modifyFile(\n            createIfNecessary: Bool,\n            permissions: FilePermissions? = nil\n        ) -> Self {\n            Write(\n                existingFile: .open,\n                newFile: createIfNecessary ? NewFile(permissions: permissions) : nil\n            )\n        }\n    }\n}\n\nextension OpenOptions {\n    /// Options for opening an existing file.\n    public enum ExistingFile: Sendable, Hashable {\n        /// Indicates that no file exists. If a file does exist then an error is thrown when\n        /// opening the file.\n        case none\n\n        /// Any existing file should be opened without modification.\n        case open\n\n        /// Truncate the existing file.\n        ///\n        /// Setting this is equivalent to opening a file with `O_TRUNC`.\n        case truncate\n    }\n\n    /// Options for creating a new file.\n    public struct NewFile: Sendable, Hashable {\n        /// The permissions to apply to the new file. `nil` implies default permissions\n        /// should be applied.\n        public var permissions: FilePermissions?\n\n        /// Whether the file should be created and updated as a single transaction, if\n        /// applicable.\n        ///\n        /// When this option is set and applied the newly created file will only materialize\n        /// on the file system when the file is closed.\n        /// When used in conjunction with\n        /// ``FileSystemProtocol/withFileHandle(forWritingAt:options:execute:)`` and\n        /// ``FileSystemProtocol/withFileHandle(forReadingAndWritingAt:options:execute:)`` the\n        /// file will only materialize when the file is closed and no errors have been thrown.\n        ///\n        /// - Important: This flag is only applied if ``OpenOptions/Write/existingFile`` is\n        ///   ``OpenOptions/ExistingFile/none``.\n        public var transactionalCreation: Bool\n\n        public init(\n            permissions: FilePermissions? = nil,\n            transactionalCreation: Bool = true\n        ) {\n            self.permissions = permissions\n            self.transactionalCreation = transactionalCreation\n        }\n    }\n}\n\nextension OpenOptions.Write {\n    @_spi(Testing)\n    public var permissionsForRegularFile: FilePermissions? {\n        if let newFile = self.newFile {\n            return newFile.permissions ?? .defaultsForRegularFile\n        } else {\n            return nil\n        }\n    }\n\n    var descriptorOptions: FileDescriptor.OpenOptions {\n        var options = FileDescriptor.OpenOptions()\n\n        if !self.followSymbolicLinks {\n            options.insert(.noFollow)\n        }\n\n        if self.closeOnExec {\n            options.insert(.closeOnExec)\n        }\n\n        if self.newFile != nil {\n            options.insert(.create)\n        }\n\n        switch self.existingFile {\n        case .none:\n            options.insert(.exclusiveCreate)\n        case .open:\n            ()\n        case .truncate:\n            options.insert(.truncate)\n        }\n\n        return options\n    }\n}\n\nextension OpenOptions.Read {\n    var descriptorOptions: FileDescriptor.OpenOptions {\n        var options = FileDescriptor.OpenOptions()\n\n        if !self.followSymbolicLinks {\n            options.insert(.noFollow)\n        }\n\n        if self.closeOnExec {\n            options.insert(.closeOnExec)\n        }\n\n        return options\n    }\n}\n\nextension OpenOptions.Directory {\n    var descriptorOptions: FileDescriptor.OpenOptions {\n        var options = FileDescriptor.OpenOptions([.directory])\n\n        if !self.followSymbolicLinks {\n            options.insert(.noFollow)\n        }\n\n        if self.closeOnExec {\n            options.insert(.closeOnExec)\n        }\n\n        return options\n    }\n}\n\nextension FileDescriptor.OpenOptions {\n    public init(_ options: OpenOptions.Read) {\n        self = options.descriptorOptions\n    }\n\n    public init(_ options: OpenOptions.Write) {\n        self = options.descriptorOptions\n    }\n\n    public init(_ options: OpenOptions.Directory) {\n        self = options.descriptorOptions\n    }\n}\n\nextension FilePermissions {\n    /// Default permissions for regular files; owner read-write, group read, other read.\n    internal static let defaultsForRegularFile: FilePermissions = [\n        .ownerReadWrite,\n        .groupRead,\n        .otherRead,\n    ]\n\n    /// Default permissions for directories; owner read-write-execute, group read-execute, other\n    /// read-execute.\n    internal static let defaultsForDirectory: FilePermissions = [\n        .ownerReadWriteExecute,\n        .groupReadExecute,\n        .otherReadExecute,\n    ]\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystem/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyTracking</key>\n\t<false/>\n\t<key>NSPrivacyAccessedAPITypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>0A2A.1</string>\n\t\t\t</array>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>\n\t\t</dict>\n\t</array>\n\t<key>NSPrivacyCollectedDataTypes</key>\n\t<array/>\n\t<key>NSPrivacyTrackingDomains</key>\n\t<array/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Sources/_NIOFileSystem/String+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension String {\n    /// Reads the contents of the file at the path into a String.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``. If the file is larger than this, an error is thrown.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    ///\n    /// - Throws: If the file is larger than `maximumSizeAllowed`, an ``FileSystemError/Code-swift.struct/resourceExhausted`` error will be thrown.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let byteBuffer = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(maximumSizeAllowed: maximumSizeAllowed)\n        }\n\n        self = Self(buffer: byteBuffer)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``. If the file is larger than this, an error is thrown.\n    ///\n    /// - Throws: If the file is larger than `maximumSizeAllowed`, an ``FileSystemError/Code-swift.struct/resourceExhausted`` error will be thrown.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/_NIOFileSystemFoundationCompat/Data+FileSystem.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n#if canImport(Darwin) || os(Linux) || os(Android)\nimport _NIOFileSystem\nimport NIOCore\nimport NIOFoundationCompat\nimport struct Foundation.Data\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension Data {\n    /// Reads the contents of the file at the path.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, in bytes, as a ``ByteCount``.\n    ///   - fileSystem: The ``FileSystemProtocol`` instance to use to read the file.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount,\n        fileSystem: some FileSystemProtocol\n    ) async throws {\n        let byteBuffer = try await fileSystem.withFileHandle(forReadingAt: path) { handle in\n            try await handle.readToEnd(maximumSizeAllowed: maximumSizeAllowed)\n        }\n\n        self = Data(buffer: byteBuffer)\n    }\n\n    /// Reads the contents of the file at the path using ``FileSystem``.\n    ///\n    /// - Parameters:\n    ///   - path: The path of the file to read.\n    ///   - maximumSizeAllowed: The maximum size of file which can be read, as a ``ByteCount``.\n    public init(\n        contentsOf path: FilePath,\n        maximumSizeAllowed: ByteCount\n    ) async throws {\n        self = try await Self(\n            contentsOf: path,\n            maximumSizeAllowed: maximumSizeAllowed,\n            fileSystem: .shared\n        )\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/_NIOFileSystemFoundationCompat/Date+FileInfo.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport _NIOFileSystem\n\nimport struct Foundation.Date\n\nextension Date {\n    public init(timespec: FileInfo.Timespec) {\n        let timeInterval = Double(timespec.seconds) + Double(timespec.nanoseconds) / 1_000_000_000\n        self = Date(timeIntervalSince1970: timeInterval)\n    }\n}\n\nextension FileInfo.Timespec {\n    /// The UTC time of the timestamp.\n    public var date: Date {\n        Date(timespec: self)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOBase64Tests/Base64Test.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\nimport _NIOBase64\n\nclass Base64Test: XCTestCase {\n    func testEncodeEmptyData() throws {\n        let data = [UInt8]()\n        let encodedData = String(_base64Encoding: data)\n        XCTAssertEqual(encodedData.count, 0)\n    }\n\n    func testBase64EncodingOfEmptyString() throws {\n        let string = \"\"\n        let encoded = String(_base64Encoding: string.utf8)\n        XCTAssertEqual(encoded, \"\")\n    }\n\n    func testBase64DecodingOfEmptyString() throws {\n        let encoded = \"\"\n        XCTAssertNoThrow {\n            let decoded = try encoded._base64Decoded()\n            XCTAssertEqual(decoded, [UInt8]())\n        }\n    }\n\n    func testBase64EncodingArrayOfNulls() throws {\n        let data = Array(repeating: UInt8(0), count: 10)\n        let encodedData = String(_base64Encoding: data)\n        XCTAssertEqual(encodedData, \"AAAAAAAAAAAAAA==\")\n    }\n\n    func testBase64DecodeArrayOfNulls() throws {\n        let encoded = \"AAAAAAAAAAAAAA==\"\n        let decoded = try! encoded._base64Decoded()\n        let expected = Array(repeating: UInt8(0), count: 10)\n        XCTAssertEqual(decoded, expected)\n    }\n\n    func testBase64EncodeingHelloWorld() throws {\n        let string = \"Hello, world!\"\n        let encoded = String(_base64Encoding: string.utf8)\n        let expected = \"SGVsbG8sIHdvcmxkIQ==\"\n        XCTAssertEqual(encoded, expected)\n    }\n\n    func testBase64DecodeHelloWorld() throws {\n        let encoded = \"SGVsbG8sIHdvcmxkIQ==\"\n        let decoded = try! encoded._base64Decoded()\n        XCTAssertEqual(decoded, \"Hello, world!\".utf8.map { UInt8($0) })\n    }\n\n    func testBase64EncodingAllTheBytesSequentially() throws {\n        let data = Array(UInt8(0)...UInt8(255))\n        let encodedData = String(_base64Encoding: data)\n        XCTAssertEqual(\n            encodedData,\n            \"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"\n        )\n    }\n\n    func testBase64DecodingWithInvalidLength() {\n        let encoded = \"dGVzbA!==\"\n        XCTAssertThrowsError(try encoded._base64Decoded()) { error in\n            XCTAssertEqual(error as? Base64Error, .invalidLength)\n        }\n    }\n\n    func testBase64DecodeWithInvalidCharacter() throws {\n        let encoded = \"SGVsbG8sI_dvcmxkIQ==\"\n        XCTAssertThrowsError(try encoded._base64Decoded()) { error in\n            XCTAssertEqual(error as? Base64Error, .invalidCharacter)\n        }\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOConcurrencyHelpersTests/NIOConcurrencyHelpersTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport XCTest\n\n@testable import NIOConcurrencyHelpers\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\nimport Glibc\n#elseif canImport(Android)\nimport Android\n#else\n#error(\"The Concurrency helpers test module was unable to identify your C library.\")\n#endif\n\nclass NIOConcurrencyHelpersTests: XCTestCase {\n    private func sumOfIntegers(until n: UInt64) -> UInt64 {\n        n * (n + 1) / 2\n    }\n\n    #if canImport(Darwin)\n    let noAsyncs: UInt64 = 50\n    #else\n    /// `swift-corelibs-libdispatch` implementation of concurrent queues only initially spawn up to `System.coreCount` threads.\n    /// Afterwards they will create one thread per second.\n    /// Therefore this test takes `noAsyncs - System.coreCount` seconds to execute.\n    /// For example if `noAsyncs == 50` and `System.coreCount == 8` this test takes ~42 seconds to execute.\n    /// On non Darwin system we therefore limit the number of async operations to `System.coreCount`.\n    let noAsyncs: UInt64 = UInt64(System.coreCount)\n    #endif\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testLargeContendedAtomicSum() {\n\n        let noCounts: UInt64 = 2_000\n\n        let q = DispatchQueue(label: \"q\", attributes: .concurrent)\n        let g = DispatchGroup()\n        let ai = NIOConcurrencyHelpers.Atomic<UInt64>(value: 0)\n        let everybodyHere = DispatchSemaphore(value: 0)\n        let go = DispatchSemaphore(value: 0)\n        for thread in 1...self.noAsyncs {\n            q.async(group: g) {\n                everybodyHere.signal()\n                go.wait()\n                for _ in 0..<noCounts {\n                    ai.add(thread)\n                }\n            }\n        }\n        for _ in 0..<self.noAsyncs {\n            everybodyHere.wait()\n        }\n        for _ in 0..<self.noAsyncs {\n            go.signal()\n        }\n        g.wait()\n        XCTAssertEqual(sumOfIntegers(until: self.noAsyncs) * noCounts, ai.load())\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testCompareAndExchangeBool() {\n        let ab = Atomic<Bool>(value: true)\n\n        XCTAssertFalse(ab.compareAndExchange(expected: false, desired: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: true, desired: true))\n\n        XCTAssertFalse(ab.compareAndExchange(expected: false, desired: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: true, desired: false))\n\n        XCTAssertTrue(ab.compareAndExchange(expected: false, desired: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testAllOperationsBool() {\n        let ab = Atomic<Bool>(value: false)\n        XCTAssertEqual(false, ab.load())\n        ab.store(false)\n        XCTAssertEqual(false, ab.load())\n        ab.store(true)\n        XCTAssertEqual(true, ab.load())\n        ab.store(true)\n        XCTAssertEqual(true, ab.load())\n        XCTAssertEqual(true, ab.exchange(with: true))\n        XCTAssertEqual(true, ab.exchange(with: false))\n        XCTAssertEqual(false, ab.exchange(with: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))\n        XCTAssertFalse(ab.compareAndExchange(expected: false, desired: true))\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testCompareAndExchangeUInts() {\n        func testFor<T: AtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) {\n            let zero: T = 0\n            let max = ~zero\n\n            let ab = Atomic<T>(value: max)\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: max, desired: max))\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: max, desired: zero))\n\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: max))\n\n            var counter = max\n            for _ in 0..<255 {\n                XCTAssertTrue(ab.compareAndExchange(expected: counter, desired: counter - 1))\n                counter = counter - 1\n            }\n        }\n\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testCompareAndExchangeInts() {\n        func testFor<T: AtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) {\n            let zero: T = 0\n            let upperBound: T = 127\n\n            let ab = Atomic<T>(value: upperBound)\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: upperBound, desired: upperBound))\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: upperBound, desired: zero))\n\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: upperBound))\n\n            var counter = upperBound\n            for _ in 0..<255 {\n                XCTAssertTrue(ab.compareAndExchange(expected: counter, desired: counter - 1))\n                XCTAssertFalse(ab.compareAndExchange(expected: counter, desired: counter))\n                counter = counter - 1\n            }\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testAddSub() {\n        func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {\n            let zero: T = 0\n\n            let ab = Atomic<T>(value: zero)\n\n            XCTAssertEqual(0, ab.add(1))\n            XCTAssertEqual(1, ab.add(41))\n            XCTAssertEqual(42, ab.add(23))\n\n            XCTAssertEqual(65, ab.load())\n\n            XCTAssertEqual(65, ab.sub(23))\n            XCTAssertEqual(42, ab.sub(41))\n            XCTAssertEqual(1, ab.sub(1))\n\n            XCTAssertEqual(0, ab.load())\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testExchange() {\n        func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {\n            let zero: T = 0\n\n            let ab = Atomic<T>(value: zero)\n\n            XCTAssertEqual(0, ab.exchange(with: 1))\n            XCTAssertEqual(1, ab.exchange(with: 42))\n            XCTAssertEqual(42, ab.exchange(with: 65))\n\n            XCTAssertEqual(65, ab.load())\n\n            XCTAssertEqual(65, ab.exchange(with: 42))\n            XCTAssertEqual(42, ab.exchange(with: 1))\n            XCTAssertEqual(1, ab.exchange(with: 0))\n\n            XCTAssertEqual(0, ab.load())\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testLoadStore() {\n        func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {\n            let zero: T = 0\n\n            let ab = Atomic<T>(value: zero)\n\n            XCTAssertEqual(0, ab.load())\n            ab.store(42)\n            XCTAssertEqual(42, ab.load())\n            ab.store(0)\n            XCTAssertEqual(0, ab.load())\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testLargeContendedNIOAtomicSum() {\n        let noCounts: UInt64 = 2_000\n\n        let q = DispatchQueue(label: \"q\", attributes: .concurrent)\n        let g = DispatchGroup()\n        let ai = NIOConcurrencyHelpers.NIOAtomic<UInt64>.makeAtomic(value: 0)\n        let everybodyHere = DispatchSemaphore(value: 0)\n        let go = DispatchSemaphore(value: 0)\n        for thread in 1...self.noAsyncs {\n            q.async(group: g) {\n                everybodyHere.signal()\n                go.wait()\n                for _ in 0..<noCounts {\n                    ai.add(thread)\n                }\n            }\n        }\n        for _ in 0..<self.noAsyncs {\n            everybodyHere.wait()\n        }\n        for _ in 0..<self.noAsyncs {\n            go.signal()\n        }\n        g.wait()\n        XCTAssertEqual(sumOfIntegers(until: self.noAsyncs) * noCounts, ai.load())\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testCompareAndExchangeBoolNIOAtomic() {\n        let ab = NIOAtomic<Bool>.makeAtomic(value: true)\n\n        XCTAssertFalse(ab.compareAndExchange(expected: false, desired: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: true, desired: true))\n\n        XCTAssertFalse(ab.compareAndExchange(expected: false, desired: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: true, desired: false))\n\n        XCTAssertTrue(ab.compareAndExchange(expected: false, desired: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testAllOperationsBoolNIOAtomic() {\n        let ab = NIOAtomic<Bool>.makeAtomic(value: false)\n        XCTAssertEqual(false, ab.load())\n        ab.store(false)\n        XCTAssertEqual(false, ab.load())\n        ab.store(true)\n        XCTAssertEqual(true, ab.load())\n        ab.store(true)\n        XCTAssertEqual(true, ab.load())\n        XCTAssertEqual(true, ab.exchange(with: true))\n        XCTAssertEqual(true, ab.exchange(with: false))\n        XCTAssertEqual(false, ab.exchange(with: false))\n        XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))\n        XCTAssertFalse(ab.compareAndExchange(expected: false, desired: true))\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testCompareAndExchangeUIntsNIOAtomic() {\n        func testFor<T: NIOAtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) {\n            let zero: T = 0\n            let max = ~zero\n\n            let ab = NIOAtomic<T>.makeAtomic(value: max)\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: max, desired: max))\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: max, desired: zero))\n\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: max))\n\n            var counter = max\n            for _ in 0..<255 {\n                XCTAssertTrue(ab.compareAndExchange(expected: counter, desired: counter - 1))\n                counter = counter - 1\n            }\n        }\n\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testCompareAndExchangeIntsNIOAtomic() {\n        func testFor<T: NIOAtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) {\n            let zero: T = 0\n            let upperBound: T = 127\n\n            let ab = NIOAtomic<T>.makeAtomic(value: upperBound)\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: upperBound, desired: upperBound))\n\n            XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: upperBound, desired: zero))\n\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: zero))\n            XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: upperBound))\n\n            var counter = upperBound\n            for _ in 0..<255 {\n                XCTAssertTrue(ab.compareAndExchange(expected: counter, desired: counter - 1))\n                XCTAssertFalse(ab.compareAndExchange(expected: counter, desired: counter))\n                counter = counter - 1\n            }\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testAddSubNIOAtomic() {\n        func testFor<T: NIOAtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {\n            let zero: T = 0\n\n            let ab = NIOAtomic<T>.makeAtomic(value: zero)\n\n            XCTAssertEqual(0, ab.add(1))\n            XCTAssertEqual(1, ab.add(41))\n            XCTAssertEqual(42, ab.add(23))\n\n            XCTAssertEqual(65, ab.load())\n\n            XCTAssertEqual(65, ab.sub(23))\n            XCTAssertEqual(42, ab.sub(41))\n            XCTAssertEqual(1, ab.sub(1))\n\n            XCTAssertEqual(0, ab.load())\n\n            let atomic = NIOAtomic<T>.makeAtomic(value: zero)\n            atomic.store(100)\n            atomic.add(1)\n            XCTAssertEqual(101, atomic.load())\n            atomic.sub(1)\n            XCTAssertEqual(100, atomic.load())\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testExchangeNIOAtomic() {\n        func testFor<T: NIOAtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {\n            let zero: T = 0\n\n            let ab = NIOAtomic<T>.makeAtomic(value: zero)\n\n            XCTAssertEqual(0, ab.exchange(with: 1))\n            XCTAssertEqual(1, ab.exchange(with: 42))\n            XCTAssertEqual(42, ab.exchange(with: 65))\n\n            XCTAssertEqual(65, ab.load())\n\n            XCTAssertEqual(65, ab.exchange(with: 42))\n            XCTAssertEqual(42, ab.exchange(with: 1))\n            XCTAssertEqual(1, ab.exchange(with: 0))\n\n            XCTAssertEqual(0, ab.load())\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testLoadStoreNIOAtomic() {\n        func testFor<T: NIOAtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {\n            let zero: T = 0\n\n            let ab = NIOAtomic<T>.makeAtomic(value: zero)\n\n            XCTAssertEqual(0, ab.load())\n            ab.store(42)\n            XCTAssertEqual(42, ab.load())\n            ab.store(0)\n            XCTAssertEqual(0, ab.load())\n        }\n\n        testFor(Int8.self)\n        testFor(Int16.self)\n        testFor(Int32.self)\n        testFor(Int64.self)\n        testFor(Int.self)\n        testFor(UInt8.self)\n        testFor(UInt16.self)\n        testFor(UInt32.self)\n        testFor(UInt64.self)\n        testFor(UInt.self)\n    }\n\n    @available(*, deprecated, message: \"Test deprecated as it tests the deprecated Lock class\")\n    func testDeprecatedLockMutualExclusion() {\n        let l = Lock()\n\n        nonisolated(unsafe) var x = 1\n        let q = DispatchQueue(label: \"q\")\n        let g = DispatchGroup()\n        let sem1 = DispatchSemaphore(value: 0)\n        let sem2 = DispatchSemaphore(value: 0)\n\n        l.lock()\n\n        q.async(group: g) {\n            sem1.signal()\n            l.lock()\n            x = 2\n            l.unlock()\n            sem2.signal()\n        }\n\n        sem1.wait()\n        XCTAssertEqual(\n            DispatchTimeoutResult.timedOut,\n            g.wait(timeout: .now() + 0.1)\n        )\n        XCTAssertEqual(1, x)\n\n        l.unlock()\n        sem2.wait()\n\n        l.lock()\n        XCTAssertEqual(2, x)\n        l.unlock()\n    }\n\n    func testLockMutualExclusion() {\n        let l = NIOLock()\n\n        nonisolated(unsafe) var x = 1\n        let q = DispatchQueue(label: \"q\")\n        let g = DispatchGroup()\n        let sem1 = DispatchSemaphore(value: 0)\n        let sem2 = DispatchSemaphore(value: 0)\n\n        l.lock()\n\n        q.async(group: g) {\n            sem1.signal()\n            l.lock()\n            x = 2\n            l.unlock()\n            sem2.signal()\n        }\n\n        sem1.wait()\n        XCTAssertEqual(\n            DispatchTimeoutResult.timedOut,\n            g.wait(timeout: .now() + 0.1)\n        )\n        XCTAssertEqual(1, x)\n\n        l.unlock()\n        sem2.wait()\n\n        l.lock()\n        XCTAssertEqual(2, x)\n        l.unlock()\n    }\n\n    func testWithLockMutualExclusion() {\n        let l = NIOLock()\n\n        nonisolated(unsafe) var x = 1\n        let q = DispatchQueue(label: \"q\")\n        let g = DispatchGroup()\n        let sem1 = DispatchSemaphore(value: 0)\n        let sem2 = DispatchSemaphore(value: 0)\n\n        l.withLock {\n            q.async(group: g) {\n                sem1.signal()\n                l.withLock {\n                    x = 2\n                }\n                sem2.signal()\n            }\n\n            sem1.wait()\n            XCTAssertEqual(\n                DispatchTimeoutResult.timedOut,\n                g.wait(timeout: .now() + 0.1)\n            )\n            XCTAssertEqual(1, x)\n        }\n        sem2.wait()\n\n        l.withLock {\n            XCTAssertEqual(2, x)\n        }\n    }\n\n    func testConditionLockMutualExclusion() {\n        let l = ConditionLock(value: 0)\n\n        nonisolated(unsafe) var x = 1\n        let q = DispatchQueue(label: \"q\")\n        let g = DispatchGroup()\n        let sem1 = DispatchSemaphore(value: 0)\n        let sem2 = DispatchSemaphore(value: 0)\n\n        l.lock()\n\n        q.async(group: g) {\n            sem1.signal()\n            l.lock()\n            x = 2\n            l.unlock()\n            sem2.signal()\n        }\n\n        sem1.wait()\n        XCTAssertEqual(\n            DispatchTimeoutResult.timedOut,\n            g.wait(timeout: .now() + 0.1)\n        )\n        XCTAssertEqual(1, x)\n\n        l.unlock()\n        sem2.wait()\n\n        l.lock()\n        XCTAssertEqual(2, x)\n        l.unlock()\n    }\n\n    func testConditionLock() {\n        let l = ConditionLock(value: 0)\n        let q = DispatchQueue(label: \"q\")\n        let sem = DispatchSemaphore(value: 0)\n\n        XCTAssertEqual(0, l.value)\n\n        l.lock()\n        l.unlock(withValue: 1)\n\n        XCTAssertEqual(1, l.value)\n\n        q.async {\n            l.lock(whenValue: 2)\n            l.unlock(withValue: 3)\n            sem.signal()\n        }\n\n        usleep(100_000)\n\n        l.lock()\n        l.unlock(withValue: 2)\n\n        sem.wait()\n        l.lock(whenValue: 3)\n        l.unlock()\n\n        XCTAssertEqual(false, l.lock(whenValue: 4, timeoutSeconds: 0.1))\n\n        XCTAssertEqual(true, l.lock(whenValue: 3, timeoutSeconds: 0.01))\n        l.unlock()\n\n        q.async {\n            usleep(100_000)\n\n            l.lock()\n            l.unlock(withValue: 4)\n            sem.signal()\n        }\n\n        XCTAssertEqual(true, l.lock(whenValue: 4, timeoutSeconds: 10))\n        l.unlock()\n    }\n\n    func testConditionLockWithDifferentConditions() {\n        for _ in 0..<200 {\n            let l = ConditionLock(value: 0)\n            let q1 = DispatchQueue(label: \"q1\")\n            let q2 = DispatchQueue(label: \"q2\")\n\n            let readySem = DispatchSemaphore(value: 0)\n            let doneSem = DispatchSemaphore(value: 0)\n\n            q1.async {\n                readySem.signal()\n\n                l.lock(whenValue: 1)\n                l.unlock()\n                XCTAssertEqual(1, l.value)\n\n                doneSem.signal()\n            }\n\n            q2.async {\n                readySem.signal()\n\n                l.lock(whenValue: 2)\n                l.unlock()\n                XCTAssertEqual(2, l.value)\n\n                doneSem.signal()\n            }\n\n            readySem.wait()\n            readySem.wait()\n            l.lock()\n            l.unlock(withValue: 1)\n\n            doneSem.wait()  // job on 'q1' is done\n\n            XCTAssertEqual(1, l.value)\n            l.lock()\n            l.unlock(withValue: 2)\n\n            doneSem.wait()  // job on 'q2' is done\n        }\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicBoxDoesNotTriviallyLeak() throws {\n        class SomeClass {}\n        weak var weakSomeInstance1: SomeClass? = nil\n        weak var weakSomeInstance2: SomeClass? = nil\n        ({\n            let someInstance = SomeClass()\n            weakSomeInstance1 = someInstance\n            let someAtomic = AtomicBox(value: someInstance)\n            let loadedFromAtomic = someAtomic.load()\n            weakSomeInstance2 = loadedFromAtomic\n            XCTAssertNotNil(weakSomeInstance1)\n            XCTAssertNotNil(weakSomeInstance2)\n            XCTAssert(someInstance === loadedFromAtomic)\n        })()\n        XCTAssertNil(weakSomeInstance1)\n        XCTAssertNil(weakSomeInstance2)\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicBoxCompareAndExchangeWorksIfEqual() throws {\n        class SomeClass {}\n        weak var weakSomeInstance1: SomeClass? = nil\n        weak var weakSomeInstance2: SomeClass? = nil\n        weak var weakSomeInstance3: SomeClass? = nil\n        ({\n            let someInstance1 = SomeClass()\n            let someInstance2 = SomeClass()\n            weakSomeInstance1 = someInstance1\n\n            let atomic = AtomicBox(value: someInstance1)\n            var loadedFromAtomic = atomic.load()\n            XCTAssert(someInstance1 === loadedFromAtomic)\n            weakSomeInstance2 = loadedFromAtomic\n\n            XCTAssertTrue(atomic.compareAndExchange(expected: loadedFromAtomic, desired: someInstance2))\n\n            loadedFromAtomic = atomic.load()\n            weakSomeInstance3 = loadedFromAtomic\n            XCTAssert(someInstance1 !== loadedFromAtomic)\n            XCTAssert(someInstance2 === loadedFromAtomic)\n\n            XCTAssertNotNil(weakSomeInstance1)\n            XCTAssertNotNil(weakSomeInstance2)\n            XCTAssertNotNil(weakSomeInstance3)\n            XCTAssert(weakSomeInstance1 === weakSomeInstance2 && weakSomeInstance2 !== weakSomeInstance3)\n        })()\n        XCTAssertNil(weakSomeInstance1)\n        XCTAssertNil(weakSomeInstance2)\n        XCTAssertNil(weakSomeInstance3)\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicBoxCompareAndExchangeWorksIfNotEqual() throws {\n        class SomeClass {}\n        weak var weakSomeInstance1: SomeClass? = nil\n        weak var weakSomeInstance2: SomeClass? = nil\n        weak var weakSomeInstance3: SomeClass? = nil\n        ({\n            let someInstance1 = SomeClass()\n            let someInstance2 = SomeClass()\n            weakSomeInstance1 = someInstance1\n\n            let atomic = AtomicBox(value: someInstance1)\n            var loadedFromAtomic = atomic.load()\n            XCTAssert(someInstance1 === loadedFromAtomic)\n            weakSomeInstance2 = loadedFromAtomic\n\n            XCTAssertFalse(atomic.compareAndExchange(expected: someInstance2, desired: someInstance2))\n            XCTAssertFalse(atomic.compareAndExchange(expected: SomeClass(), desired: someInstance2))\n            XCTAssertTrue(atomic.load() === someInstance1)\n\n            loadedFromAtomic = atomic.load()\n            weakSomeInstance3 = someInstance2\n            XCTAssert(someInstance1 === loadedFromAtomic)\n            XCTAssert(someInstance2 !== loadedFromAtomic)\n\n            XCTAssertNotNil(weakSomeInstance1)\n            XCTAssertNotNil(weakSomeInstance2)\n            XCTAssertNotNil(weakSomeInstance3)\n        })()\n        XCTAssertNil(weakSomeInstance1)\n        XCTAssertNil(weakSomeInstance2)\n        XCTAssertNil(weakSomeInstance3)\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicBoxStoreWorks() throws {\n        class SomeClass {}\n        weak var weakSomeInstance1: SomeClass? = nil\n        weak var weakSomeInstance2: SomeClass? = nil\n        weak var weakSomeInstance3: SomeClass? = nil\n        ({\n            let someInstance1 = SomeClass()\n            let someInstance2 = SomeClass()\n            weakSomeInstance1 = someInstance1\n\n            let atomic = AtomicBox(value: someInstance1)\n            var loadedFromAtomic = atomic.load()\n            XCTAssert(someInstance1 === loadedFromAtomic)\n            weakSomeInstance2 = loadedFromAtomic\n\n            atomic.store(someInstance2)\n\n            loadedFromAtomic = atomic.load()\n            weakSomeInstance3 = loadedFromAtomic\n            XCTAssert(someInstance1 !== loadedFromAtomic)\n            XCTAssert(someInstance2 === loadedFromAtomic)\n\n            XCTAssertNotNil(weakSomeInstance1)\n            XCTAssertNotNil(weakSomeInstance2)\n            XCTAssertNotNil(weakSomeInstance3)\n        })()\n        XCTAssertNil(weakSomeInstance1)\n        XCTAssertNil(weakSomeInstance2)\n        XCTAssertNil(weakSomeInstance3)\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicBoxCompareAndExchangeOntoItselfWorks() {\n        let q = DispatchQueue(label: \"q\")\n        let g = DispatchGroup()\n        let sem1 = DispatchSemaphore(value: 0)\n        let sem2 = DispatchSemaphore(value: 0)\n        final class SomeClass: Sendable {}\n        weak var weakInstance: SomeClass?\n        ({\n            let instance = SomeClass()\n            weakInstance = instance\n\n            let atomic = AtomicBox(value: instance)\n            q.async(group: g) {\n                sem1.signal()\n                sem2.wait()\n                for _ in 0..<1000 {\n                    XCTAssertTrue(atomic.compareAndExchange(expected: instance, desired: instance))\n                }\n            }\n            sem2.signal()\n            sem1.wait()\n            for _ in 0..<1000 {\n                XCTAssertTrue(atomic.compareAndExchange(expected: instance, desired: instance))\n            }\n            g.wait()\n            let v = atomic.load()\n            XCTAssert(v === instance)\n        })()\n        XCTAssertNil(weakInstance)\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicLoadMassLoadAndStore() {\n        let writer = DispatchQueue(label: \"\\(#file):writer\")\n        let reader = DispatchQueue(label: \"\\(#file):reader\")\n        let g = DispatchGroup()\n        let writerArrived = DispatchSemaphore(value: 0)\n        let readerArrived = DispatchSemaphore(value: 0)\n        let go = DispatchSemaphore(value: 0)\n        let iterations = 100_000\n\n        final class Foo: Sendable {\n            let x: Int\n\n            init(_ x: Int) {\n                self.x = x\n            }\n        }\n\n        let box: AtomicBox<Foo> = .init(value: Foo(iterations))\n\n        writer.async(group: g) {\n            writerArrived.signal()\n            go.wait()\n\n            for i in 0..<iterations {\n                box.store(Foo(i))\n            }\n        }\n\n        reader.async(group: g) {\n            readerArrived.signal()\n            go.wait()\n\n            for _ in 0..<iterations {\n                if box.load().x < 0 {\n                    XCTFail(\"bad\")\n                }\n            }\n        }\n\n        writerArrived.wait()\n        readerArrived.wait()\n        go.signal()\n        go.signal()\n\n        g.wait()\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testAtomicBoxCompareAndExchangeOntoItself() {\n        class Foo {}\n        weak var weakF: Foo? = nil\n        weak var weakG: Foo? = nil\n\n        @inline(never)\n        func doIt() {\n            let f = Foo()\n            let g = Foo()\n            weakF = f\n            weakG = g\n            let box = AtomicBox<Foo>(value: f)\n            XCTAssertFalse(box.compareAndExchange(expected: g, desired: g))\n            XCTAssertTrue(box.compareAndExchange(expected: f, desired: f))\n            XCTAssertFalse(box.compareAndExchange(expected: g, desired: g))\n            XCTAssertTrue(box.compareAndExchange(expected: f, desired: g))\n        }\n        doIt()\n        assert(weakF == nil, within: .seconds(1))\n        assert(weakG == nil, within: .seconds(1))\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testLoadAndExchangeHammering() {\n        let allDeallocations = NIOAtomic<Int>.makeAtomic(value: 0)\n        let iterations = 10_000\n\n        @inline(never)\n        func doIt() {\n            let box = AtomicBox(value: IntHolderWithDeallocationTracking(0, allDeallocations: allDeallocations))\n\n            spawnAndJoinRacingThreads(count: 6) { i in\n                switch i {\n                case 0:  // writer\n                    for i in 1...iterations {\n                        let nextObject = box.exchange(with: .init(i, allDeallocations: allDeallocations))\n                        XCTAssertEqual(nextObject.value, i - 1)\n                    }\n                default:  // readers\n                    while true {\n                        if box.load().value < 0 || box.load().value > iterations {\n                            XCTFail(\"bad\")\n                        }\n                        if box.load().value == iterations {\n                            break\n                        }\n                    }\n                }\n            }\n        }\n\n        doIt()\n        assert(allDeallocations.load() == iterations + 1, within: .seconds(1))\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testLoadAndStoreHammering() {\n        let allDeallocations = NIOAtomic<Int>.makeAtomic(value: 0)\n        let iterations = 10_000\n\n        @inline(never)\n        func doIt() {\n            let box = AtomicBox(value: IntHolderWithDeallocationTracking(0, allDeallocations: allDeallocations))\n\n            spawnAndJoinRacingThreads(count: 6) { i in\n                switch i {\n                case 0:  // writer\n                    for i in 1...iterations {\n                        box.store(IntHolderWithDeallocationTracking(i, allDeallocations: allDeallocations))\n                    }\n                default:  // readers\n                    while true {\n                        if box.load().value < 0 || box.load().value > iterations {\n                            XCTFail(\"loaded the wrong value\")\n                        }\n                        if box.load().value == iterations {\n                            break\n                        }\n                    }\n                }\n            }\n        }\n\n        doIt()\n        assert(allDeallocations.load() == iterations + 1, within: .seconds(1))\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testLoadAndCASHammering() {\n        let allDeallocations = NIOAtomic<Int>.makeAtomic(value: 0)\n        let iterations = 1_000\n\n        @inline(never)\n        func doIt() {\n            let box = AtomicBox(value: IntHolderWithDeallocationTracking(0, allDeallocations: allDeallocations))\n\n            spawnAndJoinRacingThreads(count: 6) { i in\n                switch i {\n                case 0:  // writer\n                    for i in 1...iterations {\n                        let old = box.load()\n                        XCTAssertEqual(i - 1, old.value)\n                        if !box.compareAndExchange(\n                            expected: old,\n                            desired: .init(i, allDeallocations: allDeallocations)\n                        ) {\n                            XCTFail(\"compare and exchange didn't work but it should have\")\n                        }\n                    }\n                default:  // readers\n                    while true {\n                        if box.load().value < 0 || box.load().value > iterations {\n                            XCTFail(\"loaded wrong value\")\n                        }\n                        if box.load().value == iterations {\n                            break\n                        }\n                    }\n                }\n            }\n        }\n\n        doIt()\n        assert(allDeallocations.load() == iterations + 1, within: .seconds(1))\n    }\n\n    @available(*, deprecated, message: \"AtomicBox is deprecated, this is a test for the deprecated functionality\")\n    func testMultipleLoadsRacingWhilstStoresAreGoingOn() {\n        // regression test for https://github.com/apple/swift-nio/pull/1287#discussion_r353932225\n        let allDeallocations = NIOAtomic<Int>.makeAtomic(value: 0)\n        let iterations = 10_000\n\n        @inline(never)\n        func doIt() {\n            let box = AtomicBox(value: IntHolderWithDeallocationTracking(0, allDeallocations: allDeallocations))\n            spawnAndJoinRacingThreads(count: 3) { i in\n                switch i {\n                case 0:\n                    var last = Int.min\n                    while last < iterations {\n                        let loaded = box.load()\n                        XCTAssertGreaterThanOrEqual(loaded.value, last)\n                        last = loaded.value\n                    }\n                case 1:\n                    for n in 1...iterations {\n                        box.store(.init(n, allDeallocations: allDeallocations))\n                    }\n                case 2:\n                    var last = Int.min\n                    while last < iterations {\n                        let loaded = box.load()\n                        XCTAssertGreaterThanOrEqual(loaded.value, last)\n                        last = loaded.value\n                    }\n                default:\n                    preconditionFailure(\"thread \\(i)?!\")\n                }\n            }\n        }\n\n        doIt()\n        XCTAssertEqual(iterations + 1, allDeallocations.load())\n    }\n\n    func testNIOLockedValueBox() {\n        struct State {\n            var count: Int = 0\n        }\n\n        let lv = NIOLockedValueBox<State>(State())\n        spawnAndJoinRacingThreads(count: 50) { _ in\n            for _ in 0..<1000 {\n                lv.withLockedValue { state in\n                    state.count += 1\n                }\n            }\n        }\n\n        XCTAssertEqual(50_000, lv.withLockedValue { $0.count })\n    }\n\n    func testNIOLockedValueBoxHandlesThingsWithTransitiveClassesProperly() {\n        struct State {\n            var counts: [Int] = []\n        }\n\n        let lv = NIOLockedValueBox<State>(State())\n        spawnAndJoinRacingThreads(count: 50) { _ in\n            for i in 0..<1000 {\n                lv.withLockedValue { state in\n                    state.counts.append(i)\n                }\n            }\n        }\n\n        XCTAssertEqual(50_000, lv.withLockedValue { $0.counts.count })\n    }\n}\n\nfunc spawnAndJoinRacingThreads(count: Int, _ body: @Sendable @escaping (Int) -> Void) {\n    let go = DispatchSemaphore(value: 0)  // will be incremented when the threads are supposed to run (and race).\n    let arrived = Array(repeating: DispatchSemaphore(value: 0), count: count)  // waiting for all threads to arrive\n\n    let group = DispatchGroup()\n    for i in 0..<count {\n        DispatchQueue(label: \"\\(#file):\\(#line):\\(i)\").async(group: group) {\n            arrived[i].signal()\n            go.wait()\n            body(i)\n        }\n    }\n\n    for sem in arrived {\n        sem.wait()\n    }\n    // all the threads are ready to go\n    for _ in 0..<count {\n        go.signal()\n    }\n\n    group.wait()\n}\n\nfunc assert(\n    _ condition: @autoclosure () -> Bool,\n    within time: TimeAmount,\n    testInterval: TimeAmount? = nil,\n    _ message: String = \"condition not satisfied in time\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let testInterval = testInterval ?? TimeAmount.nanoseconds(time.nanoseconds / 5)\n    let endTime = NIODeadline.now() + time\n\n    repeat {\n        if condition() { return }\n        usleep(UInt32(testInterval.nanoseconds / 1000))\n    } while NIODeadline.now() < endTime\n\n    if !condition() {\n        XCTFail(message, file: (file), line: line)\n    }\n}\n\n@available(*, deprecated, message: \"deprecated because it is used to test deprecated functionality\")\nprivate final class IntHolderWithDeallocationTracking: Sendable {\n    let value: Int\n    let allDeallocations: NIOAtomic<Int>\n\n    init(_ x: Int, allDeallocations: NIOAtomic<Int>) {\n        self.value = x\n        self.allDeallocations = allDeallocations\n    }\n\n    deinit {\n        self.allDeallocations.add(1)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AddressedEnvelopeTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport XCTest\n\nfinal class AddressedEnvelopeTests: XCTestCase {\n    func testHashable_whenEqual() throws {\n        let address = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let envelope1 = AddressedEnvelope(remoteAddress: address, data: \"foo\")\n        let envelope2 = AddressedEnvelope(remoteAddress: address, data: \"foo\")\n\n        XCTAssertEqual(envelope1, envelope2)\n        XCTAssertEqual(envelope1.hashValue, envelope2.hashValue)\n    }\n\n    func testHashable_whenDifferentData() throws {\n        let address = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let envelope1 = AddressedEnvelope(remoteAddress: address, data: \"foo\")\n        let envelope2 = AddressedEnvelope(remoteAddress: address, data: \"bar\")\n\n        XCTAssertNotEqual(envelope1, envelope2)\n    }\n\n    func testHashable_whenDifferentAddress() throws {\n        let address1 = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let address2 = try SocketAddress(ipAddress: \"127.0.0.0\", port: 444)\n        let envelope1 = AddressedEnvelope(remoteAddress: address1, data: \"foo\")\n        let envelope2 = AddressedEnvelope(remoteAddress: address2, data: \"foo\")\n\n        XCTAssertNotEqual(envelope1, envelope2)\n    }\n\n    func testHashable_whenDifferentMetadata() throws {\n        let address = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let envelope1 = AddressedEnvelope(\n            remoteAddress: address,\n            data: \"foo\",\n            metadata: .init(ecnState: .congestionExperienced)\n        )\n        let envelope2 = AddressedEnvelope(\n            remoteAddress: address,\n            data: \"foo\",\n            metadata: .init(ecnState: .transportCapableFlag0)\n        )\n\n        XCTAssertNotEqual(envelope1, envelope2)\n    }\n\n    func testHashable_whenDifferentData_andDifferentAddress() throws {\n        let address1 = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let address2 = try SocketAddress(ipAddress: \"127.0.0.0\", port: 444)\n        let envelope1 = AddressedEnvelope(remoteAddress: address1, data: \"foo\")\n        let envelope2 = AddressedEnvelope(remoteAddress: address2, data: \"bar\")\n\n        XCTAssertNotEqual(envelope1, envelope2)\n    }\n\n    func testHashable_whenDifferentData_andDifferentMetadata() throws {\n        let address = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let envelope1 = AddressedEnvelope(\n            remoteAddress: address,\n            data: \"foo\",\n            metadata: .init(ecnState: .congestionExperienced)\n        )\n        let envelope2 = AddressedEnvelope(\n            remoteAddress: address,\n            data: \"bar\",\n            metadata: .init(ecnState: .transportCapableFlag0)\n        )\n\n        XCTAssertNotEqual(envelope1, envelope2)\n    }\n\n    func testHashable_whenDifferentAddress_andDifferentMetadata() throws {\n        let address1 = try SocketAddress(ipAddress: \"127.0.0.0\", port: 443)\n        let address2 = try SocketAddress(ipAddress: \"127.0.0.0\", port: 444)\n        let envelope1 = AddressedEnvelope(\n            remoteAddress: address1,\n            data: \"foo\",\n            metadata: .init(ecnState: .congestionExperienced)\n        )\n        let envelope2 = AddressedEnvelope(\n            remoteAddress: address2,\n            data: \"bar\",\n            metadata: .init(ecnState: .transportCapableFlag0)\n        )\n\n        XCTAssertNotEqual(envelope1, envelope2)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncChannel/AsyncChannelInboundStreamTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class AsyncChannelInboundStreamTests: XCTestCase {\n    func testTestingStream() async throws {\n        let (stream, source) = NIOAsyncChannelInboundStream<Int>.makeTestingStream()\n\n        try await withThrowingTaskGroup(of: [Int].self) { group in\n            group.addTask {\n                var elements = [Int]()\n                for try await element in stream {\n                    elements.append(element)\n                }\n                return elements\n            }\n\n            for element in 0...10 {\n                source.yield(element)\n            }\n            source.finish()\n\n            let result = try await group.next()\n            XCTAssertEqual(result, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        }\n    }\n\n    func testTestingStream_whenThrowing() async throws {\n        let (stream, source) = NIOAsyncChannelInboundStream<Int>.makeTestingStream()\n\n        await withThrowingTaskGroup(of: [Int].self) { group in\n            group.addTask {\n                var elements = [Int]()\n                for try await element in stream {\n                    elements.append(element)\n                }\n                return elements\n            }\n            source.finish(throwing: ChannelError.alreadyClosed)\n\n            do {\n                _ = try await group.next()\n                XCTFail(\"Expected an error to be thrown\")\n            } catch {\n                XCTAssertEqual(error as? ChannelError, .alreadyClosed)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncChannel/AsyncChannelOutboundWriterTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class AsyncChannelOutboundWriterTests: XCTestCase {\n    func testTestingWriter() async throws {\n        let (writer, sink) = NIOAsyncChannelOutboundWriter<Int>.makeTestingWriter()\n\n        try await withThrowingTaskGroup(of: [Int].self) { group in\n            group.addTask {\n                var elements = [Int]()\n                for try await element in sink {\n                    elements.append(element)\n                }\n                return elements\n            }\n\n            for element in 0...10 {\n                try await writer.write(element)\n            }\n            writer.finish()\n\n            let result = try await group.next()\n            XCTAssertEqual(result, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncChannel/AsyncChannelTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class AsyncChannelTests: XCTestCase {\n    func testAsyncChannelCloseOnWrite() async throws {\n        final class CloseOnWriteHandler: ChannelOutboundHandler {\n            typealias OutboundIn = String\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                context.close(promise: promise)\n            }\n        }\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try channel.pipeline.syncOperations.addHandler(CloseOnWriteHandler())\n            return try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n        }\n\n        try await wrapped.executeThenClose { _, outbound in\n            try await outbound.write(\"Test\")\n        }\n    }\n\n    func testAsyncChannelBasicFunctionality() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<String, Never>(wrappingChannelSynchronously: channel)\n        }\n\n        try await wrapped.executeThenClose { inbound, _ in\n            var iterator = inbound.makeAsyncIterator()\n            try await channel.writeInbound(\"hello\")\n            let firstRead = try await iterator.next()\n            XCTAssertEqual(firstRead, \"hello\")\n\n            try await channel.writeInbound(\"world\")\n            let secondRead = try await iterator.next()\n            XCTAssertEqual(secondRead, \"world\")\n\n            try await channel.testingEventLoop.executeInContext {\n                channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n            }\n\n            let thirdRead = try await iterator.next()\n            XCTAssertNil(thirdRead)\n        }\n    }\n\n    func testAsyncChannelBasicWrites() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<Never, String>(wrappingChannelSynchronously: channel)\n        }\n\n        try await wrapped.executeThenClose { _, outbound in\n            try await outbound.write(\"hello\")\n            try await outbound.write(\"world\")\n\n            let firstRead = try await channel.waitForOutboundWrite(as: String.self)\n            let secondRead = try await channel.waitForOutboundWrite(as: String.self)\n\n            XCTAssertEqual(firstRead, \"hello\")\n            XCTAssertEqual(secondRead, \"world\")\n        }\n    }\n\n    func testAsyncChannelThrowsWhenChannelClosed() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n        }\n\n        try await channel.close(mode: .all)\n\n        do {\n            try await wrapped.executeThenClose { _, outbound in\n                try await outbound.write(\"Test\")\n            }\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertEqual(error as? ChannelError, ChannelError.ioOnClosedChannel)\n        }\n    }\n\n    func testFinishingTheWriterClosesTheWriteSideOfTheChannel() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let closeRecorder = CloseRecorder()\n        try await channel.pipeline.addHandler(closeRecorder)\n\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel(\n                wrappingChannelSynchronously: channel,\n                configuration: .init(\n                    isOutboundHalfClosureEnabled: true,\n                    inboundType: Never.self,\n                    outboundType: Never.self\n                )\n            )\n        }\n\n        try await wrapped.executeThenClose { inbound, outbound in\n            outbound.finish()\n\n            await channel.testingEventLoop.run()\n\n            try await channel.testingEventLoop.executeInContext {\n                XCTAssertEqual(1, closeRecorder.outboundCloses)\n            }\n\n            // Just use this to keep the inbound reader alive.\n            withExtendedLifetime(inbound) {}\n\n        }\n    }\n\n    func testDroppingEverythingDoesntCloseTheChannel() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let closeRecorder = CloseRecorder()\n        try await channel.pipeline.addHandler(CloseSuppressor())\n        try await channel.pipeline.addHandler(closeRecorder)\n\n        do {\n            _ = try await channel.testingEventLoop.executeInContext {\n                try NIOAsyncChannel(\n                    wrappingChannelSynchronously: channel,\n                    configuration: .init(\n                        isOutboundHalfClosureEnabled: false,\n                        inboundType: Never.self,\n                        outboundType: Never.self\n                    )\n                )\n            }\n\n            try await channel.testingEventLoop.executeInContext {\n                XCTAssertEqual(0, closeRecorder.allCloses)\n            }\n        }\n\n        // Now that everything is dead, we see full closure.\n        try await channel.testingEventLoop.executeInContext {\n            XCTAssertEqual(0, closeRecorder.allCloses)\n        }\n\n        try await channel.closeIgnoringSuppression()\n    }\n\n    func testReadsArePropagated() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<String, Never>(wrappingChannelSynchronously: channel)\n        }\n\n        try await channel.writeInbound(\"hello\")\n        let propagated = try await channel.readInbound(as: String.self)\n        XCTAssertEqual(propagated, \"hello\")\n\n        try await channel.close().get()\n\n        try await wrapped.executeThenClose { inbound, _ in\n            let reads = try await Array(inbound)\n            XCTAssertEqual(reads, [\"hello\"])\n        }\n    }\n\n    func testErrorsArePropagatedButAfterReads() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<String, Never>(wrappingChannelSynchronously: channel)\n        }\n\n        try await channel.writeInbound(\"hello\")\n        try await channel.testingEventLoop.executeInContext {\n            channel.pipeline.fireErrorCaught(TestError.bang)\n        }\n\n        try await wrapped.executeThenClose { inbound, _ in\n            var iterator = inbound.makeAsyncIterator()\n            let first = try await iterator.next()\n            XCTAssertEqual(first, \"hello\")\n\n            try await XCTAssertThrowsError(await iterator.next()) { error in\n                XCTAssertEqual(error as? TestError, .bang)\n            }\n        }\n    }\n\n    func testChannelBecomingNonWritableDelaysWriters() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<Never, String>(wrappingChannelSynchronously: channel)\n        }\n\n        try await channel.testingEventLoop.executeInContext {\n            channel.isWritable = false\n            channel.pipeline.fireChannelWritabilityChanged()\n        }\n\n        let lock = NIOLockedValueBox(false)\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                try await wrapped.executeThenClose { _, outbound in\n                    try await outbound.write(\"hello\")\n                    lock.withLockedValue {\n                        XCTAssertTrue($0)\n                    }\n                }\n            }\n\n            group.addTask {\n                // 10ms sleep before we wake the thing up\n                try await Task.sleep(nanoseconds: 10_000_000)\n\n                try await channel.testingEventLoop.executeInContext {\n                    channel.isWritable = true\n                    lock.withLockedValue { $0 = true }\n                    channel.pipeline.fireChannelWritabilityChanged()\n                }\n            }\n        }\n    }\n\n    func testBufferDropsReadsIfTheReaderIsGone() async throws {\n        let channel = NIOAsyncTestingChannel()\n        try await channel.pipeline.addHandler(CloseSuppressor()).get()\n        do {\n            // Create the NIOAsyncChannel, then drop it. The handler will still be in the pipeline.\n            _ = try await channel.testingEventLoop.executeInContext {\n                _ = try NIOAsyncChannel<Sentinel, Never>(wrappingChannelSynchronously: channel)\n            }\n        }\n\n        weak var sentinel: Sentinel?\n        do {\n            let strongSentinel: Sentinel? = Sentinel()\n            sentinel = strongSentinel!\n            try await XCTAsyncAssertNotNil(\n                await channel.pipeline.handler(type: NIOAsyncChannelHandler<Sentinel, Sentinel, Never>.self).map {\n                    _ -> Bool in\n                    true\n                }.get()\n            )\n            try await channel.writeInbound(strongSentinel!)\n            _ = try await channel.readInbound(as: Sentinel.self)\n        }\n\n        XCTAssertNil(sentinel)\n\n        try await channel.closeIgnoringSuppression()\n    }\n\n    func testManagingBackPressure() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let readCounter = ReadCounter()\n        try await channel.pipeline.addHandler(readCounter)\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel(\n                wrappingChannelSynchronously: channel,\n                configuration: .init(\n                    backPressureStrategy: .init(lowWatermark: 2, highWatermark: 4),\n                    inboundType: Void.self,\n                    outboundType: Never.self\n                )\n            )\n        }\n\n        // Attempt to read. This should succeed an arbitrary number of times.\n        XCTAssertEqual(readCounter.readCount, 0)\n        try await channel.testingEventLoop.executeInContext {\n            channel.pipeline.read()\n            channel.pipeline.read()\n            channel.pipeline.read()\n        }\n        XCTAssertEqual(readCounter.readCount, 3)\n\n        // Push 3 elements into the buffer. Reads continue to work.\n        try await channel.testingEventLoop.executeInContext {\n            channel.pipeline.fireChannelRead(())\n            channel.pipeline.fireChannelRead(())\n            channel.pipeline.fireChannelRead(())\n            channel.pipeline.fireChannelReadComplete()\n\n            channel.pipeline.read()\n            channel.pipeline.read()\n            channel.pipeline.read()\n        }\n        XCTAssertEqual(readCounter.readCount, 6)\n\n        // Add one more element into the buffer. This should flip our backpressure mode, and the reads should now be delayed.\n        try await channel.testingEventLoop.executeInContext {\n            channel.pipeline.fireChannelRead(())\n            channel.pipeline.fireChannelReadComplete()\n\n            channel.pipeline.read()\n            channel.pipeline.read()\n            channel.pipeline.read()\n        }\n        XCTAssertEqual(readCounter.readCount, 6)\n\n        // More elements don't help.\n        try await channel.testingEventLoop.executeInContext {\n            channel.pipeline.fireChannelRead(())\n            channel.pipeline.fireChannelReadComplete()\n\n            channel.pipeline.read()\n            channel.pipeline.read()\n            channel.pipeline.read()\n        }\n        XCTAssertEqual(readCounter.readCount, 6)\n\n        try await wrapped.executeThenClose { inbound, outbound in\n            // Now consume three elements from the pipeline. This should not unbuffer the read, as 3 elements remain.\n            var reader = inbound.makeAsyncIterator()\n            for _ in 0..<3 {\n                try await XCTAsyncAssertNotNil(await reader.next())\n            }\n            await channel.testingEventLoop.run()\n            XCTAssertEqual(readCounter.readCount, 6)\n\n            // Removing the next element should trigger an automatic read.\n            try await XCTAsyncAssertNotNil(await reader.next())\n            await channel.testingEventLoop.run()\n            XCTAssertEqual(readCounter.readCount, 7)\n\n            // Reads now work again, even if more data arrives.\n            try await channel.testingEventLoop.executeInContext {\n                channel.pipeline.read()\n                channel.pipeline.read()\n                channel.pipeline.read()\n\n                channel.pipeline.fireChannelRead(())\n                channel.pipeline.fireChannelReadComplete()\n\n                channel.pipeline.read()\n                channel.pipeline.read()\n                channel.pipeline.read()\n            }\n            XCTAssertEqual(readCounter.readCount, 13)\n\n            // The next reads arriving pushes us past the limit again.\n            // This time we won't read.\n            try await channel.testingEventLoop.executeInContext {\n                channel.pipeline.fireChannelRead(())\n                channel.pipeline.fireChannelRead(())\n                channel.pipeline.fireChannelReadComplete()\n            }\n            XCTAssertEqual(readCounter.readCount, 13)\n\n            // This time we'll consume 4 more elements, and we won't find a read at all.\n            for _ in 0..<4 {\n                try await XCTAsyncAssertNotNil(await reader.next())\n            }\n            await channel.testingEventLoop.run()\n            XCTAssertEqual(readCounter.readCount, 13)\n\n            // But the next reads work fine.\n            try await channel.testingEventLoop.executeInContext {\n                channel.pipeline.read()\n                channel.pipeline.read()\n                channel.pipeline.read()\n            }\n            XCTAssertEqual(readCounter.readCount, 16)\n        }\n    }\n\n    func testCanWrapAChannelSynchronously() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let wrapped = try await channel.testingEventLoop.executeInContext {\n            try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n        }\n\n        try await wrapped.executeThenClose { inbound, outbound in\n            var iterator = inbound.makeAsyncIterator()\n            try await channel.writeInbound(\"hello\")\n            let firstRead = try await iterator.next()\n            XCTAssertEqual(firstRead, \"hello\")\n\n            try await outbound.write(\"world\")\n            let write = try await channel.waitForOutboundWrite(as: String.self)\n            XCTAssertEqual(write, \"world\")\n\n            try await channel.testingEventLoop.executeInContext {\n                channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n            }\n\n            let secondRead = try await iterator.next()\n            XCTAssertNil(secondRead)\n        }\n    }\n\n    func testExecuteThenCloseFromActor() async throws {\n        final actor TestActor {\n            func test() async throws {\n                let channel = NIOAsyncTestingChannel()\n                let wrapped = try await channel.testingEventLoop.executeInContext {\n                    try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n                }\n\n                try await wrapped.executeThenClose { inbound, outbound in\n                    var iterator = inbound.makeAsyncIterator()\n                    try await channel.writeInbound(\"hello\")\n                    let firstRead = try await iterator.next()\n                    XCTAssertEqual(firstRead, \"hello\")\n\n                    try await outbound.write(\"world\")\n                    let write = try await channel.waitForOutboundWrite(as: String.self)\n                    XCTAssertEqual(write, \"world\")\n\n                    try await channel.testingEventLoop.executeInContext {\n                        channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n                    }\n\n                    let secondRead = try await iterator.next()\n                    XCTAssertNil(secondRead)\n                }\n            }\n        }\n\n        let actor = TestActor()\n        try await actor.test()\n    }\n\n    func testExecuteThenCloseFromActorReferencingSelf() async throws {\n        final actor TestActor {\n            let hello = \"hello\"\n            let world = \"world\"\n\n            func test() async throws {\n                let channel = NIOAsyncTestingChannel()\n                let wrapped = try await channel.testingEventLoop.executeInContext {\n                    try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n                }\n\n                try await wrapped.executeThenClose { inbound, outbound in\n                    var iterator = inbound.makeAsyncIterator()\n                    try await channel.writeInbound(self.hello)\n                    let firstRead = try await iterator.next()\n                    XCTAssertEqual(firstRead, \"hello\")\n\n                    try await outbound.write(self.world)\n                    let write = try await channel.waitForOutboundWrite(as: String.self)\n                    XCTAssertEqual(write, \"world\")\n\n                    try await channel.testingEventLoop.executeInContext {\n                        channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n                    }\n\n                    let secondRead = try await iterator.next()\n                    XCTAssertNil(secondRead)\n                }\n            }\n        }\n\n        let actor = TestActor()\n        try await actor.test()\n    }\n\n    func testExecuteThenCloseInboundChannelFromActor() async throws {\n        final actor TestActor {\n            func test() async throws {\n                let channel = NIOAsyncTestingChannel()\n                let wrapped = try await channel.testingEventLoop.executeInContext {\n                    try NIOAsyncChannel<String, Never>(wrappingChannelSynchronously: channel)\n                }\n\n                try await wrapped.executeThenClose { inbound in\n                    var iterator = inbound.makeAsyncIterator()\n                    try await channel.writeInbound(\"hello\")\n                    let firstRead = try await iterator.next()\n                    XCTAssertEqual(firstRead, \"hello\")\n\n                    try await channel.testingEventLoop.executeInContext {\n                        channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n                    }\n\n                    let secondRead = try await iterator.next()\n                    XCTAssertNil(secondRead)\n                }\n            }\n        }\n\n        let actor = TestActor()\n        try await actor.test()\n    }\n\n    func testExecuteThenCloseNonSendableResultCross() async throws {\n        final class NonSendable {\n            var someMutableState: Int = 5\n        }\n\n        final actor TestActor {\n            func test() async throws -> sending NonSendable {\n                let channel = NIOAsyncTestingChannel()\n                let wrapped = try await channel.testingEventLoop.executeInContext {\n                    try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n                }\n\n                return try await wrapped.executeThenClose { _, _ in\n                    NonSendable()\n                }\n            }\n        }\n\n        let actor = TestActor()\n        let r = try await actor.test()\n        XCTAssertEqual(r.someMutableState, 5)\n    }\n\n    func testExecuteThenCloseInboundNonSendableResultCross() async throws {\n        final class NonSendable {\n            var someMutableState: Int = 5\n        }\n\n        final actor TestActor {\n            func test() async throws -> sending NonSendable {\n                let channel = NIOAsyncTestingChannel()\n                let wrapped = try await channel.testingEventLoop.executeInContext {\n                    try NIOAsyncChannel<String, Never>(wrappingChannelSynchronously: channel)\n                }\n\n                return try await wrapped.executeThenClose { _ in\n                    NonSendable()\n                }\n            }\n        }\n\n        let actor = TestActor()\n        let r = try await actor.test()\n        XCTAssertEqual(r.someMutableState, 5)\n    }\n}\n\n// This is unchecked Sendable since we only call this in the testing eventloop\nprivate final class CloseRecorder: ChannelOutboundHandler, @unchecked Sendable {\n    typealias OutboundIn = Any\n    typealias outbound = Any\n\n    var outboundCloses = 0\n\n    var allCloses = 0\n\n    init() {}\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.allCloses += 1\n\n        if case .output = mode {\n            self.outboundCloses += 1\n        }\n\n        context.close(mode: mode, promise: promise)\n    }\n}\n\nprivate final class CloseSuppressor: ChannelOutboundHandler, RemovableChannelHandler, Sendable {\n    typealias OutboundIn = Any\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        // We drop the close here.\n        promise?.fail(TestError.bang)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncTestingChannel {\n    fileprivate func closeIgnoringSuppression() async throws {\n        try await self.pipeline.context(handlerType: CloseSuppressor.self).flatMap {\n            self.pipeline.syncOperations.removeHandler(context: $0)\n        }.flatMap {\n            self.close()\n        }.get()\n    }\n}\n\nprivate final class ReadCounter: ChannelOutboundHandler, @unchecked Sendable {\n    typealias OutboundIn = Any\n    typealias outbound = Any\n\n    private let _readCount = ManagedAtomic(0)\n\n    var readCount: Int {\n        self._readCount.load(ordering: .acquiring)\n    }\n\n    func read(context: ChannelHandlerContext) {\n        self._readCount.wrappingIncrement(ordering: .releasing)\n        context.read()\n    }\n}\n\nprivate enum TestError: Error {\n    case bang\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension Array {\n    fileprivate init<AS: AsyncSequence>(_ sequence: AS) async throws where AS.Element == Self.Element {\n        self = []\n\n        for try await nextElement in sequence {\n            self.append(nextElement)\n        }\n    }\n}\n\nprivate final class Sentinel: Sendable {}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncSequenceTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport XCTest\n\nprivate struct TestCase {\n    var buffers: [[UInt8]]\n    var file: StaticString\n    var line: UInt\n    init(_ buffers: [[UInt8]], file: StaticString = #filePath, line: UInt = #line) {\n        self.buffers = buffers\n        self.file = file\n        self.line = line\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class AsyncSequenceCollectTests: XCTestCase {\n    func testAsyncSequenceCollect() async throws {\n        let testCases = [\n            TestCase([\n                []\n            ]),\n            TestCase([\n                [],\n                [],\n            ]),\n            TestCase([\n                [0],\n                [],\n            ]),\n            TestCase([\n                [],\n                [0],\n            ]),\n            TestCase([\n                [0],\n                [1],\n            ]),\n            TestCase([\n                [0],\n                [1],\n            ]),\n            TestCase([\n                [0],\n                [1],\n                [2],\n            ]),\n            TestCase([\n                [],\n                [0],\n                [],\n                [1],\n                [],\n                [2],\n                [],\n            ]),\n            TestCase([\n                [0],\n                [1],\n                [2],\n                [],\n                [],\n            ]),\n            TestCase([\n                Array(0..<10)\n            ]),\n            TestCase([\n                Array(0..<10),\n                Array(10..<20),\n            ]),\n            TestCase([\n                Array(0..<10),\n                Array(10..<20),\n                Array(20..<30),\n            ]),\n            TestCase([\n                Array(0..<10),\n                Array(10..<20),\n                Array(20..<30),\n                Array(repeating: 99, count: 1000),\n            ]),\n        ]\n        for testCase in testCases {\n            let expectedBytes = testCase.buffers.flatMap({ $0 })\n\n            // happy case where maxBytes is exactly the same as number of buffers received\n\n            // test for the generic version\n            let accumulatedBytes1 = try await testCase.buffers\n                .asAsyncSequence()\n                .collect(upTo: expectedBytes.count, using: .init())\n            XCTAssertEqual(\n                accumulatedBytes1,\n                ByteBuffer(bytes: expectedBytes),\n                file: testCase.file,\n                line: testCase.line\n            )\n\n            // test for the `ByteBuffer` optimised version\n            let accumulatedBytes2 = try await testCase.buffers\n                .map(ByteBuffer.init(bytes:))\n                .asAsyncSequence()\n                .collect(upTo: expectedBytes.count)\n            XCTAssertEqual(\n                accumulatedBytes2,\n                ByteBuffer(bytes: expectedBytes),\n                file: testCase.file,\n                line: testCase.line\n            )\n\n            // unhappy case where maxBytes is one byte less than actually received\n            guard expectedBytes.count >= 1 else {\n                continue\n            }\n\n            // test for the generic version\n            let maxBytes = max(expectedBytes.count - 1, 0)\n            await XCTAssertThrowsError(\n                try await testCase.buffers\n                    .asAsyncSequence()\n                    .collect(upTo: maxBytes, using: .init()),\n                file: testCase.file,\n                line: testCase.line\n            ) { error in\n                XCTAssertTrue(\n                    error is NIOTooManyBytesError,\n                    file: testCase.file,\n                    line: testCase.line\n                )\n                guard let tooManyBytesErr = error as? NIOTooManyBytesError else {\n                    XCTFail(\n                        \"Error was not an NIOTooManyBytesError\",\n                        file: testCase.file,\n                        line: testCase.line\n                    )\n                    return\n                }\n\n                XCTAssertEqual(\n                    maxBytes,\n                    tooManyBytesErr.maxBytes,\n                    file: testCase.file,\n                    line: testCase.line\n                )\n            }\n\n            // test for the `ByteBuffer` optimised version\n            await XCTAssertThrowsError(\n                try await testCase.buffers\n                    .map(ByteBuffer.init(bytes:))\n                    .asAsyncSequence()\n                    .collect(upTo: maxBytes),\n                file: testCase.file,\n                line: testCase.line\n            ) { error in\n                XCTAssertTrue(\n                    error is NIOTooManyBytesError,\n                    file: testCase.file,\n                    line: testCase.line\n                )\n                guard let tooManyBytesErr = error as? NIOTooManyBytesError else {\n                    XCTFail(\n                        \"Error was not an NIOTooManyBytesError\",\n                        file: testCase.file,\n                        line: testCase.line\n                    )\n                    return\n                }\n\n                // Sometimes the max bytes is subtracted from the header size\n                XCTAssertTrue(\n                    tooManyBytesErr.maxBytes != nil && tooManyBytesErr.maxBytes! <= maxBytes,\n                    file: testCase.file,\n                    line: testCase.line\n                )\n            }\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nstruct AsyncSequenceFromSyncSequence<Wrapped: Sequence>: AsyncSequence {\n    typealias Element = Wrapped.Element\n    struct AsyncIterator: AsyncIteratorProtocol {\n        fileprivate var iterator: Wrapped.Iterator\n        mutating func next() async throws -> Wrapped.Element? {\n            self.iterator.next()\n        }\n    }\n\n    fileprivate let wrapped: Wrapped\n\n    func makeAsyncIterator() -> AsyncIterator {\n        .init(iterator: self.wrapped.makeIterator())\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension Sequence {\n    /// Turns `self` into an `AsyncSequence` by wending each element of `self` asynchronously.\n    func asAsyncSequence() -> AsyncSequenceFromSyncSequence<Self> {\n        .init(wrapped: self)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncSequences/NIOAsyncSequenceProducer+HighLowWatermarkBackPressureStrategyTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class NIOAsyncSequenceProducerBackPressureStrategiesHighLowWatermarkTests: XCTestCase {\n    private var strategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark!\n\n    override func setUp() {\n        super.setUp()\n\n        self.strategy = .init(\n            lowWatermark: 5,\n            highWatermark: 10\n        )\n    }\n\n    override func tearDown() {\n        self.strategy = nil\n\n        super.tearDown()\n    }\n\n    func testDidYield_whenBelowHighWatermark() {\n        XCTAssertTrue(self.strategy.didYield(bufferDepth: 5))\n    }\n\n    func testDidYield_whenAboveHighWatermark() {\n        XCTAssertFalse(self.strategy.didYield(bufferDepth: 15))\n    }\n\n    func testDidYield_whenAtHighWatermark() {\n        XCTAssertFalse(self.strategy.didYield(bufferDepth: 10))\n    }\n\n    func testDidConsume_whenBelowLowWatermark() {\n        XCTAssertTrue(self.strategy.didConsume(bufferDepth: 4))\n    }\n\n    func testDidConsume_whenAboveLowWatermark() {\n        XCTAssertTrue(self.strategy.didConsume(bufferDepth: 6))\n    }\n\n    func testDidConsume_whenAtLowWatermark() {\n        XCTAssertTrue(self.strategy.didConsume(bufferDepth: 5))\n    }\n\n    func testDidYieldWhenNoOutstandingDemand() {\n        // Hit the high watermark\n        XCTAssertFalse(self.strategy.didYield(bufferDepth: 10))\n        // Drop below it, don't read.\n        XCTAssertFalse(self.strategy.didConsume(bufferDepth: 7))\n        // Yield more, still above the low watermark, so don't produce more.\n        XCTAssertFalse(self.strategy.didYield(bufferDepth: 8))\n        // Drop below low watermark to start producing again.\n        XCTAssertTrue(self.strategy.didConsume(bufferDepth: 4))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncSequences/NIOAsyncSequenceTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class MockNIOElementStreamBackPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategy, @unchecked Sendable\n{\n    enum Event {\n        case didYield\n        case didNext\n    }\n    let events: AsyncStream<Event>\n    private let eventsContinuation: AsyncStream<Event>.Continuation\n\n    init() {\n        var eventsContinuation: AsyncStream<Event>.Continuation!\n        self.events = .init { eventsContinuation = $0 }\n        self.eventsContinuation = eventsContinuation!\n    }\n\n    var didYieldHandler: ((Int) -> Bool)?\n    func didYield(bufferDepth: Int) -> Bool {\n        self.eventsContinuation.yield(.didYield)\n        if let didYieldHandler = self.didYieldHandler {\n            return didYieldHandler(bufferDepth)\n        }\n        return false\n    }\n\n    var didNextHandler: ((Int) -> Bool)?\n    func didConsume(bufferDepth: Int) -> Bool {\n        self.eventsContinuation.yield(.didNext)\n        if let didNextHandler = self.didNextHandler {\n            return didNextHandler(bufferDepth)\n        }\n        return false\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class MockNIOBackPressuredStreamSourceDelegate: NIOAsyncSequenceProducerDelegate, @unchecked Sendable {\n    enum Event {\n        case produceMore\n        case didTerminate\n    }\n    let events: AsyncStream<Event>\n    private let eventsContinuation: AsyncStream<Event>.Continuation\n\n    init() {\n        var eventsContinuation: AsyncStream<Event>.Continuation!\n        self.events = .init { eventsContinuation = $0 }\n        self.eventsContinuation = eventsContinuation!\n    }\n\n    var produceMoreHandler: (() -> Void)?\n    func produceMore() {\n        self.eventsContinuation.yield(.produceMore)\n        if let produceMoreHandler = self.produceMoreHandler {\n            return produceMoreHandler()\n        }\n    }\n\n    var didTerminateHandler: (() -> Void)?\n    func didTerminate() {\n        self.eventsContinuation.yield(.didTerminate)\n        if let didTerminateHandler = self.didTerminateHandler {\n            return didTerminateHandler()\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class NIOAsyncSequenceProducerTests: XCTestCase {\n    private var backPressureStrategy: MockNIOElementStreamBackPressureStrategy!\n    private var delegate: MockNIOBackPressuredStreamSourceDelegate!\n    private var sequence:\n        NIOAsyncSequenceProducer<\n            Int,\n            MockNIOElementStreamBackPressureStrategy,\n            MockNIOBackPressuredStreamSourceDelegate\n        >!\n    private var source:\n        NIOAsyncSequenceProducer<\n            Int,\n            MockNIOElementStreamBackPressureStrategy,\n            MockNIOBackPressuredStreamSourceDelegate\n        >.Source!\n\n    override func setUp() {\n        super.setUp()\n\n        self.backPressureStrategy = .init()\n        self.delegate = .init()\n        let result = NIOAsyncSequenceProducer.makeSequence(\n            elementType: Int.self,\n            backPressureStrategy: self.backPressureStrategy,\n            finishOnDeinit: false,\n            delegate: self.delegate\n        )\n        self.source = result.source\n        self.sequence = result.sequence\n    }\n\n    override func tearDown() {\n        self.backPressureStrategy = nil\n        self.delegate = nil\n        self.sequence = nil\n        self.source.finish()\n        self.source = nil\n\n        super.tearDown()\n    }\n\n    // MARK: - End to end tests\n\n    func testBackPressure() async {\n        let lowWatermark = 2\n        let higherWatermark = 5\n        self.backPressureStrategy.didYieldHandler = { bufferDepth in\n            bufferDepth < higherWatermark\n        }\n        self.backPressureStrategy.didNextHandler = { bufferDepth in\n            bufferDepth < lowWatermark\n        }\n        let iterator = self.sequence.makeAsyncIterator()\n\n        XCTAssertEqual(self.source.yield(contentsOf: [1, 2, 3]), .produceMore)\n        XCTAssertEqual(self.source.yield(contentsOf: [4, 5, 6]), .stopProducing)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 1)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 2)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 3)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 4)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 5)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n        XCTAssertEqual(self.source.yield(contentsOf: [7, 8, 9, 10, 11]), .stopProducing)\n    }\n\n    func testWatermarkBackpressure_whenBelowLowwatermark_andOutstandingDemand() async {\n        let newSequence = NIOAsyncSequenceProducer.makeSequence(\n            elementType: Int.self,\n            backPressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark(\n                lowWatermark: 2,\n                highWatermark: 5\n            ),\n            finishOnDeinit: false,\n            delegate: self.delegate\n        )\n        let iterator = newSequence.sequence.makeAsyncIterator()\n        var eventsIterator = self.delegate.events.makeAsyncIterator()\n        let source = newSequence.source\n\n        XCTAssertEqual(source.yield(1), .produceMore)\n        XCTAssertEqual(source.yield(2), .produceMore)\n        XCTAssertEqual(source.yield(3), .produceMore)\n        XCTAssertEqual(source.yield(4), .produceMore)\n        XCTAssertEqual(source.yield(5), .stopProducing)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 1)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 2)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 3)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 4)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 5)\n        XCTAssertEqualWithoutAutoclosure(await eventsIterator.next(), .produceMore)\n        XCTAssertEqual(source.yield(6), .produceMore)\n        XCTAssertEqual(source.yield(7), .produceMore)\n        XCTAssertEqual(source.yield(8), .produceMore)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 6)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 7)\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), 8)\n        source.finish()\n        XCTAssertEqualWithoutAutoclosure(await iterator.next(), nil)\n        XCTAssertEqualWithoutAutoclosure(await eventsIterator.next(), .didTerminate)\n    }\n\n    // MARK: - Yield\n\n    func testYield_whenInitial_andStopDemanding() async {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n        XCTAssertEqual(result, .stopProducing)\n    }\n\n    func testYield_whenInitial_andDemandMore() async {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n        XCTAssertEqual(result, .produceMore)\n    }\n\n    func testYield_whenStreaming_andSuspended_andStopDemanding() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        async let element = sequence.first { _ in true }\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .stopProducing)\n        XCTAssertEqualWithoutAutoclosure(await element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n    }\n\n    func testYield_whenStreaming_andSuspended_andDemandMore() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        async let element = sequence.first { _ in true }\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .produceMore)\n        XCTAssertEqualWithoutAutoclosure(await element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n    }\n\n    func testYieldEmptySequence_whenStreaming_andSuspended_andStopDemanding() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = await sequence.first { _ in true }\n        }\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n        let result = self.source.yield(contentsOf: [])\n\n        XCTAssertEqual(result, .stopProducing)\n    }\n\n    func testYieldEmptySequence_whenStreaming_andSuspended_andDemandMore() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = await sequence.first { _ in true }\n        }\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n        let result = self.source.yield(contentsOf: [])\n\n        XCTAssertEqual(result, .stopProducing)\n    }\n\n    func testYield_whenStreaming_andNotSuspended_andStopDemanding() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n        // This transitions the sequence into streaming\n        _ = self.source.yield(contentsOf: [])\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .stopProducing)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didYield]\n        )\n    }\n\n    func testYield_whenStreaming_andNotSuspended_andDemandMore() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n        // This transitions the sequence into streaming\n        _ = self.source.yield(contentsOf: [])\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .produceMore)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didYield]\n        )\n    }\n\n    func testYield_whenSourceFinished() async throws {\n        self.source.finish()\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .dropped)\n    }\n\n    // MARK: - Finish\n\n    func testFinish_whenInitial() async {\n        self.source.finish()\n    }\n\n    func testFinish_whenStreaming_andSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._throwingSequence._storage._setDidSuspend { suspended.fulfill() }\n\n        async let element = sequence.first { _ in true }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.source.finish()\n\n        XCTAssertEqualWithoutAutoclosure(await element, nil)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinish_whenStreaming_andNotSuspended_andBufferEmpty() async throws {\n        _ = self.source.yield(contentsOf: [])\n\n        self.source.finish()\n\n        let element = await self.sequence.first { _ in true }\n        XCTAssertNil(element)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinish_whenStreaming_andNotSuspended_andBufferNotEmpty() async throws {\n        _ = self.source.yield(contentsOf: [1])\n\n        self.source.finish()\n\n        let element = await self.sequence.first { _ in true }\n        XCTAssertEqual(element, 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinish_whenFinished() async throws {\n        self.source.finish()\n\n        _ = await self.sequence.first { _ in true }\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n\n        self.source.finish()\n    }\n\n    // MARK: - Source Deinited\n\n    func testSourceDeinited_whenInitial() async {\n        var newSequence:\n            NIOAsyncSequenceProducer<\n                Int,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        source = nil\n        XCTAssertNil(source)\n        XCTAssertNotNil(sequence)\n    }\n\n    func testSourceDeinited_whenStreaming_andSuspended() async throws {\n        var newSequence:\n            NIOAsyncSequenceProducer<\n                Int,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            let suspended = expectation(description: \"task suspended\")\n            sequence!._throwingSequence._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                let element = await sequence!.first { _ in true }\n                return element\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            source = nil\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, nil)\n        XCTAssertNil(source)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testSourceDeinited_whenStreaming_andNotSuspended_andBufferEmpty() async throws {\n        var newSequence:\n            NIOAsyncSequenceProducer<\n                Int,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        _ = source!.yield(contentsOf: [])\n\n        source = nil\n\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                await sequence!.first { _ in true }\n            }\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertNil(element)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testSourceDeinited_whenStreaming_andNotSuspended_andBufferNotEmpty() async throws {\n        var newSequence:\n            NIOAsyncSequenceProducer<\n                Int,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        _ = source!.yield(contentsOf: [1])\n\n        source = nil\n\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                await sequence!.first { _ in true }\n            }\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    // MARK: - Task cancel\n\n    func testTaskCancel_whenStreaming_andSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._throwingSequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Never> = Task {\n            let iterator = sequence.makeAsyncIterator()\n            return await iterator.next()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        task.cancel()\n        let value = await task.value\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n        XCTAssertNil(value)\n    }\n\n    func testTaskCancel_whenStreaming_andNotSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        let resumed = expectation(description: \"task resumed\")\n        let cancelled = expectation(description: \"task cancelled\")\n\n        sequence._throwingSequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Never> = Task {\n            let iterator = sequence.makeAsyncIterator()\n\n            let value = await iterator.next()\n            resumed.fulfill()\n\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            return value\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n        _ = self.source.yield(contentsOf: [1])\n\n        await fulfillment(of: [resumed], timeout: 1)\n        task.cancel()\n        cancelled.fulfill()\n\n        let value = await task.value\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n        XCTAssertEqual(value, 1)\n    }\n\n    func testTaskCancel_whenSourceFinished() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._throwingSequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Never> = Task {\n            let iterator = sequence.makeAsyncIterator()\n            return await iterator.next()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.source.finish()\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n        task.cancel()\n        let value = await task.value\n        XCTAssertNil(value)\n    }\n\n    func testTaskCancel_whenStreaming_andTaskIsAlreadyCancelled() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task: Task<Int?, Never> = Task {\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            let iterator = sequence.makeAsyncIterator()\n            return await iterator.next()\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        let value = await task.value\n\n        XCTAssertNil(value)\n    }\n\n    // MARK: - Next\n\n    func testNext_whenInitial_whenDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = await sequence.first { _ in true }\n        }\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n    }\n\n    func testNext_whenInitial_whenNoDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in false }\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = await sequence.first { _ in true }\n        }\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n    }\n\n    func testNext_whenStreaming_whenEmptyBuffer_whenDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        _ = self.source.yield(contentsOf: [])\n\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = await sequence.first { _ in true }\n        }\n\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didNext]\n        )\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n    }\n\n    func testNext_whenStreaming_whenEmptyBuffer_whenNoDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in false }\n        _ = self.source.yield(contentsOf: [])\n\n        // We are registering our demand and sleeping a bit to make\n        // sure the other child task runs when the demand is registered\n        let sequence = try XCTUnwrap(self.sequence)\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = await sequence.first { _ in true }\n        }\n\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didNext]\n        )\n    }\n\n    func testNext_whenStreaming_whenNotEmptyBuffer_whenNoDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in false }\n        _ = self.source.yield(contentsOf: [1])\n\n        let element = await self.sequence.first { _ in true }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didNext]\n        )\n    }\n\n    func testNext_whenStreaming_whenNotEmptyBuffer_whenNewDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        _ = self.source.yield(contentsOf: [1])\n\n        let element = await self.sequence.first { _ in true }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didNext]\n        )\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n    }\n\n    func testNext_whenStreaming_whenNotEmptyBuffer_whenNewAndOutstandingDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n\n        _ = self.source.yield(contentsOf: [1])\n\n        let element = await self.sequence.first { _ in true }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didNext]\n        )\n    }\n\n    func testNext_whenSourceFinished() async throws {\n        _ = self.source.yield(contentsOf: [1, 2])\n        self.source.finish()\n\n        var elements = [Int]()\n\n        for await element in self.sequence {\n            elements.append(element)\n        }\n\n        XCTAssertEqual(elements, [1, 2])\n    }\n\n    // MARK: - SequenceDeinitialized\n\n    func testSequenceDeinitialized() async {\n        self.sequence = nil\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testSequenceDeinitialized_whenIteratorReferenced() async {\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        self.sequence = nil\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    // MARK: - IteratorDeinitialized\n\n    func testIteratorDeinitialized_whenSequenceReferenced() async {\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n\n        self.sequence = nil\n    }\n\n    func testIteratorDeinitialized_whenSequenceFinished() async {\n        self.source.finish()\n\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testIteratorDeinitialized_whenStreaming() async {\n        _ = self.source.yield(contentsOf: [1])\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n}\n\n// This is needed until async let is supported to be used in autoclosures\nprivate func XCTAssertEqualWithoutAutoclosure<T>(\n    _ expression1: T,\n    _ expression2: T,\n    _ message: @autoclosure () -> String = \"\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) where T: Equatable {\n    XCTAssertEqual(expression1, expression2, message(), file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension AsyncSequence {\n    /// Collect all elements in the sequence into an array.\n    fileprivate func collect() async rethrows -> [Element] {\n        try await self.reduce(into: []) { accumulated, next in\n            accumulated.append(next)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncSequences/NIOAsyncWriterTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport DequeModule\nimport NIOConcurrencyHelpers\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOCore\n\nprivate struct SomeError: Error, Hashable {}\n\nprivate final class MockAsyncWriterDelegate: NIOAsyncWriterSinkDelegate, @unchecked Sendable {\n    typealias Element = String\n\n    var _didYieldCallCount = NIOLockedValueBox(0)\n    var didYieldCallCount: Int {\n        self._didYieldCallCount.withLockedValue { $0 }\n    }\n    var didYieldHandler: ((Deque<String>) -> Void)?\n    func didYield(contentsOf sequence: Deque<String>) {\n        self._didYieldCallCount.withLockedValue { $0 += 1 }\n        if let didYieldHandler = self.didYieldHandler {\n            didYieldHandler(sequence)\n        }\n    }\n\n    var _didSuspendCallCount = NIOLockedValueBox(0)\n    var didSuspendCallCount: Int {\n        self._didSuspendCallCount.withLockedValue { $0 }\n    }\n    var didSuspendHandler: (() -> Void)?\n    func didSuspend() {\n        self._didSuspendCallCount.withLockedValue { $0 += 1 }\n        if let didSuspendHandler = self.didSuspendHandler {\n            didSuspendHandler()\n        }\n    }\n\n    var _didTerminateCallCount = NIOLockedValueBox(0)\n    var didTerminateCallCount: Int {\n        self._didTerminateCallCount.withLockedValue { $0 }\n    }\n    var didTerminateHandler: ((Error?) -> Void)?\n    func didTerminate(error: Error?) {\n        self._didTerminateCallCount.withLockedValue { $0 += 1 }\n        if let didTerminateHandler = self.didTerminateHandler {\n            didTerminateHandler(error)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class NIOAsyncWriterTests: XCTestCase {\n    private var writer: NIOAsyncWriter<String, MockAsyncWriterDelegate>!\n    private var sink: NIOAsyncWriter<String, MockAsyncWriterDelegate>.Sink!\n    private var delegate: MockAsyncWriterDelegate!\n\n    override func setUp() {\n        super.setUp()\n\n        let delegate = MockAsyncWriterDelegate()\n        self.delegate = delegate\n        let newWriter = NIOAsyncWriter.makeWriter(\n            elementType: String.self,\n            isWritable: true,\n            finishOnDeinit: false,\n            delegate: self.delegate\n        )\n        self.writer = newWriter.writer\n        self.sink = newWriter.sink\n        self.sink._storage._setDidSuspend { delegate.didSuspend() }\n    }\n\n    override func tearDown() {\n        if let writer = self.writer {\n            writer.finish()\n        }\n        if let sink = self.sink {\n            sink.finish()\n        }\n        self.delegate = nil\n        self.writer = nil\n        self.sink = nil\n\n        super.tearDown()\n    }\n\n    func assert(\n        suspendCallCount: Int,\n        yieldCallCount: Int,\n        terminateCallCount: Int,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) {\n        XCTAssertEqual(\n            self.delegate.didSuspendCallCount,\n            suspendCallCount,\n            \"Unexpeced suspends\",\n            file: file,\n            line: line\n        )\n        XCTAssertEqual(self.delegate.didYieldCallCount, yieldCallCount, \"Unexpected yields\", file: file, line: line)\n        XCTAssertEqual(\n            self.delegate.didTerminateCallCount,\n            terminateCallCount,\n            \"Unexpected terminates\",\n            file: file,\n            line: line\n        )\n    }\n\n    func testMultipleConcurrentWrites() async throws {\n        var elements = 0\n        self.delegate.didYieldHandler = { elements += $0.count }\n        let task1 = Task { [writer] in\n            for i in 0...9 {\n                try await writer!.yield(\"message\\(i)\")\n            }\n        }\n        let task2 = Task { [writer] in\n            for i in 10...19 {\n                try await writer!.yield(\"message\\(i)\")\n            }\n        }\n        let task3 = Task { [writer] in\n            for i in 20...29 {\n                try await writer!.yield(\"message\\(i)\")\n            }\n        }\n\n        try await task1.value\n        try await task2.value\n        try await task3.value\n\n        XCTAssertEqual(elements, 30)\n    }\n\n    func testMultipleConcurrentBatchWrites() async throws {\n        var elements = 0\n        self.delegate.didYieldHandler = { elements += $0.count }\n        let task1 = Task { [writer] in\n            for i in 0...9 {\n                try await writer!.yield(contentsOf: [\"message\\(i).1\", \"message\\(i).2\"])\n            }\n        }\n        let task2 = Task { [writer] in\n            for i in 10...19 {\n                try await writer!.yield(contentsOf: [\"message\\(i).1\", \"message\\(i).2\"])\n            }\n        }\n        let task3 = Task { [writer] in\n            for i in 20...29 {\n                try await writer!.yield(contentsOf: [\"message\\(i).1\", \"message\\(i).2\"])\n            }\n        }\n\n        try await task1.value\n        try await task2.value\n        try await task3.value\n\n        XCTAssertEqual(elements, 60)\n    }\n\n    // MARK: - WriterDeinitialized\n\n    func testWriterDeinitialized_whenInitial() async throws {\n        var newWriter: NIOAsyncWriter<String, MockAsyncWriterDelegate>.NewWriter? = NIOAsyncWriter.makeWriter(\n            elementType: String.self,\n            isWritable: true,\n            finishOnDeinit: true,\n            delegate: self.delegate\n        )\n        let sink = newWriter!.sink\n        var writer: NIOAsyncWriter<String, MockAsyncWriterDelegate>? = newWriter!.writer\n        newWriter = nil\n\n        writer = nil\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n        XCTAssertNil(writer)\n\n        sink.finish()\n    }\n\n    func testWriterDeinitialized_whenStreaming() async throws {\n        var newWriter: NIOAsyncWriter<String, MockAsyncWriterDelegate>.NewWriter? = NIOAsyncWriter.makeWriter(\n            elementType: String.self,\n            isWritable: true,\n            finishOnDeinit: true,\n            delegate: self.delegate\n        )\n        let sink = newWriter!.sink\n        var writer: NIOAsyncWriter<String, MockAsyncWriterDelegate>? = newWriter!.writer\n        newWriter = nil\n\n        try await writer!.yield(\"message1\")\n        writer = nil\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 1)\n        XCTAssertNil(writer)\n\n        sink.finish()\n    }\n\n    func testWriterDeinitialized_whenWriterFinished() async throws {\n        try await writer.yield(\"message1\")\n        self.writer.finish()\n        self.writer = nil\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 1)\n    }\n\n    func testWriterDeinitialized_whenFinished() async throws {\n        self.sink.finish()\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n\n        self.writer = nil\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    // MARK: - ToggleWritability\n\n    func testSetWritability_whenInitial() async throws {\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        Task { [writer] in\n            try await writer!.yield(\"message1\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testSetWritability_whenStreaming_andBecomingUnwritable() async throws {\n        try await self.writer.yield(\"message1\")\n        XCTAssertEqual(self.delegate.didYieldCallCount, 1)\n\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        Task { [writer] in\n            try await writer!.yield(\"message2\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testSetWritability_whenStreaming_andBecomingWritable() async throws {\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n        let resumed = expectation(description: \"yield completed\")\n\n        Task { [writer] in\n            try await writer!.yield(\"message2\")\n            resumed.fulfill()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.sink.setWritability(to: true)\n\n        await fulfillment(of: [resumed], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testSetWritability_whenStreaming_andSettingSameWritability() async throws {\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        Task { [writer] in\n            try await writer!.yield(\"message1\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        // Setting the writability to the same state again shouldn't change anything\n        self.sink.setWritability(to: false)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testSetWritability_whenWriterFinished() async throws {\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n        let resumed = expectation(description: \"yield completed\")\n\n        Task { [writer] in\n            try await writer!.yield(\"message1\")\n            resumed.fulfill()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.writer.finish()\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 0, terminateCallCount: 0)\n\n        self.sink.setWritability(to: true)\n\n        await fulfillment(of: [resumed], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 1)\n    }\n\n    func testSetWritability_whenFinished() async throws {\n        self.sink.finish()\n\n        self.sink.setWritability(to: false)\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    // MARK: - Yield\n\n    func testYield_whenInitial_andWritable() async throws {\n        try await self.writer.yield(\"message1\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testYield_whenInitial_andNotWritable() async throws {\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        Task { [writer] in\n            try await writer!.yield(\"message2\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testYield_whenStreaming_andWritable() async throws {\n        try await self.writer.yield(\"message1\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n\n        try await self.writer.yield(\"message2\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 2, terminateCallCount: 0)\n    }\n\n    func testYield_whenStreaming_andNotWritable() async throws {\n        try await self.writer.yield(\"message1\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        Task { [writer] in\n            try await writer!.yield(\"message2\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testYield_whenStreaming_andYieldCancelled() async throws {\n        try await self.writer.yield(\"message1\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task = Task { [writer] in\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            try await writer!.yield(\"message2\")\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        await XCTAssertThrowsError(try await task.value) { error in\n            XCTAssertTrue(error is CancellationError)\n        }\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testYield_cancelWhenStreamingAndNotWritable() async throws {\n        try await self.writer.yield(\"message1\")\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n        // Ensure the yield suspends\n        self.sink.setWritability(to: false)\n\n        let task = Task { [writer] in\n            try await writer!.yield(\"message2\")\n        }\n        task.cancel()\n\n        await XCTAssertThrowsError(try await task.value) { error in\n            XCTAssertTrue(error is CancellationError)\n        }\n    }\n\n    func testYield_whenWriterFinished() async throws {\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        Task { [writer] in\n            try await writer!.yield(\"message1\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.writer.finish()\n\n        await XCTAssertThrowsError(try await self.writer.yield(\"message1\")) { error in\n            XCTAssertEqual(error as? NIOAsyncWriterError, .alreadyFinished())\n        }\n        self.assert(suspendCallCount: 1, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testYield_whenFinished() async throws {\n        self.sink.finish()\n\n        await XCTAssertThrowsError(try await self.writer.yield(\"message1\")) { error in\n            XCTAssertEqual(error as? NIOAsyncWriterError, .alreadyFinished())\n        }\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testYield_whenFinishedError() async throws {\n        self.sink.finish(error: SomeError())\n\n        await XCTAssertThrowsError(try await self.writer.yield(\"message1\")) { error in\n            XCTAssertTrue(error is SomeError)\n        }\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    // MARK: - Cancel\n\n    func testCancel_whenInitial() async throws {\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task = Task { [writer] in\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            try await writer!.yield(\"message1\")\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        await XCTAssertThrowsError(try await task.value) { error in\n            XCTAssertTrue(error is CancellationError)\n        }\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testCancel_whenStreaming_andCancelBeforeYield() async throws {\n        try await self.writer.yield(\"message1\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task = Task { [writer] in\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            try await writer!.yield(\"message2\")\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        await XCTAssertThrowsError(try await task.value) { error in\n            XCTAssertTrue(error is CancellationError)\n        }\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testCancel_whenStreaming_andCancelAfterSuspendedYield() async throws {\n        try await self.writer.yield(\"message1\")\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n\n        let task = Task { [writer] in\n            try await writer!.yield(\"message2\")\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 0)\n\n        task.cancel()\n\n        await XCTAssertThrowsError(try await task.value) { error in\n            XCTAssertTrue(error is CancellationError)\n        }\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 0)\n\n        self.sink.setWritability(to: true)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testCancel_whenFinished() async throws {\n        self.writer.finish()\n\n        XCTAssertEqual(self.delegate.didTerminateCallCount, 1)\n\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task = Task { [writer] in\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            try await writer!.yield(\"message1\")\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        await XCTAssertThrowsError(try await task.value) { error in\n            XCTAssertEqual(error as? NIOAsyncWriterError, .alreadyFinished())\n        }\n        XCTAssertEqual(self.delegate.didYieldCallCount, 0)\n    }\n\n    // MARK: - Writer Finish\n\n    func testWriterFinish_whenInitial() async throws {\n        self.writer.finish()\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n    }\n\n    func testWriterFinish_whenInitial_andFailure() async throws {\n        self.writer.finish(error: SomeError())\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n    }\n\n    func testWriterFinish_whenStreaming() async throws {\n        try await self.writer!.yield(\"message1\")\n\n        self.writer.finish()\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 1)\n    }\n\n    func testWriterFinish_whenStreaming_AndBufferedElements() async throws {\n        // We are setting up a suspended yield here to check that it gets resumed\n        self.sink.setWritability(to: false)\n\n        let suspended = expectation(description: \"suspended on yield\")\n        self.delegate.didSuspendHandler = {\n            suspended.fulfill()\n        }\n        let task = Task { [writer] in\n            try await writer!.yield(\"message1\")\n        }\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.writer.finish()\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 0, terminateCallCount: 0)\n\n        // We have to become writable again to unbuffer the yield\n        self.sink.setWritability(to: true)\n\n        await XCTAssertNoThrow(try await task.value)\n\n        self.assert(suspendCallCount: 1, yieldCallCount: 1, terminateCallCount: 1)\n    }\n\n    @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n    func testWriterFinish_AndSuspendBufferedYield() async throws {\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            try await withManualTaskExecutors { taskExecutor1, taskExecutor2 in\n                self.sink.setWritability(to: false)\n\n                self.delegate.didYieldHandler = { _ in\n                    if self.delegate.didYieldCallCount == 1 {\n                        // This is the yield of the first task. Run the second task until it suspends again\n                        self.assert(suspendCallCount: 2, yieldCallCount: 1, terminateCallCount: 0)\n                        taskExecutor2.runUntilQueueIsEmpty()\n                        self.assert(suspendCallCount: 3, yieldCallCount: 1, terminateCallCount: 0)\n                    }\n                }\n\n                group.addTask(executorPreference: taskExecutor1) { [writer] in\n                    try await writer!.yield(\"message1\")\n                }\n                group.addTask(executorPreference: taskExecutor2) { [writer] in\n                    try await writer!.yield(\"message2\")\n                }\n\n                // Run tasks until they are both suspended\n                taskExecutor1.runUntilQueueIsEmpty()\n                taskExecutor2.runUntilQueueIsEmpty()\n                self.assert(suspendCallCount: 2, yieldCallCount: 0, terminateCallCount: 0)\n\n                self.writer.finish()\n\n                // We have to become writable again to unbuffer the yields\n                self.sink.setWritability(to: true)\n\n                // Run the first task, which will complete its yield\n                // During this yield, didYieldHandler will run the second task, which will suspend again\n                taskExecutor1.runUntilQueueIsEmpty()\n                self.assert(suspendCallCount: 3, yieldCallCount: 1, terminateCallCount: 0)\n\n                // Run the second task to complete its yield\n                taskExecutor2.runUntilQueueIsEmpty()\n                self.assert(suspendCallCount: 3, yieldCallCount: 2, terminateCallCount: 1)\n\n                await XCTAssertNoThrow(try await group.next())\n                await XCTAssertNoThrow(try await group.next())\n            }\n        }\n    }\n\n    func testWriterFinish_whenFinished() {\n        // This tests just checks that finishing again is a no-op\n        self.writer.finish()\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n\n        self.writer.finish()\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n    }\n\n    // MARK: - Sink Finish\n\n    func testSinkFinish_whenInitial() async throws {\n        var newWriter: NIOAsyncWriter<String, MockAsyncWriterDelegate>.NewWriter? = NIOAsyncWriter.makeWriter(\n            elementType: String.self,\n            isWritable: true,\n            finishOnDeinit: true,\n            delegate: self.delegate\n        )\n        var sink: NIOAsyncWriter<String, MockAsyncWriterDelegate>.Sink? = newWriter!.sink\n        let writer = newWriter!.writer\n        newWriter = nil\n\n        sink = nil\n\n        XCTAssertNil(sink)\n        XCTAssertNotNil(writer)\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 0)\n    }\n\n    func testSinkFinish_whenStreaming() async throws {\n        var newWriter: NIOAsyncWriter<String, MockAsyncWriterDelegate>.NewWriter? = NIOAsyncWriter.makeWriter(\n            elementType: String.self,\n            isWritable: true,\n            finishOnDeinit: true,\n            delegate: self.delegate\n        )\n        var sink: NIOAsyncWriter<String, MockAsyncWriterDelegate>.Sink? = newWriter!.sink\n        let writer = newWriter!.writer\n        newWriter = nil\n\n        try await writer.yield(\"message1\")\n\n        sink = nil\n\n        XCTAssertNil(sink)\n        self.assert(suspendCallCount: 0, yieldCallCount: 1, terminateCallCount: 0)\n    }\n\n    func testSinkFinish_whenFinished() async throws {\n        self.writer.finish()\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n\n        self.sink = nil\n\n        self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/AsyncSequences/NIOThrowingAsyncSequenceTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class NIOThrowingAsyncSequenceProducerTests: XCTestCase {\n    private var backPressureStrategy: MockNIOElementStreamBackPressureStrategy!\n    private var delegate: MockNIOBackPressuredStreamSourceDelegate!\n    private var sequence:\n        NIOThrowingAsyncSequenceProducer<\n            Int,\n            Error,\n            MockNIOElementStreamBackPressureStrategy,\n            MockNIOBackPressuredStreamSourceDelegate\n        >!\n    private var source:\n        NIOThrowingAsyncSequenceProducer<\n            Int,\n            Error,\n            MockNIOElementStreamBackPressureStrategy,\n            MockNIOBackPressuredStreamSourceDelegate\n        >.Source!\n\n    override func setUp() {\n        super.setUp()\n\n        self.backPressureStrategy = .init()\n        self.delegate = .init()\n        let result = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: Int.self,\n            failureType: Error.self,\n            backPressureStrategy: self.backPressureStrategy,\n            finishOnDeinit: false,\n            delegate: self.delegate\n        )\n        self.source = result.source\n        self.sequence = result.sequence\n    }\n\n    override func tearDown() {\n        self.backPressureStrategy = nil\n        self.delegate = nil\n        self.sequence = nil\n        self.source.finish()\n        self.source = nil\n\n        super.tearDown()\n    }\n\n    // MARK: - End to end tests\n\n    func testBackPressure() async throws {\n        let lowWatermark = 2\n        let higherWatermark = 5\n        self.backPressureStrategy.didYieldHandler = { bufferDepth in\n            bufferDepth < higherWatermark\n        }\n        self.backPressureStrategy.didNextHandler = { bufferDepth in\n            bufferDepth < lowWatermark\n        }\n        let iterator = self.sequence.makeAsyncIterator()\n\n        XCTAssertEqual(self.source.yield(contentsOf: [1, 2, 3]), .produceMore)\n        XCTAssertEqual(self.source.yield(contentsOf: [4, 5, 6]), .stopProducing)\n        XCTAssertEqualWithoutAutoclosure(try await iterator.next(), 1)\n        XCTAssertEqualWithoutAutoclosure(try await iterator.next(), 2)\n        XCTAssertEqualWithoutAutoclosure(try await iterator.next(), 3)\n        XCTAssertEqualWithoutAutoclosure(try await iterator.next(), 4)\n        XCTAssertEqualWithoutAutoclosure(try await iterator.next(), 5)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n        XCTAssertEqual(self.source.yield(contentsOf: [7, 8, 9, 10, 11]), .stopProducing)\n    }\n\n    // MARK: - Yield\n\n    func testYield_whenInitial_andStopProducing() async {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n        XCTAssertEqual(result, .stopProducing)\n    }\n\n    func testYield_whenInitial_andProduceMore() async {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n        XCTAssertEqual(result, .produceMore)\n    }\n\n    func testYield_whenStreaming_andSuspended_andStopProducing() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n\n        let sequence = try XCTUnwrap(self.sequence)\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n\n            let suspended = expectation(description: \"task suspended\")\n            sequence._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                try await sequence.first { _ in true }\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n            let result = self.source.yield(contentsOf: [1])\n\n            XCTAssertEqual(result, .stopProducing)\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n    }\n\n    func testYield_whenStreaming_andSuspended_andProduceMore() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n\n        let sequence = try XCTUnwrap(self.sequence)\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n\n            let suspended = expectation(description: \"task suspended\")\n            sequence._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                try await sequence.first { _ in true }\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n            let result = self.source.yield(contentsOf: [1])\n\n            XCTAssertEqual(result, .produceMore)\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n    }\n\n    func testYieldEmptySequence_whenStreaming_andSuspended_andStopProducing() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n\n        let sequence = try XCTUnwrap(self.sequence)\n        await withThrowingTaskGroup(of: Void.self) { group in\n\n            let suspended = expectation(description: \"task suspended\")\n            sequence._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                _ = try await sequence.first { _ in true }\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n            let result = self.source.yield(contentsOf: [])\n\n            XCTAssertEqual(result, .stopProducing)\n\n            group.cancelAll()\n        }\n    }\n\n    func testYieldEmptySequence_whenStreaming_andSuspended_andProduceMore() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n\n        let sequence = try XCTUnwrap(self.sequence)\n        await withThrowingTaskGroup(of: Void.self) { group in\n\n            let suspended = expectation(description: \"task suspended\")\n            sequence._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                _ = try await sequence.first { _ in true }\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n\n            let result = self.source.yield(contentsOf: [])\n\n            XCTAssertEqual(result, .stopProducing)\n\n            group.cancelAll()\n        }\n    }\n\n    func testYield_whenStreaming_andNotSuspended_andStopProducing() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in false }\n        // This transitions the sequence into streaming\n        _ = self.source.yield(contentsOf: [])\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .stopProducing)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didYield]\n        )\n    }\n\n    func testYield_whenStreaming_andNotSuspended_andProduceMore() async throws {\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n        // This transitions the sequence into streaming\n        _ = self.source.yield(contentsOf: [])\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .produceMore)\n        XCTAssertEqualWithoutAutoclosure(\n            await self.backPressureStrategy.events.prefix(2).collect(),\n            [.didYield, .didYield]\n        )\n    }\n\n    func testYield_whenSourceFinished() async throws {\n        self.source.finish()\n\n        let result = self.source.yield(contentsOf: [1])\n\n        XCTAssertEqual(result, .dropped)\n    }\n\n    // MARK: - Finish\n\n    func testFinish_whenInitial() async {\n        self.source.finish()\n    }\n\n    func testFinish_whenStreaming_andSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n\n            let suspended = expectation(description: \"task suspended\")\n            sequence._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                let element = try await sequence.first { _ in true }\n                return element\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            self.source.finish()\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, nil)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinish_whenStreaming_andNotSuspended_andBufferEmpty() async throws {\n        _ = self.source.yield(contentsOf: [])\n\n        self.source.finish()\n\n        let sequence = try XCTUnwrap(self.sequence)\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await sequence.first { _ in true }\n            }\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertNil(element)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinish_whenStreaming_andNotSuspended_andBufferNotEmpty() async throws {\n        _ = self.source.yield(contentsOf: [1])\n\n        self.source.finish()\n\n        let sequence = try XCTUnwrap(self.sequence)\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await sequence.first { _ in true }\n            }\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinish_whenFinished() async throws {\n        self.source.finish()\n\n        _ = try await self.sequence.first { _ in true }\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n\n        self.source.finish()\n    }\n\n    // MARK: - Finish with Error\n\n    func testFinishError_whenInitial() async {\n        self.source.finish(ChannelError.alreadyClosed)\n\n        await XCTAssertThrowsError(try await self.sequence.first { _ in true }) { error in\n            XCTAssertEqual(error as? ChannelError, .alreadyClosed)\n        }\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinishError_whenStreaming_andSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n        await XCTAssertThrowsError(\n            try await withThrowingTaskGroup(of: Void.self) { group in\n\n                let suspended = expectation(description: \"task suspended\")\n                sequence._storage._setDidSuspend { suspended.fulfill() }\n\n                group.addTask {\n                    _ = try await sequence.first { _ in true }\n                }\n\n                await fulfillment(of: [suspended], timeout: 1)\n\n                self.source.finish(ChannelError.alreadyClosed)\n\n                try await group.next()\n            }\n        ) { error in\n            XCTAssertEqual(error as? ChannelError, .alreadyClosed)\n        }\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinishError_whenStreaming_andNotSuspended_andBufferEmpty() async throws {\n        _ = self.source.yield(contentsOf: [])\n\n        self.source.finish(ChannelError.alreadyClosed)\n\n        let sequence = try XCTUnwrap(self.sequence)\n        await XCTAssertThrowsError(\n            try await withThrowingTaskGroup(of: Void.self) { group in\n                group.addTask {\n                    _ = try await sequence.first { _ in true }\n                }\n\n                try await group.next()\n            }\n        ) { error in\n            XCTAssertEqual(error as? ChannelError, .alreadyClosed)\n        }\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinishError_whenStreaming_andNotSuspended_andBufferNotEmpty() async throws {\n        _ = self.source.yield(contentsOf: [1])\n\n        self.source.finish(ChannelError.alreadyClosed)\n\n        var elements = [Int]()\n\n        await XCTAssertThrowsError(\n            try await {\n                for try await element in self.sequence {\n                    elements.append(element)\n                }\n            }()\n        ) { error in\n            XCTAssertEqual(error as? ChannelError, .alreadyClosed)\n        }\n\n        XCTAssertEqual(elements, [1])\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testFinishError_whenFinished() async throws {\n        self.source.finish()\n        let iterator = self.sequence.makeAsyncIterator()\n\n        _ = try await iterator.next()\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n\n        self.source.finish(ChannelError.alreadyClosed)\n\n        // This call should just return nil\n        _ = try await iterator.next()\n    }\n\n    // MARK: - Source Deinited\n\n    func testSourceDeinited_whenInitial() async {\n        var newSequence:\n            NIOThrowingAsyncSequenceProducer<\n                Int,\n                any Error,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOThrowingAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        source = nil\n\n        XCTAssertNil(source)\n        XCTAssertNotNil(sequence)\n    }\n\n    func testSourceDeinited_whenStreaming_andSuspended() async throws {\n        var newSequence:\n            NIOThrowingAsyncSequenceProducer<\n                Int,\n                any Error,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOThrowingAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n\n            let suspended = expectation(description: \"task suspended\")\n            sequence!._storage._setDidSuspend { suspended.fulfill() }\n\n            group.addTask {\n                let element = try await sequence!.first { _ in true }\n                return element\n            }\n\n            await fulfillment(of: [suspended], timeout: 1)\n\n            source = nil\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, nil)\n        XCTAssertNil(source)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testSourceDeinited_whenStreaming_andNotSuspended_andBufferEmpty() async throws {\n        var newSequence:\n            NIOThrowingAsyncSequenceProducer<\n                Int,\n                any Error,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOThrowingAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        _ = source!.yield(contentsOf: [])\n\n        source = nil\n\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await sequence!.first { _ in true }\n            }\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertNil(element)\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testSourceDeinited_whenStreaming_andNotSuspended_andBufferNotEmpty() async throws {\n        var newSequence:\n            NIOThrowingAsyncSequenceProducer<\n                Int,\n                any Error,\n                MockNIOElementStreamBackPressureStrategy,\n                MockNIOBackPressuredStreamSourceDelegate\n            >.NewSequence? = NIOThrowingAsyncSequenceProducer.makeSequence(\n                elementType: Int.self,\n                backPressureStrategy: self.backPressureStrategy,\n                finishOnDeinit: true,\n                delegate: self.delegate\n            )\n        let sequence = newSequence?.sequence\n        var source = newSequence?.source\n        newSequence = nil\n\n        _ = source!.yield(contentsOf: [1])\n\n        source = nil\n\n        let element: Int? = try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await sequence!.first { _ in true }\n            }\n\n            return try await group.next() ?? nil\n        }\n\n        XCTAssertEqual(element, 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    // MARK: - Task cancel\n\n    func testTaskCancel_whenStreaming_andSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Error> = Task {\n            let iterator = sequence.makeAsyncIterator()\n            return try await iterator.next()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        task.cancel()\n        let result = await task.result\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n        await XCTAssertThrowsError(try result.get()) { error in\n            XCTAssertTrue(error is CancellationError)\n        }\n    }\n\n    @available(*, deprecated, message: \"tests the deprecated custom generic failure type\")\n    func testTaskCancel_whenStreaming_andSuspended_withCustomErrorType() async throws {\n        struct CustomError: Error {}\n        let backPressureStrategy = MockNIOElementStreamBackPressureStrategy()\n        let delegate = MockNIOBackPressuredStreamSourceDelegate()\n        let new = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: Int.self,\n            failureType: CustomError.self,\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        let sequence = new.sequence\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Error> = Task {\n            let iterator = sequence.makeAsyncIterator()\n            return try await iterator.next()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        task.cancel()\n        let result = await task.result\n        XCTAssertEqualWithoutAutoclosure(await delegate.events.prefix(1).collect(), [.didTerminate])\n\n        try withExtendedLifetime(new.source) {\n            XCTAssertNil(try result.get())\n        }\n    }\n\n    func testTaskCancel_whenStreaming_andNotSuspended() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n        let suspended = expectation(description: \"task suspended\")\n        let resumed = expectation(description: \"task resumed\")\n        let cancelled = expectation(description: \"task cancelled\")\n\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Error> = Task {\n            let iterator = sequence.makeAsyncIterator()\n            let element = try await iterator.next()\n            resumed.fulfill()\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            return element\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        _ = self.source.yield(contentsOf: [1])\n\n        await fulfillment(of: [resumed], timeout: 1)\n\n        task.cancel()\n        cancelled.fulfill()\n\n        let value = try await task.value\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n        XCTAssertEqual(value, 1)\n    }\n\n    func testTaskCancel_whenSourceFinished() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        let task: Task<Int?, Error> = Task {\n            let iterator = sequence.makeAsyncIterator()\n            return try await iterator.next()\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        self.source.finish()\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n        task.cancel()\n        let value = try await task.value\n        XCTAssertNil(value)\n    }\n\n    func testTaskCancel_whenStreaming_andTaskIsAlreadyCancelled() async throws {\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task: Task<Int?, Error> = Task {\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            let iterator = sequence.makeAsyncIterator()\n            return try await iterator.next()\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        let result = await task.result\n\n        await XCTAssertThrowsError(try result.get()) { error in\n            XCTAssertTrue(error is CancellationError, \"unexpected error \\(error)\")\n        }\n    }\n\n    @available(*, deprecated, message: \"tests the deprecated custom generic failure type\")\n    func testTaskCancel_whenStreaming_andTaskIsAlreadyCancelled_withCustomErrorType() async throws {\n        struct CustomError: Error {}\n        let backPressureStrategy = MockNIOElementStreamBackPressureStrategy()\n        let delegate = MockNIOBackPressuredStreamSourceDelegate()\n        let new = NIOThrowingAsyncSequenceProducer.makeSequence(\n            elementType: Int.self,\n            failureType: CustomError.self,\n            backPressureStrategy: backPressureStrategy,\n            delegate: delegate\n        )\n        let sequence = new.sequence\n\n        let cancelled = expectation(description: \"task cancelled\")\n\n        let task: Task<Int?, Error> = Task {\n            await XCTWaiter().fulfillment(of: [cancelled], timeout: 1)\n            let iterator = sequence.makeAsyncIterator()\n            return try await iterator.next()\n        }\n\n        task.cancel()\n        cancelled.fulfill()\n\n        let result = await task.result\n        try withExtendedLifetime(new.source) {\n            XCTAssertNil(try result.get())\n        }\n    }\n\n    // MARK: - Next\n\n    func testNext_whenInitial_whenDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = try await sequence.first { _ in true }\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n    }\n\n    func testNext_whenInitial_whenNoDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in false }\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = try await sequence.first { _ in true }\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n    }\n\n    func testNext_whenStreaming_whenEmptyBuffer_whenDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        _ = self.source.yield(contentsOf: [])\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = try await sequence.first { _ in true }\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n    }\n\n    func testNext_whenStreaming_whenEmptyBuffer_whenNoDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in false }\n        _ = self.source.yield(contentsOf: [])\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n\n        let sequence = try XCTUnwrap(self.sequence)\n\n        let suspended = expectation(description: \"task suspended\")\n        sequence._storage._setDidSuspend { suspended.fulfill() }\n\n        Task {\n            // Would prefer to use async let _ here but that is not allowed yet\n            _ = try await sequence.first { _ in true }\n        }\n\n        await fulfillment(of: [suspended], timeout: 1)\n\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n    }\n\n    func testNext_whenStreaming_whenNotEmptyBuffer_whenNoDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in false }\n        _ = self.source.yield(contentsOf: [1])\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n\n        let element = try await self.sequence.first { _ in true }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n    }\n\n    func testNext_whenStreaming_whenNotEmptyBuffer_whenNewDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        _ = self.source.yield(contentsOf: [1])\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n\n        let element = try await self.sequence.first { _ in true }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.produceMore])\n    }\n\n    func testNext_whenStreaming_whenNotEmptyBuffer_whenNewAndOutstandingDemand() async throws {\n        self.backPressureStrategy.didNextHandler = { _ in true }\n        self.backPressureStrategy.didYieldHandler = { _ in true }\n\n        _ = self.source.yield(contentsOf: [1])\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didYield])\n\n        let element = try await self.sequence.first { _ in true }\n\n        XCTAssertEqual(element, 1)\n        XCTAssertEqualWithoutAutoclosure(await self.backPressureStrategy.events.prefix(1).collect(), [.didNext])\n    }\n\n    func testNext_whenSourceFinished() async throws {\n        _ = self.source.yield(contentsOf: [1, 2])\n        self.source.finish()\n\n        var elements = [Int]()\n\n        for try await element in self.sequence {\n            elements.append(element)\n        }\n\n        XCTAssertEqual(elements, [1, 2])\n    }\n\n    // MARK: - SequenceDeinitialized\n\n    func testSequenceDeinitialized() async {\n        self.sequence = nil\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testSequenceDeinitialized_whenIteratorReferenced() async {\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        self.sequence = nil\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    // MARK: - IteratorDeinitialized\n\n    func testIteratorDeinitialized_whenSequenceReferenced() async {\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n\n        self.sequence = nil\n    }\n\n    func testIteratorDeinitialized_whenSequenceFinished() async {\n        self.source.finish()\n\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testIteratorDeinitialized_whenStreaming() async {\n        _ = self.source.yield(contentsOf: [1])\n        var iterator = self.sequence?.makeAsyncIterator()\n\n        XCTAssertNotNil(iterator)\n        iterator = nil\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n\n    func testIteratorThrows_whenCancelled() async {\n        _ = self.source.yield(contentsOf: Array(1...100))\n        guard let sequence = self.sequence else {\n            return XCTFail(\"Expected to have an AsyncSequence\")\n        }\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                var itemsYieldedCounter = 0\n\n                do {\n                    for try await next in sequence {\n                        itemsYieldedCounter += 1\n                        XCTAssertEqual(next, itemsYieldedCounter)\n                    }\n                    XCTFail(\"Expected that this throws\")\n                } catch is CancellationError {\n                    // expected\n                } catch {\n                    XCTFail(\"Unexpected error: \\(error)\")\n                }\n\n                XCTAssertLessThanOrEqual(itemsYieldedCounter, 100)\n            }\n\n            group.cancelAll()\n        }\n\n        XCTAssertEqualWithoutAutoclosure(await self.delegate.events.prefix(1).collect(), [.didTerminate])\n    }\n}\n\n// This is needed until async let is supported to be used in autoclosures\nprivate func XCTAssertEqualWithoutAutoclosure<T>(\n    _ expression1: T,\n    _ expression2: T,\n    _ message: @autoclosure () -> String = \"\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) where T: Equatable {\n    XCTAssertEqual(expression1, expression2, message(), file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension AsyncSequence {\n    /// Collect all elements in the sequence into an array.\n    fileprivate func collect() async rethrows -> [Element] {\n        try await self.reduce(into: []) { accumulated, next in\n            accumulated.append(next)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/BaseObjectsTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\nclass BaseObjectTest: XCTestCase {\n    func testNIOByteBufferConversion() {\n        let expected = ByteBufferAllocator().buffer(capacity: 1024)\n        let asAny = NIOAny(expected)\n        XCTAssertEqual(expected, asAny.forceAs(type: ByteBuffer.self))\n        XCTAssertEqual(expected, asAny.forceAsByteBuffer())\n        if let actual = asAny.tryAs(type: ByteBuffer.self) {\n            XCTAssertEqual(expected, actual)\n        } else {\n            XCTFail(\"tryAs didn't work\")\n        }\n        if let actual = asAny.tryAsByteBuffer() {\n            XCTAssertEqual(expected, actual)\n        } else {\n            XCTFail(\"tryAs didn't work\")\n        }\n    }\n\n    func testNIOIODataConversion() {\n        let expected = IOData.byteBuffer(ByteBufferAllocator().buffer(capacity: 1024))\n        let asAny = NIOAny(expected)\n        XCTAssertEqual(expected, asAny.forceAs(type: IOData.self))\n        XCTAssertEqual(expected, asAny.forceAsIOData())\n        if let actual = asAny.tryAs(type: IOData.self) {\n            XCTAssertEqual(expected, actual)\n        } else {\n            XCTFail(\"tryAs didn't work\")\n        }\n        if let actual = asAny.tryAsIOData() {\n            XCTAssertEqual(expected, actual)\n        } else {\n            XCTFail(\"tryAs didn't work\")\n        }\n    }\n\n    func testNIOFileRegionConversion() {\n        let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n        let expected = FileRegion(fileHandle: handle, readerIndex: 1, endIndex: 2)\n        defer {\n            // fake descriptor, so shouldn't be closed.\n            XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n        }\n        let asAny = NIOAny(expected)\n        XCTAssert(expected == asAny.forceAs(type: FileRegion.self))\n        XCTAssert(expected == asAny.forceAsFileRegion())\n        if let actual = asAny.tryAs(type: FileRegion.self) {\n            XCTAssert(expected == actual)\n        } else {\n            XCTFail(\"tryAs didn't work\")\n        }\n        if let actual = asAny.tryAsFileRegion() {\n            XCTAssert(expected == actual)\n        } else {\n            XCTFail(\"tryAs didn't work\")\n        }\n    }\n\n    func testBadConversions() {\n        let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n        let bb = ByteBufferAllocator().buffer(capacity: 1024)\n        let fr = FileRegion(fileHandle: handle, readerIndex: 1, endIndex: 2)\n        defer {\n            // fake descriptor, so shouldn't be closed.\n            XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n        }\n        let id = IOData.byteBuffer(bb)\n\n        XCTAssertNil(NIOAny(bb).tryAsFileRegion())\n        XCTAssertNil(NIOAny(fr).tryAsByteBuffer())\n        XCTAssertNil(NIOAny(id).tryAsFileRegion())\n    }\n\n    func testByteBufferFromIOData() {\n        let expected = ByteBufferAllocator().buffer(capacity: 1024)\n        let wrapped = IOData.byteBuffer(expected)\n        XCTAssertEqual(expected, NIOAny(wrapped).tryAsByteBuffer())\n    }\n\n    func testFileRegionFromIOData() {\n        let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n        let expected = FileRegion(fileHandle: handle, readerIndex: 1, endIndex: 2)\n        defer {\n            // fake descriptor, so shouldn't be closed.\n            XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n        }\n        let wrapped = IOData.fileRegion(expected)\n        XCTAssert(expected == NIOAny(wrapped).tryAsFileRegion())\n    }\n\n    func testIODataEquals() {\n        let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n        var bb1 = ByteBufferAllocator().buffer(capacity: 1024)\n        let bb2 = ByteBufferAllocator().buffer(capacity: 1024)\n        bb1.writeString(\"hello\")\n        let fr = FileRegion(fileHandle: handle, readerIndex: 1, endIndex: 2)\n        defer {\n            // fake descriptor, so shouldn't be closed.\n            XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n        }\n        XCTAssertEqual(IOData.byteBuffer(bb1), IOData.byteBuffer(bb1))\n        XCTAssertNotEqual(IOData.byteBuffer(bb1), IOData.byteBuffer(bb2))\n        XCTAssertNotEqual(IOData.byteBuffer(bb1), IOData.fileRegion(fr))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/ByteBufferBinaryEncodedLengthPrefixTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n/// A strategy which just writes integers as UInt8. Enforces the integer must be a particular number to aid testing. Forbids reads\nstruct UInt8WritingTestStrategy: NIOBinaryIntegerEncodingStrategy {\n    let expectedWrite: Int\n\n    func readInteger<IntegerType: FixedWidthInteger>(\n        as: IntegerType.Type,\n        from buffer: inout ByteBuffer\n    ) -> IntegerType? {\n        XCTFail(\"This should not be called\")\n        return 1\n    }\n\n    func writeInteger<IntegerType: FixedWidthInteger>(_ integer: IntegerType, to buffer: inout ByteBuffer) -> Int {\n        XCTAssertEqual(Int(integer), self.expectedWrite)\n        return buffer.writeInteger(UInt8(integer))\n    }\n\n    func writeInteger(_ integer: Int, reservedCapacity: Int, to buffer: inout ByteBuffer) -> Int {\n        XCTFail(\"This should not be called\")\n        return 1\n    }\n}\n\n// A which reads a single UInt8 for the length. Forbids writes\nstruct UInt8ReadingTestStrategy: NIOBinaryIntegerEncodingStrategy {\n    let expectedRead: UInt8\n\n    func readInteger<IntegerType: FixedWidthInteger>(\n        as: IntegerType.Type,\n        from buffer: inout ByteBuffer\n    ) -> IntegerType? {\n        let value = buffer.readInteger(as: UInt8.self)\n        XCTAssertEqual(value, self.expectedRead)\n        return value.flatMap(IntegerType.init)\n    }\n\n    func writeInteger<IntegerType: FixedWidthInteger>(_ integer: IntegerType, to buffer: inout ByteBuffer) -> Int {\n        XCTFail(\"This should not be called\")\n        return 1\n    }\n\n    func writeInteger(_ integer: Int, reservedCapacity: Int, to buffer: inout ByteBuffer) -> Int {\n        XCTFail(\"This should not be called\")\n        return 1\n    }\n\n    var requiredBytesHint: Int { 1 }\n}\n\nfinal class ByteBufferBinaryEncodedLengthPrefixTests: XCTestCase {\n    // MARK: - simple readEncodedInteger and writeEncodedInteger tests\n\n    func testReadWriteEncodedInteger() {\n        struct TestStrategy: NIOBinaryIntegerEncodingStrategy {\n            func readInteger<IntegerType: FixedWidthInteger>(\n                as: IntegerType.Type,\n                from buffer: inout ByteBuffer\n            ) -> IntegerType? {\n                10\n            }\n\n            func writeInteger<IntegerType: FixedWidthInteger>(\n                _ integer: IntegerType,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTAssertEqual(integer, 10)\n                return 1\n            }\n\n            func writeInteger(\n                _ integer: Int,\n                reservedCapacity: Int,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n        }\n\n        // This should just call down to the strategy function\n        var buffer = ByteBuffer()\n        XCTAssertEqual(buffer.readEncodedInteger(strategy: TestStrategy()), 10)\n        XCTAssertEqual(buffer.writeEncodedInteger(10, strategy: TestStrategy()), 1)\n    }\n\n    // MARK: - writeLengthPrefixed tests\n\n    func testWriteLengthPrefixedFitsInReservedCapacity() {\n        struct TestStrategy: NIOBinaryIntegerEncodingStrategy {\n            func readInteger<IntegerType: FixedWidthInteger>(\n                as: IntegerType.Type,\n                from buffer: inout ByteBuffer\n            ) -> IntegerType? {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger<IntegerType: FixedWidthInteger>(\n                _ integer: IntegerType,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger(\n                _ integer: Int,\n                reservedCapacity: Int,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTAssertEqual(Int(integer), 4)\n                XCTAssertEqual(reservedCapacity, 1)\n                return buffer.writeInteger(UInt8(integer))\n            }\n\n            var requiredBytesHint: Int { 1 }\n        }\n\n        var buffer = ByteBuffer()\n        buffer.writeLengthPrefixed(strategy: TestStrategy()) { writer in\n            writer.writeString(\"test\")\n        }\n\n        XCTAssertEqual(buffer.readableBytes, 5)\n        XCTAssertEqual(buffer.readBytes(length: 5), [4] + \"test\".utf8)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    func testWriteLengthPrefixedNeedsMoreThanReservedCapacity() {\n        struct TestStrategy: NIOBinaryIntegerEncodingStrategy {\n            func readInteger<IntegerType: FixedWidthInteger>(\n                as: IntegerType.Type,\n                from buffer: inout ByteBuffer\n            ) -> IntegerType? {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger<IntegerType: FixedWidthInteger>(\n                _ integer: IntegerType,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger(\n                _ integer: Int,\n                reservedCapacity: Int,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTAssertEqual(Int(integer), 4)\n                XCTAssertEqual(reservedCapacity, 1)\n                // We use 8 bytes, but only one was reserved\n                return buffer.writeInteger(UInt64(integer))\n            }\n\n            var requiredBytesHint: Int { 1 }\n        }\n\n        var buffer = ByteBuffer()\n        buffer.writeLengthPrefixed(strategy: TestStrategy()) { writer in\n            writer.writeString(\"test\")\n        }\n\n        // The strategy above uses 8 bytes for encoding the length. The data is 4, making a total of 12 bytes written\n        XCTAssertEqual(buffer.readableBytes, 12)\n        XCTAssertEqual(buffer.readBytes(length: 12), [0, 0, 0, 0, 0, 0, 0, 4] + \"test\".utf8)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    func testWriteLengthPrefixedNeedsLessThanReservedCapacity() {\n        struct TestStrategy: NIOBinaryIntegerEncodingStrategy {\n            func readInteger<IntegerType: FixedWidthInteger>(\n                as: IntegerType.Type,\n                from buffer: inout ByteBuffer\n            ) -> IntegerType? {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger<IntegerType: FixedWidthInteger>(\n                _ integer: IntegerType,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger(\n                _ integer: Int,\n                reservedCapacity: Int,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTAssertEqual(Int(integer), 4)\n                XCTAssertEqual(reservedCapacity, 8)\n                return buffer.writeInteger(UInt8(integer))\n            }\n\n            var requiredBytesHint: Int { 8 }\n        }\n\n        var buffer = ByteBuffer()\n        buffer.writeLengthPrefixed(strategy: TestStrategy()) { writer in\n            writer.writeString(\"test\")\n        }\n\n        // The strategy above reserves 8 bytes, but only uses 1\n        // The implementation will take care of removing the 7 spare bytes for us\n        XCTAssertEqual(buffer.readableBytes, 5)\n        XCTAssertEqual(buffer.readBytes(length: 5), [4] + \"test\".utf8)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    func testWriteLengthPrefixedThrowing() {\n        // A strategy which fails the test if anything is called\n        struct NeverCallStrategy: NIOBinaryIntegerEncodingStrategy {\n            func readInteger<IntegerType: FixedWidthInteger>(\n                as: IntegerType.Type,\n                from buffer: inout ByteBuffer\n            ) -> IntegerType? {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger<IntegerType: FixedWidthInteger>(\n                _ integer: IntegerType,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            func writeInteger(\n                _ integer: Int,\n                reservedCapacity: Int,\n                to buffer: inout ByteBuffer\n            ) -> Int {\n                XCTFail(\"This should not be called\")\n                return 1\n            }\n\n            var requiredBytesHint: Int { 1 }\n        }\n\n        struct TestError: Error {}\n\n        var buffer = ByteBuffer()\n        do {\n            try buffer.writeLengthPrefixed(strategy: NeverCallStrategy()) { _ in\n                throw TestError()\n            }\n            XCTFail(\"Expected call to throw\")\n        } catch {\n            // Nothing should have happened, buffer should still be empty\n            XCTAssertTrue(buffer.readableBytesView.isEmpty)\n        }\n    }\n\n    // MARK: - readLengthPrefixed tests\n\n    func testReadLengthPrefixedSlice() {\n        var buffer = ByteBuffer()\n        buffer.writeBytes([5, 1, 2, 3, 4, 5])\n        let slice = buffer.readLengthPrefixedSlice(strategy: UInt8ReadingTestStrategy(expectedRead: 5))\n        XCTAssertEqual(slice?.readableBytesView, [1, 2, 3, 4, 5])\n    }\n\n    func testReadLengthPrefixedSliceInsufficientBytes() {\n        var buffer = ByteBuffer()\n        buffer.writeBytes([5, 1, 2, 3])  // We put a length of 5, followed by only 3 bytes\n        let slice = buffer.readLengthPrefixedSlice(strategy: UInt8ReadingTestStrategy(expectedRead: 5))\n        XCTAssertNil(slice)\n        // The original buffer reader index should NOT move\n        XCTAssertEqual(buffer.readableBytesView, [5, 1, 2, 3])\n    }\n\n    // MARK: - writeLengthPrefixed* tests\n\n    func testWriteVariableLengthPrefixedString() {\n        var buffer = ByteBuffer()\n        let strategy = UInt8WritingTestStrategy(expectedWrite: 11)\n        let testString = \"Hello World\"  // length = 11\n        let bytesWritten = buffer.writeLengthPrefixedString(testString, strategy: strategy)\n        XCTAssertEqual(bytesWritten, 11 + 1)  // we use 1 byte to write the length\n\n        XCTAssertEqual(buffer.readableBytes, 12)\n        XCTAssertEqual(buffer.readBytes(length: 12), [11] + testString.utf8)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    func testWriteVariableLengthPrefixedBytes() {\n        var buffer = ByteBuffer()\n        let strategy = UInt8WritingTestStrategy(expectedWrite: 10)\n        let testBytes = [UInt8](repeating: 1, count: 10)\n        let bytesWritten = buffer.writeLengthPrefixedBytes(testBytes, strategy: strategy)\n        XCTAssertEqual(bytesWritten, 10 + 1)  // we use 1 byte to write the length\n\n        XCTAssertEqual(buffer.readableBytes, 11)\n        XCTAssertEqual(buffer.readBytes(length: 11), [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    func testWriteVariableLengthPrefixedBuffer() {\n        var buffer = ByteBuffer()\n        let strategy = UInt8WritingTestStrategy(expectedWrite: 4)\n        let testBuffer = ByteBuffer(string: \"test\")\n        let bytesWritten = buffer.writeLengthPrefixedBuffer(testBuffer, strategy: strategy)\n        XCTAssertEqual(bytesWritten, 4 + 1)  // we use 1 byte to write the length\n\n        XCTAssertEqual(buffer.readableBytes, 5)\n        XCTAssertEqual(buffer.readBytes(length: 5), [4] + \"test\".utf8)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/ByteBufferCustomAllocatorTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\n@_spi(CustomByteBufferAllocator) @testable import NIOCore\nimport XCTest\n\n// Module-level tracker and hooks (required because C function pointers can't be instance methods)\nprivate final class AllocationTracker {\n    struct ReallocCall: @unchecked Sendable {\n        let ptr: UnsafeMutableRawPointer?\n        let oldSize: Int\n        let newSize: Int\n    }\n\n    private let _mallocCalls = NIOLockedValueBox<[Int]>([])\n    private let _reallocCalls = NIOLockedValueBox<[ReallocCall]>([])\n    private let _freeCalls = NIOLockedValueBox<[UnsafeMutableRawPointer]>([])\n\n    var mallocCalls: [Int] {\n        self._mallocCalls.withLockedValue { $0 }\n    }\n\n    var reallocCalls: [ReallocCall] {\n        self._reallocCalls.withLockedValue { $0 }\n    }\n\n    var freeCalls: [UnsafeMutableRawPointer] {\n        self._freeCalls.withLockedValue { $0 }\n    }\n\n    func recordMalloc(size: Int) {\n        self._mallocCalls.withLockedValue { $0.append(size) }\n    }\n\n    func recordRealloc(ptr: UnsafeMutableRawPointer?, oldSize: Int, newSize: Int) {\n        self._reallocCalls.withLockedValue { $0.append(ReallocCall(ptr: ptr, oldSize: oldSize, newSize: newSize)) }\n    }\n\n    func recordFree(ptr: UnsafeMutableRawPointer) {\n        self._freeCalls.withLockedValue { $0.append(ptr) }\n    }\n\n    func reset() {\n        self._mallocCalls.withLockedValue { $0.removeAll() }\n        self._reallocCalls.withLockedValue { $0.removeAll() }\n        self._freeCalls.withLockedValue { $0.removeAll() }\n    }\n}\n\n// Static tracker instance - tests will reset this in setUp()\n// Note: Safe because XCTest runs tests within a class serially, not in parallel\nprivate nonisolated(unsafe) let testTracker = AllocationTracker()\n\n// C-callable function pointers that delegate to the tracker\nprivate func testMallocHook(_ size: Int) -> UnsafeMutableRawPointer? {\n    testTracker.recordMalloc(size: size)\n    return malloc(size)\n}\n\nprivate func testReallocHook(\n    _ ptr: UnsafeMutableRawPointer?,\n    _ oldSize: Int,\n    _ newSize: Int\n) -> UnsafeMutableRawPointer? {\n    testTracker.recordRealloc(ptr: ptr, oldSize: oldSize, newSize: newSize)\n    return realloc(ptr, newSize)\n}\n\nprivate func testFreeHook(_ ptr: UnsafeMutableRawPointer) {\n    testTracker.recordFree(ptr: ptr)\n    free(ptr)\n}\n\nprivate func testMemcpyHook(_ dst: UnsafeMutableRawPointer, _ src: UnsafeRawPointer, _ count: Int) {\n    _ = memcpy(dst, src, count)\n}\n\nclass ByteBufferCustomAllocatorTest: XCTestCase {\n\n    override func setUp() {\n        super.setUp()\n        testTracker.reset()\n    }\n\n    private func makeTrackedAllocator() -> ByteBufferAllocator {\n        ByteBufferAllocator(\n            allocate: testMallocHook,\n            reallocate: testReallocHook,\n            deallocate: testFreeHook,\n            copy: testMemcpyHook\n        )\n    }\n\n    func testCustomAllocatorReceivesCorrectReallocSizes() {\n        let allocator = self.makeTrackedAllocator()\n\n        var buffer = allocator.buffer(capacity: 64)\n        XCTAssertEqual(testTracker.mallocCalls.count, 1)\n        XCTAssertEqual(testTracker.mallocCalls[0], 64)\n\n        // Write enough data to trigger realloc\n        buffer.writeBytes(Array(repeating: UInt8(0x42), count: 64))\n        buffer.writeBytes(Array(repeating: UInt8(0x43), count: 1))\n\n        // Should have triggered at least one realloc\n        XCTAssertGreaterThan(testTracker.reallocCalls.count, 0)\n\n        // Verify the realloc call had correct old and new sizes\n        let firstRealloc = testTracker.reallocCalls[0]\n        XCTAssertEqual(firstRealloc.oldSize, 64, \"Old size should be original capacity\")\n        XCTAssertGreaterThan(firstRealloc.newSize, 64, \"New size should be larger than old size\")\n    }\n\n    func testCustomAllocatorReallocReceivesOldSizeOnMultipleGrows() {\n        let allocator = self.makeTrackedAllocator()\n\n        var buffer = allocator.buffer(capacity: 16)\n\n        // Trigger multiple reallocs by writing incrementally\n        for _ in 0..<10 {\n            buffer.writeBytes(Array(repeating: UInt8(0x42), count: 16))\n        }\n\n        let reallocCalls = testTracker.reallocCalls\n        XCTAssertGreaterThan(reallocCalls.count, 0)\n\n        // Verify each realloc has the previous capacity as old size\n        for i in 0..<reallocCalls.count {\n            let call = reallocCalls[i]\n            if i == 0 {\n                XCTAssertEqual(call.oldSize, 16, \"First realloc should have initial capacity as old size\")\n            } else {\n                let previousNewSize = reallocCalls[i - 1].newSize\n                XCTAssertEqual(\n                    call.oldSize,\n                    previousNewSize,\n                    \"Each realloc should receive previous capacity as old size\"\n                )\n            }\n            XCTAssertGreaterThan(call.newSize, call.oldSize, \"New size should always be larger than old size\")\n        }\n    }\n\n    func testAdoptingExternalMemory() {\n        let capacity = 256\n        let ptr = malloc(capacity)!\n\n        // Initialize some data in the external memory\n        let boundPtr = ptr.bindMemory(to: UInt8.self, capacity: capacity)\n        for i in 0..<10 {\n            boundPtr[i] = UInt8(i)\n        }\n\n        let allocator = self.makeTrackedAllocator()\n\n        var buffer = ByteBuffer(\n            takingOwnershipOf: UnsafeMutableRawBufferPointer(start: ptr, count: capacity),\n            allocator: allocator\n        )\n\n        // No malloc should have been called since we adopted existing memory\n        XCTAssertEqual(testTracker.mallocCalls.count, 0)\n\n        // Verify the data is accessible\n        XCTAssertEqual(buffer.readableBytes, capacity)\n        let readData = buffer.readBytes(length: 10)!\n        XCTAssertEqual(readData, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n\n        // When buffer is deallocated, free should be called on our pointer\n        buffer = ByteBuffer()\n\n        // Verify free was called\n        XCTAssertGreaterThan(testTracker.freeCalls.count, 0)\n    }\n\n    func testAdoptingExternalMemoryWithCustomIndices() {\n        let capacity = 100\n        let ptr = malloc(capacity)!\n\n        let boundPtr = ptr.bindMemory(to: UInt8.self, capacity: capacity)\n        for i in 0..<capacity {\n            boundPtr[i] = UInt8(i % 256)\n        }\n\n        let allocator = ByteBufferAllocator()\n\n        var buffer = ByteBuffer(\n            takingOwnershipOf: UnsafeMutableRawBufferPointer(start: ptr, count: capacity),\n            allocator: allocator,\n            readerIndex: 10,\n            writerIndex: 50\n        )\n\n        XCTAssertEqual(buffer.readerIndex, 10)\n        XCTAssertEqual(buffer.writerIndex, 50)\n        XCTAssertEqual(buffer.readableBytes, 40)\n        XCTAssertEqual(buffer.capacity, 100)\n\n        // Verify the actual byte values are correct\n        let readBytes = buffer.readBytes(length: 40)!\n        for (index, byte) in readBytes.enumerated() {\n            XCTAssertEqual(byte, UInt8((10 + index) % 256), \"Byte at offset \\(index) should be \\((10 + index) % 256)\")\n        }\n    }\n\n    func testWithVeryUnsafeMutableBytesWithStorageManagement() {\n        var buffer = ByteBufferAllocator().buffer(capacity: 100)\n        buffer.writeString(\"Hello\")\n\n        let result: String? = buffer.withVeryUnsafeMutableBytesWithStorageManagement { pointer, storage in\n            // Verify we can mutate the buffer\n            pointer.baseAddress!.advanced(by: 5).storeBytes(of: UInt8(ascii: \"!\"), as: UInt8.self)\n\n            // Verify storage reference is valid\n            _ = storage.retain()\n            storage.release()\n\n            return String(decoding: UnsafeRawBufferPointer(rebasing: pointer.prefix(6)), as: UTF8.self)\n        }\n\n        XCTAssertEqual(result, \"Hello!\")\n\n        // Verify the buffer was actually mutated\n        var readBuffer = buffer\n        readBuffer.moveReaderIndex(to: 0)\n        readBuffer.moveWriterIndex(to: 6)\n        XCTAssertEqual(readBuffer.readString(length: 6), \"Hello!\")\n    }\n\n    func testCustomAllocatorFreeCalled() {\n        let allocator = self.makeTrackedAllocator()\n\n        do {\n            var buffer = allocator.buffer(capacity: 64)\n            buffer.writeString(\"test\")\n            XCTAssertEqual(testTracker.mallocCalls.count, 1)\n        }\n\n        // Buffer should be deallocated now, free should have been called\n        XCTAssertGreaterThan(testTracker.freeCalls.count, 0)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/ByteBufferLengthPrefixTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nfinal class ByteBufferLengthPrefixTests: XCTestCase {\n    private var buffer = ByteBuffer()\n\n    // MARK: - writeLengthPrefixed Tests\n    func testWriteMessageWithLengthOfZero() throws {\n        let bytesWritten = try buffer.writeLengthPrefixed(as: UInt8.self) { buffer in\n            // write nothing\n            0\n        }\n        XCTAssertEqual(bytesWritten, 1)\n        XCTAssertEqual(buffer.readInteger(as: UInt8.self), 0)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n    func testWriteMessageWithLengthOfOne() throws {\n        let bytesWritten = try buffer.writeLengthPrefixed(as: UInt8.self) { buffer in\n            buffer.writeString(\"A\")\n        }\n        XCTAssertEqual(bytesWritten, 2)\n        XCTAssertEqual(buffer.readInteger(as: UInt8.self), 1)\n        XCTAssertEqual(buffer.readString(length: 1), \"A\")\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n    func testWriteMessageWithMultipleWrites() throws {\n        let bytesWritten = try buffer.writeLengthPrefixed(as: UInt8.self) { buffer in\n            buffer.writeString(\"Hello\") + buffer.writeString(\" \") + buffer.writeString(\"World\")\n        }\n        XCTAssertEqual(bytesWritten, 12)\n        XCTAssertEqual(buffer.readInteger(as: UInt8.self), 11)\n        XCTAssertEqual(buffer.readString(length: 11), \"Hello World\")\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n    func testWriteMessageWithMaxLength() throws {\n        let messageWithMaxLength = String(repeating: \"A\", count: 255)\n        let bytesWritten = try buffer.writeLengthPrefixed(as: UInt8.self) { buffer in\n            buffer.writeString(messageWithMaxLength)\n        }\n        XCTAssertEqual(bytesWritten, 256)\n        XCTAssertEqual(buffer.readInteger(as: UInt8.self), 255)\n        XCTAssertEqual(buffer.readString(length: 255), messageWithMaxLength)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n    func testWriteTooLongMessage() throws {\n        let messageWithMaxLength = String(repeating: \"A\", count: 256)\n        XCTAssertThrowsError(\n            try buffer.writeLengthPrefixed(as: UInt8.self) { buffer in\n                buffer.writeString(messageWithMaxLength)\n            }\n        )\n    }\n    func testWriteMessageWithBigEndianInteger() throws {\n        let message = String(repeating: \"A\", count: 256)\n        let bytesWritten = try buffer.writeLengthPrefixed(endianness: .big, as: UInt16.self) { buffer in\n            buffer.writeString(message)\n        }\n        XCTAssertEqual(bytesWritten, 258)\n        XCTAssertEqual(buffer.readInteger(endianness: .big, as: UInt16.self), 256)\n        XCTAssertEqual(buffer.readString(length: 256), message)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n    func testWriteMessageWithLittleEndianInteger() throws {\n        let message = String(repeating: \"A\", count: 256)\n        let bytesWritten = try buffer.writeLengthPrefixed(endianness: .little, as: UInt16.self) { buffer in\n            buffer.writeString(message)\n        }\n        XCTAssertEqual(bytesWritten, 258)\n        XCTAssertEqual(buffer.readInteger(endianness: .little, as: UInt16.self), 256)\n        XCTAssertEqual(buffer.readString(length: 256), message)\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    // MARK: - readLengthPrefixed Tests\n    func testReadMessageWithLengthOfZero() {\n        buffer.writeInteger(UInt8(0))\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: UInt8.self) { buffer in\n                buffer\n            },\n            ByteBuffer()\n        )\n    }\n    func testReadMessageWithLengthOfOne() {\n        buffer.writeInteger(UInt8(1))\n        buffer.writeString(\"A\")\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: UInt8.self) { buffer in\n                var buffer = buffer\n                return buffer.readString(length: buffer.readableBytes)\n            },\n            \"A\"\n        )\n    }\n    func testReadMessageWithLengthOfTen() {\n        buffer.writeInteger(UInt8(11))\n        buffer.writeString(\"Hello World\")\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: UInt8.self) { buffer in\n                var buffer = buffer\n                return buffer.readString(length: buffer.readableBytes)\n            },\n            \"Hello World\"\n        )\n    }\n    func testReadMessageWithMaxLength() {\n        buffer.writeInteger(UInt8(255))\n        buffer.writeString(String(repeating: \"A\", count: 255))\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: UInt8.self) { buffer in\n                var buffer = buffer\n                return buffer.readString(length: buffer.readableBytes)\n            },\n            String(repeating: \"A\", count: 255)\n        )\n    }\n    func testReadOneByteTooMuch() {\n        buffer.writeInteger(UInt8(1))\n        buffer.writeString(\"AB\")\n        XCTAssertThrowsError(\n            try buffer.readLengthPrefixed(as: UInt8.self) { buffer -> String? in\n                var buffer = buffer\n                XCTAssertEqual(buffer.readString(length: buffer.readableBytes), \"A\")\n                return buffer.readString(length: 1)\n            }\n        )\n    }\n    func testReadOneByteTooFew() {\n        buffer.writeInteger(UInt8(2))\n        buffer.writeString(\"AB\")\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: UInt8.self) { buffer -> String? in\n                var buffer = buffer\n                return buffer.readString(length: buffer.readableBytes - 1)\n            },\n            \"A\"\n        )\n    }\n    func testReadMessageWithBigEndianInteger() {\n        buffer.writeInteger(UInt16(256), endianness: .big)\n        buffer.writeString(String(repeating: \"A\", count: 256))\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(endianness: .big, as: UInt16.self) { buffer in\n                var buffer = buffer\n                return buffer.readString(length: buffer.readableBytes)\n            },\n            String(repeating: \"A\", count: 256)\n        )\n    }\n    func testReadMessageWithLittleEndianInteger() {\n        buffer.writeInteger(UInt16(256), endianness: .little)\n        buffer.writeString(String(repeating: \"A\", count: 256))\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(endianness: .little, as: UInt16.self) { buffer in\n                var buffer = buffer\n                return buffer.readString(length: buffer.readableBytes)\n            },\n            String(repeating: \"A\", count: 256)\n        )\n    }\n    func testReadMessageWithMaliciousLength() {\n        buffer.writeInteger(UInt64(Int.max) + 1)\n        buffer.writeString(\"A\")\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: UInt64.self) { buffer -> ByteBuffer in\n                XCTFail(\"should never be called\")\n                return buffer\n            },\n            nil\n        )\n    }\n    func testReadMessageWithNegativeLength() {\n        buffer.writeInteger(Int8(-1))\n        buffer.writeString(\"A\")\n        XCTAssertEqual(\n            try buffer.readLengthPrefixed(as: Int8.self) { buffer -> ByteBuffer in\n                XCTFail(\"should never be called\")\n                return buffer\n            },\n            nil\n        )\n    }\n\n    // MARK: - readLengthPrefixedSlice\n    func testReadSliceWithBigEndianInteger() {\n        buffer.writeInteger(UInt16(256), endianness: .big)\n        buffer.writeString(String(repeating: \"A\", count: 256))\n        XCTAssertEqual(\n            buffer.readLengthPrefixedSlice(endianness: .big, as: UInt16.self),\n            ByteBuffer(string: String(repeating: \"A\", count: 256))\n        )\n        XCTAssertTrue(buffer.readableBytes == 0)\n    }\n    func testReadSliceWithLittleEndianInteger() {\n        buffer.writeInteger(UInt16(256), endianness: .little)\n        buffer.writeString(String(repeating: \"A\", count: 256))\n        XCTAssertEqual(\n            buffer.readLengthPrefixedSlice(endianness: .little, as: UInt16.self),\n            ByteBuffer(string: String(repeating: \"A\", count: 256))\n        )\n        XCTAssertTrue(buffer.readableBytes == 0)\n    }\n\n    // MARK: - getLengthPrefixedSlice\n    func testGetSliceWithBigEndianInteger() {\n        buffer.writeString(\"some data before the length prefix\")\n        buffer.writeInteger(UInt16(256), endianness: .big)\n        buffer.writeString(String(repeating: \"A\", count: 256))\n        XCTAssertEqual(\n            buffer.getLengthPrefixedSlice(at: 34, endianness: .big, as: UInt16.self),\n            ByteBuffer(string: String(repeating: \"A\", count: 256))\n        )\n        XCTAssertTrue(buffer.readerIndex == 0)\n    }\n    func testGetSliceWithLittleEndianInteger() {\n        buffer.writeString(\"some data before the length prefix\")\n        buffer.writeInteger(UInt16(256), endianness: .little)\n        buffer.writeString(String(repeating: \"A\", count: 256))\n        XCTAssertEqual(\n            buffer.getLengthPrefixedSlice(at: 34, endianness: .little, as: UInt16.self),\n            ByteBuffer(string: String(repeating: \"A\", count: 256))\n        )\n        XCTAssertTrue(buffer.readerIndex == 0)\n    }\n\n    // MARK: - peekLengthPrefixedSlice Tests\n\n    func testPeekLengthPrefixedSlice_Normal() {\n        var buffer = ByteBuffer()\n        let message: [UInt8] = [0xDE, 0xAD, 0xBE, 0xEF]\n        // Write a length prefix (UInt8).\n        buffer.writeInteger(UInt8(message.count))\n        buffer.writeBytes(message)\n\n        // Peeks the length prefix, reads that many bytes into a slice.\n        guard let slice = buffer.peekLengthPrefixedSlice(as: UInt8.self) else {\n            XCTFail(\"Expected a valid length-prefixed slice.\")\n            return\n        }\n        XCTAssertEqual(slice.readableBytes, message.count)\n        XCTAssertEqual(slice.getBytes(at: 0, length: message.count), message)\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekLengthPrefixedSlice() should not advance reader index.\")\n    }\n\n    func testPeekLengthPrefixedSlice_InvalidPrefix() {\n        var buffer = ByteBuffer()\n        buffer.writeInteger(UInt8(10))\n        buffer.writeBytes([1, 2, 3])\n\n        let slice = buffer.peekLengthPrefixedSlice(as: UInt8.self)\n        XCTAssertNil(slice, \"Should return nil if actual data is less than the length prefix.\")\n    }\n\n    func testPeekLengthPrefixedSlice_Repeated() {\n        var buffer = ByteBuffer()\n        let message: [UInt8] = [0x01, 0x02, 0x03]\n        buffer.writeInteger(UInt8(message.count))\n        buffer.writeBytes(message)\n\n        let firstPeek = buffer.peekLengthPrefixedSlice(as: UInt8.self)\n        let secondPeek = buffer.peekLengthPrefixedSlice(as: UInt8.self)\n        XCTAssertNotNil(firstPeek)\n        XCTAssertNotNil(secondPeek, \"Repeated calls should yield the same slice.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index remains unchanged after repeated peeks.\")\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/ByteBufferQUICBinaryEncodingStrategyTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\nfinal class ByteBufferQUICBinaryEncodingStrategyTests: XCTestCase {\n    // MARK: - writeEncodedInteger tests\n\n    func testWriteOneByteQUICVariableLengthInteger() {\n        // One byte, ie less than 63, just write out as-is\n        for number in 0..<63 {\n            var buffer = ByteBuffer()\n            let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n            let bytesWritten = strategy.writeInteger(number, to: &buffer)\n            XCTAssertEqual(bytesWritten, 1)\n            // The number is written exactly as is\n            XCTAssertEqual(buffer.readInteger(as: UInt8.self), UInt8(number))\n            XCTAssertEqual(buffer.readableBytes, 0)\n        }\n    }\n\n    func testWriteBigUInt8() {\n        // This test case specifically tests the scenario where 2 bytes are needed, but the number being written is UInt8.\n        // A naive implementation of the quic variable length integer encoder might check whether the number is in\n        // the range of 64..<16383, to determine that it should be written with 2 bytes.\n        // However, constructing such a range on a UInt8 would actually construct 64..<0, because 16383 can't be represented as UInt8.\n        // So this test makes sure we didn't make that mistake\n        let number: UInt8 = .max\n        var buffer = ByteBuffer()\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        let bytesWritten = strategy.writeInteger(number, to: &buffer)\n        XCTAssertEqual(bytesWritten, 2)\n        XCTAssertEqual(buffer.readInteger(as: UInt16.self), 0b01000000_11111111)\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testWriteTwoByteQUICVariableLengthInteger() {\n        var buffer = ByteBuffer()\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        let bytesWritten = strategy.writeInteger(0b00111011_10111101, to: &buffer)\n        XCTAssertEqual(bytesWritten, 2)\n        // We need to mask the first 2 bits with 01 to indicate this is a 2 byte integer\n        // Final result 0b01111011_10111101\n        XCTAssertEqual(buffer.readInteger(as: UInt16.self), 0b01111011_10111101)\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testWriteFourByteQUICVariableLengthInteger() {\n        var buffer = ByteBuffer()\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        let bytesWritten = strategy.writeInteger(0b00011101_01111111_00111110_01111101 as Int64, to: &buffer)\n        XCTAssertEqual(bytesWritten, 4)\n        // 2 bit mask is 10 for 4 bytes so this becomes 0b10011101_01111111_00111110_01111101\n        XCTAssertEqual(buffer.readInteger(as: UInt32.self), 0b10011101_01111111_00111110_01111101)\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testWriteEightByteQUICVariableLengthInteger() {\n        var buffer = ByteBuffer()\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        let bytesWritten = strategy.writeInteger(\n            0b00000010_00011001_01111100_01011110_11111111_00010100_11101000_10001100 as Int64,\n            to: &buffer\n        )\n        XCTAssertEqual(bytesWritten, 8)\n        // 2 bit mask is 11 for 8 bytes so this becomes 0b11000010_00011001_01111100_01011110_11111111_00010100_11101000_10001100\n        XCTAssertEqual(\n            buffer.readInteger(as: UInt64.self),\n            0b11000010_00011001_01111100_01011110_11111111_00010100_11101000_10001100\n        )\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    // MARK: - writeEncodedIntegerWithReservedCapacity tests\n\n    func testWriteOneByteQUICVariableLengthIntegerWithTwoBytesReserved() {\n        // We only need one byte but the encoder will use 2 because we reserved 2\n        var buffer = ByteBuffer()\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        let bytesWritten = strategy.writeInteger(0b00000001, reservedCapacity: 2, to: &buffer)\n        XCTAssertEqual(bytesWritten, 2)\n        XCTAssertEqual(buffer.readInteger(as: UInt16.self), UInt16(0b01000000_00000001))\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testRoundtripWithReservedCapacity() {\n        // This test makes sure that a number encoded with more space than necessary can still be decoded as normal\n        for reservedCapacity in [0, 1, 2, 4, 8] {\n            let testNumbers: [Int64] = [0, 63, 15293, 494_878_333, 151_288_809_941_952_652]\n            for testNumber in testNumbers {\n                var buffer = ByteBuffer()\n                let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n                let bytesWritten = strategy.writeInteger(\n                    testNumber,\n                    reservedCapacity: reservedCapacity,\n                    to: &buffer\n                )\n                let minRequiredBytes = ByteBuffer.QUICBinaryEncodingStrategy.bytesNeededForInteger(testNumber)\n                // If the reserved capacity is higher than the min required, use the reserved number\n                let expectedUsedBytes = max(minRequiredBytes, reservedCapacity)\n                XCTAssertEqual(bytesWritten, expectedUsedBytes)\n                XCTAssertEqual(strategy.readInteger(as: UInt64.self, from: &buffer), UInt64(testNumber))\n                XCTAssertEqual(buffer.readableBytes, 0)\n            }\n        }\n    }\n\n    // MARK: - readEncodedInteger tests\n\n    func testReadEmptyQUICVariableLengthInteger() {\n        var buffer = ByteBuffer()\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        XCTAssertNil(strategy.readInteger(as: Int.self, from: &buffer))\n    }\n\n    func testWriteReadQUICVariableLengthInteger() {\n        let strategy = ByteBuffer.QUICBinaryEncodingStrategy.quic\n        let testNumbers: [Int64] = [37, 15293, 494_878_333, 151_288_809_941_952_652]\n        for integer in testNumbers {\n            var buffer = ByteBuffer()\n            _ = strategy.writeInteger(integer, to: &buffer)\n            XCTAssertEqual(strategy.readInteger(as: Int64.self, from: &buffer), integer)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/ByteBufferSpanTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport Testing\n\n#if compiler(>=6.2)\n@Suite\nstruct ByteBufferSpanTests {\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesSpanOfEmptyByteBuffer() {\n        let bb = ByteBuffer()\n        #expect(bb.readableBytesSpan.byteCount == 0)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesSpanOfSimpleBuffer() {\n        let bb = ByteBuffer(string: \"Hello, world!\")\n        #expect(bb.readableBytesSpan.byteCount == 13)\n        let bytesEqual = bb.readableBytesSpan.elementsEqual(\"Hello, world!\".utf8)\n        #expect(bytesEqual)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesSpanNotAtTheStart() {\n        var bb = ByteBuffer(string: \"Hello, world!\")\n        bb.moveReaderIndex(forwardBy: 5)\n        #expect(bb.readableBytesSpan.byteCount == 8)\n        let bytesEqual = bb.readableBytesSpan.elementsEqual(\", world!\".utf8)\n        #expect(bytesEqual)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesSpanOfSlice() {\n        let first = ByteBuffer(string: \"Hello, world!\")\n        let bb = first.getSlice(at: 5, length: 5)!\n        #expect(bb.readableBytesSpan.byteCount == 5)\n        let bytesEqual = bb.readableBytesSpan.elementsEqual(\", wor\".utf8)\n        #expect(bytesEqual)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testMutableReadableBytesSpanOfEmptyByteBuffer() {\n        var bb = ByteBuffer()\n        #expect(bb.mutableReadableBytesSpan.byteCount == 0)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testMutableReadableBytesSpanOfSimpleBuffer() {\n        var bb = ByteBuffer(string: \"Hello, world!\")\n        #expect(bb.mutableReadableBytesSpan.byteCount == 13)\n        let bytesEqual = bb.mutableReadableBytesSpan.elementsEqual(\"Hello, world!\".utf8)\n        #expect(bytesEqual)\n\n        var readableBytes = bb.mutableReadableBytesSpan\n        readableBytes.storeBytes(of: UInt8(ascii: \"o\"), toByteOffset: 5, as: UInt8.self)\n\n        #expect(String(buffer: bb) == \"Helloo world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testMutableReadableBytesSpanNotAtTheStart() {\n        var bb = ByteBuffer(string: \"Hello, world!\")\n        bb.moveReaderIndex(forwardBy: 5)\n        #expect(bb.mutableReadableBytesSpan.byteCount == 8)\n        let bytesEqual = bb.mutableReadableBytesSpan.elementsEqual(\", world!\".utf8)\n        #expect(bytesEqual)\n\n        var readableBytes = bb.mutableReadableBytesSpan\n        readableBytes.storeBytes(of: UInt8(ascii: \"o\"), toByteOffset: 5, as: UInt8.self)\n\n        #expect(String(buffer: bb) == \", worod!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testMutableReadableBytesSpanOfSlice() {\n        let first = ByteBuffer(string: \"Hello, world!\")\n        var bb = first.getSlice(at: 5, length: 5)!\n        #expect(bb.mutableReadableBytesSpan.byteCount == 5)\n        let bytesEqual = bb.mutableReadableBytesSpan.elementsEqual(\", wor\".utf8)\n        #expect(bytesEqual)\n\n        var readableBytes = bb.mutableReadableBytesSpan\n        readableBytes.storeBytes(of: UInt8(ascii: \"o\"), toByteOffset: 4, as: UInt8.self)\n\n        #expect(String(buffer: bb) == \", woo\")\n        #expect(String(buffer: first) == \"Hello, world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testEvenCreatingMutableSpanTriggersCoW() {\n        let first = ByteBuffer(string: \"Hello, world!\")\n        var second = first\n\n        let firstBackingPtr = first.withVeryUnsafeBytes { $0 }.baseAddress\n        let secondBackingPtr = second.withVeryUnsafeBytes { $0 }.baseAddress\n        #expect(firstBackingPtr == secondBackingPtr)\n\n        let readableBytes = second.mutableReadableBytesSpan\n        _ = consume readableBytes\n        let firstNewBackingPtr = first.withVeryUnsafeBytes { $0 }.baseAddress\n        let secondNewBackingPtr = second.withVeryUnsafeBytes { $0 }.baseAddress\n        #expect(firstNewBackingPtr != secondNewBackingPtr)\n        #expect(firstBackingPtr == firstNewBackingPtr)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testAppendingToEmptyBufferViaOutputSpan() {\n        var bb = ByteBuffer()\n        bb.writeWithOutputRawSpan(minimumWritableBytes: 15) { span in\n            #expect(span.byteCount == 0)\n            #expect(span.capacity >= 15)\n            #expect(span.freeCapacity >= 15)\n            var bytesEqual = span.initializedElementsEqual([])\n            #expect(bytesEqual)\n\n            span.append(contentsOf: \"Hello, world!\".utf8)\n\n            #expect(span.byteCount == 13)\n            #expect(span.capacity >= 2)\n            #expect(span.freeCapacity >= 2)\n\n            bytesEqual = span.initializedElementsEqual(\"Hello, world!\".utf8)\n            #expect(bytesEqual)\n        }\n        #expect(bb.readableBytes == 13)\n        #expect(String(buffer: bb) == \"Hello, world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testAppendingToNonEmptyBufferViaOutputSpanDoesNotExposeInitialBytes() {\n        var bb = ByteBuffer()\n        bb.writeString(\"Hello\")\n        bb.writeWithOutputRawSpan(minimumWritableBytes: 8) { span in\n            #expect(span.byteCount == 0)\n            #expect(span.capacity >= 8)\n            #expect(span.freeCapacity >= 8)\n            var bytesEqual = span.initializedElementsEqual([])\n            #expect(bytesEqual)\n\n            span.append(contentsOf: \", world!\".utf8)\n\n            #expect(span.byteCount == 8)\n            #expect(span.capacity >= 0)\n            #expect(span.freeCapacity >= 0)\n            bytesEqual = span.initializedElementsEqual(\", world!\".utf8)\n            #expect(bytesEqual)\n        }\n        #expect(bb.readableBytes == 13)\n        #expect(String(buffer: bb) == \"Hello, world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testAppendingToASliceViaOutputSpan() {\n        let first = ByteBuffer(string: \"Hello, world!\")\n        var bb = first.getSlice(at: 5, length: 5)!\n        #expect(bb.mutableReadableBytesSpan.byteCount == 5)\n        let bytesEqual = bb.mutableReadableBytesSpan.elementsEqual(\", wor\".utf8)\n        #expect(bytesEqual)\n\n        bb.writeWithOutputRawSpan(minimumWritableBytes: 5) { span in\n            span.append(contentsOf: \"olleh\".utf8)\n        }\n\n        #expect(String(buffer: bb) == \", worolleh\")\n        #expect(String(buffer: first) == \"Hello, world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testEvenCreatingAnOutputSpanTriggersCoW() {\n        let first = ByteBuffer(string: \"Hello, world!\")\n        var second = first\n\n        let firstBackingPtr = first.withVeryUnsafeBytes { $0 }.baseAddress\n        let secondBackingPtr = second.withVeryUnsafeBytes { $0 }.baseAddress\n        #expect(firstBackingPtr == secondBackingPtr)\n\n        second.writeWithOutputRawSpan(minimumWritableBytes: 5) { _ in }\n        let firstNewBackingPtr = first.withVeryUnsafeBytes { $0 }.baseAddress\n        let secondNewBackingPtr = second.withVeryUnsafeBytes { $0 }.baseAddress\n        #expect(firstNewBackingPtr != secondNewBackingPtr)\n        #expect(firstBackingPtr == firstNewBackingPtr)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testCanCreateEmptyBufferDirectly() {\n        let bb = ByteBuffer(initialCapacity: 15) { span in\n            #expect(span.byteCount == 0)\n            #expect(span.capacity >= 15)\n            #expect(span.freeCapacity >= 15)\n            var bytesEqual = span.initializedElementsEqual([])\n            #expect(bytesEqual)\n\n            span.append(contentsOf: \"Hello, world!\".utf8)\n\n            #expect(span.byteCount == 13)\n            #expect(span.capacity >= 2)\n            #expect(span.freeCapacity >= 2)\n            bytesEqual = span.initializedElementsEqual(\"Hello, world!\".utf8)\n            #expect(bytesEqual)\n        }\n        #expect(bb.readableBytes == 13)\n        #expect(String(buffer: bb) == \"Hello, world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testCanCreateEmptyBufferDirectlyFromAllocator() {\n        let bb = ByteBufferAllocator().buffer(capacity: 15) { span in\n            #expect(span.byteCount == 0)\n            #expect(span.capacity >= 15)\n            #expect(span.freeCapacity >= 15)\n            var bytesEqual = span.initializedElementsEqual([])\n            #expect(bytesEqual)\n\n            span.append(contentsOf: \"Hello, world!\".utf8)\n\n            #expect(span.byteCount == 13)\n            #expect(span.capacity >= 2)\n            #expect(span.freeCapacity >= 2)\n            bytesEqual = span.initializedElementsEqual(\"Hello, world!\".utf8)\n            #expect(bytesEqual)\n        }\n        #expect(bb.readableBytes == 13)\n        #expect(String(buffer: bb) == \"Hello, world!\")\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesUInt8SpanOfEmptyByteBuffer() {\n        let bb = ByteBuffer()\n        #expect(bb.readableBytesUInt8Span.count == 0)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesUInt8SpanOfSimpleBuffer() {\n        let bb = ByteBuffer(string: \"Hello, world!\")\n        #expect(bb.readableBytesUInt8Span.count == 13)\n        let bytesEqual = bb.readableBytesUInt8Span.elementsEqual(\"Hello, world!\".utf8)\n        #expect(bytesEqual)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesUInt8SpanNotAtTheStart() {\n        var bb = ByteBuffer(string: \"Hello, world!\")\n        bb.moveReaderIndex(forwardBy: 5)\n        #expect(bb.readableBytesUInt8Span.count == 8)\n        let bytesEqual = bb.readableBytesUInt8Span.elementsEqual(\", world!\".utf8)\n        #expect(bytesEqual)\n    }\n\n    @Test\n    @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\n    func testReadableBytesUInt8SpanOfSlice() {\n        let first = ByteBuffer(string: \"Hello, world!\")\n        let bb = first.getSlice(at: 5, length: 5)!\n        #expect(bb.readableBytesUInt8Span.count == 5)\n        let bytesEqual = bb.readableBytesUInt8Span.elementsEqual(\", wor\".utf8)\n        #expect(bytesEqual)\n    }\n}\n\n@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\nextension RawSpan {\n    func elementsEqual<Other: Collection>(_ other: Other) -> Bool where Other.Element == UInt8 {\n        guard other.count == self.byteCount else { return false }\n\n        var index = other.startIndex\n        var offset = 0\n        while index < other.endIndex {\n            guard other[index] == self.unsafeLoadUnaligned(fromByteOffset: offset, as: UInt8.self) else {\n                return false\n            }\n            other.formIndex(after: &index)\n            offset &+= 1\n        }\n\n        return true\n    }\n}\n\n@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\nextension Span<UInt8> {\n    func elementsEqual<Other: Collection>(_ other: Other) -> Bool where Other.Element == UInt8 {\n        guard other.count == self.count else { return false }\n        guard var offset = self.indices.first else { return true }\n\n        var index = other.startIndex\n        while index < other.endIndex {\n            guard other[index] == self[offset] else {\n                return false\n            }\n            other.formIndex(after: &index)\n            offset &+= 1\n        }\n\n        return true\n    }\n}\n\n@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\nextension MutableRawSpan {\n    func elementsEqual<Other: Collection>(_ other: Other) -> Bool where Other.Element == UInt8 {\n        self.bytes.elementsEqual(other)\n    }\n}\n\n@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0, *)\nextension OutputRawSpan {\n    func initializedElementsEqual<Other: Collection>(_ other: Other) -> Bool where Other.Element == UInt8 {\n        self.bytes.elementsEqual(other)\n    }\n\n    @_lifetime(self: copy self)\n    mutating func append<Other: Collection>(contentsOf other: Other) where Other.Element == UInt8 {\n        for element in other {\n            self.append(element)\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Tests/NIOCoreTests/ByteBufferTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\n@_spi(CustomByteBufferAllocator) @testable import NIOCore\nimport NIOFoundationCompat\nimport XCTest\nimport _NIOBase64\n\nimport struct Foundation.Data\n\nclass ByteBufferTest: XCTestCase {\n    private let allocator = ByteBufferAllocator()\n    private var buf: ByteBuffer! = nil\n\n    private func setGetInt<T: FixedWidthInteger>(index: Int, v: T) throws {\n        var buffer = allocator.buffer(capacity: 32)\n\n        XCTAssertEqual(MemoryLayout<T>.size, buffer.setInteger(v, at: index))\n        buffer.moveWriterIndex(to: index + MemoryLayout<T>.size)\n        buffer.moveReaderIndex(to: index)\n        XCTAssertEqual(v, buffer.getInteger(at: index))\n    }\n\n    private func writeReadInt<T: FixedWidthInteger>(v: T) throws {\n        var buffer = allocator.buffer(capacity: 32)\n        XCTAssertEqual(0, buffer.writerIndex)\n        XCTAssertEqual(MemoryLayout<T>.size, buffer.writeInteger(v))\n        XCTAssertEqual(MemoryLayout<T>.size, buffer.writerIndex)\n\n        XCTAssertEqual(v, buffer.readInteger())\n        XCTAssertEqual(0, buffer.readableBytes)\n    }\n\n    override func setUp() {\n        super.setUp()\n\n        self.buf = allocator.buffer(capacity: 1024)\n        self.buf.writeBytes(Array(repeating: UInt8(0xff), count: 1024))\n        self.buf = self.buf.getSlice(at: 256, length: 512)\n        self.buf.clear()\n    }\n\n    override func tearDown() {\n        self.buf = nil\n\n        super.tearDown()\n    }\n\n    func testAllocateAndCount() {\n        let b = allocator.buffer(capacity: 1024)\n        XCTAssertEqual(1024, b.capacity)\n    }\n\n    func testEqualsComparesReadBuffersOnly() throws {\n        // Only cares about the read buffer\n        self.buf.writeInteger(Int8.max)\n        self.buf.writeString(\"oh hi\")\n        let actual: Int8 = buf.readInteger()!  // Just getting rid of it from the read buffer\n        XCTAssertEqual(Int8.max, actual)\n\n        var otherBuffer = allocator.buffer(capacity: 32)\n        otherBuffer.writeString(\"oh hi\")\n        XCTAssertEqual(otherBuffer, buf)\n    }\n\n    func testHasherUsesReadBuffersOnly() {\n        // Only cares about the read buffer\n        self.buf.clear()\n        self.buf.writeString(\"oh hi\")\n\n        var hasher = Hasher()\n        // We need to force unwrap the implicitly unwrapped optional here in order to\n        // mark it as unwrapped for the compiler *before* the function call. Otherwise\n        // the implementation of the optional's conditional conformance is triggered,\n        // that will change the hash. For more information please see:\n        // https://github.com/apple/swift-nio/pull/1326\n        // https://bugs.swift.org/browse/SR-11975\n        hasher.combine(self.buf!)\n        let hash = hasher.finalize()\n\n        var otherBuffer = allocator.buffer(capacity: 6)\n        otherBuffer.writeString(\"oh hi\")\n\n        var otherHasher = Hasher()\n        otherHasher.combine(otherBuffer)\n        let otherHash = otherHasher.finalize()\n\n        XCTAssertEqual(hash, otherHash)\n    }\n\n    func testSimpleReadTest() throws {\n        buf.withUnsafeReadableBytes { ptr in\n            XCTAssertEqual(ptr.count, 0)\n        }\n\n        buf.writeString(\"Hello world!\")\n        buf.withUnsafeReadableBytes { ptr in\n            XCTAssertEqual(12, ptr.count)\n        }\n    }\n\n    func testSimpleWrites() {\n        var written = buf.writeString(\"\")\n        XCTAssertEqual(0, written)\n        XCTAssertEqual(0, buf.readableBytes)\n\n        written = buf.writeString(\"X\")\n        XCTAssertEqual(1, written)\n        XCTAssertEqual(1, buf.readableBytes)\n\n        written = buf.writeString(\"XXXXX\")\n        XCTAssertEqual(5, written)\n        XCTAssertEqual(6, buf.readableBytes)\n    }\n\n    func makeSliceToBufferWhichIsDeallocated() -> ByteBuffer {\n        var buf = self.allocator.buffer(capacity: 16)\n        let oldCapacity = buf.capacity\n        buf.writeBytes(0..<16)\n        XCTAssertEqual(oldCapacity, buf.capacity)\n        return buf.getSlice(at: 15, length: 1)!\n    }\n\n    func testMakeSureUniquelyOwnedSliceDoesNotGetReallocatedOnWrite() {\n        var slice = self.makeSliceToBufferWhichIsDeallocated()\n        XCTAssertEqual(1, slice.capacity)\n        XCTAssertEqual(16, slice.storageCapacity)\n        let oldStorageBegin = slice.withUnsafeReadableBytes { ptr in\n            UInt(bitPattern: ptr.baseAddress!)\n        }\n        slice.setInteger(1, at: 0, as: UInt8.self)\n        let newStorageBegin = slice.withUnsafeReadableBytes { ptr in\n            UInt(bitPattern: ptr.baseAddress!)\n        }\n        XCTAssertEqual(oldStorageBegin, newStorageBegin)\n    }\n\n    func testWriteToUniquelyOwnedSliceWhichTriggersAReallocation() {\n        var slice = self.makeSliceToBufferWhichIsDeallocated()\n        XCTAssertEqual(1, slice.capacity)\n        XCTAssertEqual(16, slice.storageCapacity)\n        // this will cause a re-allocation, the whole buffer should be 32 bytes then, the slice having 17 of that.\n        // this fills 16 bytes so will still fit\n        slice.writeBytes(Array(16..<32))\n        XCTAssertEqual(Array(15..<32), slice.readBytes(length: slice.readableBytes)!)\n\n        // and this will need another re-allocation\n        slice.writeBytes(Array(32..<47))\n    }\n\n    func testReadWrite() {\n        buf.writeString(\"X\")\n        buf.writeString(\"Y\")\n        let d = buf.readData(length: 1)\n        XCTAssertNotNil(d)\n        if let d = d {\n            XCTAssertEqual(1, d.count)\n            XCTAssertEqual(\"X\".utf8.first!, d.first!)\n        }\n    }\n\n    func testStaticStringReadTests() throws {\n        var allBytes = 0\n        for testString in [\"\", \"Hello world!\", \"👍\", \"🇬🇧🇺🇸🇪🇺\"] as [StaticString] {\n            buf.withUnsafeReadableBytes { ptr in\n                XCTAssertEqual(0, ptr.count)\n            }\n            XCTAssertEqual(0, buf.readableBytes)\n            XCTAssertEqual(allBytes, buf.readerIndex)\n\n            let bytes = buf.writeStaticString(testString)\n            XCTAssertEqual(testString.utf8CodeUnitCount, Int(bytes))\n            allBytes += bytes\n            XCTAssertEqual(allBytes - bytes, buf.readerIndex)\n\n            let expected = testString.withUTF8Buffer { buf in\n                String(decoding: buf, as: Unicode.UTF8.self)\n            }\n            buf.withUnsafeReadableBytes { ptr in\n                let actual = String(decoding: ptr, as: Unicode.UTF8.self)\n                XCTAssertEqual(expected, actual)\n            }\n            let d = buf.readData(length: testString.utf8CodeUnitCount)\n            XCTAssertEqual(allBytes, buf.readerIndex)\n            XCTAssertNotNil(d)\n            XCTAssertEqual(d?.count, testString.utf8CodeUnitCount)\n            XCTAssertEqual(expected, String(decoding: d!, as: Unicode.UTF8.self))\n        }\n    }\n\n    func testString() {\n        let written = buf.writeString(\"Hello\")\n        let string = buf.getString(at: 0, length: written)\n        XCTAssertEqual(\"Hello\", string)\n    }\n\n    func testNullTerminatedString() {\n        let writtenHello = buf.writeNullTerminatedString(\"Hello\")\n        XCTAssertEqual(writtenHello, 6)\n        XCTAssertEqual(buf.readableBytes, 6)\n\n        let writtenEmpty = buf.writeNullTerminatedString(\"\")\n        XCTAssertEqual(writtenEmpty, 1)\n        XCTAssertEqual(buf.readableBytes, 7)\n\n        let writtenFoo = buf.writeNullTerminatedString(\"foo\")\n        XCTAssertEqual(writtenFoo, 4)\n        XCTAssertEqual(buf.readableBytes, 11)\n\n        XCTAssertEqual(buf.getNullTerminatedString(at: 0), \"Hello\")\n        XCTAssertEqual(buf.getNullTerminatedString(at: 6), \"\")\n        XCTAssertEqual(buf.getNullTerminatedString(at: 7), \"foo\")\n\n        XCTAssertEqual(buf.readNullTerminatedString(), \"Hello\")\n        XCTAssertEqual(buf.readerIndex, 6)\n\n        XCTAssertEqual(buf.readNullTerminatedString(), \"\")\n        XCTAssertEqual(buf.readerIndex, 7)\n\n        XCTAssertEqual(buf.readNullTerminatedString(), \"foo\")\n        XCTAssertEqual(buf.readerIndex, 11)\n    }\n\n    func testReadNullTerminatedStringWithoutNullTermination() {\n        buf.writeString(\"Hello\")\n        XCTAssertNil(buf.readNullTerminatedString())\n    }\n\n    func testGetNullTerminatedStringOutOfRangeTests() {\n        buf.writeNullTerminatedString(\"Hello\")\n        XCTAssertNil(buf.getNullTerminatedString(at: 100))\n        buf.moveReaderIndex(forwardBy: 6)\n        XCTAssertNil(buf.readNullTerminatedString())\n        XCTAssertNil(buf.getNullTerminatedString(at: 0))\n        buf.writeInteger(UInt8(0))\n        XCTAssertEqual(buf.readNullTerminatedString(), \"\")\n    }\n\n    func testWriteSubstring() {\n        var text = \"Hello\"\n        let written = buf.writeSubstring(text[...])\n        var string = buf.getString(at: 0, length: written)\n        XCTAssertEqual(text, string)\n\n        text = \"\"\n        buf.writeSubstring(text[...])\n        string = buf.getString(at: 0, length: written)\n        XCTAssertEqual(\"Hello\", string)\n    }\n\n    func testSetSubstring() {\n        let text = \"Hello\"\n        buf.writeSubstring(text[...])\n\n        var written = buf.setSubstring(text[...], at: 0)\n        var string = buf.getString(at: 0, length: written)\n        XCTAssertEqual(text, string)\n\n        written = buf.setSubstring(text[text.index(after: text.startIndex)...], at: 1)\n        string = buf.getString(at: 0, length: written + 1)\n        XCTAssertEqual(text, string)\n\n        written = buf.setSubstring(text[text.index(after: text.startIndex)...], at: 0)\n        string = buf.getString(at: 0, length: written)\n        XCTAssertEqual(\"ello\", string)\n    }\n\n    func testSliceEasy() {\n        buf.writeString(\"0123456789abcdefg\")\n        for i in 0..<16 {\n            let slice = buf.getSlice(at: i, length: 1)\n            XCTAssertEqual(1, slice?.capacity)\n            XCTAssertEqual(buf.getData(at: i, length: 1), slice?.getData(at: 0, length: 1))\n        }\n    }\n\n    func testWriteStringMovesWriterIndex() throws {\n        var buf = allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n        XCTAssertEqual(5, buf.writerIndex)\n        buf.withUnsafeReadableBytes { (ptr: UnsafeRawBufferPointer) -> Void in\n            let s = String(decoding: ptr, as: Unicode.UTF8.self)\n            XCTAssertEqual(\"hello\", s)\n        }\n    }\n\n    func testSetExpandsBufferOnUpperBoundsCheckFailure() {\n        let initialCapacity = buf.capacity\n        XCTAssertEqual(5, buf.setString(\"oh hi\", at: buf.capacity))\n        XCTAssert(initialCapacity < buf.capacity)\n    }\n\n    func testCoWWorks() {\n        buf.writeString(\"Hello\")\n        var a = buf!\n        let b = buf!\n        a.writeString(\" World\")\n        XCTAssertEqual(buf, b)\n        XCTAssertNotEqual(buf, a)\n    }\n\n    func testWithMutableReadPointerMovesReaderIndexAndReturnsNumBytesConsumed() {\n        XCTAssertEqual(0, buf.readerIndex)\n        // We use mutable read pointers when we're consuming the data\n        // so first we need some data there!\n        buf.writeString(\"hello again\")\n\n        let bytesConsumed = buf.readWithUnsafeReadableBytes { dst in\n            // Pretend we did some operation which made use of entire 11 byte string\n            11\n        }\n        XCTAssertEqual(11, bytesConsumed)\n        XCTAssertEqual(11, buf.readerIndex)\n    }\n\n    func testWithMutableWritePointerMovesWriterIndexAndReturnsNumBytesWritten() {\n        XCTAssertEqual(0, buf.writerIndex)\n\n        let bytesWritten = buf.writeWithUnsafeMutableBytes(minimumWritableBytes: 5) {\n            XCTAssertTrue($0.count >= 5)\n            return 5\n        }\n        XCTAssertEqual(5, bytesWritten)\n        XCTAssertEqual(5, buf.writerIndex)\n    }\n\n    func testWithMutableWritePointerWithMinimumSpecifiedAdjustsCapacity() {\n        XCTAssertEqual(0, buf.writerIndex)\n        XCTAssertEqual(1024, buf.capacity)\n\n        var bytesWritten = buf.writeWithUnsafeMutableBytes(minimumWritableBytes: 256) {\n            XCTAssertTrue($0.count >= 256)\n            return 256\n        }\n        XCTAssertEqual(256, bytesWritten)\n        XCTAssertEqual(256, buf.writerIndex)\n        XCTAssertEqual(1024, buf.capacity)\n\n        bytesWritten += buf.writeWithUnsafeMutableBytes(minimumWritableBytes: 1024) {\n            XCTAssertTrue($0.count >= 1024)\n            return 1024\n        }\n        let expectedBytesWritten = 256 + 1024\n        XCTAssertEqual(expectedBytesWritten, bytesWritten)\n        XCTAssertEqual(expectedBytesWritten, buf.writerIndex)\n        XCTAssertTrue(buf.capacity >= expectedBytesWritten)\n    }\n\n    func testWithMutableWritePointerWithMinimumSpecifiedWhileAtMaxCapacity() {\n        XCTAssertEqual(0, buf.writerIndex)\n        XCTAssertEqual(1024, buf.capacity)\n\n        var bytesWritten = buf.writeWithUnsafeMutableBytes(minimumWritableBytes: 512) {\n            XCTAssertTrue($0.count >= 512)\n            return 512\n        }\n        XCTAssertEqual(512, bytesWritten)\n        XCTAssertEqual(512, buf.writerIndex)\n        XCTAssertEqual(1024, buf.capacity)\n\n        bytesWritten += buf.writeWithUnsafeMutableBytes(minimumWritableBytes: 1) {\n            XCTAssertTrue($0.count >= 1)\n            return 1\n        }\n        let expectedBytesWritten = 512 + 1\n        XCTAssertEqual(expectedBytesWritten, bytesWritten)\n        XCTAssertEqual(expectedBytesWritten, buf.writerIndex)\n        XCTAssertTrue(buf.capacity >= expectedBytesWritten)\n    }\n\n    func testSetGetInt8() throws {\n        try setGetInt(index: 0, v: Int8.max)\n    }\n\n    func testSetGetInt16() throws {\n        try setGetInt(index: 1, v: Int16.max)\n    }\n\n    func testSetGetInt32() throws {\n        try setGetInt(index: 2, v: Int32.max)\n    }\n\n    func testSetGetInt64() throws {\n        try setGetInt(index: 3, v: Int64.max)\n    }\n\n    func testSetGetUInt8() throws {\n        try setGetInt(index: 4, v: UInt8.max)\n    }\n\n    func testSetGetUInt16() throws {\n        try setGetInt(index: 5, v: UInt16.max)\n    }\n\n    func testSetGetUInt32() throws {\n        try setGetInt(index: 6, v: UInt32.max)\n    }\n\n    func testSetGetUInt64() throws {\n        try setGetInt(index: 7, v: UInt64.max)\n    }\n\n    func testWriteReadInt8() throws {\n        try writeReadInt(v: Int8.max)\n    }\n\n    func testWriteReadInt16() throws {\n        try writeReadInt(v: Int16.max)\n    }\n\n    func testWriteReadInt32() throws {\n        try writeReadInt(v: Int32.max)\n    }\n\n    func testWriteReadInt64() throws {\n        try writeReadInt(v: Int32.max)\n    }\n\n    func testWriteReadUInt8() throws {\n        try writeReadInt(v: UInt8.max)\n    }\n\n    func testWriteReadUInt16() throws {\n        try writeReadInt(v: UInt16.max)\n    }\n\n    func testWriteReadUInt32() throws {\n        try writeReadInt(v: UInt32.max)\n    }\n\n    func testWriteReadUInt64() throws {\n        try writeReadInt(v: UInt32.max)\n    }\n\n    func testSlice() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        XCTAssertEqual(MemoryLayout<UInt64>.size, buffer.writeInteger(UInt64.max))\n        var slice = buffer.slice()\n        XCTAssertEqual(MemoryLayout<UInt64>.size, slice.readableBytes)\n        XCTAssertEqual(UInt64.max, slice.readInteger())\n        XCTAssertEqual(MemoryLayout<UInt64>.size, buffer.readableBytes)\n        XCTAssertEqual(UInt64.max, buffer.readInteger())\n    }\n\n    func testSliceWithParams() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        XCTAssertEqual(MemoryLayout<UInt64>.size, buffer.writeInteger(UInt64.max))\n        var slice = buffer.getSlice(at: 0, length: MemoryLayout<UInt64>.size)!\n        XCTAssertEqual(MemoryLayout<UInt64>.size, slice.readableBytes)\n        XCTAssertEqual(UInt64.max, slice.readInteger())\n        XCTAssertEqual(MemoryLayout<UInt64>.size, buffer.readableBytes)\n        XCTAssertEqual(UInt64.max, buffer.readInteger())\n    }\n\n    func testReadSlice() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        XCTAssertEqual(MemoryLayout<UInt64>.size, buffer.writeInteger(UInt64.max))\n        var slice = buffer.readSlice(length: buffer.readableBytes)!\n        XCTAssertEqual(MemoryLayout<UInt64>.size, slice.readableBytes)\n        XCTAssertEqual(UInt64.max, slice.readInteger())\n        XCTAssertEqual(0, buffer.readableBytes)\n        let value: UInt64? = buffer.readInteger()\n        XCTAssertTrue(value == nil)\n    }\n\n    func testSliceNoCopy() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        XCTAssertEqual(MemoryLayout<UInt64>.size, buffer.writeInteger(UInt64.max))\n        let slice = buffer.readSlice(length: buffer.readableBytes)!\n\n        buffer.withVeryUnsafeBytes { ptr1 in\n            slice.withVeryUnsafeBytes { ptr2 in\n                XCTAssertEqual(ptr1.baseAddress, ptr2.baseAddress)\n            }\n        }\n    }\n\n    func testSetGetData() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        let data = Data([1, 2, 3])\n\n        XCTAssertEqual(3, buffer.setBytes(data, at: 0))\n        XCTAssertEqual(0, buffer.readableBytes)\n        buffer.moveReaderIndex(to: 0)\n        buffer.moveWriterIndex(to: 3)\n        XCTAssertEqual(data, buffer.getData(at: 0, length: 3))\n    }\n\n    func testWriteReadData() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        let data = Data([1, 2, 3])\n\n        XCTAssertEqual(3, buffer.writeBytes(data))\n        XCTAssertEqual(3, buffer.readableBytes)\n        XCTAssertEqual(data, buffer.readData(length: 3))\n    }\n\n    func testDiscardReadBytes() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        buffer.writeInteger(1, as: UInt8.self)\n        buffer.writeInteger(UInt8(2))\n        buffer.writeInteger(3 as UInt8)\n        buffer.writeInteger(4, as: UInt8.self)\n        XCTAssertEqual(4, buffer.readableBytes)\n        buffer.moveReaderIndex(forwardBy: 2)\n        XCTAssertEqual(2, buffer.readableBytes)\n        XCTAssertEqual(2, buffer.readerIndex)\n        XCTAssertEqual(4, buffer.writerIndex)\n        XCTAssertTrue(buffer.discardReadBytes())\n        XCTAssertEqual(2, buffer.readableBytes)\n        XCTAssertEqual(0, buffer.readerIndex)\n        XCTAssertEqual(2, buffer.writerIndex)\n        XCTAssertEqual(UInt8(3), buffer.readInteger())\n        XCTAssertEqual(UInt8(4), buffer.readInteger())\n        XCTAssertEqual(0, buffer.readableBytes)\n        XCTAssertTrue(buffer.discardReadBytes())\n        XCTAssertFalse(buffer.discardReadBytes())\n    }\n\n    func testDiscardReadBytesCoW() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        let bytesWritten = buffer.writeBytes(\"0123456789abcdef0123456789ABCDEF\".data(using: .utf8)!)\n        XCTAssertEqual(32, bytesWritten)\n\n        func testAssumptionOriginalBuffer(_ buf: inout ByteBuffer) {\n            XCTAssertEqual(32, buf.capacity)\n            XCTAssertEqual(0, buf.readerIndex)\n            XCTAssertEqual(32, buf.writerIndex)\n            XCTAssertEqual(\"0123456789abcdef0123456789ABCDEF\".data(using: .utf8)!, buf.getData(at: 0, length: 32)!)\n        }\n        testAssumptionOriginalBuffer(&buffer)\n\n        var buffer10Missing = buffer\n        let first10Bytes = buffer10Missing.readData(length: 10)  // make the first 10 bytes disappear\n        let otherBuffer10Missing = buffer10Missing\n        XCTAssertEqual(\"0123456789\".data(using: .utf8)!, first10Bytes)\n        testAssumptionOriginalBuffer(&buffer)\n        XCTAssertEqual(10, buffer10Missing.readerIndex)\n        XCTAssertEqual(32, buffer10Missing.writerIndex)\n\n        let nextBytes1 = buffer10Missing.getData(at: 10, length: 22)\n        XCTAssertEqual(\"abcdef0123456789ABCDEF\".data(using: .utf8)!, nextBytes1)\n\n        buffer10Missing.discardReadBytes()\n        XCTAssertEqual(0, buffer10Missing.readerIndex)\n        XCTAssertEqual(22, buffer10Missing.writerIndex)\n        testAssumptionOriginalBuffer(&buffer)\n\n        XCTAssertEqual(10, otherBuffer10Missing.readerIndex)\n        XCTAssertEqual(32, otherBuffer10Missing.writerIndex)\n\n        let nextBytes2 = buffer10Missing.getData(at: 0, length: 22)\n        XCTAssertEqual(\"abcdef0123456789ABCDEF\".data(using: .utf8)!, nextBytes2)\n\n        let nextBytes3 = otherBuffer10Missing.getData(at: 10, length: 22)\n        XCTAssertEqual(\"abcdef0123456789ABCDEF\".data(using: .utf8)!, nextBytes3)\n        testAssumptionOriginalBuffer(&buffer)\n\n    }\n\n    func testDiscardReadBytesSlice() throws {\n        var buffer = allocator.buffer(capacity: 32)\n        buffer.writeInteger(UInt8(1))\n        buffer.writeInteger(UInt8(2))\n        buffer.writeInteger(UInt8(3))\n        buffer.writeInteger(UInt8(4))\n        XCTAssertEqual(4, buffer.readableBytes)\n        var slice = buffer.getSlice(at: 1, length: 3)!\n        XCTAssertEqual(3, slice.readableBytes)\n        XCTAssertEqual(0, slice.readerIndex)\n\n        slice.moveReaderIndex(forwardBy: 1)\n        XCTAssertEqual(2, slice.readableBytes)\n        XCTAssertEqual(1, slice.readerIndex)\n        XCTAssertEqual(3, slice.writerIndex)\n        XCTAssertTrue(slice.discardReadBytes())\n        XCTAssertEqual(2, slice.readableBytes)\n        XCTAssertEqual(0, slice.readerIndex)\n        XCTAssertEqual(2, slice.writerIndex)\n        XCTAssertEqual(UInt8(3), slice.readInteger())\n        XCTAssertEqual(UInt8(4), slice.readInteger())\n        XCTAssertEqual(0, slice.readableBytes)\n        XCTAssertTrue(slice.discardReadBytes())\n        XCTAssertFalse(slice.discardReadBytes())\n    }\n\n    func testWithDataSlices() throws {\n        let testStringPrefix = \"0123456789\"\n        let testStringSuffix = \"abcdef\"\n        let testString = \"\\(testStringPrefix)\\(testStringSuffix)\"\n\n        var buffer = allocator.buffer(capacity: testString.utf8.count)\n        buffer.writeString(testStringPrefix)\n        buffer.writeString(testStringSuffix)\n        XCTAssertEqual(testString.utf8.count, buffer.capacity)\n\n        func runTestForRemaining(string: String, buffer: ByteBuffer) {\n            buffer.withUnsafeReadableBytes { ptr in\n                XCTAssertEqual(string.utf8.count, ptr.count)\n\n                for (idx, expected) in zip(0..<string.utf8.count, string.utf8) {\n                    let actual = ptr[idx]\n                    XCTAssertEqual(expected, actual, \"character at index \\(idx) is \\(actual) but should be \\(expected)\")\n                }\n            }\n\n            buffer.withUnsafeReadableBytes { data -> Void in\n                XCTAssertEqual(string.utf8.count, data.count)\n                for (idx, expected) in zip(data.startIndex..<data.startIndex + string.utf8.count, string.utf8) {\n                    XCTAssertEqual(expected, data[idx])\n                }\n            }\n\n            buffer.withUnsafeReadableBytes { slice in\n                XCTAssertEqual(string, String(decoding: slice, as: Unicode.UTF8.self))\n            }\n        }\n\n        runTestForRemaining(string: testString, buffer: buffer)\n        let prefixBuffer = buffer.readSlice(length: testStringPrefix.utf8.count)\n        XCTAssertNotNil(prefixBuffer)\n        if let prefixBuffer = prefixBuffer {\n            runTestForRemaining(string: testStringPrefix, buffer: prefixBuffer)\n        }\n        runTestForRemaining(string: testStringSuffix, buffer: buffer)\n    }\n\n    func testEndianness() throws {\n        let value: UInt32 = 0x1234_5678\n        buf.writeInteger(value)\n        let actualRead: UInt32 = buf.readInteger()!\n        XCTAssertEqual(value, actualRead)\n        buf.writeInteger(value, endianness: .big)\n        buf.writeInteger(value, endianness: .little)\n        buf.writeInteger(value)\n        let actual = buf.getData(at: 4, length: 12)!\n        let expected = Data([0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12, 0x12, 0x34, 0x56, 0x78])\n        XCTAssertEqual(expected, actual)\n        let actualA: UInt32 = buf.readInteger(endianness: .big)!\n        let actualB: UInt32 = buf.readInteger(endianness: .little)!\n        let actualC: UInt32 = buf.readInteger()!\n        XCTAssertEqual(value, actualA)\n        XCTAssertEqual(value, actualB)\n        XCTAssertEqual(value, actualC)\n    }\n\n    func testExpansion() throws {\n        var buf = allocator.buffer(capacity: 16)\n        XCTAssertEqual(16, buf.capacity)\n        buf.writeBytes(\"0123456789abcdef\".data(using: .utf8)!)\n        XCTAssertEqual(16, buf.capacity)\n        XCTAssertEqual(16, buf.writerIndex)\n        XCTAssertEqual(0, buf.readerIndex)\n        buf.writeBytes(\"X\".data(using: .utf8)!)\n        XCTAssertGreaterThan(buf.capacity, 16)\n        XCTAssertEqual(17, buf.writerIndex)\n        XCTAssertEqual(0, buf.readerIndex)\n        buf.withUnsafeReadableBytes { ptr in\n            let bPtr = UnsafeBufferPointer(\n                start: ptr.baseAddress!.bindMemory(to: UInt8.self, capacity: ptr.count),\n                count: ptr.count\n            )\n            XCTAssertEqual(\"0123456789abcdefX\".data(using: .utf8)!, Data(buffer: bPtr))\n        }\n    }\n\n    func testExpansion2() throws {\n        var buf = allocator.buffer(capacity: 2)\n        XCTAssertEqual(2, buf.capacity)\n        buf.writeBytes(\"0123456789abcdef\".data(using: .utf8)!)\n        XCTAssertEqual(16, buf.capacity)\n        XCTAssertEqual(16, buf.writerIndex)\n        buf.withUnsafeReadableBytes { ptr in\n            let bPtr = UnsafeBufferPointer(\n                start: ptr.baseAddress!.bindMemory(to: UInt8.self, capacity: ptr.count),\n                count: ptr.count\n            )\n            XCTAssertEqual(\"0123456789abcdef\".data(using: .utf8)!, Data(buffer: bPtr))\n        }\n    }\n\n    func testNotEnoughBytesToReadForIntegers() throws {\n        let byteCount = 15\n        func initBuffer() {\n            let written = buf.writeBytes(Data(Array(repeating: 0, count: byteCount)))\n            XCTAssertEqual(byteCount, written)\n        }\n\n        func tryWith<T: FixedWidthInteger>(_ type: T.Type) {\n            initBuffer()\n\n            let tooMany = (byteCount + 1) / MemoryLayout<T>.size\n            for _ in 1..<tooMany {\n                // read just enough ones that we should be able to read in one go\n                XCTAssertNotNil(buf.getInteger(at: buf.readerIndex) as T?)\n                let actual: T? = buf.readInteger()\n                XCTAssertNotNil(actual)\n                XCTAssertEqual(0, actual)\n            }\n            // now see that trying to read one more fails\n            let actual: T? = buf.readInteger()\n            XCTAssertNil(actual)\n\n            buf.clear()\n        }\n\n        tryWith(UInt16.self)\n        tryWith(UInt32.self)\n        tryWith(UInt64.self)\n    }\n\n    func testNotEnoughBytesToReadForData() throws {\n        let cap = buf.capacity\n        let expected = Data(Array(repeating: 0, count: cap))\n        let written = buf.writeBytes(expected)\n        XCTAssertEqual(cap, written)\n        XCTAssertEqual(cap, buf.capacity)\n\n        XCTAssertNil(buf.readData(length: cap + 1))  // too many\n        XCTAssertEqual(expected, buf.readData(length: cap))  // to make sure it can work\n    }\n\n    func testSlicesThatAreOutOfBands() throws {\n        self.buf.moveReaderIndex(to: 0)\n        self.buf.moveWriterIndex(to: self.buf.capacity)\n        let goodSlice = self.buf.getSlice(at: 0, length: self.buf.capacity)\n        XCTAssertNotNil(goodSlice)\n\n        let badSlice1 = self.buf.getSlice(at: 0, length: self.buf.capacity + 1)\n        XCTAssertNil(badSlice1)\n\n        let badSlice2 = self.buf.getSlice(at: self.buf.capacity - 1, length: 2)\n        XCTAssertNil(badSlice2)\n    }\n\n    func testMutableBytesCoW() throws {\n        let cap = buf.capacity\n        var otherBuf = buf\n        XCTAssertEqual(otherBuf, buf)\n        otherBuf?.writeWithUnsafeMutableBytes(minimumWritableBytes: 0) { ptr in\n            XCTAssertEqual(cap, ptr.count)\n            let intPtr = ptr.baseAddress!.bindMemory(to: UInt8.self, capacity: ptr.count)\n            for i in 0..<ptr.count {\n                intPtr[i] = UInt8(truncatingIfNeeded: i)\n            }\n            return ptr.count\n        }\n        XCTAssertEqual(cap, otherBuf?.capacity)\n        XCTAssertNotEqual(buf, otherBuf)\n        otherBuf?.withUnsafeReadableBytes { ptr in\n            XCTAssertEqual(cap, ptr.count)\n            for i in 0..<cap {\n                XCTAssertEqual(ptr[i], UInt8(truncatingIfNeeded: i))\n            }\n        }\n    }\n\n    func testWritableBytesTriggersCoW() throws {\n        let cap = buf.capacity\n        var otherBuf = buf\n        XCTAssertEqual(otherBuf, buf)\n\n        // Write to both buffers.\n        let firstResult = buf!.withUnsafeMutableWritableBytes { (ptr: UnsafeMutableRawBufferPointer) -> Bool in\n            XCTAssertEqual(cap, ptr.count)\n            memset(ptr.baseAddress!, 0, ptr.count)\n            return false\n        }\n        let secondResult = otherBuf!.withUnsafeMutableWritableBytes { (ptr: UnsafeMutableRawBufferPointer) -> Bool in\n            XCTAssertEqual(cap, ptr.count)\n            let intPtr = ptr.baseAddress!.bindMemory(to: UInt8.self, capacity: ptr.count)\n            for i in 0..<ptr.count {\n                intPtr[i] = UInt8(truncatingIfNeeded: i)\n            }\n            return true\n        }\n        XCTAssertFalse(firstResult)\n        XCTAssertTrue(secondResult)\n        XCTAssertEqual(cap, otherBuf!.capacity)\n        XCTAssertEqual(buf!.readableBytes, 0)\n        XCTAssertEqual(otherBuf!.readableBytes, 0)\n\n        // Move both writer indices forwards by the amount of data we wrote.\n        buf!.moveWriterIndex(forwardBy: cap)\n        otherBuf!.moveWriterIndex(forwardBy: cap)\n\n        // These should now be unequal. Check their bytes to be sure.\n        XCTAssertNotEqual(buf, otherBuf)\n        buf!.withUnsafeReadableBytes { ptr in\n            XCTAssertEqual(cap, ptr.count)\n            for i in 0..<cap {\n                XCTAssertEqual(ptr[i], 0)\n            }\n        }\n        otherBuf!.withUnsafeReadableBytes { ptr in\n            XCTAssertEqual(cap, ptr.count)\n            for i in 0..<cap {\n                XCTAssertEqual(ptr[i], UInt8(truncatingIfNeeded: i))\n            }\n        }\n    }\n\n    func testBufferWithZeroBytes() throws {\n        var buf = allocator.buffer(capacity: 0)\n        XCTAssertEqual(0, buf.capacity)\n\n        var otherBuf = buf\n\n        otherBuf.setBytes(Data(), at: 0)\n        buf.setBytes(Data(), at: 0)\n\n        XCTAssertEqual(0, buf.capacity)\n        XCTAssertEqual(0, otherBuf.capacity)\n\n        XCTAssertNil(otherBuf.readData(length: 1))\n        XCTAssertNil(buf.readData(length: 1))\n    }\n\n    func testPastEnd() throws {\n        let buf = allocator.buffer(capacity: 4)\n        XCTAssertEqual(4, buf.capacity)\n\n        XCTAssertNil(buf.getInteger(at: 0) as UInt64?)\n        XCTAssertNil(buf.getData(at: 0, length: 5))\n    }\n\n    func testReadDataNotEnoughAvailable() throws {\n        // write some bytes\n        self.buf.writeBytes(Data([0, 1, 2, 3]))\n\n        // make more available in the buffer that should not be readable\n        self.buf.setBytes(Data([4, 5, 6, 7]), at: 4)\n\n        let actualNil = buf.readData(length: 5)\n        XCTAssertNil(actualNil)\n\n        self.buf.moveReaderIndex(to: 0)\n        self.buf.moveWriterIndex(to: 5)\n        let actualGoodDirect = buf.getData(at: 0, length: 5)\n        XCTAssertEqual(Data([0, 1, 2, 3, 4]), actualGoodDirect)\n\n        let actualGood = self.buf.readData(length: 4)\n        XCTAssertEqual(Data([0, 1, 2, 3]), actualGood)\n    }\n\n    func testReadSliceNotEnoughAvailable() throws {\n        // write some bytes\n        self.buf.writeBytes(Data([0, 1, 2, 3]))\n\n        // make more available in the buffer that should not be readable\n        self.buf.setBytes(Data([4, 5, 6, 7]), at: 4)\n\n        let actualNil = self.buf.readSlice(length: 5)\n        XCTAssertNil(actualNil)\n\n        self.buf.moveWriterIndex(forwardBy: 1)\n        let actualGoodDirect = self.buf.getSlice(at: 0, length: 5)\n        XCTAssertEqual(Data([0, 1, 2, 3, 4]), actualGoodDirect?.getData(at: 0, length: 5))\n\n        var actualGood = self.buf.readSlice(length: 4)\n        XCTAssertEqual(Data([0, 1, 2, 3]), actualGood?.readData(length: 4))\n    }\n\n    func testSetBuffer() throws {\n        var src = self.allocator.buffer(capacity: 4)\n        src.writeBytes(Data([0, 1, 2, 3]))\n\n        self.buf.setBuffer(src, at: 1)\n\n        // Should bit increase the writerIndex of the src buffer\n        XCTAssertEqual(4, src.readableBytes)\n        XCTAssertEqual(0, self.buf.readableBytes)\n\n        self.buf.moveWriterIndex(to: 5)\n        self.buf.moveReaderIndex(to: 1)\n        XCTAssertEqual(Data([0, 1, 2, 3]), self.buf.getData(at: 1, length: 4))\n    }\n\n    func testWriteBuffer() throws {\n        var src = allocator.buffer(capacity: 4)\n        src.writeBytes(Data([0, 1, 2, 3]))\n\n        buf.writeBuffer(&src)\n\n        // Should increase the writerIndex of the src buffer\n        XCTAssertEqual(0, src.readableBytes)\n        XCTAssertEqual(4, buf.readableBytes)\n        XCTAssertEqual(Data([0, 1, 2, 3]), buf.readData(length: 4))\n    }\n\n    func testMisalignedIntegerRead() throws {\n        let value = UInt64(7)\n\n        buf.writeBytes(Data([1]))\n        buf.writeInteger(value)\n        let actual = buf.readData(length: 1)\n        XCTAssertEqual(Data([1]), actual)\n\n        buf.withUnsafeReadableBytes { ptr in\n            // make sure pointer is actually misaligned for an integer\n            let pointerBitPattern = UInt(bitPattern: ptr.baseAddress!)\n            let lastBit = pointerBitPattern & 0x1\n            XCTAssertEqual(\n                1,\n                lastBit\n            )  // having a 1 as the last bit makes that pointer clearly misaligned for UInt64\n        }\n\n        XCTAssertEqual(value, buf.readInteger())\n    }\n\n    func testSetAndWriteBytes() throws {\n        let str = \"hello world!\"\n        let hwData = str.data(using: .utf8)!\n        // write once, ...\n        buf.writeString(str)\n        var written1: Int = -1\n        var written2: Int = -1\n        hwData.withUnsafeBytes { ptr in\n            // ... write a second time and ...\n            written1 = buf.setBytes(ptr, at: buf.writerIndex)\n            buf.moveWriterIndex(forwardBy: written1)\n            // ... a lucky third time!\n            written2 = buf.writeBytes(ptr)\n        }\n        XCTAssertEqual(written1, written2)\n        XCTAssertEqual(str.utf8.count, written1)\n        XCTAssertEqual(3 * str.utf8.count, buf.readableBytes)\n        let actualData = buf.readData(length: 3 * str.utf8.count)!\n        let actualString = String(decoding: actualData, as: Unicode.UTF8.self)\n        XCTAssertEqual(Array(repeating: str, count: 3).joined(), actualString)\n    }\n\n    func testCopyBytesWithNegativeLength() {\n        self.buf.writeBytes([0x0, 0x1])\n        XCTAssertThrowsError(try self.buf.copyBytes(at: self.buf.readerIndex, to: self.buf.readerIndex + 1, length: -1))\n        {\n            XCTAssertEqual($0 as? ByteBuffer.CopyBytesError, .negativeLength)\n        }\n    }\n\n    func testCopyBytesNonReadable() {\n        let oldReaderIndex = self.buf.readerIndex\n        self.buf.writeBytes([0x0, 0x1, 0x2])\n        // Partially consume the bytes.\n        self.buf.moveReaderIndex(forwardBy: 2)\n\n        // Copy two read bytes.\n        XCTAssertThrowsError(try self.buf.copyBytes(at: oldReaderIndex, to: self.buf.writerIndex, length: 2)) {\n            XCTAssertEqual($0 as? ByteBuffer.CopyBytesError, .unreadableSourceBytes)\n        }\n\n        // Copy one read byte and one readable byte.\n        XCTAssertThrowsError(try self.buf.copyBytes(at: oldReaderIndex + 1, to: self.buf.writerIndex, length: 2)) {\n            XCTAssertEqual($0 as? ByteBuffer.CopyBytesError, .unreadableSourceBytes)\n        }\n\n        // Copy one readable byte and one uninitialized byte.\n        XCTAssertThrowsError(try self.buf.copyBytes(at: oldReaderIndex + 3, to: self.buf.writerIndex, length: 2)) {\n            XCTAssertEqual($0 as? ByteBuffer.CopyBytesError, .unreadableSourceBytes)\n        }\n\n        // Copy two uninitialized bytes.\n        XCTAssertThrowsError(try self.buf.copyBytes(at: self.buf.writerIndex, to: oldReaderIndex, length: 2)) {\n            XCTAssertEqual($0 as? ByteBuffer.CopyBytesError, .unreadableSourceBytes)\n        }\n    }\n\n    func testCopyBytes() throws {\n        self.buf.writeBytes([0, 1, 2, 3])\n        XCTAssertNoThrow(try self.buf.copyBytes(at: self.buf.readerIndex, to: self.buf.readerIndex + 2, length: 2))\n        XCTAssertEqual(self.buf.readableBytes, 4)\n        XCTAssertEqual(self.buf.readBytes(length: self.buf.readableBytes), [0, 1, 0, 1])\n    }\n\n    func testCopyZeroBytesOutOfBoundsIsOk() throws {\n        XCTAssertEqual(try self.buf.copyBytes(at: self.buf.writerIndex, to: self.buf.writerIndex + 42, length: 0), 0)\n    }\n\n    func testCopyBytesBeyondWriterIndex() throws {\n        self.buf.writeBytes([0, 1, 2, 3])\n        // Write beyond the writerIndex\n        XCTAssertNoThrow(try self.buf.copyBytes(at: self.buf.readerIndex, to: self.buf.readerIndex + 4, length: 2))\n        XCTAssertEqual(self.buf.readableBytes, 4)\n        XCTAssertEqual(self.buf.readBytes(length: 2), [0, 1])\n        XCTAssertNotNil(self.buf.readBytes(length: 2))  // could be anything!\n        self.buf.moveWriterIndex(forwardBy: 2)  // We know these have been written.\n        XCTAssertEqual(self.buf.readBytes(length: 2), [0, 1])\n    }\n\n    func testCopyBytesOverSelf() throws {\n        self.buf.writeBytes([0, 1, 2, 3])\n        XCTAssertNoThrow(try self.buf.copyBytes(at: self.buf.readerIndex, to: self.buf.readerIndex + 1, length: 3))\n        XCTAssertEqual(self.buf.readableBytes, 4)\n        XCTAssertEqual(self.buf.readBytes(length: self.buf.readableBytes), [0, 0, 1, 2])\n\n        self.buf.writeBytes([0, 1, 2, 3])\n        XCTAssertNoThrow(try self.buf.copyBytes(at: self.buf.readerIndex + 1, to: self.buf.readerIndex, length: 3))\n        XCTAssertEqual(self.buf.readableBytes, 4)\n        XCTAssertEqual(self.buf.readBytes(length: self.buf.readableBytes), [1, 2, 3, 3])\n    }\n\n    func testCopyBytesCoWs() throws {\n        let bytes: [UInt8] = (0..<self.buf.writableBytes).map { UInt8($0 % Int(UInt8.max)) }\n        self.buf.writeBytes(bytes)\n        var otherBuf = self.buf!\n\n        XCTAssertEqual(self.buf.writableBytes, 0)\n\n        XCTAssertNoThrow(try self.buf.copyBytes(at: self.buf.readerIndex, to: self.buf.readerIndex + 2, length: 1))\n        XCTAssertNotEqual(\n            self.buf.readBytes(length: self.buf.readableBytes),\n            otherBuf.readBytes(length: otherBuf.readableBytes)\n        )\n    }\n\n    func testWriteABunchOfCollections() throws {\n        let overallData = \"0123456789abcdef\".data(using: .utf8)!\n        buf.writeBytes(\"0123\".utf8)\n        \"4567\".withCString { ptr in\n            ptr.withMemoryRebound(to: UInt8.self, capacity: 4) { ptr in\n                _ = buf.writeBytes(UnsafeBufferPointer<UInt8>(start: ptr, count: 4))\n            }\n        }\n        buf.writeBytes(Array(\"89ab\".utf8))\n        buf.writeBytes(\"cdef\".data(using: .utf8)!)\n        let actual = buf.getData(at: 0, length: buf.readableBytes)\n        XCTAssertEqual(overallData, actual)\n    }\n\n    func testSetABunchOfCollections() throws {\n        let overallData = \"0123456789abcdef\".data(using: .utf8)!\n        self.buf.setBytes(\"0123\".utf8, at: 0)\n        _ = \"4567\".withCString { ptr in\n            ptr.withMemoryRebound(to: UInt8.self, capacity: 4) { ptr in\n                self.buf.setBytes(UnsafeBufferPointer<UInt8>(start: ptr, count: 4), at: 4)\n            }\n        }\n        self.buf.setBytes(Array(\"89ab\".utf8), at: 8)\n        self.buf.setBytes(\"cdef\".data(using: .utf8)!, at: 12)\n        self.buf.moveReaderIndex(to: 0)\n        self.buf.moveWriterIndex(to: 16)\n        let actual = self.buf.getData(at: 0, length: 16)\n        XCTAssertEqual(overallData, actual)\n    }\n\n    func testTryStringTooLong() throws {\n        let capacity = self.buf.capacity\n        for i in 0..<self.buf.capacity {\n            self.buf.setString(\"x\", at: i)\n        }\n        XCTAssertEqual(\n            capacity,\n            self.buf.capacity,\n            \"buffer capacity needlessly changed from \\(capacity) to \\(self.buf.capacity)\"\n        )\n        XCTAssertNil(self.buf.getString(at: 0, length: capacity + 1))\n    }\n\n    func testWriteEmptyByteArray() throws {\n        var buffer = ByteBufferAllocator().buffer(capacity: 32)\n        buffer.moveWriterIndex(to: 16)\n        buffer.moveReaderIndex(to: 16)\n        XCTAssertEqual(buffer.setBytes([], at: 16), 0)\n        XCTAssertEqual(buffer.readableBytes, 0)\n        XCTAssertEqual(buffer.writableBytes, 16)\n        XCTAssertEqual(buffer.writerIndex, 16)\n        XCTAssertEqual(buffer.readerIndex, 16)\n    }\n\n    func testSetGetBytesAllFine() throws {\n        self.buf.moveReaderIndex(to: 0)\n        self.buf.setBytes([1, 2, 3, 4], at: 0)\n        self.buf.moveWriterIndex(to: 4)\n        XCTAssertEqual([1, 2, 3, 4], self.buf.getBytes(at: 0, length: 4) ?? [])\n\n        let capacity = self.buf.capacity\n        for i in 0..<self.buf.capacity {\n            self.buf.setBytes([0xFF], at: i)\n        }\n        self.buf.moveWriterIndex(to: self.buf.capacity)\n        XCTAssertEqual(capacity, buf.capacity, \"buffer capacity needlessly changed from \\(capacity) to \\(buf.capacity)\")\n        XCTAssertEqual(Array(repeating: 0xFF, count: capacity), self.buf.getBytes(at: 0, length: capacity))\n\n    }\n\n    func testGetBytesTooLong() throws {\n        XCTAssertNil(buf.getBytes(at: 0, length: buf.capacity + 1))\n        XCTAssertNil(buf.getBytes(at: buf.capacity, length: 1))\n    }\n\n    func testReadWriteBytesOkay() throws {\n        buf.reserveCapacity(24)\n        buf.clear()\n        let capacity = buf.capacity\n        for i in 0..<capacity {\n            let expected = Array(repeating: UInt8(i % 255), count: i)\n            buf.writeBytes(expected)\n            let actual = buf.readBytes(length: i)!\n            XCTAssertEqual(expected, actual)\n            XCTAssertEqual(\n                capacity,\n                buf.capacity,\n                \"buffer capacity needlessly changed from \\(capacity) to \\(buf.capacity)\"\n            )\n            buf.clear()\n        }\n    }\n\n    func testReadTooLong() throws {\n        XCTAssertNotNil(buf.readBytes(length: buf.readableBytes))\n        XCTAssertNil(buf.readBytes(length: buf.readableBytes + 1))\n    }\n\n    func testReadWithUnsafeReadableBytesVariantsNothingToRead() throws {\n        buf.reserveCapacity(1024)\n        buf.clear()\n        XCTAssertEqual(0, buf.readerIndex)\n        XCTAssertEqual(0, buf.writerIndex)\n\n        var rInt = buf.readWithUnsafeReadableBytes { ptr in\n            XCTAssertEqual(0, ptr.count)\n            return 0\n        }\n        XCTAssertEqual(0, rInt)\n\n        rInt = buf.readWithUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(0, ptr.count)\n            return 0\n        }\n        XCTAssertEqual(0, rInt)\n\n        var rString = buf.readWithUnsafeReadableBytes { (ptr: UnsafeRawBufferPointer) -> (Int, String) in\n            XCTAssertEqual(0, ptr.count)\n            return (0, \"blah\")\n        }\n        XCTAssert(rString == \"blah\")\n\n        rString = buf.readWithUnsafeMutableReadableBytes { (ptr: UnsafeMutableRawBufferPointer) -> (Int, String) in\n            XCTAssertEqual(0, ptr.count)\n            return (0, \"blah\")\n        }\n        XCTAssert(rString == \"blah\")\n    }\n\n    func testReadWithUnsafeReadableBytesVariantsSomethingToRead() throws {\n        var buf = ByteBufferAllocator().buffer(capacity: 1)\n        buf.clear()\n        buf.writeBytes([1, 2, 3, 4, 5, 6, 7, 8])\n        XCTAssertEqual(0, buf.readerIndex)\n        XCTAssertEqual(8, buf.writerIndex)\n\n        var rInt = buf.readWithUnsafeReadableBytes { ptr in\n            XCTAssertEqual(8, ptr.count)\n            return 0\n        }\n        XCTAssertEqual(0, rInt)\n\n        rInt = buf.readWithUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(8, ptr.count)\n            return 1\n        }\n        XCTAssertEqual(1, rInt)\n\n        var rString = buf.readWithUnsafeReadableBytes { (ptr: UnsafeRawBufferPointer) -> (Int, String) in\n            XCTAssertEqual(7, ptr.count)\n            return (2, \"blah\")\n        }\n        XCTAssert(rString == \"blah\")\n\n        rString = buf.readWithUnsafeMutableReadableBytes { (ptr: UnsafeMutableRawBufferPointer) -> (Int, String) in\n            XCTAssertEqual(5, ptr.count)\n            return (3, \"blah\")\n        }\n        XCTAssert(rString == \"blah\")\n\n        XCTAssertEqual(6, buf.readerIndex)\n        XCTAssertEqual(8, buf.writerIndex)\n    }\n\n    func testSomePotentialIntegerUnderOrOverflows() throws {\n        buf.reserveCapacity(1024)\n        buf.writeStaticString(\"hello world, just some trap bytes here\")\n\n        func testIndexAndLengthFunc<T>(_ body: (Int, Int) -> T?, file: StaticString = #filePath, line: UInt = #line) {\n            XCTAssertNil(body(Int.max, 1), file: (file), line: line)\n            XCTAssertNil(body(Int.max - 1, 2), file: (file), line: line)\n            XCTAssertNil(body(1, Int.max), file: (file), line: line)\n            XCTAssertNil(body(2, Int.max - 1), file: (file), line: line)\n            XCTAssertNil(body(Int.max, Int.max), file: (file), line: line)\n            XCTAssertNil(body(Int.min, Int.min), file: (file), line: line)\n            XCTAssertNil(body(Int.max, Int.min), file: (file), line: line)\n            XCTAssertNil(body(Int.min, Int.max), file: (file), line: line)\n        }\n\n        func testIndexOrLengthFunc<T>(_ body: (Int) -> T?, file: StaticString = #filePath, line: UInt = #line) {\n            XCTAssertNil(body(Int.max))\n            XCTAssertNil(body(Int.max - 1))\n            XCTAssertNil(body(Int.min))\n        }\n\n        testIndexOrLengthFunc({ buf.readBytes(length: $0) })\n        testIndexOrLengthFunc({ buf.readData(length: $0) })\n        testIndexOrLengthFunc({ buf.readSlice(length: $0) })\n        testIndexOrLengthFunc({ buf.readString(length: $0) })\n        testIndexOrLengthFunc({ buf.readDispatchData(length: $0) })\n\n        testIndexOrLengthFunc({ buf.getInteger(at: $0, as: UInt8.self) })\n        testIndexOrLengthFunc({ buf.getInteger(at: $0, as: UInt16.self) })\n        testIndexOrLengthFunc({ buf.getInteger(at: $0, as: UInt32.self) })\n        testIndexOrLengthFunc({ buf.getInteger(at: $0, as: UInt64.self) })\n        testIndexAndLengthFunc(buf.getBytes)\n        testIndexAndLengthFunc(buf.getData)\n        testIndexAndLengthFunc(buf.getSlice)\n        testIndexAndLengthFunc(buf.getString)\n        testIndexAndLengthFunc(buf.getDispatchData)\n        testIndexAndLengthFunc(buf.viewBytes(at:length:))\n    }\n\n    func testWriteForContiguousCollections() throws {\n        buf.clear()\n        var written = buf.writeBytes([1, 2, 3, 4])\n        XCTAssertEqual(4, written)\n        // UnsafeRawBufferPointer\n        written += [5 as UInt8, 6, 7, 8].withUnsafeBytes { ptr in\n            buf.writeBytes(ptr)\n        }\n        XCTAssertEqual(8, written)\n        // UnsafeBufferPointer<UInt8>\n        written += [9 as UInt8, 10, 11, 12].withUnsafeBufferPointer { ptr in\n            buf.writeBytes(ptr)\n        }\n        XCTAssertEqual(12, written)\n        // ContiguousArray\n        written += buf.writeBytes(ContiguousArray<UInt8>([13, 14, 15, 16]))\n        XCTAssertEqual(16, written)\n\n        // Data\n        written += buf.writeBytes(\"EFGH\".data(using: .utf8)!)\n        XCTAssertEqual(20, written)\n        var more = Array(\"IJKL\".utf8)\n\n        // UnsafeMutableRawBufferPointer\n        written += more.withUnsafeMutableBytes { ptr in\n            buf.writeBytes(ptr)\n        }\n        more = Array(\"MNOP\".utf8)\n        // UnsafeMutableBufferPointer<UInt8>\n        written += more.withUnsafeMutableBufferPointer { ptr in\n            buf.writeBytes(ptr)\n        }\n        more = Array(\"mnopQRSTuvwx\".utf8)\n\n        // ArraySlice\n        written += buf.writeBytes(more.dropFirst(4).dropLast(4))\n\n        let moreCA = ContiguousArray(\"qrstUVWXyz01\".utf8)\n        // ContiguousArray's slice (== ArraySlice)\n        written += buf.writeBytes(moreCA.dropFirst(4).dropLast(4))\n\n        // Slice<UnsafeRawBufferPointer>\n        written += Array(\"uvwxYZ01abcd\".utf8).withUnsafeBytes { ptr in\n            buf.writeBytes(ptr.dropFirst(4).dropLast(4) as UnsafeRawBufferPointer.SubSequence)\n        }\n        more = Array(\"2345\".utf8)\n        written += more.withUnsafeMutableBytes { ptr in\n            buf.writeBytes(ptr.dropFirst(0)) + buf.writeBytes(ptr.dropFirst(4))  // drop all of them\n        }\n\n        let expected = Array(1...16) + Array(\"EFGHIJKLMNOPQRSTUVWXYZ012345\".utf8)\n\n        XCTAssertEqual(expected, buf.readBytes(length: written)!)\n    }\n\n    func testWriteForNonContiguousCollections() throws {\n        buf.clear()\n        let written = buf.writeBytes(\"ABCD\".utf8)\n        XCTAssertEqual(4, written)\n\n        let expected = [\"A\".utf8.first!, \"B\".utf8.first!, \"C\".utf8.first!, \"D\".utf8.first!]\n\n        XCTAssertEqual(expected, buf.readBytes(length: written)!)\n    }\n\n    func testReadStringOkay() throws {\n        buf.clear()\n        let expected = \"hello\"\n        buf.writeString(expected)\n        let actual = buf.readString(length: expected.utf8.count)\n        XCTAssertEqual(expected, actual)\n        XCTAssertEqual(\"\", buf.readString(length: 0))\n        XCTAssertNil(buf.readString(length: 1))\n    }\n\n    func testReadStringTooMuch() throws {\n        buf.clear()\n        XCTAssertNil(buf.readString(length: 1))\n\n        buf.writeString(\"a\")\n        XCTAssertNil(buf.readString(length: 2))\n\n        XCTAssertEqual(\"a\", buf.readString(length: 1))\n    }\n\n    func testReadUTF8ValidatedString() throws {\n        guard #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) else {\n            throw XCTSkip(\"'readUTF8ValidatedString' is only available in Swift 6 and later\")\n        }\n        buf.clear()\n        let expected = \"hello\"\n        buf.writeString(expected)\n        let actual = try buf.readUTF8ValidatedString(length: expected.utf8.count)\n        XCTAssertEqual(expected, actual)\n        XCTAssertEqual(\"\", try buf.readUTF8ValidatedString(length: 0))\n        XCTAssertNil(try buf.readUTF8ValidatedString(length: 1))\n    }\n\n    func testGetUTF8ValidatedString() throws {\n        guard #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) else {\n            throw XCTSkip(\"'getUTF8ValidatedString' is only available in Swift 6 and later\")\n        }\n        buf.clear()\n        let expected = \"hello, goodbye\"\n        buf.writeString(expected)\n        let actual = try buf.getUTF8ValidatedString(at: 7, length: 7)\n        XCTAssertEqual(\"goodbye\", actual)\n    }\n\n    func testReadUTF8InvalidString() throws {\n        guard #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) else {\n            throw XCTSkip(\"'readUTF8ValidatedString' is only available in Swift 6 and later\")\n        }\n        buf.clear()\n        buf.writeBytes([UInt8](repeating: 255, count: 16))\n        XCTAssertThrowsError(try buf.readUTF8ValidatedString(length: 16)) { error in\n            switch error {\n            case is ByteBuffer.ReadUTF8ValidationError:\n                break\n            default:\n                XCTFail(\"Error: \\(error)\")\n            }\n        }\n        XCTAssertEqual(buf.readableBytes, 16)\n    }\n\n    func testSetIntegerBeyondCapacity() throws {\n        var buf = ByteBufferAllocator().buffer(capacity: 32)\n        XCTAssertLessThan(buf.capacity, 200)\n\n        buf.setInteger(17, at: 201)\n        buf.moveWriterIndex(to: 201 + MemoryLayout<Int>.size)\n        buf.moveReaderIndex(to: 201)\n        let i: Int = buf.getInteger(at: 201)!\n        XCTAssertEqual(17, i)\n        XCTAssertGreaterThanOrEqual(buf.capacity, 200 + MemoryLayout.size(ofValue: i))\n    }\n\n    func testGetIntegerBeyondCapacity() throws {\n        let buf = ByteBufferAllocator().buffer(capacity: 32)\n        XCTAssertLessThan(buf.capacity, 200)\n\n        let i: Int? = buf.getInteger(at: 201)\n        XCTAssertNil(i)\n    }\n\n    func testSetStringBeyondCapacity() throws {\n        var buf = ByteBufferAllocator().buffer(capacity: 32)\n        XCTAssertLessThan(buf.capacity, 200)\n\n        buf.setString(\"HW\", at: 201)\n        buf.moveWriterIndex(to: 201 + 2)\n        buf.moveReaderIndex(to: 201)\n        let s = buf.getString(at: 201, length: 2)!\n        XCTAssertEqual(\"HW\", s)\n        XCTAssertGreaterThanOrEqual(buf.capacity, 202)\n    }\n\n    func testGetStringBeyondCapacity() throws {\n        let buf = ByteBufferAllocator().buffer(capacity: 32)\n        XCTAssertLessThan(buf.capacity, 200)\n\n        let i: String? = buf.getString(at: 201, length: 1)\n        XCTAssertNil(i)\n    }\n\n    func testAllocationOfReallyBigByteBuffer() throws {\n        #if arch(arm) || arch(i386) || arch(arm64_32) || arch(wasm32)\n        // this test doesn't work on 32-bit platforms because the address space is only 4GB large and we're trying\n        // to make a 4GB ByteBuffer which just won't fit. Even going down to 2GB won't make it better.\n        return\n        #endif\n        let alloc = ByteBufferAllocator(\n            allocate: { testAllocationOfReallyBigByteBuffer_mallocHook($0) },\n            reallocate: { testAllocationOfReallyBigByteBuffer_reallocHook($0, $1, $2) },\n            deallocate: { testAllocationOfReallyBigByteBuffer_freeHook($0) },\n            copy: { testAllocationOfReallyBigByteBuffer_memcpyHook($0, $1, $2) }\n        )\n\n        let reallyBigSize = Int(Int32.max)\n        XCTAssertEqual(AllocationExpectationState.begin, testAllocationOfReallyBigByteBuffer_state)\n        var buf = alloc.buffer(capacity: reallyBigSize)\n        XCTAssertEqual(AllocationExpectationState.mallocDone, testAllocationOfReallyBigByteBuffer_state)\n        XCTAssertGreaterThanOrEqual(buf.capacity, reallyBigSize)\n\n        buf.setBytes([1], at: 0)\n        // now make it expand (will trigger realloc)\n        buf.setBytes([1], at: buf.capacity)\n\n        XCTAssertEqual(AllocationExpectationState.reallocDone, testAllocationOfReallyBigByteBuffer_state)\n        XCTAssertEqual(buf.capacity, Int(UInt32.max))\n    }\n\n    func testWritableBytesAccountsForSlicing() throws {\n        var buf = ByteBufferAllocator().buffer(capacity: 32)\n        XCTAssertEqual(buf.capacity, 32)\n        XCTAssertEqual(buf.writableBytes, 32)\n        let oldWriterIndex = buf.writerIndex\n        buf.writeStaticString(\"01234567\")\n        let newBuf = buf.getSlice(at: oldWriterIndex, length: 8)!\n        XCTAssertEqual(newBuf.capacity, 8)\n        XCTAssertEqual(newBuf.writableBytes, 0)\n    }\n\n    func testClearDupesStorageIfTheresTwoBuffersSharingStorage() throws {\n        let alloc = ByteBufferAllocator()\n        var buf1 = alloc.buffer(capacity: 16)\n        let buf2 = buf1\n\n        var buf1PtrVal: UInt = 1\n        var buf2PtrVal: UInt = 2\n\n        buf1.withUnsafeReadableBytes { ptr in\n            buf1PtrVal = UInt(bitPattern: ptr.baseAddress!)\n        }\n        buf2.withUnsafeReadableBytes { ptr in\n            buf2PtrVal = UInt(bitPattern: ptr.baseAddress!)\n        }\n        XCTAssertEqual(buf1PtrVal, buf2PtrVal)\n\n        buf1.clear()\n\n        buf1.withUnsafeReadableBytes { ptr in\n            buf1PtrVal = UInt(bitPattern: ptr.baseAddress!)\n        }\n        buf2.withUnsafeReadableBytes { ptr in\n            buf2PtrVal = UInt(bitPattern: ptr.baseAddress!)\n        }\n        XCTAssertNotEqual(buf1PtrVal, buf2PtrVal)\n    }\n\n    func testClearDoesNotDupeStorageIfTheresOnlyOneBuffer() throws {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n\n        var bufPtrValPre: UInt = 1\n        var bufPtrValPost: UInt = 2\n\n        buf.withUnsafeReadableBytes { ptr in\n            bufPtrValPre = UInt(bitPattern: ptr.baseAddress!)\n        }\n\n        buf.clear()\n\n        buf.withUnsafeReadableBytes { ptr in\n            bufPtrValPost = UInt(bitPattern: ptr.baseAddress!)\n        }\n        XCTAssertEqual(bufPtrValPre, bufPtrValPost)\n    }\n\n    func testClearWithBiggerMinimumCapacityDupesStorageIfTheresTwoBuffersSharingStorage() throws {\n        let alloc = ByteBufferAllocator()\n        let buf1 = alloc.buffer(capacity: 16)\n        var buf2 = buf1\n\n        var buf1PtrVal: UInt = 1\n        var buf2PtrVal: UInt = 2\n\n        buf1PtrVal = buf1.storagePointerIntegerValue()\n        buf2PtrVal = buf2.storagePointerIntegerValue()\n\n        XCTAssertEqual(buf1PtrVal, buf2PtrVal)\n\n        buf2.clear(minimumCapacity: 32)\n\n        buf1PtrVal = buf1.storagePointerIntegerValue()\n        buf2PtrVal = buf2.storagePointerIntegerValue()\n\n        XCTAssertNotEqual(buf1PtrVal, buf2PtrVal)\n        XCTAssertLessThan(buf1.capacity, 32)\n        XCTAssertGreaterThanOrEqual(buf2.capacity, 32)\n    }\n\n    func testClearWithSmallerMinimumCapacityDupesStorageIfTheresTwoBuffersSharingStorage() throws {\n        let alloc = ByteBufferAllocator()\n        let buf1 = alloc.buffer(capacity: 16)\n        var buf2 = buf1\n\n        var buf1PtrVal: UInt = 1\n        var buf2PtrVal: UInt = 2\n\n        buf1PtrVal = buf1.storagePointerIntegerValue()\n        buf2PtrVal = buf2.storagePointerIntegerValue()\n\n        XCTAssertEqual(buf1PtrVal, buf2PtrVal)\n\n        buf2.clear(minimumCapacity: 4)\n\n        buf1PtrVal = buf1.storagePointerIntegerValue()\n        buf2PtrVal = buf2.storagePointerIntegerValue()\n\n        XCTAssertNotEqual(buf1PtrVal, buf2PtrVal)\n        XCTAssertGreaterThanOrEqual(buf1.capacity, 16)\n        XCTAssertLessThan(buf2.capacity, 16)\n    }\n\n    func testClearWithBiggerMinimumCapacityDoesNotDupeStorageIfTheresOnlyOneBuffer() throws {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n\n        XCTAssertLessThan(buf.capacity, 32)\n        let preCapacity = buf.capacity\n\n        buf.clear(minimumCapacity: 32)\n        let postCapacity = buf.capacity\n\n        XCTAssertGreaterThanOrEqual(buf.capacity, 32)\n        XCTAssertNotEqual(preCapacity, postCapacity)\n    }\n\n    func testClearWithSmallerMinimumCapacityDoesNotDupeStorageIfTheresOnlyOneBuffer() throws {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n\n        var bufPtrValPre: UInt = 1\n        var bufPtrValPost: UInt = 2\n\n        let preCapacity = buf.capacity\n        XCTAssertGreaterThanOrEqual(buf.capacity, 16)\n\n        bufPtrValPre = buf.storagePointerIntegerValue()\n        buf.clear(minimumCapacity: 8)\n        bufPtrValPost = buf.storagePointerIntegerValue()\n        let postCapacity = buf.capacity\n\n        XCTAssertEqual(bufPtrValPre, bufPtrValPost)\n        XCTAssertEqual(preCapacity, postCapacity)\n    }\n\n    func testClearWithBiggerCapacityDoesReallocateStorageCorrectlyIfTheresOnlyOneBuffer() throws {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n\n        buf.clear(minimumCapacity: 32)\n\n        XCTAssertEqual(buf._storage.capacity, 32)\n    }\n\n    func testClearWithSmallerCapacityDoesReallocateStorageCorrectlyIfTheresOnlyOneBuffer() throws {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n\n        buf.clear(minimumCapacity: 8)\n\n        XCTAssertEqual(buf._storage.capacity, 16)\n    }\n\n    func testClearDoesAllocateStorageCorrectlyIfTheresTwoBuffersSharingStorage() throws {\n        let alloc = ByteBufferAllocator()\n        var buf1 = alloc.buffer(capacity: 16)\n        let buf2 = buf1\n\n        buf1.clear(minimumCapacity: 8)\n\n        XCTAssertEqual(buf1._storage.capacity, 8)\n        XCTAssertEqual(buf2._storage.capacity, 16)\n    }\n\n    func testClearResetsTheSliceCapacityIfTheresOnlyOneBuffer() {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n        buf.writeString(\"qwertyuiop\")\n        XCTAssertEqual(buf.capacity, 16)\n\n        var slice = buf.getSlice(at: 3, length: 4)!\n        XCTAssertEqual(slice.capacity, 4)\n\n        slice.clear()\n        XCTAssertEqual(slice.capacity, 16)\n    }\n\n    func testClearResetsTheSliceCapacityIfTheresTwoSlicesSharingStorage() {\n        let alloc = ByteBufferAllocator()\n        var buf = alloc.buffer(capacity: 16)\n        buf.writeString(\"qwertyuiop\")\n\n        var slice1 = buf.getSlice(at: 3, length: 4)!\n        let slice2 = slice1\n\n        slice1.clear()\n        XCTAssertEqual(slice1.capacity, 16)\n        XCTAssertEqual(slice2.capacity, 4)\n    }\n\n    func testWeUseFastWriteForContiguousCollections() throws {\n        struct WrongCollection: Collection {\n            let storage: [UInt8] = [1, 2, 3]\n            typealias Element = UInt8\n            typealias Index = Array<UInt8>.Index\n            typealias SubSequence = Array<UInt8>.SubSequence\n            typealias Indices = Array<UInt8>.Indices\n            public var indices: Indices {\n                self.storage.indices\n            }\n            public subscript(bounds: Range<Index>) -> SubSequence {\n                self.storage[bounds]\n            }\n\n            public subscript(position: Index) -> Element {\n                // this is wrong but we need to check that we don't access this\n                XCTFail(\"shouldn't have been called\")\n                return 0xff\n            }\n\n            public var startIndex: Index {\n                self.storage.startIndex\n            }\n\n            public var endIndex: Index {\n                self.storage.endIndex\n            }\n\n            func index(after i: Index) -> Index {\n                self.storage.index(after: i)\n            }\n\n            func withContiguousStorageIfAvailable<R>(_ body: (UnsafeBufferPointer<UInt8>) throws -> R) rethrows -> R? {\n                try self.storage.withUnsafeBufferPointer(body)\n            }\n        }\n        buf.clear()\n        buf.writeBytes(WrongCollection())\n        XCTAssertEqual(3, buf.readableBytes)\n        XCTAssertEqual(1, buf.readInteger()! as UInt8)\n        XCTAssertEqual(2, buf.readInteger()! as UInt8)\n        XCTAssertEqual(3, buf.readInteger()! as UInt8)\n        buf.setBytes(WrongCollection(), at: 0)\n        XCTAssertEqual(0, buf.readableBytes)\n        buf.moveWriterIndex(to: 3)\n        buf.moveReaderIndex(to: 0)\n        XCTAssertEqual(1, buf.getInteger(at: 0, as: UInt8.self))\n        XCTAssertEqual(2, buf.getInteger(at: 1, as: UInt8.self))\n        XCTAssertEqual(3, buf.getInteger(at: 2, as: UInt8.self))\n    }\n\n    func testUnderestimatingSequenceWorks() throws {\n        struct UnderestimatingSequence: Sequence {\n            let storage: [UInt8] = Array(0...255)\n            typealias Element = UInt8\n\n            public var indices: CountableRange<Int> {\n                self.storage.indices\n            }\n\n            public subscript(position: Int) -> Element {\n                self.storage[position]\n            }\n\n            public var underestimatedCount: Int {\n                8\n            }\n\n            func makeIterator() -> Array<UInt8>.Iterator {\n                self.storage.makeIterator()\n            }\n        }\n        buf = self.allocator.buffer(capacity: 4)\n        buf.clear()\n        buf.writeBytes(UnderestimatingSequence())\n        XCTAssertEqual(256, buf.readableBytes)\n        for i in 0..<256 {\n            let actual = Int(buf.readInteger()! as UInt8)\n            XCTAssertEqual(i, actual)\n        }\n        buf = self.allocator.buffer(capacity: 4)\n        buf.setBytes(UnderestimatingSequence(), at: 0)\n        XCTAssertEqual(0, buf.readableBytes)\n        buf.moveWriterIndex(to: 256)\n        buf.moveReaderIndex(to: 0)\n        for i in 0..<256 {\n            XCTAssertEqual(i, buf.getInteger(at: i, as: UInt8.self).map(Int.init))\n        }\n    }\n\n    func testZeroSizeByteBufferResizes() {\n        var buf = ByteBuffer()\n        buf.writeStaticString(\"x\")\n        XCTAssertEqual(buf.writerIndex, 1)\n    }\n\n    func testSpecifyTypesAndEndiannessForIntegerMethods() {\n        self.buf.clear()\n        self.buf.writeInteger(-1, endianness: .big, as: Int64.self)\n        XCTAssertEqual(-1, self.buf.readInteger(endianness: .big, as: Int64.self))\n        self.buf.setInteger(0xdead_beef, at: 0, endianness: .little, as: UInt64.self)\n        self.buf.moveWriterIndex(to: 8)\n        self.buf.moveReaderIndex(to: 0)\n        XCTAssertEqual(0xdead_beef, self.buf.getInteger(at: 0, endianness: .little, as: UInt64.self))\n    }\n\n    func testByteBufferFitsInACoupleOfEnums() throws {\n        enum Level4 {\n            case case1(ByteBuffer)\n            case case2(ByteBuffer)\n            case case3(ByteBuffer)\n            case case4(ByteBuffer)\n        }\n        enum Level3 {\n            case case1(Level4)\n            case case2(Level4)\n            case case3(Level4)\n            case case4(Level4)\n        }\n        enum Level2 {\n            case case1(Level3)\n            case case2(Level3)\n            case case3(Level3)\n            case case4(Level3)\n        }\n        enum Level1 {\n            case case1(Level2)\n            case case2(Level2)\n            case case3(Level2)\n            case case4(Level2)\n        }\n\n        XCTAssertLessThanOrEqual(MemoryLayout<ByteBuffer>.size, 23)\n        XCTAssertLessThanOrEqual(MemoryLayout<Level1>.size, 24)\n\n        XCTAssertLessThanOrEqual(MemoryLayout.size(ofValue: Level1.case1(.case2(.case3(.case4(self.buf))))), 24)\n        XCTAssertLessThanOrEqual(MemoryLayout.size(ofValue: Level1.case1(.case3(.case4(.case1(self.buf))))), 24)\n    }\n\n    func testLargeSliceBegin16MBIsOkayAndDoesNotCopy() throws {\n        var fourMBBuf = self.allocator.buffer(capacity: 4 * 1024 * 1024)\n        fourMBBuf.writeBytes([UInt8](repeating: 0xff, count: fourMBBuf.capacity))\n        let totalBufferSize = 5 * fourMBBuf.readableBytes\n        XCTAssertEqual(4 * 1024 * 1024, fourMBBuf.readableBytes)\n        var buf = self.allocator.buffer(capacity: totalBufferSize)\n        for _ in 0..<5 {\n            var fresh = fourMBBuf\n            buf.writeBuffer(&fresh)\n        }\n\n        let offset = Int(_UInt24.max)\n\n        // mark some special bytes\n        buf.setInteger(0xaa, at: 0, as: UInt8.self)\n        buf.setInteger(0xbb, at: offset - 1, as: UInt8.self)\n        buf.setInteger(0xcc, at: offset, as: UInt8.self)\n        buf.setInteger(0xdd, at: buf.writerIndex - 1, as: UInt8.self)\n\n        XCTAssertEqual(totalBufferSize, buf.readableBytes)\n\n        let oldPtrVal = buf.withUnsafeReadableBytes {\n            UInt(bitPattern: $0.baseAddress!.advanced(by: offset))\n        }\n\n        let expectedReadableBytes = totalBufferSize - offset\n        let slice = buf.getSlice(at: offset, length: expectedReadableBytes)!\n        XCTAssertEqual(expectedReadableBytes, slice.readableBytes)\n        let newPtrVal = slice.withUnsafeReadableBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n        XCTAssertEqual(oldPtrVal, newPtrVal)\n\n        XCTAssertEqual(0xcc, slice.getInteger(at: 0, as: UInt8.self))\n        XCTAssertEqual(0xdd, slice.getInteger(at: slice.writerIndex - 1, as: UInt8.self))\n    }\n\n    func testLargeSliceBeginMoreThan16MBIsOkay() throws {\n        var fourMBBuf = self.allocator.buffer(capacity: 4 * 1024 * 1024)\n        fourMBBuf.writeBytes([UInt8](repeating: 0xff, count: fourMBBuf.capacity))\n        let totalBufferSize = 5 * fourMBBuf.readableBytes + 1\n        XCTAssertEqual(4 * 1024 * 1024, fourMBBuf.readableBytes)\n        var buf = self.allocator.buffer(capacity: totalBufferSize)\n        for _ in 0..<5 {\n            var fresh = fourMBBuf\n            buf.writeBuffer(&fresh)\n        }\n\n        let offset = Int(_UInt24.max) + 1\n\n        // mark some special bytes\n        buf.setInteger(0xaa, at: 0, as: UInt8.self)\n        buf.setInteger(0xbb, at: offset - 1, as: UInt8.self)\n        buf.setInteger(0xcc, at: offset, as: UInt8.self)\n        buf.writeInteger(0xdd, as: UInt8.self)  // write extra byte so the slice is the same length as above\n        XCTAssertEqual(totalBufferSize, buf.readableBytes)\n\n        let expectedReadableBytes = totalBufferSize - offset\n        let slice = buf.getSlice(at: offset, length: expectedReadableBytes)!\n        XCTAssertEqual(expectedReadableBytes, slice.readableBytes)\n        XCTAssertEqual(0, slice.readerIndex)\n        XCTAssertEqual(expectedReadableBytes, slice.writerIndex)\n        XCTAssertEqual(Int(UInt32(expectedReadableBytes).nextPowerOf2()), slice.capacity)\n\n        XCTAssertEqual(0xcc, slice.getInteger(at: 0, as: UInt8.self))\n        XCTAssertEqual(0xdd, slice.getInteger(at: slice.writerIndex - 1, as: UInt8.self))\n    }\n\n    func testSliceOfMassiveBufferWithAdvancedReaderIndexIsOk() throws {\n        // We only want to run this test on 64-bit systems: 32-bit systems can't allocate buffers\n        // large enough to run this test safely.\n        guard MemoryLayout<Int>.size >= 8 else {\n            throw XCTSkip(\"This test is only supported on 64-bit systems.\")\n        }\n\n        // This allocator assumes that we'll never call realloc.\n        let fakeAllocator = ByteBufferAllocator(\n            allocate: { _ in .init(bitPattern: 0xdedbeef) },\n            reallocate: { _, _, _ in fatalError() },\n            deallocate: { precondition($0 == .init(bitPattern: 0xdedbeef)!) },\n            copy: { _, _, _ in }\n        )\n\n        let targetSize = Int(UInt32.max)\n        var buffer = fakeAllocator.buffer(capacity: targetSize)\n\n        // Move the reader index forward such that we hit the slow path.\n        let offset = Int(_UInt24.max) + 1\n        buffer.moveWriterIndex(to: offset)\n        buffer.moveReaderIndex(to: offset)\n\n        // Pretend we wrote a UInt32.\n        buffer.moveWriterIndex(forwardBy: 4)\n\n        // We're going to move the readerIndex forward by 1, and then slice.\n        buffer.moveReaderIndex(forwardBy: 1)\n        let slice = buffer.getSlice(at: buffer.readerIndex, length: 3)!\n        XCTAssertEqual(slice.readableBytes, 3)\n        XCTAssertEqual(slice.readerIndex, 0)\n        XCTAssertEqual(Int(UInt32(3).nextPowerOf2()), slice.capacity)\n    }\n\n    func testSliceOnSliceAfterHitting16MBMark() {\n        // This test ensures that a slice will get a new backing storage if its start is more than\n        // 16MiB after the originating backing storage.\n\n        // create a buffer with 16MiB + 1 byte\n        let inputBufferLength = 16 * 1024 * 1024 + 1\n        var inputBuffer = ByteBufferAllocator().buffer(capacity: inputBufferLength)\n        inputBuffer.writeRepeatingByte(1, count: 8)\n        inputBuffer.writeRepeatingByte(2, count: inputBufferLength - 9)\n        inputBuffer.writeRepeatingByte(3, count: 1)\n        // read a small slice from the inputBuffer, to create an offset of eight bytes\n        XCTAssertEqual(inputBuffer.readInteger(as: UInt64.self), 0x0101_0101_0101_0101)\n\n        // read the remaining bytes into a new slice (this will have a length of 16MiB - 7Bbytes)\n        let remainingSliceLength = inputBufferLength - 8\n        XCTAssertEqual(inputBuffer.readableBytes, remainingSliceLength)\n        var remainingSlice = inputBuffer.readSlice(length: remainingSliceLength)!\n\n        let finalSliceLength = 1\n        // let's create a new buffer that uses all but one byte\n        XCTAssertEqual(\n            remainingSlice.readBytes(length: remainingSliceLength - finalSliceLength),\n            [UInt8](repeating: 2, count: remainingSliceLength - finalSliceLength)\n        )\n\n        // there should only be one byte left.\n        XCTAssertEqual(remainingSlice.readableBytes, finalSliceLength)\n\n        // with just one byte left, the last byte is exactly one byte above the 16MiB threshold.\n        // For this reason a slice of the last byte, will need to get a new backing storage.\n        let finalSlice = remainingSlice.readSlice(length: finalSliceLength)\n        XCTAssertNotEqual(finalSlice?.storagePointerIntegerValue(), remainingSlice.storagePointerIntegerValue())\n        XCTAssertEqual(finalSlice?.storageCapacity, 1)\n        XCTAssertEqual(finalSlice, ByteBuffer(integer: 3, as: UInt8.self))\n\n        XCTAssertEqual(remainingSlice.readableBytes, 0)\n    }\n\n    func testDiscardReadBytesOnConsumedBuffer() {\n        var buffer = self.allocator.buffer(capacity: 8)\n        buffer.writeInteger(0xaa, as: UInt8.self)\n        XCTAssertEqual(1, buffer.readableBytes)\n        XCTAssertEqual(0xaa, buffer.readInteger(as: UInt8.self))\n        XCTAssertEqual(0, buffer.readableBytes)\n\n        let buffer2 = buffer\n        XCTAssertTrue(buffer.discardReadBytes())\n        XCTAssertEqual(0, buffer.readerIndex)\n        XCTAssertEqual(0, buffer.writerIndex)\n        // As we fully consumed the buffer we should only have adjusted the indices but not triggered a copy as result of CoW semantics.\n        // So we should still be able to also read the old data.\n        buffer.moveWriterIndex(to: 1)\n        buffer.moveReaderIndex(to: 0)\n        XCTAssertEqual(0xaa, buffer.getInteger(at: 0, as: UInt8.self))\n        XCTAssertEqual(0, buffer2.readableBytes)\n    }\n\n    func testShrinkBufferCapacityWithNoLeadingUnwrittenBytes() {\n        let desiredCapacity = 1024\n        var buffer = self.allocator.buffer(capacity: 512)\n\n        // For any item, it should not shrink buffer capacity to a value larger than the current buffer capacity\n        buffer.clear()\n        buffer.writeString(\"Any item\")\n        XCTAssertFalse(buffer.shrinkBufferCapacity(to: 2048))\n        XCTAssertEqual(buffer.capacity, 512)\n\n        // If desired capacity are less than or equal to buffer capacity, should not shrink\n        buffer.clear()\n        buffer.writeString(String(repeating: \"x\", count: desiredCapacity))\n        XCTAssertEqual(buffer.capacity, 1024)  // Before\n        XCTAssertFalse(buffer.shrinkBufferCapacity(to: desiredCapacity))\n        XCTAssertEqual(buffer.capacity, 1024)  // After\n\n        // If desiredCapacity is less than readable bytes, do not shrink\n        buffer.clear()\n        buffer.writeString(String(repeating: \"x\", count: desiredCapacity + 1))\n        XCTAssertEqual(buffer.capacity, 2048)\n        XCTAssertFalse(buffer.shrinkBufferCapacity(to: desiredCapacity))\n        XCTAssertEqual(buffer.capacity, 2048)\n\n        // If desired capacity is greater than or equal the readable bytes and less than buffer capacity, should shrink\n        buffer.clear()\n        buffer.writeString(String(repeating: \"x\", count: desiredCapacity))\n        XCTAssertEqual(buffer.capacity, 2048)\n        XCTAssertTrue(buffer.shrinkBufferCapacity(to: desiredCapacity))\n        XCTAssertEqual(buffer.capacity, 1024)\n    }\n\n    func testShrinkBufferCapacityWithLeadingUnwrittenBytes() {\n        var buffer = self.allocator.buffer(capacity: 16384)\n        buffer.moveWriterIndex(to: 16000)\n        buffer.moveReaderIndex(to: 16000)\n        buffer.writeString(\"WW\")\n        buffer.shrinkBufferCapacity(to: 4)\n        XCTAssertEqual(\"WW\", String(buffer: buffer))\n\n        // If readable bytes is exactly the same as buffer capacity shrunken to\n        buffer = self.allocator.buffer(capacity: 16)\n        buffer.moveWriterIndex(to: 8)\n        buffer.moveReaderIndex(to: 8)\n        buffer.writeString(\"WWWWWWWW\")  // 8 bytes written\n        buffer.shrinkBufferCapacity(to: 4)  // Invisible padding makes this 8 bytes\n        XCTAssertEqual(\"WWWWWWWW\", String(buffer: buffer))  // All 8 bytes are returned!\n    }\n\n    func testExpansionOfCapacityWithPadding() throws {\n        XCTAssertEqual(ByteBuffer.roundUpToUsableCapacity(12), 16)\n        XCTAssertEqual(ByteBuffer.roundUpToUsableCapacity(0), 0)\n        XCTAssertEqual(ByteBuffer.roundUpToUsableCapacity(UInt32.min), 0)\n        XCTAssertEqual(ByteBuffer.roundUpToUsableCapacity(UInt32.max), UInt32.max)\n    }\n\n    func testDumpBytesFormat() throws {\n        self.buf.clear()\n        for f in UInt8.min...UInt8.max {\n            self.buf.writeInteger(f)\n        }\n        let actual = self.buf._storage.dumpBytes(slice: self.buf._slice, offset: 0, length: self.buf.readableBytes)\n        let expected = \"\"\"\n            [ 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f \\\n            20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f \\\n            40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f \\\n            60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f \\\n            80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f \\\n            a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf \\\n            c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df \\\n            e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff ]\n            \"\"\"\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testWriteHexEncodedBytes() throws {\n        var buffer = try ByteBuffer(plainHexEncodedBytes: \"68 65 6c 6c 6f 20 77 6f 72 6c 64 0a\")\n        XCTAssertEqual(try buffer.writePlainHexEncodedBytes(\"68656c6c6f20776f726c64\"), 11)\n        XCTAssertEqual(try buffer.writePlainHexEncodedBytes(\"     0a    \"), 1)\n        XCTAssertEqual(try buffer.writePlainHexEncodedBytes(\"\"), 0)\n        XCTAssertEqual(try buffer.writePlainHexEncodedBytes(\"      \"), 0)\n        XCTAssertEqual(ByteBuffer(string: \"hello world\\nhello world\\n\"), buffer)\n    }\n\n    func testWriteHexEncodedBytesFails() throws {\n        var buffer = ByteBuffer()\n        XCTAssertThrowsError(try buffer.writePlainHexEncodedBytes(\"    1  \")) { error in\n            XCTAssertTrue((error as? ByteBuffer.HexDecodingError) == ByteBuffer.HexDecodingError.invalidCharacter)\n        }\n        XCTAssertThrowsError(try buffer.writePlainHexEncodedBytes(\"    1\")) { error in\n            XCTAssertTrue((error as? ByteBuffer.HexDecodingError) == ByteBuffer.HexDecodingError.invalidHexLength)\n        }\n        XCTAssertThrowsError(try buffer.writePlainHexEncodedBytes(\"1       \")) { error in\n            XCTAssertTrue((error as? ByteBuffer.HexDecodingError) == ByteBuffer.HexDecodingError.invalidCharacter)\n        }\n        XCTAssertThrowsError(try buffer.writePlainHexEncodedBytes(\"🤓\")) { error in\n            XCTAssertTrue((error as? ByteBuffer.HexDecodingError) == ByteBuffer.HexDecodingError.invalidCharacter)\n        }\n        XCTAssertThrowsError(try buffer.writePlainHexEncodedBytes(\"1 1\")) { error in\n            XCTAssertTrue((error as? ByteBuffer.HexDecodingError) == ByteBuffer.HexDecodingError.invalidCharacter)\n        }\n\n        // The first byte (68 = \"h\") is valid, the method throws and the valid byte IS NOT written to the ByteBuffer\n        XCTAssertThrowsError(try buffer.writePlainHexEncodedBytes(\"68 1\")) { error in\n            XCTAssertTrue((error as? ByteBuffer.HexDecodingError) == ByteBuffer.HexDecodingError.invalidHexLength)\n        }\n        XCTAssertTrue(buffer.readableBytesView.isEmpty)\n    }\n\n    func testHexInitialiser() throws {\n        var allBytes = ByteBufferAllocator().buffer(capacity: Int(UInt8.max))\n        for x in UInt8.min...UInt8.max {\n            allBytes.writeInteger(x)\n        }\n\n        let allBytesHex = allBytes.hexDump(format: .plain)\n        let allBytesDecoded = try ByteBuffer(plainHexEncodedBytes: allBytesHex)\n        XCTAssertEqual(allBytes, allBytesDecoded)\n\n        // Edge cases\n        XCTAssertEqual(try ByteBuffer(plainHexEncodedBytes: \" \"), ByteBufferAllocator.zeroCapacityWithDefaultAllocator)\n        XCTAssertThrowsError(try ByteBuffer(plainHexEncodedBytes: \" 1  \"))\n    }\n\n    func testHexDumpPlain() {\n        let buf = ByteBuffer(string: \"Hello\")\n        XCTAssertEqual(\"48 65 6c 6c 6f\", buf.hexDump(format: .plain))\n    }\n\n    func testHexDumpPlainEmptyBuffer() {\n        let buf = ByteBuffer(string: \"\")\n        XCTAssertEqual(\"\", buf.hexDump(format: .plain))\n    }\n\n    func testHexDumpPlainWithReaderIndexOffset() {\n        var buf = ByteBuffer(string: \"Hello\")\n        let firstTwo = buf.readBytes(length: 2)!\n        XCTAssertEqual([72, 101], firstTwo)\n        XCTAssertEqual(\"6c 6c 6f\", buf.hexDump(format: .plain))\n    }\n\n    func testHexDumpPlainWithMaxBytes() {\n        self.buf.clear()\n        for f in UInt8.min...UInt8.max {\n            self.buf.writeInteger(f)\n        }\n        let actual = self.buf.hexDump(format: .plain(maxBytes: 10))\n        let expected = \"00 01 02 03 04 ... fb fc fd fe ff\"\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testHexDumpCompact() {\n        let buf = ByteBuffer(string: \"Hello\")\n        XCTAssertEqual(\"48656c6c6f\", buf.hexDump(format: .compact))\n    }\n\n    func testHexDumpCompactReadableBytesLessThenMaxBytes() {\n        let buf = ByteBuffer(string: \"hello world\")\n        XCTAssertEqual(\"68656c6c6f20776f726c64\", buf.hexDump(format: .compact(maxBytes: 100)))\n    }\n\n    func testHexDumpCompactEmptyBuffer() {\n        let buf = ByteBuffer(string: \"\")\n        XCTAssertEqual(\"\", buf.hexDump(format: .compact))\n    }\n\n    func testHexDumpCompactWithReaderIndexOffset() {\n        var buf = ByteBuffer(string: \"Hello\")\n        let firstTwo = buf.readBytes(length: 2)!\n        XCTAssertEqual([72, 101], firstTwo)\n        XCTAssertEqual(\"6c6c6f\", buf.hexDump(format: .compact))\n    }\n\n    func testHexDumpCompactWithMaxBytes() {\n        self.buf.clear()\n        for f in UInt8.min...UInt8.max {\n            self.buf.writeInteger(f)\n        }\n        let actual = self.buf.hexDump(format: .compact(maxBytes: 10))\n        let expected = \"0001020304...fbfcfdfeff\"\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testHexDumpDetailed() {\n        let buf = ByteBuffer(string: \"Goodbye, world! It was nice knowing you.\\n\")\n        let expected = \"\"\"\n            00000000  47 6f 6f 64 62 79 65 2c  20 77 6f 72 6c 64 21 20  |Goodbye, world! |\n            00000010  49 74 20 77 61 73 20 6e  69 63 65 20 6b 6e 6f 77  |It was nice know|\n            00000020  69 6e 67 20 79 6f 75 2e  0a                       |ing you..|\n            00000029\n            \"\"\"\n        let actual = buf.hexDump(format: .detailed)\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testHexDumpDetailedWithMaxBytes() {\n        let buf = ByteBuffer(string: \"Goodbye, world! It was nice knowing you.\\n\")\n        let expected = \"\"\"\n            00000000  47 6f 6f 64 62 79 65 2c                           |Goodbye,        |\n            ........  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  ..................\n            00000020                           6e 67 20 79 6f 75 2e 0a  |        ng you..|\n            00000029\n            \"\"\"\n        let actual = buf.hexDump(format: .detailed(maxBytes: 16))\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testHexDumpDetailedWithMultilineFrontAndBack() {\n        let buf = ByteBuffer(\n            string: \"\"\"\n                Goodbye, world! It was nice knowing you.\n                I will miss this pull request with all of it's 94+ comments.\n                \"\"\"\n        )\n\n        let expected = \"\"\"\n            00000000  47 6f 6f 64 62 79 65 2c  20 77 6f 72 6c 64 21 20  |Goodbye, world! |\n            00000010  49 74                                             |It              |\n            ........  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  ..................\n            00000050           69 74 27 73 20  39 34 2b 20 63 6f 6d 6d  |   it's 94+ comm|\n            00000060  65 6e 74 73 2e                                    |ents.|\n            00000065\n            \"\"\"\n        let actual = buf.hexDump(format: .detailed(maxBytes: 36))\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testHexDumpDetailedWithOffset() {\n        var buf = ByteBuffer(string: \"Goodbye, world! It was nice knowing you.\\n\")\n        let _ = buf.readBytes(length: 5)\n        let expected = \"\"\"\n            00000000  79 65 2c 20 77 6f 72 6c  64 21 20 49 74 20 77 61  |ye, world! It wa|\n            00000010  73 20 6e 69 63 65 20 6b  6e 6f 77 69 6e 67 20 79  |s nice knowing y|\n            00000020  6f 75 2e 0a                                       |ou..|\n            00000024\n            \"\"\"\n        let actual = buf.hexDump(format: .detailed)\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testHexDumpLongEmptyBuffer() {\n        let buf = ByteBuffer()\n        let expected = \"\"\n        let actual = buf.hexDump(format: .detailed)\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testReadableBytesView() throws {\n        self.buf.clear()\n        self.buf.writeString(\"hello world 012345678\")\n        XCTAssertEqual(\"hello \", self.buf.readString(length: 6))\n        self.buf.moveWriterIndex(to: self.buf.writerIndex - 10)\n        XCTAssertEqual(\"world\", String(decoding: self.buf.readableBytesView, as: Unicode.UTF8.self))\n        XCTAssertEqual(\"world\", self.buf.readString(length: self.buf.readableBytes))\n    }\n\n    func testReadableBytesViewNoReadableBytes() throws {\n        self.buf.clear()\n        let view = self.buf.readableBytesView\n        XCTAssertEqual(0, view.count)\n    }\n\n    func testBytesView() throws {\n        self.buf.clear()\n        self.buf.writeString(\"hello world 012345678\")\n        XCTAssertEqual(\n            self.buf.viewBytes(\n                at: self.buf.readerIndex,\n                length: self.buf.writerIndex - self.buf.readerIndex\n            ).map { (view: ByteBufferView) -> String in\n                String(decoding: view, as: Unicode.UTF8.self)\n            },\n            self.buf.getString(at: self.buf.readerIndex, length: self.buf.readableBytes)\n        )\n        XCTAssertEqual(self.buf.viewBytes(at: 0, length: 0).map { Array($0) }, [])\n        XCTAssertEqual(\n            Array(\"hello world 012345678\".utf8),\n            self.buf.viewBytes(at: 0, length: self.buf.readableBytes).map(Array.init)\n        )\n    }\n\n    func testViewsStartIndexIsStable() throws {\n        self.buf.writeString(\"hello\")\n        let view: ByteBufferView? = self.buf.viewBytes(at: 1, length: 3)\n        XCTAssertEqual(1, view?.startIndex)\n        XCTAssertEqual(3, view?.count)\n        XCTAssertEqual(4, view?.endIndex)\n        XCTAssertEqual(\"ell\", view.map { String(decoding: $0, as: Unicode.UTF8.self) })\n    }\n\n    func testSlicesOfByteBufferViewsAreByteBufferViews() throws {\n        self.buf.writeString(\"hello\")\n        let view: ByteBufferView? = self.buf.viewBytes(at: 1, length: 3)\n        XCTAssertEqual(\"ell\", view.map { String(decoding: $0, as: Unicode.UTF8.self) })\n        let viewSlice: ByteBufferView? = view.map { $0[$0.startIndex + 1..<$0.endIndex] }\n        XCTAssertEqual(\"ll\", viewSlice.map { String(decoding: $0, as: Unicode.UTF8.self) })\n        XCTAssertEqual(\"l\", viewSlice.map { String(decoding: $0.dropFirst(), as: Unicode.UTF8.self) })\n        XCTAssertEqual(\"\", viewSlice.map { String(decoding: $0.dropFirst().dropLast(), as: Unicode.UTF8.self) })\n    }\n\n    func testReadableBufferViewRangeEqualCapacity() throws {\n        self.buf.clear()\n        self.buf.moveWriterIndex(forwardBy: buf.capacity)\n        let view = self.buf.readableBytesView\n        let viewSlice: ByteBufferView = view[view.startIndex..<view.endIndex]\n        XCTAssertEqual(buf.readableBytes, viewSlice.count)\n    }\n\n    func testBufferViewCoWs() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2])\n        var view = self.buf.readableBytesView\n        view.replaceSubrange(view.indices, with: [0xa, 0xb, 0xc])\n\n        XCTAssertEqual(self.buf.readBytes(length: 3), [0x0, 0x1, 0x2])\n        XCTAssertTrue(view.elementsEqual([0xa, 0xb, 0xc]))\n\n        self.buf.writeBytes([0x0, 0x1, 0x2])\n        view = self.buf.readableBytesView\n        view.replaceSubrange(view.indices, with: [0xa, 0xb])\n\n        XCTAssertEqual(self.buf.readBytes(length: 3), [0x0, 0x1, 0x2])\n        XCTAssertTrue(view.elementsEqual([0xa, 0xb]))\n\n        self.buf.writeBytes([0x0, 0x1, 0x2])\n        view = self.buf.readableBytesView\n        view.replaceSubrange(view.indices, with: [0xa, 0xb, 0xc, 0xd])\n\n        XCTAssertEqual(self.buf.readBytes(length: 3), [0x0, 0x1, 0x2])\n        XCTAssertTrue(view.elementsEqual([0xa, 0xb, 0xc, 0xd]))\n    }\n\n    func testBufferViewMutationViaSubscriptIndex() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2])\n        var view = self.buf.readableBytesView\n\n        view[0] = 0xa\n        view[1] = 0xb\n        view[2] = 0xc\n\n        XCTAssertTrue(view.elementsEqual([0xa, 0xb, 0xc]))\n    }\n\n    func testBufferViewReplaceBeyondEndOfRange() throws {\n        self.buf.writeBytes([1, 2, 3])\n        var view = self.buf.readableBytesView\n        view.replaceSubrange(2..<3, with: [2, 3, 4])\n        XCTAssertTrue(view.elementsEqual([1, 2, 2, 3, 4]))\n    }\n\n    func testBufferViewReplaceWithSubrangeOfSelf() throws {\n        let oneToNine: [UInt8] = (1...9).map { $0 }\n        self.buf.writeBytes(oneToNine)\n        var view = self.buf.readableBytesView\n\n        view[6..<9] = view[0..<3]\n        XCTAssertTrue(view.elementsEqual([1, 2, 3, 4, 5, 6, 1, 2, 3]))\n\n        view[0..<3] = view[1..<4]\n        XCTAssertTrue(view.elementsEqual([2, 3, 4, 4, 5, 6, 1, 2, 3]))\n\n        view[1..<4] = view[0..<3]\n        XCTAssertTrue(view.elementsEqual([2, 2, 3, 4, 5, 6, 1, 2, 3]))\n    }\n\n    func testBufferViewMutationViaSubscriptRange() throws {\n        let oneToNine: [UInt8] = (1...9).map { $0 }\n        var oneToNineBuffer = self.allocator.buffer(capacity: 9)\n        oneToNineBuffer.writeBytes(oneToNine)\n        let oneToNineView = oneToNineBuffer.readableBytesView\n\n        self.buf.writeBytes(Array(repeating: UInt8(0), count: 9))\n        var view = self.buf.readableBytesView\n\n        view[0..<3] = oneToNineView[0..<3]\n        XCTAssertTrue(view.elementsEqual([1, 2, 3, 0, 0, 0, 0, 0, 0]))\n\n        // Replace with shorter range\n        view[3..<6] = oneToNineView[3..<5]\n        XCTAssertTrue(view.elementsEqual([1, 2, 3, 4, 5, 0, 0, 0]))\n\n        // Replace with longer range\n        view[5..<8] = oneToNineView[5..<9]\n        XCTAssertTrue(view.elementsEqual(oneToNine))\n    }\n\n    func testBufferViewReplaceSubrangeWithEqualLengthBytes() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2, 0x3, 0x4])\n\n        var view = ByteBufferView(self.buf)\n        XCTAssertEqual(view.count, self.buf.readableBytes)\n\n        view.replaceSubrange(view.indices.suffix(3), with: [0xd, 0xe, 0xf])\n\n        var modifiedBuf = ByteBuffer(view)\n        XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)\n        XCTAssertEqual(self.buf.writerIndex, modifiedBuf.writerIndex)\n        XCTAssertEqual([0x0, 0x1, 0xd, 0xe, 0xf], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)\n    }\n\n    func testBufferViewReplaceSubrangeWithFewerBytes() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2, 0x3, 0x4])\n\n        var view = ByteBufferView(self.buf)\n        view.replaceSubrange(view.indices.suffix(3), with: [0xd])\n\n        var modifiedBuf = ByteBuffer(view)\n        XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)\n        XCTAssertEqual(self.buf.writerIndex - 2, modifiedBuf.writerIndex)\n        XCTAssertEqual([0x0, 0x1, 0xd], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)\n    }\n\n    func testBufferViewReplaceSubrangeWithMoreBytes() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2, 0x3])\n\n        var view = ByteBufferView(self.buf)\n        XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3]))\n\n        view.replaceSubrange(view.indices.suffix(1), with: [0xa, 0xb])\n        XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0xa, 0xb]))\n\n        var modifiedBuf = ByteBuffer(view)\n        XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)\n        XCTAssertEqual(self.buf.writerIndex + 1, modifiedBuf.writerIndex)\n        XCTAssertEqual([0x0, 0x1, 0x2, 0xa, 0xb], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)\n    }\n\n    func testBufferViewAppend() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2, 0x3])\n\n        var view = ByteBufferView(self.buf)\n        XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3]))\n\n        view.append(0xa)\n        XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3, 0xa]))\n\n        var modifiedBuf = ByteBuffer(view)\n        XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)\n        XCTAssertEqual(self.buf.writerIndex + 1, modifiedBuf.writerIndex)\n        XCTAssertEqual([0x0, 0x1, 0x2, 0x3, 0xa], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)\n    }\n\n    func testBufferViewAppendContentsOf() throws {\n        self.buf.writeBytes([0x0, 0x1, 0x2, 0x3])\n\n        var view = ByteBufferView(self.buf)\n        XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3]))\n\n        view.append(contentsOf: [0xa, 0xb])\n        XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3, 0xa, 0xb]))\n\n        var modifiedBuf = ByteBuffer(view)\n        XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)\n        XCTAssertEqual(self.buf.writerIndex + 2, modifiedBuf.writerIndex)\n        XCTAssertEqual([0x0, 0x1, 0x2, 0x3, 0xa, 0xb], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)\n    }\n\n    func testBufferViewEmpty() throws {\n        self.buf.writeBytes([0, 1, 2])\n\n        var view = ByteBufferView()\n        view[0..<0] = self.buf.readableBytesView\n        XCTAssertEqual(view.indices, 0..<3)\n\n        self.buf = ByteBuffer(view)\n        XCTAssertEqual(self.buf.readerIndex, 0)\n        XCTAssertEqual(self.buf.writerIndex, 3)\n\n        let anotherBuf = self.buf!\n        XCTAssertEqual([0, 1, 2], self.buf.readBytes(length: self.buf.readableBytes))\n\n        var anotherView = anotherBuf.readableBytesView\n        anotherView.replaceSubrange(0..<3, with: [])\n        XCTAssertTrue(anotherView.isEmpty)\n\n        self.buf = ByteBuffer(anotherView)\n        XCTAssertEqual(self.buf.readerIndex, 0)\n        XCTAssertEqual(self.buf.writerIndex, 0)\n        XCTAssertEqual([], self.buf.readBytes(length: self.buf.readableBytes))\n    }\n\n    func testBufferViewFirstIndex() {\n        self.buf.clear()\n        self.buf.writeBytes(Array(repeating: UInt8(0x4E), count: 1024))\n        self.buf.setBytes([UInt8(0x59)], at: 1000)\n        self.buf.setBytes([UInt8(0x59)], at: 1001)\n        self.buf.setBytes([UInt8(0x59)], at: 1022)\n        self.buf.setBytes([UInt8(0x59)], at: 3)\n        self.buf.setBytes([UInt8(0x3F)], at: 1023)\n        self.buf.setBytes([UInt8(0x3F)], at: 2)\n        let view = self.buf.viewBytes(at: 5, length: 1010)\n        XCTAssertEqual(1000, view?.firstIndex(of: UInt8(0x59)))\n        XCTAssertNil(view?.firstIndex(of: UInt8(0x3F)))\n    }\n\n    func testBufferViewFirstIndexWithWhereClosure() {\n        self.buf.clear()\n        self.buf.writeBytes(Array(repeating: UInt8(0x4E), count: 1024))\n        self.buf.setBytes([UInt8(0x59)], at: 1000)\n        self.buf.setBytes([UInt8(0x59)], at: 1001)\n        self.buf.setBytes([UInt8(0x59)], at: 1022)\n        self.buf.setBytes([UInt8(0x59)], at: 3)\n        self.buf.setBytes([UInt8(0x3F)], at: 1023)\n        self.buf.setBytes([UInt8(0x3F)], at: 2)\n        let view = self.buf.viewBytes(at: 5, length: 1010)\n        XCTAssertEqual(1000, view?.firstIndex(where: { $0 == UInt8(0x59) }))\n        XCTAssertNil(view?.firstIndex(where: { $0 == UInt8(0x3F) }))\n    }\n\n    func testBufferViewLastIndex() {\n        self.buf.clear()\n        self.buf.writeBytes(Array(repeating: UInt8(0x4E), count: 1024))\n        self.buf.setBytes([UInt8(0x3F)], at: 2)\n        self.buf.setBytes([UInt8(0x59)], at: 3)\n        self.buf.setBytes([UInt8(0x61)], at: 1000)\n        self.buf.setBytes([UInt8(0x59)], at: 1001)\n        self.buf.setBytes([UInt8(0x61)], at: 1002)\n        self.buf.setBytes([UInt8(0x59)], at: 1003)\n        self.buf.setBytes([UInt8(0x61)], at: 1004)\n        self.buf.setBytes([UInt8(0x59)], at: 1023)\n        self.buf.setBytes([UInt8(0x3F)], at: 1024)\n        let view = self.buf.viewBytes(at: 5, length: 1010)\n        XCTAssertEqual(1003, view?.lastIndex(of: UInt8(0x59)))\n        XCTAssertNil(view?.lastIndex(of: UInt8(0x3F)))\n    }\n\n    func testBufferViewLastIndexWithWhereClosure() {\n        self.buf.clear()\n        self.buf.writeBytes(Array(repeating: UInt8(0x4E), count: 1024))\n        self.buf.setBytes([UInt8(0x3F)], at: 2)\n        self.buf.setBytes([UInt8(0x59)], at: 3)\n        self.buf.setBytes([UInt8(0x61)], at: 1000)\n        self.buf.setBytes([UInt8(0x59)], at: 1001)\n        self.buf.setBytes([UInt8(0x61)], at: 1002)\n        self.buf.setBytes([UInt8(0x59)], at: 1003)\n        self.buf.setBytes([UInt8(0x61)], at: 1004)\n        self.buf.setBytes([UInt8(0x59)], at: 1023)\n        self.buf.setBytes([UInt8(0x3F)], at: 1024)\n        let view = self.buf.viewBytes(at: 5, length: 1010)\n        XCTAssertEqual(1003, view?.lastIndex(where: { $0 == UInt8(0x59) }))\n        XCTAssertNil(view?.lastIndex(where: { $0 == UInt8(0x3F) }))\n    }\n\n    func testBufferViewContains() {\n        self.buf.clear()\n        self.buf.writeBytes(Array(repeating: UInt8(0x4E), count: 1024))\n        self.buf.setBytes([UInt8(0x59)], at: 1000)\n        let view: ByteBufferView? = self.buf.viewBytes(at: 5, length: 1010)\n        XCTAssertTrue(view?.contains(UInt8(0x4E)) == true)\n        XCTAssertTrue(view?.contains(UInt8(0x59)) == true)\n        XCTAssertTrue(view?.contains(UInt8(0x3F)) == false)\n    }\n\n    func testByteBuffersCanBeInitializedFromByteBufferViews() throws {\n        self.buf.writeString(\"hello\")\n\n        let readableByteBuffer = ByteBuffer(self.buf.readableBytesView)\n        XCTAssertEqual(self.buf, readableByteBuffer)\n\n        let sliceByteBuffer = self.buf.viewBytes(at: 1, length: 3).map(ByteBuffer.init)\n        XCTAssertEqual(\"ell\", sliceByteBuffer.flatMap { $0.getString(at: 0, length: $0.readableBytes) })\n\n        self.buf.clear()\n\n        let emptyByteBuffer = ByteBuffer(self.buf.readableBytesView)\n        XCTAssertEqual(self.buf, emptyByteBuffer)\n\n        var fixedCapacityBuffer = self.allocator.buffer(capacity: 16)\n        let capacity = fixedCapacityBuffer.capacity\n        fixedCapacityBuffer.writeString(String(repeating: \"x\", count: capacity))\n        XCTAssertEqual(capacity, fixedCapacityBuffer.capacity)\n        XCTAssertEqual(fixedCapacityBuffer, ByteBuffer(fixedCapacityBuffer.readableBytesView))\n    }\n\n    func testReserveCapacityWhenOversize() throws {\n        let oldCapacity = buf.capacity\n        let oldPtrVal = buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        buf.reserveCapacity(oldCapacity - 1)\n        let newPtrVal = buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        XCTAssertEqual(buf.capacity, oldCapacity)\n        XCTAssertEqual(oldPtrVal, newPtrVal)\n    }\n\n    func testReserveCapacitySameCapacity() throws {\n        let oldCapacity = buf.capacity\n        let oldPtrVal = buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        buf.reserveCapacity(oldCapacity)\n        let newPtrVal = buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        XCTAssertEqual(buf.capacity, oldCapacity)\n        XCTAssertEqual(oldPtrVal, newPtrVal)\n    }\n\n    func testReserveCapacityLargerUniquelyReferencedCallsRealloc() throws {\n        testReserveCapacityLarger_reallocCount.store(0, ordering: .sequentiallyConsistent)\n        testReserveCapacityLarger_mallocCount.store(0, ordering: .sequentiallyConsistent)\n\n        let alloc = ByteBufferAllocator(\n            allocate: testReserveCapacityLarger_mallocHook,\n            reallocate: testReserveCapacityLarger_reallocHook,\n            deallocate: testReserveCapacityLarger_freeHook,\n            copy: testReserveCapacityLarger_memcpyHook\n        )\n        var buf = alloc.buffer(capacity: 16)\n\n        let oldCapacity = buf.capacity\n\n        XCTAssertEqual(testReserveCapacityLarger_mallocCount.load(ordering: .sequentiallyConsistent), 1)\n        XCTAssertEqual(testReserveCapacityLarger_reallocCount.load(ordering: .sequentiallyConsistent), 0)\n        buf.reserveCapacity(32)\n        XCTAssertEqual(testReserveCapacityLarger_mallocCount.load(ordering: .sequentiallyConsistent), 1)\n        XCTAssertEqual(testReserveCapacityLarger_reallocCount.load(ordering: .sequentiallyConsistent), 1)\n        XCTAssertNotEqual(buf.capacity, oldCapacity)\n    }\n\n    func testReserveCapacityLargerMultipleReferenceCallsMalloc() throws {\n        testReserveCapacityLarger_reallocCount.store(0, ordering: .sequentiallyConsistent)\n        testReserveCapacityLarger_mallocCount.store(0, ordering: .sequentiallyConsistent)\n\n        let alloc = ByteBufferAllocator(\n            allocate: testReserveCapacityLarger_mallocHook,\n            reallocate: testReserveCapacityLarger_reallocHook,\n            deallocate: testReserveCapacityLarger_freeHook,\n            copy: testReserveCapacityLarger_memcpyHook\n        )\n        var buf = alloc.buffer(capacity: 16)\n        var bufCopy = buf\n\n        withExtendedLifetime(bufCopy) {\n            let oldCapacity = buf.capacity\n            let oldPtrVal = buf.withVeryUnsafeBytes {\n                UInt(bitPattern: $0.baseAddress!)\n            }\n\n            XCTAssertEqual(testReserveCapacityLarger_mallocCount.load(ordering: .sequentiallyConsistent), 1)\n            XCTAssertEqual(testReserveCapacityLarger_reallocCount.load(ordering: .sequentiallyConsistent), 0)\n            buf.reserveCapacity(32)\n            XCTAssertEqual(testReserveCapacityLarger_mallocCount.load(ordering: .sequentiallyConsistent), 2)\n            XCTAssertEqual(testReserveCapacityLarger_reallocCount.load(ordering: .sequentiallyConsistent), 0)\n\n            let newPtrVal = buf.withVeryUnsafeBytes {\n                UInt(bitPattern: $0.baseAddress!)\n            }\n\n            XCTAssertNotEqual(buf.capacity, oldCapacity)\n            XCTAssertNotEqual(oldPtrVal, newPtrVal)\n        }\n        // stops the optimiser removing `bufCopy` which would make `reserveCapacity` use malloc instead of realloc\n        bufCopy.writeString(\"foo\")\n    }\n\n    func testReserveCapacityWithMinimumWritableBytesWhenNotEnoughWritableBytes() {\n        // Ensure we have a non-empty buffer since the writer index is involved here.\n        self.buf.writeBytes((UInt8.min...UInt8.max))\n\n        let writableBytes = self.buf.writableBytes\n        self.buf.reserveCapacity(minimumWritableBytes: writableBytes + 1)\n        XCTAssertGreaterThanOrEqual(self.buf.writableBytes, writableBytes + 1)\n    }\n\n    func testReserveCapacityWithMinimumWritableBytesWhenEnoughWritableBytes() {\n        // Ensure we have a non-empty buffer since the writer index is involved here.\n        self.buf.writeBytes((UInt8.min...UInt8.max))\n\n        // Ensure we have some space.\n        self.buf.reserveCapacity(minimumWritableBytes: 5)\n\n        let oldPtrVal = self.buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        let writableBytes = self.buf.writableBytes\n        self.buf.reserveCapacity(minimumWritableBytes: writableBytes - 1)\n\n        let newPtrVal = self.buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        XCTAssertEqual(self.buf.writableBytes, writableBytes)\n        XCTAssertEqual(oldPtrVal, newPtrVal)\n    }\n\n    func testReserveCapacityWithMinimumWritableBytesWhenSameWritableBytes() {\n        // Ensure we have a non-empty buffer since the writer index is involved here.\n        self.buf.writeBytes((UInt8.min...UInt8.max))\n\n        // Ensure we have some space.\n        self.buf.reserveCapacity(minimumWritableBytes: 5)\n\n        let oldPtrVal = self.buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        let writableBytes = self.buf.writableBytes\n        self.buf.reserveCapacity(minimumWritableBytes: writableBytes)\n\n        let newPtrVal = self.buf.withVeryUnsafeBytes {\n            UInt(bitPattern: $0.baseAddress!)\n        }\n\n        XCTAssertEqual(self.buf.writableBytes, writableBytes)\n        XCTAssertEqual(oldPtrVal, newPtrVal)\n    }\n\n    func testReadWithFunctionsThatReturnNumberOfReadBytesAreDiscardable() {\n        var buf = self.buf!\n        buf.writeString(\"ABCD\")\n\n        // deliberately not ignoring the result\n        buf.readWithUnsafeReadableBytes { buffer in\n            XCTAssertEqual(4, buffer.count)\n            return 2\n        }\n\n        // deliberately not ignoring the result\n        buf.readWithUnsafeMutableReadableBytes { buffer in\n            XCTAssertEqual(2, buffer.count)\n            return 2\n        }\n\n        XCTAssertEqual(0, buf.readableBytes)\n    }\n\n    func testWriteAndSetAndGetAndReadEncoding() throws {\n        var buf = self.buf!\n        buf.clear()\n\n        var writtenBytes = try assertNoThrowWithValue(buf.writeString(\"ÆBCD\", encoding: .utf16LittleEndian))\n        XCTAssertEqual(writtenBytes, 8)\n        XCTAssertEqual(buf.readableBytes, 8)\n        XCTAssertEqual(buf.getString(at: buf.readerIndex + 2, length: 6, encoding: .utf16LittleEndian), \"BCD\")\n\n        writtenBytes = try assertNoThrowWithValue(buf.setString(\"EFGH\", encoding: .utf32BigEndian, at: buf.readerIndex))\n        XCTAssertEqual(writtenBytes, 16)\n        XCTAssertEqual(buf.readableBytes, 8)\n        XCTAssertEqual(buf.readString(length: 8, encoding: .utf32BigEndian), \"EF\")\n        XCTAssertEqual(buf.readableBytes, 0)\n\n        buf.clear()\n\n        // Confirm that we do throw.\n        XCTAssertThrowsError(try buf.setString(\"🤷‍♀️\", encoding: .ascii, at: buf.readerIndex)) {\n            XCTAssertEqual($0 as? ByteBufferFoundationError, .failedToEncodeString)\n        }\n        XCTAssertThrowsError(try buf.writeString(\"🤷‍♀️\", encoding: .ascii)) {\n            XCTAssertEqual($0 as? ByteBufferFoundationError, .failedToEncodeString)\n        }\n    }\n\n    func testPossiblyLazilyBridgedString() {\n        // won't hit the String writing fast path\n        let utf16Bytes = Data([\n            0xfe, 0xff, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0xe4, 0x00, 0xe4, 0x00, 0xe4, 0x00, 0x0a,\n        ])\n        let slowString = String(data: utf16Bytes, encoding: .utf16)!\n\n        self.buf.clear()\n        let written = self.buf.writeString(slowString as String)\n        XCTAssertEqual(10, written)\n        XCTAssertEqual(\"abcäää\\n\", String(decoding: self.buf.readableBytesView, as: Unicode.UTF8.self))\n    }\n\n    func testWithVeryUnsafeMutableBytesWorksOnEmptyByteBuffer() {\n        var buf = self.allocator.buffer(capacity: 0)\n        XCTAssertEqual(0, buf.capacity)\n        buf.withVeryUnsafeMutableBytes { ptr in\n            XCTAssertEqual(0, ptr.count)\n        }\n    }\n\n    func testWithVeryUnsafeMutableBytesYieldsPointerToWholeStorage() {\n        var buf = self.allocator.buffer(capacity: 16)\n        let capacity = buf.capacity\n        XCTAssertGreaterThanOrEqual(capacity, 16)\n        buf.writeString(\"1234\")\n        XCTAssertEqual(capacity, buf.capacity)\n        buf.withVeryUnsafeMutableBytes { ptr in\n            XCTAssertEqual(capacity, ptr.count)\n            XCTAssertEqual(\"1234\", String(decoding: ptr[0..<4], as: Unicode.UTF8.self))\n        }\n    }\n\n    func testWithVeryUnsafeMutableBytesYieldsPointerToWholeStorageAndCanBeWritenTo() {\n        var buf = self.allocator.buffer(capacity: 16)\n        let capacity = buf.capacity\n        XCTAssertGreaterThanOrEqual(capacity, 16)\n        buf.writeString(\"1234\")\n        XCTAssertEqual(capacity, buf.capacity)\n        buf.withVeryUnsafeMutableBytes { ptr in\n            XCTAssertEqual(capacity, ptr.count)\n            XCTAssertEqual(\"1234\", String(decoding: ptr[0..<4], as: Unicode.UTF8.self))\n            UnsafeMutableRawBufferPointer(rebasing: ptr[4..<8]).copyBytes(from: \"5678\".utf8)\n        }\n        buf.moveWriterIndex(forwardBy: 4)\n        XCTAssertEqual(\"12345678\", buf.readString(length: buf.readableBytes))\n\n        buf.withVeryUnsafeMutableBytes { ptr in\n            XCTAssertEqual(capacity, ptr.count)\n            XCTAssertEqual(\"12345678\", String(decoding: ptr[0..<8], as: Unicode.UTF8.self))\n            ptr[0] = \"X\".utf8.first!\n            UnsafeMutableRawBufferPointer(rebasing: ptr[8..<16]).copyBytes(from: \"abcdefgh\".utf8)\n        }\n        buf.moveWriterIndex(forwardBy: 8)\n        XCTAssertEqual(\"abcdefgh\", buf.readString(length: buf.readableBytes))\n        buf.moveWriterIndex(to: 1)\n        buf.moveReaderIndex(to: 0)\n        XCTAssertEqual(\"X\", buf.getString(at: 0, length: 1))\n    }\n\n    func testWithVeryUnsafeMutableBytesDoesCoW() {\n        var buf = self.allocator.buffer(capacity: 16)\n        let capacity = buf.capacity\n        XCTAssertGreaterThanOrEqual(capacity, 16)\n        buf.writeString(\"1234\")\n        let bufCopy = buf\n        XCTAssertEqual(capacity, buf.capacity)\n        buf.withVeryUnsafeMutableBytes { ptr in\n            XCTAssertEqual(capacity, ptr.count)\n            XCTAssertEqual(\"1234\", String(decoding: ptr[0..<4], as: Unicode.UTF8.self))\n            UnsafeMutableRawBufferPointer(rebasing: ptr[0..<8]).copyBytes(from: \"abcdefgh\".utf8)\n        }\n        buf.moveWriterIndex(forwardBy: 4)\n        XCTAssertEqual(\"1234\", String(decoding: bufCopy.readableBytesView, as: Unicode.UTF8.self))\n        XCTAssertEqual(\"abcdefgh\", String(decoding: buf.readableBytesView, as: Unicode.UTF8.self))\n    }\n\n    func testWithVeryUnsafeMutableBytesDoesCoWonSlices() {\n        var buf = self.allocator.buffer(capacity: 16)\n        let capacity = buf.capacity\n        XCTAssertGreaterThanOrEqual(capacity, 16)\n        buf.writeString(\"1234567890\")\n        var buf2 = buf.getSlice(at: 4, length: 4)!\n        XCTAssertEqual(capacity, buf.capacity)\n        let capacity2 = buf2.capacity\n        buf2.withVeryUnsafeMutableBytes { ptr in\n            XCTAssertEqual(capacity2, ptr.count)\n            XCTAssertEqual(\"5678\", String(decoding: ptr[0..<4], as: Unicode.UTF8.self))\n            UnsafeMutableRawBufferPointer(rebasing: ptr[0..<4]).copyBytes(from: \"QWER\".utf8)\n        }\n        XCTAssertEqual(\"QWER\", String(decoding: buf2.readableBytesView, as: Unicode.UTF8.self))\n        XCTAssertEqual(\"1234567890\", String(decoding: buf.readableBytesView, as: Unicode.UTF8.self))\n    }\n\n    func testGetDispatchDataWorks() {\n        self.buf.clear()\n        self.buf.writeString(\"abcdefgh\")\n\n        XCTAssertEqual(0, self.buf.getDispatchData(at: 7, length: 0)!.count)\n        XCTAssertNil(self.buf.getDispatchData(at: self.buf.capacity, length: 1))\n        XCTAssertEqual(\"abcdefgh\", String(decoding: self.buf.getDispatchData(at: 0, length: 8)!, as: Unicode.UTF8.self))\n        XCTAssertEqual(\"ef\", String(decoding: self.buf.getDispatchData(at: 4, length: 2)!, as: Unicode.UTF8.self))\n    }\n\n    func testGetDispatchDataReadWrite() {\n        let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 4, alignment: 0)\n        buffer.copyBytes(from: \"1234\".utf8)\n        defer {\n            buffer.deallocate()\n        }\n        self.buf.clear()\n        self.buf.writeString(\"abcdefgh\")\n        self.buf.writeDispatchData(DispatchData.empty)\n        self.buf.writeDispatchData(DispatchData(bytes: UnsafeRawBufferPointer(buffer)))\n        XCTAssertEqual(12, self.buf.readableBytes)\n        XCTAssertEqual(\"abcdefgh1234\", String(decoding: self.buf.readDispatchData(length: 12)!, as: Unicode.UTF8.self))\n        XCTAssertNil(self.buf.readDispatchData(length: 1))\n        XCTAssertEqual(0, self.buf.readDispatchData(length: 0)?.count ?? 12)\n    }\n\n    func testVariousContiguousStorageAccessors() {\n        self.buf.clear()\n        self.buf.writeStaticString(\"abc0123456789efg\")\n        self.buf.moveReaderIndex(to: 3)\n        self.buf.moveWriterIndex(to: 13)\n\n        func inspectContiguousBytes<Bytes: ContiguousBytes>(bytes: Bytes, expectedString: String) {\n            bytes.withUnsafeBytes { bytes in\n                XCTAssertEqual(expectedString, String(decoding: bytes, as: Unicode.UTF8.self))\n            }\n        }\n        inspectContiguousBytes(bytes: self.buf.readableBytesView, expectedString: \"0123456789\")\n        let r1 = self.buf.readableBytesView.withContiguousStorageIfAvailable { bytes -> String in\n            String(decoding: bytes, as: Unicode.UTF8.self)\n        }\n        XCTAssertEqual(\"0123456789\", r1)\n\n        self.buf.clear()\n        inspectContiguousBytes(bytes: self.buf.readableBytesView, expectedString: \"\")\n        let r2 = self.buf.readableBytesView.withContiguousStorageIfAvailable { bytes -> String in\n            String(decoding: bytes, as: Unicode.UTF8.self)\n        }\n        XCTAssertEqual(\"\", r2)\n    }\n\n    func testGetBytesThatAreNotReadable() {\n        var buf = self.allocator.buffer(capacity: 256)\n\n        // 1) Nothing available\n        // no `get*` should work\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt8.self))\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt16.self))\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt32.self))\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt64.self))\n        XCTAssertNil(buf.getString(at: 0, length: 1))\n        XCTAssertNil(buf.getSlice(at: 0, length: 1))\n        XCTAssertNil(buf.getData(at: 0, length: 1))\n        XCTAssertNil(buf.getDispatchData(at: 0, length: 1))\n        XCTAssertNil(buf.getBytes(at: 0, length: 1))\n        XCTAssertNil(buf.getString(at: 0, length: 1, encoding: .utf8))\n        XCTAssertNil(buf.viewBytes(at: 0, length: 1))\n\n        // but some `get*` should be able to produce empties\n        XCTAssertEqual(\"\", buf.getString(at: 0, length: 0))\n        XCTAssertEqual(0, buf.getSlice(at: 0, length: 0)?.capacity)\n        XCTAssertEqual(Data(), buf.getData(at: 0, length: 0))\n        XCTAssertEqual(0, buf.getDispatchData(at: 0, length: 0)?.count)\n        XCTAssertEqual([], buf.getBytes(at: 0, length: 0))\n        XCTAssertEqual(\"\", buf.getString(at: 0, length: 0, encoding: .utf8))\n        XCTAssertEqual(\"\", buf.viewBytes(at: 0, length: 0).map { String(decoding: $0, as: Unicode.UTF8.self) })\n\n        // 2) One byte available at the beginning\n        buf.writeInteger(0x41, as: UInt8.self)\n\n        // for most `get*`s, we can make them just not work\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt16.self))\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt32.self))\n        XCTAssertNil(buf.getInteger(at: 0, as: UInt64.self))\n        XCTAssertNil(buf.getString(at: 0, length: 2))\n        XCTAssertNil(buf.getSlice(at: 0, length: 2))\n        XCTAssertNil(buf.getData(at: 0, length: 2))\n        XCTAssertNil(buf.getDispatchData(at: 0, length: 2))\n        XCTAssertNil(buf.getBytes(at: 0, length: 2))\n        XCTAssertNil(buf.getString(at: 0, length: 2, encoding: .utf8))\n        XCTAssertNil(buf.viewBytes(at: 0, length: 2))\n\n        XCTAssertNil(buf.getInteger(at: 1, as: UInt8.self))\n        XCTAssertNil(buf.getInteger(at: 1, as: UInt16.self))\n        XCTAssertNil(buf.getInteger(at: 1, as: UInt32.self))\n        XCTAssertNil(buf.getInteger(at: 1, as: UInt64.self))\n        XCTAssertNil(buf.getString(at: 1, length: 1))\n        XCTAssertNil(buf.getSlice(at: 1, length: 1))\n        XCTAssertNil(buf.getData(at: 1, length: 1))\n        XCTAssertNil(buf.getDispatchData(at: 1, length: 1))\n        XCTAssertNil(buf.getBytes(at: 1, length: 1))\n        XCTAssertNil(buf.getString(at: 1, length: 1, encoding: .utf8))\n        XCTAssertNil(buf.viewBytes(at: 1, length: 1))\n\n        // on the other hand, we should be able to take that one byte out\n        XCTAssertEqual(0x41, buf.getInteger(at: 0, as: UInt8.self))\n        XCTAssertEqual(\"A\", buf.getString(at: 0, length: 1))\n        XCTAssertEqual(1, buf.getSlice(at: 0, length: 1)?.capacity)\n        XCTAssertEqual(Data(\"A\".utf8), buf.getData(at: 0, length: 1))\n        XCTAssertEqual(1, buf.getDispatchData(at: 0, length: 1)?.count)\n        XCTAssertEqual([\"A\".utf8.first!], buf.getBytes(at: 0, length: 1))\n        XCTAssertEqual(\"A\", buf.getString(at: 0, length: 1, encoding: .utf8))\n        XCTAssertEqual(\"A\", buf.viewBytes(at: 0, length: 1).map { String(decoding: $0, as: Unicode.UTF8.self) })\n\n        // 3) Now let's have 4 bytes towards the end\n\n        // we can make pretty much all `get*`s fail\n        buf.setInteger(0x4141_4141, at: 251, as: UInt32.self)\n        buf.moveWriterIndex(to: 255)\n        buf.moveReaderIndex(to: 251)\n        XCTAssertNil(buf.getInteger(at: 251, as: UInt64.self))\n        XCTAssertNil(buf.getString(at: 251, length: 5))\n        XCTAssertNil(buf.getSlice(at: 251, length: 5))\n        XCTAssertNil(buf.getData(at: 251, length: 5))\n        XCTAssertNil(buf.getDispatchData(at: 251, length: 5))\n        XCTAssertNil(buf.getBytes(at: 251, length: 5))\n        XCTAssertNil(buf.getString(at: 251, length: 5, encoding: .utf8))\n        XCTAssertNil(buf.viewBytes(at: 251, length: 5))\n\n        XCTAssertEqual(0x41, buf.getInteger(at: 254, as: UInt8.self))\n        XCTAssertEqual(0x4141, buf.getInteger(at: 253, as: UInt16.self))\n        XCTAssertEqual(0x4141_4141, buf.getInteger(at: 251, as: UInt32.self))\n        XCTAssertEqual(\"AAAA\", buf.getString(at: 251, length: 4))\n        XCTAssertEqual(4, buf.getSlice(at: 251, length: 4)?.capacity)\n        XCTAssertEqual(Data(\"AAAA\".utf8), buf.getData(at: 251, length: 4))\n        XCTAssertEqual(4, buf.getDispatchData(at: 251, length: 4)?.count)\n        XCTAssertEqual(Array(repeating: \"A\".utf8.first!, count: 4), buf.getBytes(at: 251, length: 4))\n        XCTAssertEqual(\"AAAA\", buf.getString(at: 251, length: 4, encoding: .utf8))\n        XCTAssertEqual(\"AAAA\", buf.viewBytes(at: 251, length: 4).map { String(decoding: $0, as: Unicode.UTF8.self) })\n    }\n\n    func testByteBufferViewAsDataProtocol() {\n        func checkEquals<D: DataProtocol>(expected: String, actual: D) {\n            var actualBytesAsArray: [UInt8] = []\n            for region in actual.regions {\n                actualBytesAsArray += Array(region)\n            }\n            XCTAssertEqual(expected, String(decoding: actualBytesAsArray, as: Unicode.UTF8.self))\n        }\n        var buf = self.allocator.buffer(capacity: 32)\n        buf.writeStaticString(\"0123abcd4567\")\n        buf.moveReaderIndex(forwardBy: 4)\n        buf.moveWriterIndex(to: buf.writerIndex - 4)\n        checkEquals(expected: \"abcd\", actual: buf.readableBytesView)\n    }\n\n    func testDataByteTransferStrategyNoCopy() {\n        let byteCount = 200_000  // this needs to be large because Data might also decide to copy.\n        self.buf.clear()\n        self.buf.writeString(String(repeating: \"x\", count: byteCount))\n        var byteBufferPointerValue: UInt = 0xbad\n        var dataPointerValue: UInt = 0xdead\n        self.buf.withUnsafeReadableBytes { ptr in\n            byteBufferPointerValue = UInt(bitPattern: ptr.baseAddress)\n        }\n        if let data = self.buf.readData(length: byteCount, byteTransferStrategy: .noCopy) {\n            data.withUnsafeBytes { ptr in\n                dataPointerValue = UInt(bitPattern: ptr.baseAddress)\n            }\n        } else {\n            XCTFail(\"unable to read Data from ByteBuffer\")\n        }\n\n        XCTAssertEqual(byteBufferPointerValue, dataPointerValue)\n    }\n\n    func testDataByteTransferStrategyCopy() {\n        let byteCount = 200_000  // this needs to be large because Data might also decide to copy.\n        self.buf.clear()\n        self.buf.writeString(String(repeating: \"x\", count: byteCount))\n        var byteBufferPointerValue: UInt = 0xbad\n        var dataPointerValue: UInt = 0xdead\n        self.buf.withUnsafeReadableBytes { ptr in\n            byteBufferPointerValue = UInt(bitPattern: ptr.baseAddress)\n        }\n        if let data = self.buf.readData(length: byteCount, byteTransferStrategy: .copy) {\n            data.withUnsafeBytes { ptr in\n                dataPointerValue = UInt(bitPattern: ptr.baseAddress)\n            }\n        } else {\n            XCTFail(\"unable to read Data from ByteBuffer\")\n        }\n\n        XCTAssertNotEqual(byteBufferPointerValue, dataPointerValue)\n    }\n\n    func testDataByteTransferStrategyAutomaticMayNotCopy() {\n        let byteCount = 500_000  // this needs to be larger than ByteBuffer's heuristic's threshold.\n        self.buf.clear()\n        self.buf.writeString(String(repeating: \"x\", count: byteCount))\n        var byteBufferPointerValue: UInt = 0xbad\n        var dataPointerValue: UInt = 0xdead\n        self.buf.withUnsafeReadableBytes { ptr in\n            byteBufferPointerValue = UInt(bitPattern: ptr.baseAddress)\n        }\n        if let data = self.buf.readData(length: byteCount, byteTransferStrategy: .automatic) {\n            data.withUnsafeBytes { ptr in\n                dataPointerValue = UInt(bitPattern: ptr.baseAddress)\n            }\n        } else {\n            XCTFail(\"unable to read Data from ByteBuffer\")\n        }\n\n        XCTAssertEqual(byteBufferPointerValue, dataPointerValue)\n    }\n\n    func testDataByteTransferStrategyAutomaticMayCopy() {\n        let byteCount = 200_000  // above Data's 'do not copy' but less than ByteBuffer's 'do not copy' threshold.\n        self.buf.clear()\n        self.buf.writeString(String(repeating: \"x\", count: byteCount))\n        var byteBufferPointerValue: UInt = 0xbad\n        var dataPointerValue: UInt = 0xdead\n        self.buf.withUnsafeReadableBytes { ptr in\n            byteBufferPointerValue = UInt(bitPattern: ptr.baseAddress)\n        }\n        if let data = self.buf.readData(length: byteCount, byteTransferStrategy: .automatic) {\n            data.withUnsafeBytes { ptr in\n                dataPointerValue = UInt(bitPattern: ptr.baseAddress)\n            }\n        } else {\n            XCTFail(\"unable to read Data from ByteBuffer\")\n        }\n\n        XCTAssertNotEqual(byteBufferPointerValue, dataPointerValue)\n    }\n\n    func testViewBytesIsHappyWithNegativeValues() {\n        self.buf.clear()\n        XCTAssertNil(self.buf.viewBytes(at: -1, length: 0))\n        XCTAssertNil(self.buf.viewBytes(at: 0, length: -1))\n        XCTAssertNil(self.buf.viewBytes(at: -1, length: -1))\n\n        self.buf.writeString(\"hello world\")\n        self.buf.moveWriterIndex(forwardBy: 6)\n\n        XCTAssertNil(self.buf.viewBytes(at: -1, length: 0))\n        XCTAssertNil(self.buf.viewBytes(at: 0, length: -1))\n        XCTAssertNil(self.buf.viewBytes(at: -1, length: -1))\n    }\n\n    func testByteBufferAllocatorSize1Capacity() {\n        let buffer = ByteBufferAllocator().buffer(capacity: 1)\n        XCTAssertEqual(1, buffer.capacity)\n    }\n\n    func testByteBufferModifiedWithoutAllocationLogic() {\n        var buffer = ByteBufferAllocator().buffer(capacity: 1)\n        let firstResult = buffer.modifyIfUniquelyOwned {\n            $0.readableBytes\n        }\n        XCTAssertEqual(firstResult, 0)\n\n        withExtendedLifetime(buffer) {\n            var localCopy = buffer\n            let secondResult = localCopy.modifyIfUniquelyOwned {\n                $0.readableBytes\n            }\n            let thirdResult = buffer.modifyIfUniquelyOwned {\n                $0.readableBytes\n            }\n            XCTAssertNil(secondResult)\n            XCTAssertNil(thirdResult)\n            localCopy.writeString(\"foo\")  // stops the optimiser getting rid of `localCopy`\n        }\n\n        let fourthResult = buffer.modifyIfUniquelyOwned {\n            $0.readableBytes\n        }\n        XCTAssertEqual(fourthResult, 0)\n\n        let fifthResult = buffer.modifyIfUniquelyOwned {\n            $0.modifyIfUniquelyOwned {\n                $0.readableBytes\n            }\n        }\n        XCTAssertEqual(fifthResult, 0)\n    }\n\n    func testByteBufferModifyIfUniquelyOwnedMayThrow() {\n        struct MyError: Error {}\n\n        func doAThrow(_ b: inout ByteBuffer) throws {\n            throw MyError()\n        }\n\n        var buffer = ByteBufferAllocator().buffer(capacity: 1)\n\n        XCTAssertThrowsError(try buffer.modifyIfUniquelyOwned(doAThrow(_:))) { error in\n            XCTAssertTrue(error is MyError)\n        }\n\n        // This can't actually throw but XCTAssertNoThrow isn't doing well here.\n        try! withExtendedLifetime(buffer) {\n            var localCopy = buffer\n            XCTAssertNoThrow(try localCopy.modifyIfUniquelyOwned(doAThrow(_:)))\n            XCTAssertNoThrow(try buffer.modifyIfUniquelyOwned(doAThrow(_:)))\n        }\n\n        XCTAssertThrowsError(try buffer.modifyIfUniquelyOwned(doAThrow(_:))) { error in\n            XCTAssertTrue(error is MyError)\n        }\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testDeprecatedSetBytes() {\n        self.buf.clear()\n        self.buf.writeString(\"hello\")\n        self.buf.set(buffer: self.buf, at: 5)\n        self.buf.moveWriterIndex(forwardBy: 5)\n        XCTAssertEqual(\"hellohello\", self.buf.readString(length: 10))\n    }\n\n    func testWriteRepeatingBytes() {\n        func write(count: Int, line: UInt = #line) {\n            self.buf.clear()\n            let written = self.buf.writeRepeatingByte(9, count: count)\n            XCTAssertEqual(count, written)\n            XCTAssertEqual(Array(repeating: UInt8(9), count: count), Array(self.buf.readableBytesView))\n        }\n\n        write(count: 1_000_000)\n        write(count: 0)\n    }\n\n    func testSetRepeatingBytes() {\n        func set(count: Int, at index: Int, padding: [UInt8] = [], line: UInt = #line) {\n\n            // first write some bytes\n            self.buf.clear()\n            self.buf.writeBytes(padding)\n            self.buf.writeRepeatingByte(9, count: count)\n            self.buf.writeBytes(padding)\n\n            // now overwrite\n            let previousWriterIndex = self.buf.writerIndex\n            let written = self.buf.setRepeatingByte(8, count: count, at: index)\n            XCTAssertEqual(previousWriterIndex, self.buf.writerIndex)  // writer index shouldn't have changed\n            XCTAssertEqual(count, written)\n            XCTAssertEqual(Array(repeating: UInt8(8), count: count), self.buf.getBytes(at: index, length: count)!)\n\n            // check the padding is still ok\n            XCTAssertEqual(self.buf.getBytes(at: 0, length: padding.count)!, padding)\n            XCTAssertEqual(self.buf.getBytes(at: count + padding.count, length: padding.count)!, padding)\n        }\n\n        set(count: 1_000_000, at: 0)\n        set(count: 0, at: 0)\n        set(count: 10, at: 5, padding: [1, 1, 1, 1, 1])\n    }\n\n    func testSetRepeatingBytes_unqiueReference() {\n\n        var buffer = self.buf!\n        let copy = buffer\n\n        buffer.writeRepeatingByte(2, count: 100)\n        XCTAssertEqual(Array(buffer.readableBytesView), Array(repeating: 2, count: 100))\n        XCTAssertNotEqual(buffer, copy)\n    }\n\n    func testWriteOptionalWorksForNilCase() {\n        self.buf.writeString(\"hello\")\n        var startingWithNil: ByteBuffer? = nil\n        let bytesWritten = startingWithNil.setOrWriteBuffer(&self.buf)\n        XCTAssertEqual(5, bytesWritten)\n        self.buf.writeString(\"hello\")\n        XCTAssertEqual(self.buf, startingWithNil)\n    }\n\n    func testWriteOptionalWorksForNonNilCase() {\n        self.buf.writeString(\"hello\")\n        var nonNilBuffer: ByteBuffer? = self.buf\n        let bytesWritten = nonNilBuffer.setOrWriteBuffer(&self.buf)\n        XCTAssertEqual(5, bytesWritten)\n        self.buf.writeString(\"hellohello\")\n        XCTAssertEqual(self.buf, nonNilBuffer)\n    }\n\n    func testWriteImmutableOptionalWorksForNilCase() {\n        self.buf.writeString(\"hello\")\n        var startingWithNil: ByteBuffer? = nil\n        let bytesWritten = startingWithNil.setOrWriteImmutableBuffer(self.buf)\n        XCTAssertEqual(5, bytesWritten)\n        XCTAssertEqual(self.buf, startingWithNil)\n    }\n\n    func testWriteImmutableOptionalWorksForNonNilCase() {\n        self.buf.writeString(\"hello\")\n        var nonNilBuffer: ByteBuffer? = self.buf\n        let bytesWritten = nonNilBuffer.setOrWriteImmutableBuffer(self.buf)\n        XCTAssertEqual(5, bytesWritten)\n        self.buf.writeString(\"hello\")\n        XCTAssertEqual(self.buf, nonNilBuffer)\n    }\n\n    func testWritingToEmptyDoesNotCauseTrouble() {\n        var fromEmpty = ByteBuffer()\n        XCTAssertEqual(0, fromEmpty.readableBytes)\n        XCTAssertEqual(0, fromEmpty.capacity)\n        let emptyStorage = fromEmpty.storagePointerIntegerValue()\n\n        fromEmpty.writeInteger(1, as: UInt8.self)\n        XCTAssertEqual(1, fromEmpty.readableBytes)\n        XCTAssertNotEqual(emptyStorage, fromEmpty.storagePointerIntegerValue())\n        XCTAssertGreaterThan(fromEmpty.capacity, 0)\n\n        let empty = ByteBuffer()\n        XCTAssertEqual(0, empty.readableBytes)\n        XCTAssertEqual(0, empty.capacity)\n        XCTAssertEqual(emptyStorage, empty.storagePointerIntegerValue())\n    }\n\n    func testReadEmptySliceFromEmpty() {\n        self.buf = ByteBuffer()\n        XCTAssertEqual(ByteBuffer(), self.buf.readSlice(length: 0))\n    }\n\n    func testConvenienceStringInitWorks() {\n        let bufEmpty = ByteBuffer(string: \"\")\n        let bufNonEmpty = ByteBuffer(string: \"👩🏼‍✈️hello🙈\")\n        XCTAssertEqual(\"\", String(buffer: bufEmpty))\n        XCTAssertEqual(\"👩🏼‍✈️hello🙈\", String(buffer: bufNonEmpty))\n\n        XCTAssertEqual(self.allocator.buffer(string: \"👩🏼‍✈️hello🙈\"), bufNonEmpty)\n    }\n\n    func testConvenienceCreateUInt64() {\n        var intBuffer = ByteBuffer(integer: UInt64(0x00_1122_3344_5566_7788))\n        XCTAssertEqual(self.allocator.buffer(integer: UInt64(0x00_1122_3344_5566_7788)), intBuffer)\n        let int = intBuffer.readInteger(as: UInt64.self)\n        XCTAssertEqual(0x00_1122_3344_5566_7788, int)\n    }\n\n    func testConvenienceCreateUInt8() {\n        var intBuffer = ByteBuffer(integer: UInt8(0x88))\n        XCTAssertEqual(self.allocator.buffer(integer: UInt8(0x88)), intBuffer)\n        let int = intBuffer.readInteger(as: UInt8.self)\n        XCTAssertEqual(0x88, int)\n    }\n\n    func testConvenienceCreateBuffer() {\n        self.buf.writeString(\"hey\")\n        self.buf.writeString(\"you\")\n        self.buf.writeString(\"buffer\")\n        XCTAssertEqual(\"hey\", self.buf.readString(length: 3))\n        self.buf.moveWriterIndex(to: self.buf.writerIndex - 6)\n        let newBuf = ByteBuffer(buffer: self.buf)\n        XCTAssertEqual(self.allocator.buffer(buffer: self.buf), newBuf)\n\n        XCTAssertEqual(newBuf, self.buf)\n    }\n\n    func testConvenienceCreateRepeatingByte() {\n        var buf = ByteBuffer(repeating: 0x12, count: 100)\n        XCTAssertEqual(self.allocator.buffer(repeating: 0x12, count: 100), buf)\n        XCTAssertEqual(Array(repeating: UInt8(0x12), count: 100), buf.readBytes(length: 100))\n        XCTAssertEqual(0, buf.readableBytes)\n    }\n\n    func testConvenienceCreateData() {\n        let data = Data(\"helloyou\\0buffer\".utf8)\n        let subData = data[data.firstIndex(of: UInt8(ascii: \"y\"))!..<data.firstIndex(of: UInt8(ascii: \"b\"))!]\n        XCTAssertNotEqual(0, subData.startIndex)\n        let buffer = ByteBuffer(data: subData)\n        XCTAssertEqual(ByteBuffer(string: \"you\\0\"), buffer)\n        XCTAssertEqual(self.allocator.buffer(string: \"you\\0\"), buffer)\n    }\n\n    func testConvenienceCreateDispatchData() {\n        var dd = DispatchData.empty\n        for s in [\"s\", \"t\", \"ri\\0n\", \"g\"] {\n            XCTAssertNotNil(\n                s.utf8.withContiguousStorageIfAvailable { ptr in\n                    dd.append(UnsafeRawBufferPointer(ptr))\n                }\n            )\n        }\n        // The DispatchData should now be discontiguous.\n        XCTAssertEqual(ByteBuffer(string: \"stri\\0ng\"), ByteBuffer(dispatchData: dd))\n        XCTAssertEqual(ByteBuffer(dispatchData: dd), self.allocator.buffer(dispatchData: dd))\n    }\n\n    func testConvenienceCreateStaticString() {\n        XCTAssertEqual(ByteBuffer(string: \"hello\"), ByteBuffer(staticString: \"hello\"))\n        XCTAssertEqual(ByteBuffer(string: \"hello\"), self.allocator.buffer(staticString: \"hello\"))\n    }\n\n    func testConvenienceCreateSubstring() {\n        XCTAssertEqual(ByteBuffer(string: \"hello\"), ByteBuffer(substring: \"hello\"[...]))\n        XCTAssertEqual(ByteBuffer(string: \"hello\"), self.allocator.buffer(substring: \"hello\"[...]))\n    }\n\n    func testConvenienceCreateBytes() {\n        XCTAssertEqual(ByteBuffer(string: \"\\0string\\0\"), ByteBuffer(bytes: [UInt8(0)] + Array(\"string\\0\".utf8)))\n        XCTAssertEqual(\n            ByteBuffer(string: \"\\0string\\0\"),\n            self.allocator.buffer(bytes: [UInt8(0)] + Array(\"string\\0\".utf8))\n        )\n    }\n\n    func testAllocatorGivesStableZeroSizedBuffers() {\n        let b1 = ByteBufferAllocator().buffer(capacity: 0)\n        let b2 = ByteBufferAllocator().buffer(capacity: 0)\n        let b3 = self.allocator.buffer(capacity: 0)\n        let b4 = self.allocator.buffer(capacity: 0)\n        XCTAssertEqual(b1.storagePointerIntegerValue(), b2.storagePointerIntegerValue())\n        XCTAssertEqual(b3.storagePointerIntegerValue(), b4.storagePointerIntegerValue())\n    }\n\n    func testClearOnZeroCapacityActuallyAllocates() {\n        var b = ByteBufferAllocator().buffer(capacity: 0)\n        let bEmptyStorage1 = b.storagePointerIntegerValue()\n        b.clear()\n        let bEmptyStorage2 = b.storagePointerIntegerValue()\n        XCTAssertNotEqual(bEmptyStorage1, bEmptyStorage2)\n    }\n\n    func testCreateBufferFromSequence() {\n        self.buf.writeString(\"hello\")\n        let aSequenceThatIsNotACollection = Array(buffer: self.buf).makeIterator()\n        XCTAssertEqual(self.buf, self.allocator.buffer(bytes: aSequenceThatIsNotACollection))\n        XCTAssertEqual(self.buf, ByteBuffer(bytes: aSequenceThatIsNotACollection))\n    }\n\n    func testWeDoNotResizeIfWeHaveExactlyTheRightCapacityAvailable() {\n        let bufferSize = 32 * 1024\n        var buffer = self.allocator.buffer(capacity: bufferSize)\n        buffer.moveWriterIndex(forwardBy: bufferSize / 2)\n        XCTAssertEqual(bufferSize, buffer.capacity)\n        let oldBufferStorage = buffer.storagePointerIntegerValue()\n        buffer.writeWithUnsafeMutableBytes(minimumWritableBytes: bufferSize / 2, { _ in 0 })\n        XCTAssertEqual(bufferSize, buffer.capacity)\n        let newBufferStorage = buffer.storagePointerIntegerValue()\n        XCTAssertEqual(oldBufferStorage, newBufferStorage)\n    }\n\n    func testWithUnsafeMutableReadableBytesNoCoW() {\n        let storageID = self.buf.storagePointerIntegerValue()\n        self.buf.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(0, ptr.count)\n        }\n\n        self.buf.writeString(\"hello \\0 world!\")\n        self.buf.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(\"hello \\0 world!\", String(decoding: ptr, as: UTF8.self))\n            ptr.copyBytes(from: \"HELLO\".utf8)\n        }\n\n        XCTAssertEqual(\"HELLO \\0\", self.buf.readString(length: 7))\n        var slice = self.buf.getSlice(at: 8, length: 5) ?? ByteBuffer()\n        self.buf = ByteBuffer()\n        slice.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(\"world\", String(decoding: ptr, as: UTF8.self))\n            ptr.copyBytes(from: \"WORLD\".utf8)\n        }\n        XCTAssertEqual(\"WORLD\", String(buffer: slice))\n        XCTAssertEqual(storageID, slice.storagePointerIntegerValue() - 8)\n    }\n\n    func testWithUnsafeMutableReadableBytesCoWOfNonSlice() {\n        let storageID = self.buf.storagePointerIntegerValue()\n        self.buf.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(0, ptr.count)\n        }\n\n        self.buf.writeWithUnsafeMutableBytes(minimumWritableBytes: 5) { ptr in\n            XCTAssertGreaterThanOrEqual(ptr.count, 5)\n            ptr.copyBytes(from: \"hello\".utf8)\n            return 5\n        }\n\n        var slice = self.buf.getSlice(at: 2, length: 2) ?? ByteBuffer()\n        self.buf.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(\"hello\", String(decoding: ptr, as: UTF8.self))\n            ptr.copyBytes(from: \"HELLO\".utf8)\n        }\n        XCTAssertNotEqual(storageID, self.buf.storagePointerIntegerValue())\n        XCTAssertEqual(\"ll\", String(buffer: slice))\n        slice.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(\"ll\", String(decoding: ptr, as: UTF8.self))\n            ptr.copyBytes(from: \"XX\".utf8)\n        }\n        XCTAssertEqual(storageID, slice.storagePointerIntegerValue() - 2)\n        XCTAssertNotEqual(self.buf.storagePointerIntegerValue(), slice.storagePointerIntegerValue() - 2)\n        XCTAssertEqual(\"XX\", String(buffer: slice))\n    }\n\n    func testWithUnsafeMutableReadableBytesCoWOfSlice() {\n        let storageID = self.buf.storagePointerIntegerValue()\n        self.buf.writeString(\"hello\")\n        var slice = self.buf.getSlice(at: 2, length: 3) ?? ByteBuffer()\n        slice.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(\"llo\", String(decoding: ptr, as: UTF8.self))\n            ptr.copyBytes(from: \"foo\".utf8)\n        }\n        XCTAssertNotEqual(storageID, slice.storagePointerIntegerValue() - 2)\n        XCTAssertEqual(\"hello\", String(buffer: self.buf))\n        XCTAssertEqual(\"foo\", String(buffer: slice))\n    }\n\n    func testWithUnsafeMutableReadableBytesAllThingsNonZero() {\n        var buf = self.allocator.buffer(capacity: 32)\n        let storageID = buf.storagePointerIntegerValue()\n\n        // We start with reader/writer/sliceBegin indices = 0\n        XCTAssertEqual(32, buf.capacity)\n        XCTAssertEqual(0, buf.readerIndex)\n        XCTAssertEqual(0, buf.writerIndex)\n\n        buf.writeString(\"0123456789abcdef\")\n        XCTAssertEqual(32, buf.capacity)\n        XCTAssertEqual(0, buf.readerIndex)\n        XCTAssertEqual(16, buf.writerIndex)\n\n        XCTAssertEqual(\"012\", buf.readString(length: 3))\n        XCTAssertEqual(32, buf.capacity)\n        XCTAssertEqual(3, buf.readerIndex)\n        XCTAssertEqual(16, buf.writerIndex)\n\n        buf.withUnsafeMutableReadableBytes { ptr in\n            ptr[ptr.endIndex - 1] = UInt8(ascii: \"X\")\n        }\n\n        var slice = buf.readSlice(length: 12) ?? ByteBuffer()\n        XCTAssertEqual(\"X\", String(buffer: buf))\n\n        XCTAssertEqual(32, buf.capacity)\n        XCTAssertEqual(15, buf.readerIndex)\n        XCTAssertEqual(16, buf.writerIndex)\n\n        XCTAssertEqual(0, slice.readerIndex)\n        XCTAssertEqual(12, slice.writerIndex)\n        XCTAssertEqual(\"34567\", slice.readString(length: 5))\n        XCTAssertEqual(5, slice.readerIndex)\n        XCTAssertEqual(12, slice.writerIndex)\n\n        buf = ByteBuffer()  // make `slice` the owner of the storage\n        slice.withUnsafeMutableReadableBytes { ptr in\n            XCTAssertEqual(\"89abcde\", String(decoding: ptr, as: UTF8.self))\n            XCTAssertEqual(7, ptr.count)\n            ptr.copyBytes(from: \"7 bytes\".utf8)\n        }\n\n        XCTAssertEqual(storageID, slice.storagePointerIntegerValue() - 3)\n        XCTAssertEqual(\"7 bytes\", String(buffer: slice))\n    }\n}\n\nprivate enum AllocationExpectationState: Int {\n    case begin\n    case mallocDone\n    case reallocDone\n    case freeDone\n}\n\nprivate let _testAllocationOfReallyBigByteBuffer_state = ManagedAtomic<Int>(AllocationExpectationState.begin.rawValue)\nprivate var testAllocationOfReallyBigByteBuffer_state: AllocationExpectationState {\n    get {\n        .init(rawValue: _testAllocationOfReallyBigByteBuffer_state.load(ordering: .acquiring))!\n    }\n    set {\n        _testAllocationOfReallyBigByteBuffer_state.store(newValue.rawValue, ordering: .releasing)\n    }\n}\nprivate func testAllocationOfReallyBigByteBuffer_freeHook(_ ptr: UnsafeMutableRawPointer?) {\n    precondition(AllocationExpectationState.reallocDone == testAllocationOfReallyBigByteBuffer_state)\n    testAllocationOfReallyBigByteBuffer_state = .freeDone\n    // free the pointer initially produced by malloc and then rebased by realloc offsetting it back\n    free(ptr!.advanced(by: Int(Int32.max)))\n}\n\nprivate func testAllocationOfReallyBigByteBuffer_mallocHook(_ size: Int) -> UnsafeMutableRawPointer? {\n    precondition(AllocationExpectationState.begin == testAllocationOfReallyBigByteBuffer_state)\n    testAllocationOfReallyBigByteBuffer_state = .mallocDone\n    // return a 16 byte pointer here, good enough to write an integer in there\n    return malloc(16)\n}\n\nprivate func testAllocationOfReallyBigByteBuffer_reallocHook(\n    _ ptr: UnsafeMutableRawPointer?,\n    _ oldSize: Int,\n    _ newSize: Int\n) -> UnsafeMutableRawPointer? {\n    precondition(AllocationExpectationState.mallocDone == testAllocationOfReallyBigByteBuffer_state)\n    testAllocationOfReallyBigByteBuffer_state = .reallocDone\n    // rebase this pointer by -Int32.max so that the byte copy extending the ByteBuffer below will land at actual index 0 into this buffer ;)\n    return ptr!.advanced(by: -Int(Int32.max))\n}\n\nprivate func testAllocationOfReallyBigByteBuffer_memcpyHook(\n    _ dst: UnsafeMutableRawPointer,\n    _ src: UnsafeRawPointer,\n    _ count: Int\n) {\n    // not actually doing any copies\n}\n\nprivate let testReserveCapacityLarger_reallocCount = ManagedAtomic(0)\nprivate let testReserveCapacityLarger_mallocCount = ManagedAtomic(0)\nprivate func testReserveCapacityLarger_freeHook(_ ptr: UnsafeMutableRawPointer) {\n    free(ptr)\n}\n\nprivate func testReserveCapacityLarger_mallocHook(_ size: Int) -> UnsafeMutableRawPointer? {\n    testReserveCapacityLarger_mallocCount.wrappingIncrement(ordering: .sequentiallyConsistent)\n    return malloc(size)\n}\n\nprivate func testReserveCapacityLarger_reallocHook(\n    _ ptr: UnsafeMutableRawPointer?,\n    _ oldSize: Int,\n    _ newSize: Int\n) -> UnsafeMutableRawPointer? {\n    testReserveCapacityLarger_reallocCount.wrappingIncrement(ordering: .sequentiallyConsistent)\n    return realloc(ptr, newSize)\n}\n\nprivate func testReserveCapacityLarger_memcpyHook(_ dst: UnsafeMutableRawPointer, _ src: UnsafeRawPointer, _ count: Int)\n{\n    // No copying\n}\n\nextension ByteBuffer {\n    func storagePointerIntegerValue() -> UInt {\n        var pointer: UInt = 0\n        self.withVeryUnsafeBytes { ptr in\n            pointer = UInt(bitPattern: ptr.baseAddress!)\n        }\n        return pointer\n    }\n}\n\n// MARK: - Array init\nextension ByteBufferTest {\n\n    func testCreateArrayFromBuffer() {\n        let testString = \"some sample data\"\n        let buffer = ByteBuffer(ByteBufferView(testString.utf8))\n        XCTAssertEqual(Array(buffer: buffer), Array(testString.utf8))\n    }\n\n}\n\n// MARK: - String init\nextension ByteBufferTest {\n\n    func testCreateStringFromBuffer() {\n        let testString = \"some sample data\"\n        let buffer = ByteBuffer(ByteBufferView(testString.utf8))\n        XCTAssertEqual(String(buffer: buffer), testString)\n    }\n\n}\n\n// MARK: - Int / FixedWidthInteger init\nextension ByteBufferTest {\n    func testCreateIntegersFromByteBuffer() {\n        let uint32BufferLE = ByteBuffer(bytes: [0x04, 0x03, 0x02, 0x01])\n        let uint32BufferBE = ByteBuffer(bytes: [0x01, 0x02, 0x03, 0x04])\n        let tooSmallInt32Buffer = ByteBuffer(bytes: [0x01, 0x02, 0x03])\n\n        XCTAssertEqual(Int32(buffer: uint32BufferLE, endianness: .little), 0x0102_0304)\n        XCTAssertEqual(Int32(buffer: uint32BufferBE, endianness: .big), 0x0102_0304)\n        XCTAssertNil(Int32(buffer: tooSmallInt32Buffer))\n\n        let uint64BufferLE = ByteBuffer(bytes: [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01])\n        let uint64BufferBE = ByteBuffer(bytes: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08])\n        let tooSmallInt64Buffer = ByteBuffer(bytes: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07])\n        let tooBigInt64Buffer = ByteBuffer(bytes: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09])\n\n        XCTAssertEqual(Int64(buffer: uint64BufferLE, endianness: .little), 0x0102_0304_0506_0708)\n        XCTAssertEqual(Int64(buffer: uint64BufferBE, endianness: .big), 0x0102_0304_0506_0708)\n        XCTAssertNil(Int64(buffer: tooSmallInt64Buffer))\n        XCTAssertNil(Int64(buffer: tooBigInt64Buffer))\n    }\n}\n\n// MARK: - DispatchData init\nextension ByteBufferTest {\n\n    func testCreateDispatchDataFromBuffer() {\n        let testString = \"some sample data\"\n        let buffer = ByteBuffer(ByteBufferView(testString.utf8))\n        let expectedData = testString.data(using: .utf8)!.withUnsafeBytes { (pointer) in\n            DispatchData(bytes: pointer)\n        }\n        XCTAssertTrue(DispatchData(buffer: buffer).elementsEqual(expectedData))\n    }\n\n}\n\n// MARK: - ExpressibleByArrayLiteral init\nextension ByteBufferTest {\n\n    func testCreateBufferFromArray() {\n        let bufferView: ByteBufferView = [0x00, 0x01, 0x02]\n        let buffer = ByteBuffer(ByteBufferView(bufferView))\n\n        XCTAssertEqual(buffer.readableBytesView, [0x00, 0x01, 0x02])\n    }\n\n}\n\n// MARK: - Equatable\nextension ByteBufferTest {\n\n    func testByteBufferViewEqualityWithRange() {\n        var buffer = self.allocator.buffer(capacity: 8)\n        buffer.writeString(\"AAAABBBB\")\n\n        let view = ByteBufferView(buffer: buffer, range: 2..<6)\n        let comparisonBuffer: ByteBufferView = [0x41, 0x41, 0x42, 0x42]\n\n        XCTAssertEqual(view, comparisonBuffer)\n    }\n\n    func testInvalidBufferEqualityWithDifferentRange() {\n        var buffer = self.allocator.buffer(capacity: 4)\n        buffer.writeString(\"AAAA\")\n\n        let view = ByteBufferView(buffer: buffer, range: 0..<2)\n        let comparisonBuffer: ByteBufferView = [0x41, 0x41, 0x41, 0x41]\n\n        XCTAssertNotEqual(view, comparisonBuffer)\n    }\n\n    func testInvalidBufferEqualityWithDifferentContent() {\n        var buffer = self.allocator.buffer(capacity: 4)\n        buffer.writeString(\"AAAA\")\n\n        let view = ByteBufferView(buffer: buffer, range: 0..<4)\n        let comparisonBuffer: ByteBufferView = [0x41, 0x41, 0x00, 0x00]\n\n        XCTAssertNotEqual(view, comparisonBuffer)\n    }\n\n}\n\n// MARK: - Hashable\nextension ByteBufferTest {\n\n    func testHashableConformance() {\n        let bufferView: ByteBufferView = [0x00, 0x01, 0x02]\n        let comparisonBufferView: ByteBufferView = [0x00, 0x01, 0x02]\n\n        XCTAssertEqual(bufferView.hashValue, comparisonBufferView.hashValue)\n    }\n\n    func testInvalidHash() {\n        let bufferView: ByteBufferView = [0x00, 0x00, 0x00]\n        let comparisonBufferView: ByteBufferView = [0x00, 0x01, 0x02]\n\n        XCTAssertNotEqual(bufferView.hashValue, comparisonBufferView.hashValue)\n    }\n\n    func testValidHashFromSlice() {\n        var buffer = self.allocator.buffer(capacity: 4)\n        buffer.writeString(\"AAAA\")\n\n        let bufferView = ByteBufferView(buffer: buffer, range: 0..<2)\n        let comparisonBufferView = ByteBufferView(buffer: buffer, range: 2..<4)\n\n        XCTAssertEqual(bufferView.hashValue, comparisonBufferView.hashValue)\n    }\n\n    func testWritingMultipleIntegers() {\n        let w1 = self.buf.writeMultipleIntegers(UInt32(1), UInt8(2), UInt16(3), UInt64(4), UInt16(5), endianness: .big)\n        let w2 = self.buf.writeMultipleIntegers(\n            UInt32(1),\n            UInt8(2),\n            UInt16(3),\n            UInt64(4),\n            UInt16(5),\n            endianness: .little\n        )\n        XCTAssertEqual(17, w1)\n        XCTAssertEqual(17, w2)\n\n        let one1 = self.buf.readInteger(endianness: .big, as: UInt32.self)\n        let two1 = self.buf.readInteger(endianness: .big, as: UInt8.self)\n        let three1 = self.buf.readInteger(endianness: .big, as: UInt16.self)\n        let four1 = self.buf.readInteger(endianness: .big, as: UInt64.self)\n        let five1 = self.buf.readInteger(endianness: .big, as: UInt16.self)\n        let one2 = self.buf.readInteger(endianness: .little, as: UInt32.self)\n        let two2 = self.buf.readInteger(endianness: .little, as: UInt8.self)\n        let three2 = self.buf.readInteger(endianness: .little, as: UInt16.self)\n        let four2 = self.buf.readInteger(endianness: .little, as: UInt64.self)\n        let five2 = self.buf.readInteger(endianness: .little, as: UInt16.self)\n\n        XCTAssertEqual(1, one1)\n        XCTAssertEqual(1, one2)\n        XCTAssertEqual(2, two1)\n        XCTAssertEqual(2, two2)\n        XCTAssertEqual(3, three1)\n        XCTAssertEqual(3, three2)\n        XCTAssertEqual(4, four1)\n        XCTAssertEqual(4, four2)\n        XCTAssertEqual(5, five1)\n        XCTAssertEqual(5, five2)\n\n        XCTAssertEqual(self.buf.readableBytes, 0)\n    }\n\n    func testReadAndWriteMultipleIntegers() {\n        for endianness in [Endianness.little, .big] {\n            let v1: UInt8 = .random(in: .min ... .max)\n            let v2: UInt16 = .random(in: .min ... .max)\n            let v3: UInt32 = .random(in: .min ... .max)\n            let v4: UInt64 = .random(in: .min ... .max)\n            let v5: UInt64 = .random(in: .min ... .max)\n            let v6: UInt32 = .random(in: .min ... .max)\n            let v7: UInt16 = .random(in: .min ... .max)\n            let v8: UInt8 = .random(in: .min ... .max)\n            let v9: UInt16 = .random(in: .min ... .max)\n            let v10: UInt32 = .random(in: .min ... .max)\n\n            let startWriterIndex = self.buf.writerIndex\n            let written = self.buf.writeMultipleIntegers(\n                v1,\n                v2,\n                v3,\n                v4,\n                v5,\n                v6,\n                v7,\n                v8,\n                v9,\n                v10,\n                endianness: endianness,\n                as: (UInt8, UInt16, UInt32, UInt64, UInt64, UInt32, UInt16, UInt8, UInt16, UInt32).self\n            )\n            XCTAssertEqual(startWriterIndex + written, self.buf.writerIndex)\n            XCTAssertEqual(written, self.buf.readableBytes)\n\n            let result = self.buf.readMultipleIntegers(\n                endianness: endianness,\n                as: (UInt8, UInt16, UInt32, UInt64, UInt64, UInt32, UInt16, UInt8, UInt16, UInt32).self\n            )\n            XCTAssertNotNil(result)\n            XCTAssertEqual(0, self.buf.readableBytes)\n\n            XCTAssertEqual(v1, result?.0, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v2, result?.1, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v3, result?.2, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v4, result?.3, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v5, result?.4, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v6, result?.5, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v7, result?.6, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v8, result?.7, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v9, result?.8, \"endianness: \\(endianness)\")\n            XCTAssertEqual(v10, result?.9, \"endianness: \\(endianness)\")\n        }\n    }\n\n    func testAllByteBufferMultiByteVersions() {\n        let i = UInt8(86)\n        self.buf.writeMultipleIntegers(i, i)\n        self.buf.writeMultipleIntegers(i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i)\n        XCTAssertEqual(Array(repeating: UInt8(86), count: 119), Array(self.buf.readableBytesView))\n        var values2 = self.buf.readMultipleIntegers(as: (UInt8, UInt8).self)!\n        var values3 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8).self)!\n        var values4 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8).self)!\n        var values5 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values6 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values7 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values8 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values9 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values10 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values11 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values12 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values13 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values14 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values15 = self.buf.readMultipleIntegers(\n            as: (\n                UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8\n            ).self\n        )!\n\n        XCTAssertEqual([i, i], withUnsafeBytes(of: &values2, { Array($0) }))\n        XCTAssertEqual([i, i, i], withUnsafeBytes(of: &values3, { Array($0) }))\n        XCTAssertEqual([i, i, i, i], withUnsafeBytes(of: &values4, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i], withUnsafeBytes(of: &values5, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i], withUnsafeBytes(of: &values6, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i], withUnsafeBytes(of: &values7, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values8, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values9, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values10, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values11, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values12, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values13, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values14, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values15, { Array($0) }))\n\n        XCTAssertEqual(0, self.buf.readableBytes)\n    }\n\n    func testPeekAndWriteMultipleIntegers() {\n        // This test mirrors 'testReadAndWriteMultipleIntegers' but uses peekMultipleIntegers\n        for endianness in [Endianness.little, .big] {\n            let v1: UInt8 = .random(in: .min ... .max)\n            let v2: UInt16 = .random(in: .min ... .max)\n            let v3: UInt32 = .random(in: .min ... .max)\n            let v4: UInt64 = .random(in: .min ... .max)\n            let v5: UInt64 = .random(in: .min ... .max)\n            let v6: UInt32 = .random(in: .min ... .max)\n            let v7: UInt16 = .random(in: .min ... .max)\n            let v8: UInt8 = .random(in: .min ... .max)\n            let v9: UInt16 = .random(in: .min ... .max)\n            let v10: UInt32 = .random(in: .min ... .max)\n\n            let startWriterIndex = self.buf.writerIndex\n            let written = self.buf.writeMultipleIntegers(\n                v1,\n                v2,\n                v3,\n                v4,\n                v5,\n                v6,\n                v7,\n                v8,\n                v9,\n                v10,\n                endianness: endianness,\n                as: (UInt8, UInt16, UInt32, UInt64, UInt64, UInt32, UInt16, UInt8, UInt16, UInt32).self\n            )\n            XCTAssertEqual(startWriterIndex + written, self.buf.writerIndex)\n            XCTAssertEqual(written, self.buf.readableBytes)\n\n            // Check peek does not advance readerIndex\n            let startReadable = self.buf.readableBytes\n            let peeked = self.buf.peekMultipleIntegers(\n                endianness: endianness,\n                as: (UInt8, UInt16, UInt32, UInt64, UInt64, UInt32, UInt16, UInt8, UInt16, UInt32).self\n            )\n            XCTAssertNotNil(peeked, \"peekMultipleIntegers should succeed.\")\n            XCTAssertEqual(startReadable, self.buf.readableBytes, \"Peeking should not consume any bytes.\")\n\n            XCTAssertEqual(peeked?.0, v1, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.1, v2, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.2, v3, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.3, v4, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.4, v5, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.5, v6, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.6, v7, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.7, v8, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.8, v9, \"endianness: \\(endianness)\")\n            XCTAssertEqual(peeked?.9, v10, \"endianness: \\(endianness)\")\n\n            let result = self.buf.readMultipleIntegers(\n                endianness: endianness,\n                as: (UInt8, UInt16, UInt32, UInt64, UInt64, UInt32, UInt16, UInt8, UInt16, UInt32).self\n            )\n            XCTAssertNotNil(result, \"Expected to successfully read after peeking.\")\n            XCTAssertEqual(result?.0, v1, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.1, v2, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.2, v3, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.3, v4, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.4, v5, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.5, v6, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.6, v7, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.7, v8, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.8, v9, \"endianness: \\(endianness)\")\n            XCTAssertEqual(result?.9, v10, \"endianness: \\(endianness)\")\n            XCTAssertEqual(0, self.buf.readableBytes)\n        }\n    }\n\n    func testAllByteBufferMultiByteVersionsPeek() {\n        // This test mirrors 'testAllByteBufferMultiByteVersions' but using peekMultipleIntegers\n        let i = UInt8(86)\n        self.buf.writeMultipleIntegers(i, i)\n        self.buf.writeMultipleIntegers(i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i, i, i)\n        self.buf.writeMultipleIntegers(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i)\n\n        XCTAssertEqual(Array(repeating: UInt8(86), count: 119), Array(self.buf.readableBytesView))\n\n        let peek2 = self.buf.peekMultipleIntegers(as: (UInt8, UInt8).self)\n        XCTAssertNotNil(peek2, \"Expected to peek 2 UInt8s.\")\n        XCTAssertEqual(peek2?.0, i, \"First value mismatch in peek2\")\n        XCTAssertEqual(peek2?.1, i, \"Second value mismatch in peek2\")\n        XCTAssertEqual(\n            Array(self.buf.readableBytesView),\n            Array(repeating: i, count: 119),\n            \"No bytes should be consumed by peek.\"\n        )\n        let offset2 = MemoryLayout<UInt8>.size * 2\n        let peek3 = self.buf.getSlice(at: self.buf.readerIndex + offset2, length: 3)?.peekMultipleIntegers(\n            as: (UInt8, UInt8, UInt8).self\n        )\n        XCTAssertNotNil(peek3, \"Expected to peek 3 UInt8s from the next region.\")\n        XCTAssertEqual(peek3?.0, i, \"First value mismatch in peek3\")\n        XCTAssertEqual(peek3?.1, i, \"Second value mismatch in peek3\")\n        XCTAssertEqual(peek3?.2, i, \"Third value mismatch in peek3\")\n        var values2 = self.buf.readMultipleIntegers(as: (UInt8, UInt8).self)!\n        var values3 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8).self)!\n        var values4 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8).self)!\n        var values5 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values6 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values7 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values8 = self.buf.readMultipleIntegers(as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self)!\n        var values9 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values10 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values11 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values12 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values13 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values14 = self.buf.readMultipleIntegers(\n            as: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self\n        )!\n        var values15 = self.buf.readMultipleIntegers(\n            as: (\n                UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8\n            ).self\n        )!\n\n        let iArray2 = withUnsafeBytes(of: &values2, { Array($0) })\n        XCTAssertEqual([i, i], iArray2)\n        XCTAssertEqual([i, i, i], withUnsafeBytes(of: &values3, { Array($0) }))\n        XCTAssertEqual([i, i, i, i], withUnsafeBytes(of: &values4, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i], withUnsafeBytes(of: &values5, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i], withUnsafeBytes(of: &values6, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i], withUnsafeBytes(of: &values7, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values8, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values9, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values10, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values11, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values12, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values13, { Array($0) }))\n        XCTAssertEqual([i, i, i, i, i, i, i, i, i, i, i, i, i, i], withUnsafeBytes(of: &values14, { Array($0) }))\n        XCTAssertEqual(\n            [i, i, i, i, i, i, i, i, i, i, i, i, i, i, i],\n            withUnsafeBytes(of: &values15, { Array($0) })\n        )\n\n        XCTAssertEqual(0, self.buf.readableBytes, \"Buffer should be fully consumed after all reads.\")\n    }\n\n    func testByteBufferEncode() throws {\n        let encoder = JSONEncoder()\n        let hello = \"Hello, world!\"\n        let buffer = ByteBuffer(string: hello)\n\n        let encoded = try encoder.encode(buffer)\n        let expected = \"\\\"SGVsbG8sIHdvcmxkIQ==\\\"\"\n        XCTAssertEqual(String(data: encoded, encoding: .utf8)!, expected)\n    }\n\n    func testByteBufferDecode() throws {\n        let decoder = JSONDecoder()\n        var encodedData = Data()\n        encodedData.append(contentsOf: \"\\\"SGVsbG8sIHdvcmxkIQ==\\\"\".utf8)\n        let decoded = try decoder.decode(ByteBuffer.self, from: encodedData)\n\n        let expected = ByteBuffer(string: \"Hello, world!\").readableBytesView\n        XCTAssertEqual(decoded.readableBytesView, expected)\n    }\n\n    func testByteBufferDecodeWithInvalidLength() {\n        let decoder = JSONDecoder()\n        var encodedData = Data()\n        encodedData.append(contentsOf: \"\\\"SGVsbG8sIHdvcmxkIQyy==\\\"\".utf8)\n        XCTAssertThrowsError(try decoder.decode(ByteBuffer.self, from: encodedData)) { error in\n            XCTAssertEqual(error as? Base64Error, .invalidLength)\n        }\n    }\n\n    func testByteBufferDecodeWithInvalidCharacters() {\n        let decoder = JSONDecoder()\n        var encodedData = Data()\n        encodedData.append(contentsOf: \"\\\"SGVsbG8sIHdvcmxkI_==\\\"\".utf8)\n        XCTAssertThrowsError(try decoder.decode(ByteBuffer.self, from: encodedData)) { error in\n            XCTAssertEqual(error as? Base64Error, .invalidCharacter)\n        }\n    }\n\n    func testByteBufferDescription() {\n        let buffer = ByteBuffer(string: \"hello world\")\n\n        XCTAssertEqual(buffer.description, \"[68656c6c6f20776f726c64](11 bytes)\")\n\n        XCTAssertEqual(buffer.description, buffer.debugDescription)\n    }\n\n    func testByteBufferDescriptionEmpty() {\n        let buffer = ByteBuffer()\n\n        XCTAssertEqual(buffer.description, \"[](0 bytes)\")\n\n        XCTAssertEqual(buffer.description, buffer.debugDescription)\n    }\n\n    func testByteBufferDescriptionTruncated() {\n        let buffer = ByteBuffer(\n            string: \"iloveswiftnioiloveswiftnioiloveswiftnioiloveswiftnioiloveswiftnioiloveswiftnio\"\n        )\n\n        XCTAssertEqual(\n            buffer.description,\n            \"[696c6f766573776966746e696f696c6f766573776966746e696f696c6f766573...6966746e696f696c6f766573776966746e696f696c6f766573776966746e696f](78 bytes)\"\n        )\n\n        XCTAssertEqual(buffer.description, buffer.debugDescription)\n    }\n\n    // Test that peekInteger correctly reads a UInt8.\n    func testPeekIntegerUInt8() {\n        var buffer: ByteBuffer = ByteBuffer()\n        let value: UInt8 = 0xAB\n        _ = buffer.writeInteger(value)\n\n        // Use peekInteger to get the value at readerIndex.\n        guard let peeked: UInt8 = buffer.peekInteger(as: UInt8.self) else {\n            XCTFail(\"peekInteger failed to return a value\")\n            return\n        }\n        XCTAssertEqual(peeked, value)\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    // Test that peekInteger correctly reads a UInt16.\n    func testPeekIntegerUInt16() {\n        var buffer: ByteBuffer = ByteBuffer()\n        let value: UInt16 = 0xABCD\n        _ = buffer.writeInteger(value)\n\n        guard let peeked: UInt16 = buffer.peekInteger(as: UInt16.self) else {\n            XCTFail(\"peekInteger failed to return a value\")\n            return\n        }\n        XCTAssertEqual(peeked, value)\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    // Test that peekInteger returns nil when there are not enough bytes for a UInt32.\n    func testPeekIntegerNotEnoughBytes() {\n        let buffer: ByteBuffer = ByteBuffer()\n        // Do not write any bytes, so there are not enough bytes for a UInt32.\n        let peeked: UInt32? = buffer.peekInteger(as: UInt32.self)\n        XCTAssertNil(peeked, \"Expected nil when there are not enough bytes\")\n    }\n\n    // Test that after writing multiple values, peekInteger always returns the first integer.\n    func testPeekIntegerAfterMultipleWrites() {\n        var buffer: ByteBuffer = ByteBuffer()\n        let first: UInt8 = 0x12\n        let second: UInt8 = 0x34\n        _ = buffer.writeInteger(first)\n        _ = buffer.writeInteger(second)\n\n        // First peek to check the first integer.\n        guard let peeked1: UInt8 = buffer.peekInteger(as: UInt8.self) else {\n            XCTFail(\"peekInteger failed to return a value on first call\")\n            return\n        }\n        XCTAssertEqual(peeked1, first)\n        XCTAssertEqual(buffer.readerIndex, 0)\n\n        // Second peek should return the same value, confirming readerIndex is unchanged.\n        guard let peeked2: UInt8 = buffer.peekInteger(as: UInt8.self) else {\n            XCTFail(\"peekInteger failed to return a value on second call\")\n            return\n        }\n        XCTAssertEqual(peeked2, first)\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    func testPeekBytesFull() {\n        var buffer: ByteBuffer = ByteBuffer()\n        let bytes: [UInt8] = [10, 20, 30, 40, 50]\n\n        let written = buffer.writeBytes(bytes)\n        XCTAssertEqual(written, bytes.count)\n\n        guard let peeked = buffer.peekBytes(length: bytes.count) else {\n            XCTFail(\"peekBytes should return the bytes that were written\")\n            return\n        }\n\n        // Verify the peeked bytes match what was written.\n        XCTAssertEqual(peeked, bytes)\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    func testPeekBytesPartial() {\n        var buffer: ByteBuffer = ByteBuffer()\n        let bytes: [UInt8] = [1, 2, 3, 4, 5, 6]\n\n        _ = buffer.writeBytes(bytes)\n\n        // Peek only the first 4 bytes.\n        guard let peeked = buffer.peekBytes(length: 4) else {\n            XCTFail(\"peekBytes should return the first 4 bytes\")\n            return\n        }\n\n        XCTAssertEqual(peeked, [1, 2, 3, 4])\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    func testPeekBytesWhenBufferEmpty() {\n        let buffer: ByteBuffer = ByteBuffer()\n\n        // With an empty buffer, peeking any number of bytes should return nil.\n        let peeked = buffer.peekBytes(length: 5)\n        XCTAssertNil(peeked, \"peekBytes should return nil when there are no bytes available\")\n    }\n\n    func testPeekBytesDoesNotAdvanceReaderIndex() {\n        var buffer: ByteBuffer = ByteBuffer()\n        let bytes: [UInt8] = [100, 101, 102]\n\n        _ = buffer.writeBytes(bytes)\n\n        guard let firstPeek = buffer.peekBytes(length: bytes.count) else {\n            XCTFail(\"peekBytes failed on first call\")\n            return\n        }\n        XCTAssertEqual(firstPeek, bytes)\n\n        guard let secondPeek = buffer.peekBytes(length: bytes.count) else {\n            XCTFail(\"peekBytes failed on second call\")\n            return\n        }\n        XCTAssertEqual(secondPeek, bytes)\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    // MARK: - peekString Tests\n\n    func testPeekString_Normal() {\n        var buffer = ByteBuffer()\n        let testString = \"Hello, SwiftNIO!\"\n        let written = buffer.writeString(testString)\n        XCTAssertEqual(written, testString.utf8.count, \"Expected correct byte count written for string.\")\n\n        guard let peeked = buffer.peekString(length: written) else {\n            XCTFail(\"peekString() failed to return a value on normal call.\")\n            return\n        }\n        XCTAssertEqual(peeked, testString, \"peekString() should return the full string.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekString() should not advance the reader index.\")\n    }\n\n    func testPeekString_Empty() {\n        var buffer = ByteBuffer()\n        // Write an empty string.\n        let written = buffer.writeString(\"\")\n        XCTAssertEqual(written, 0, \"Writing an empty string should result in zero bytes written.\")\n\n        let peeked = buffer.peekString(length: 0)\n        XCTAssertEqual(peeked, \"\", \"peekString() should return an empty string when no bytes are written.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index should remain unchanged for empty peek.\")\n    }\n\n    func testPeekString_Repeated() {\n        var buffer = ByteBuffer()\n        let testString = \"Repeated Peek\"\n        let written = buffer.writeString(testString)\n        guard let firstPeek = buffer.peekString(length: written) else {\n            XCTFail(\"peekString() failed on first call.\")\n            return\n        }\n        guard let secondPeek = buffer.peekString(length: written) else {\n            XCTFail(\"peekString() failed on second call.\")\n            return\n        }\n        XCTAssertEqual(firstPeek, secondPeek, \"Repeated peekString() calls should return the same string.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekString() should not change the reader index.\")\n    }\n\n    func testPeekString_Partial() {\n        var buffer = ByteBuffer()\n        let testString = \"PartialString\"\n        let written = buffer.writeString(testString)\n        // Peek only the first half of the bytes.\n        let partialLength = written / 2\n        guard let peeked = buffer.peekString(length: partialLength) else {\n            XCTFail(\"peekString() failed for partial length.\")\n            return\n        }\n        // Since getString does not guarantee returning a complete valid string if length is arbitrary,\n        // we simply ensure that the returned substring is a prefix of the original.\n        XCTAssertTrue(testString.hasPrefix(peeked), \"The peeked string should be a prefix of the original string.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekString() should not advance the reader index.\")\n    }\n\n    // MARK: - peekNullTerminatedString Tests\n\n    func testPeekNullTerminatedString_Normal() {\n        var buffer = ByteBuffer()\n        let testString = \"NullTerminated\"\n        let _ = buffer.writeNullTerminatedString(testString)\n        // peekNullTerminatedString should return the string without the null terminator.\n        guard let peeked = buffer.peekNullTerminatedString() else {\n            XCTFail(\"peekNullTerminatedString() failed on normal call.\")\n            return\n        }\n        XCTAssertEqual(peeked, testString, \"peekNullTerminatedString() should return the correct string.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekNullTerminatedString() should not modify the reader index.\")\n    }\n\n    func testPeekNullTerminatedString_Repeated() {\n        var buffer = ByteBuffer()\n        let testString = \"RepeatNull\"\n        let _ = buffer.writeNullTerminatedString(testString)\n        guard let firstPeek = buffer.peekNullTerminatedString() else {\n            XCTFail(\"First peekNullTerminatedString() call failed.\")\n            return\n        }\n        guard let secondPeek = buffer.peekNullTerminatedString() else {\n            XCTFail(\"Second peekNullTerminatedString() call failed.\")\n            return\n        }\n        XCTAssertEqual(\n            firstPeek,\n            secondPeek,\n            \"Repeated calls to peekNullTerminatedString() should yield the same result.\"\n        )\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index should remain unchanged on peekNullTerminatedString().\")\n    }\n\n    func testPeekNullTerminatedString_Incomplete() {\n        var buffer = ByteBuffer()\n        // Write a string without a null terminator using writeString.\n        let testString = \"Incomplete\"\n        _ = buffer.writeString(testString)\n        let peeked = buffer.peekNullTerminatedString()\n        XCTAssertNil(peeked, \"peekNullTerminatedString() should return nil if the null terminator is missing.\")\n    }\n\n    // MARK: - peekUTF8ValidatedString Tests (available in Swift 6+)\n\n    func testPeekUTF8ValidatedString_Normal() throws {\n        guard #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) else {\n            throw XCTSkip(\"'peekUTF8ValidatedString' is only available in Swift 6 and later\")\n        }\n        var buffer = ByteBuffer()\n        let testString = \"UTF8 Validated\"\n        let written = buffer.writeString(testString)\n        let peeked = try buffer.peekUTF8ValidatedString(length: written)\n        XCTAssertEqual(peeked, testString, \"peekUTF8ValidatedString() should return the correct validated string.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index should remain unchanged.\")\n    }\n\n    func testPeekUTF8ValidatedString_Empty() throws {\n        guard #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) else {\n            throw XCTSkip(\"'peekUTF8ValidatedString' is only available in Swift 6 and later\")\n        }\n        var buffer = ByteBuffer()\n        _ = buffer.writeString(\"\")\n        let peeked = try buffer.peekUTF8ValidatedString(length: 0)\n        XCTAssertEqual(peeked, \"\", \"peekUTF8ValidatedString() should return an empty string when no bytes are written.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index should remain unchanged for empty peek.\")\n    }\n\n    func testPeekUTF8ValidatedString_Repeated() throws {\n        guard #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) else {\n            throw XCTSkip(\"'peekUTF8ValidatedString' is only available in Swift 6 and later\")\n        }\n        var buffer = ByteBuffer()\n        let testString = \"Repeat UTF8\"\n        let written = buffer.writeString(testString)\n        let firstPeek = try buffer.peekUTF8ValidatedString(length: written)\n        let secondPeek = try buffer.peekUTF8ValidatedString(length: written)\n        XCTAssertEqual(\n            firstPeek,\n            secondPeek,\n            \"Repeated peekUTF8ValidatedString() calls should yield identical results.\"\n        )\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekUTF8ValidatedString() should not advance the reader index.\")\n    }\n\n    // MARK: - peekDispatchData Tests (available when Dispatch is imported)\n\n    #if canImport(Dispatch)\n    func testPeekDispatchData_Normal() {\n        var buffer = ByteBuffer()\n        let testBytes: [UInt8] = [65, 66, 67, 68]\n        let written = buffer.writeBytes(testBytes)\n        XCTAssertEqual(written, testBytes.count, \"All bytes should be written to the buffer.\")\n\n        guard let peekedData = buffer.peekDispatchData(length: testBytes.count) else {\n            XCTFail(\"peekDispatchData() should return DispatchData on normal call.\")\n            return\n        }\n        var result = [UInt8](repeating: 0, count: testBytes.count)\n        // peekedData.copyBytes(to: &result, count: testBytes.count)\n        result.withUnsafeMutableBytes { dest in\n            peekedData.copyBytes(to: dest, count: testBytes.count)\n        }\n        XCTAssertEqual(result, testBytes, \"peekDispatchData() should return the correct data.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekDispatchData() should not change the reader index.\")\n    }\n\n    func testPeekDispatchData_Empty() {\n        let buffer = ByteBuffer()\n        let peekedData = buffer.peekDispatchData(length: 5)\n        XCTAssertNil(peekedData, \"peekDispatchData() should return nil when the buffer is empty.\")\n    }\n\n    func testPeekDispatchData_Repeated() {\n        var buffer = ByteBuffer()\n        let testBytes: [UInt8] = [100, 101, 102]\n        _ = buffer.writeBytes(testBytes)\n\n        guard let firstPeek = buffer.peekDispatchData(length: testBytes.count) else {\n            XCTFail(\"First call to peekDispatchData() failed.\")\n            return\n        }\n        guard let secondPeek = buffer.peekDispatchData(length: testBytes.count) else {\n            XCTFail(\"Second call to peekDispatchData() failed.\")\n            return\n        }\n        var firstResult = [UInt8](repeating: 0, count: testBytes.count)\n        var secondResult = [UInt8](repeating: 0, count: testBytes.count)\n        firstResult.withUnsafeMutableBytes { dest in\n            firstPeek.copyBytes(to: dest, count: testBytes.count)\n        }\n        secondResult.withUnsafeMutableBytes { dest in\n            secondPeek.copyBytes(to: dest, count: testBytes.count)\n        }\n        XCTAssertEqual(firstResult, secondResult, \"Repeated peekDispatchData() calls should return the same data.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekDispatchData() should not advance the reader index.\")\n    }\n    #endif\n\n    // MARK: - peekSlice Tests\n\n    func testPeekSlice_Normal() {\n        var buffer = ByteBuffer()\n        let bytes: [UInt8] = [0x01, 0x02, 0x03, 0x04]\n        buffer.writeBytes(bytes)\n\n        // Peek a slice of length 2.\n        guard let slice = buffer.peekSlice(length: 2) else {\n            XCTFail(\"Expected a valid slice.\")\n            return\n        }\n        XCTAssertEqual(slice.readableBytes, 2, \"Slice should contain 2 readable bytes.\")\n        XCTAssertEqual(slice.getBytes(at: 0, length: 2), [0x01, 0x02])\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekSlice() should not advance the reader index.\")\n    }\n\n    func testPeekSlice_OutOfRange() {\n        var buffer = ByteBuffer()\n        buffer.writeRepeatingByte(0xFF, count: 3)\n        // Request more bytes than available.\n        let slice = buffer.peekSlice(length: 10)\n        XCTAssertNil(slice, \"Should return nil when requesting out-of-range slice.\")\n    }\n\n    func testPeekSlice_Repeated() {\n        var buffer = ByteBuffer()\n        let bytes: [UInt8] = [0xAA, 0xBB, 0xCC, 0xDD]\n        buffer.writeBytes(bytes)\n\n        let firstPeek = buffer.peekSlice(length: 4)\n        let secondPeek = buffer.peekSlice(length: 4)\n        XCTAssertEqual(firstPeek?.readableBytes, 4)\n        XCTAssertEqual(secondPeek?.readableBytes, 4)\n        XCTAssertEqual(buffer.readerIndex, 0, \"Repeated peekSlice() calls should not change reader index.\")\n    }\n\n    // MARK: - peekData Tests\n\n    func testPeekData_Normal() {\n        var buffer = ByteBuffer()\n        let bytes: [UInt8] = [0x10, 0x20, 0x30]\n        buffer.writeBytes(bytes)\n        // Force a `.copy` strategy.\n        guard let data = buffer.peekData(length: bytes.count, byteTransferStrategy: .copy) else {\n            XCTFail(\"Expected non-nil Data.\")\n            return\n        }\n        XCTAssertEqual(Array(data), bytes, \"peekData() should return the correct bytes.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekData() should not change the reader index.\")\n    }\n\n    func testPeekData_OutOfRange() {\n        var buffer = ByteBuffer()\n        buffer.writeBytes([0x01, 0x02])\n        // Request more bytes than written.\n        let data = buffer.peekData(length: 10, byteTransferStrategy: .copy)\n        XCTAssertNil(data, \"Should return nil if requested length is not readable.\")\n    }\n\n    func testPeekData_Repeated() {\n        var buffer = ByteBuffer()\n        let bytes: [UInt8] = [0xFF, 0x01, 0x02]\n        buffer.writeBytes(bytes)\n\n        // Repeated calls.\n        let firstPeek = buffer.peekData(length: bytes.count, byteTransferStrategy: .noCopy)\n        let secondPeek = buffer.peekData(length: bytes.count, byteTransferStrategy: .automatic)\n        XCTAssertEqual(firstPeek, secondPeek, \"Repeated peeks should return the same Data.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index should remain unchanged.\")\n    }\n\n    // MARK: - peekUUIDBytes Tests\n\n    func testPeekUUIDBytes_Normal() {\n        var buffer = ByteBuffer()\n        // Write 16 bytes that form a UUID.\n        let uuidBytes: [UInt8] = Array(repeating: 0xAB, count: 16)\n        buffer.writeBytes(uuidBytes)\n\n        guard let uuid = buffer.peekUUIDBytes() else {\n            XCTFail(\"Expected valid UUID bytes.\")\n            return\n        }\n        // Convert the returned UUID to its 16-byte representation\n        let extracted = withUnsafeBytes(of: uuid.uuid) { Array($0) }\n        XCTAssertEqual(extracted, uuidBytes, \"peekUUIDBytes() should read back the correct 16 bytes.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekUUIDBytes() should not advance the reader index.\")\n    }\n\n    func testPeekUUIDBytes_NotEnoughBytes() {\n        var buffer = ByteBuffer()\n        buffer.writeBytes([0xAA, 0xBB])\n        let result = buffer.peekUUIDBytes()\n        XCTAssertNil(result, \"peekUUIDBytes() should return nil when fewer than 16 bytes are readable.\")\n    }\n}\n\n#if compiler(>=6.2)\nextension ByteBufferTest {\n    func testWriteBytesRawSpan() throws {\n        guard #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) else {\n            throw XCTSkip(\"Span methods only available on 26 OSes\")\n        }\n        // Write 16 bytes into buffer using a RawSpan\n        let byteArray: [UInt8] = Array(0..<16)\n        let rawSpan = byteArray.span.bytes\n        let writeLength = self.buf.writeBytes(rawSpan)\n        XCTAssertEqual(writeLength, rawSpan.byteCount)\n\n        let read = self.buf.readBytes(length: 4)\n        XCTAssertEqual([0, 1, 2, 3], read)\n        XCTAssertEqual(buf.readerIndex, 4)\n\n        let peek = self.buf.peekBytes(length: 4)\n        XCTAssertEqual([4, 5, 6, 7], peek)\n        XCTAssertEqual(buf.readerIndex, 4)\n\n        let rest = self.buf.readBytes(length: 12)\n        XCTAssertEqual([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], rest)\n        XCTAssertEqual(buf.readerIndex, 16)\n    }\n\n    func testSetBytesRawSpan() throws {\n        guard #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) else {\n            throw XCTSkip(\"Span methods only available on 26 OSes\")\n        }\n        // Write 4 bytes using setBytes\n        let byteArray: [UInt8] = Array(0..<4)\n        let rawSpan = byteArray.span.bytes\n        let writeLength = self.buf.setBytes(rawSpan, at: 0)\n        XCTAssertEqual(writeLength, rawSpan.byteCount)\n\n        // Should not be readable as writer index is not moved by setBytes\n        let shouldBeNil = self.buf.readBytes(length: 4)\n        XCTAssertNil(shouldBeNil)\n\n        // Move writer index\n        self.buf.moveWriterIndex(to: 4)\n        let result = self.buf.readBytes(length: 4)\n        XCTAssertEqual(Array(0..<4), result!)\n    }\n\n    func testReadInlineArrayOfUInt8() throws {\n        guard #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) else {\n            throw XCTSkip(\"Span methods only available on 26 OSes\")\n        }\n        let bytes = (0..<10).map { _ in UInt8.random(in: .min ... .max) }\n\n        let startWriterIndex = self.buf.writerIndex\n        let written = self.buf.writeBytes(bytes)\n        XCTAssertEqual(startWriterIndex + written, self.buf.writerIndex)\n        XCTAssertEqual(written, self.buf.readableBytes)\n\n        let result = try XCTUnwrap(\n            self.buf.readInlineArray(as: InlineArray<10, UInt8>.self)\n        )\n        XCTAssertEqual(10, result.count)\n        for idx in result.indices {\n            XCTAssertEqual(bytes[idx], result[idx])\n        }\n        XCTAssertEqual(0, self.buf.readableBytes)\n        XCTAssertEqual(10, self.buf.readerIndex)\n    }\n\n    func testReadInlineArrayOfUInt64() throws {\n        guard #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) else {\n            throw XCTSkip(\"Span methods only available on 26 OSes\")\n        }\n        let bytes = (0..<15).map { _ in UInt64.random(in: .min ... .max) }\n\n        let startWriterIndex = self.buf.writerIndex\n        var written = 0\n        for byte in bytes {\n            written += self.buf.writeInteger(byte)\n        }\n        XCTAssertEqual(startWriterIndex + written, self.buf.writerIndex)\n        XCTAssertEqual(written, self.buf.readableBytes)\n\n        let result = try XCTUnwrap(\n            self.buf.readInlineArray(as: InlineArray<15, UInt64>.self)\n        )\n        XCTAssertEqual(15, result.count)\n        for idx in result.indices {\n            XCTAssertEqual(bytes[idx], result[idx])\n        }\n        XCTAssertEqual(0, self.buf.readableBytes)\n        XCTAssertEqual(120, self.buf.readerIndex)\n    }\n\n    func testNotEnoughBytesToReadInlineArrayOfInt32() throws {\n        guard #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) else {\n            throw XCTSkip(\"Span methods only available on 26 OSes\")\n        }\n        let startWriterIndex = self.buf.writerIndex\n        var written = 0\n        /// Write 15 bytes. This won't be enough to read an `InlineArray<5, Int32>`.\n        for _ in 0..<15 {\n            written += self.buf.writeInteger(UInt8.random(in: .min ... .max))\n        }\n        XCTAssertEqual(startWriterIndex + written, self.buf.writerIndex)\n        XCTAssertEqual(written, self.buf.readableBytes)\n\n        let result = self.buf.readInlineArray(as: InlineArray<5, Int32>.self)\n\n        XCTAssertNil(result)\n        XCTAssertEqual(written, self.buf.readableBytes)\n        XCTAssertEqual(0, self.buf.readerIndex)\n    }\n}\n#endif\n"
  },
  {
    "path": "Tests/NIOCoreTests/ChannelOptionStorageTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\nclass ChannelOptionStorageTest: XCTestCase {\n    func testWeStartWithNoOptions() throws {\n        let cos = ChannelOptions.Storage()\n        let optionsCollector = OptionsCollectingChannel()\n        XCTAssertNoThrow(try cos.applyAllChannelOptions(to: optionsCollector).wait())\n        XCTAssertEqual(0, optionsCollector.allOptions.count)\n    }\n\n    func testSetTwoOptionsOfDifferentType() throws {\n        var cos = ChannelOptions.Storage()\n        let optionsCollector = OptionsCollectingChannel()\n        cos.append(key: .socketOption(.so_reuseaddr), value: 1)\n        cos.append(key: .backlog, value: 2)\n        XCTAssertNoThrow(try cos.applyAllChannelOptions(to: optionsCollector).wait())\n        XCTAssertEqual(2, optionsCollector.allOptions.count)\n    }\n\n    func testSetTwoOptionsOfSameType() throws {\n        let options: [(ChannelOptions.Types.SocketOption, SocketOptionValue)] = [\n            (.socketOption(.so_reuseaddr), 1),\n            (.socketOption(.so_rcvtimeo), 2),\n        ]\n        var cos = ChannelOptions.Storage()\n        let optionsCollector = OptionsCollectingChannel()\n        for kv in options {\n            cos.append(key: kv.0, value: kv.1)\n        }\n        XCTAssertNoThrow(try cos.applyAllChannelOptions(to: optionsCollector).wait())\n        XCTAssertEqual(2, optionsCollector.allOptions.count)\n        XCTAssertEqual(\n            options.map { $0.0 },\n            optionsCollector.allOptions.map { option in\n                option.0 as! ChannelOptions.Types.SocketOption\n            }\n        )\n        XCTAssertEqual(\n            options.map { $0.1 },\n            optionsCollector.allOptions.map { option in\n                option.1 as! SocketOptionValue\n            }\n        )\n    }\n\n    func testSetOneOptionTwice() throws {\n        var cos = ChannelOptions.Storage()\n        let optionsCollector = OptionsCollectingChannel()\n        cos.append(key: .socketOption(.so_reuseaddr), value: 1)\n        cos.append(key: .socketOption(.so_reuseaddr), value: 2)\n        XCTAssertNoThrow(try cos.applyAllChannelOptions(to: optionsCollector).wait())\n        XCTAssertEqual(1, optionsCollector.allOptions.count)\n        XCTAssertEqual(\n            [.socketOption(.so_reuseaddr)],\n            optionsCollector.allOptions.map { option in\n                option.0 as! ChannelOptions.Types.SocketOption\n            }\n        )\n        XCTAssertEqual(\n            [SocketOptionValue(2)],\n            optionsCollector.allOptions.map { option in\n                option.1 as! SocketOptionValue\n            }\n        )\n    }\n\n    func testClearingOptions() throws {\n        var cos = ChannelOptions.Storage()\n        let optionsCollector = OptionsCollectingChannel()\n        cos.append(key: .socketOption(.so_reuseaddr), value: 1)\n        cos.append(key: .socketOption(.so_reuseaddr), value: 2)\n        cos.append(key: .socketOption(.so_keepalive), value: 3)\n        cos.append(key: .socketOption(.so_reuseaddr), value: 4)\n        cos.append(key: .socketOption(.so_rcvbuf), value: 5)\n        cos.append(key: .socketOption(.so_reuseaddr), value: 6)\n        cos.remove(key: .socketOption(.so_reuseaddr))\n        XCTAssertNoThrow(try cos.applyAllChannelOptions(to: optionsCollector).wait())\n        XCTAssertEqual(2, optionsCollector.allOptions.count)\n        XCTAssertEqual(\n            [\n                .socketOption(.so_keepalive),\n                .socketOption(.so_rcvbuf),\n            ],\n            optionsCollector.allOptions.map { option in\n                option.0 as! ChannelOptions.Types.SocketOption\n            }\n        )\n        XCTAssertEqual(\n            [SocketOptionValue(3), SocketOptionValue(5)],\n            optionsCollector.allOptions.map { option in\n                option.1 as! SocketOptionValue\n            }\n        )\n    }\n}\n\nfinal class OptionsCollectingChannel: Channel {\n    private let _allOptions = NIOLockedValueBox<[(any Sendable, any Sendable)]>([])\n    var allOptions: [(any Sendable, any Sendable)] {\n        get {\n            self._allOptions.withLockedValue { $0 }\n        }\n        set {\n            self._allOptions.withLockedValue { $0 = newValue }\n        }\n    }\n\n    var allocator: ByteBufferAllocator { fatalError() }\n\n    var closeFuture: EventLoopFuture<Void> { fatalError() }\n\n    var pipeline: ChannelPipeline { fatalError() }\n\n    var localAddress: SocketAddress? { fatalError() }\n\n    var remoteAddress: SocketAddress? { fatalError() }\n\n    var parent: Channel? { fatalError() }\n\n    func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void> {\n        self.allOptions.append((option, value))\n        return self.eventLoop.makeSucceededFuture(())\n    }\n\n    func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value> {\n        fatalError()\n    }\n\n    var isWritable: Bool { fatalError() }\n\n    var isActive: Bool { fatalError() }\n\n    var _channelCore: ChannelCore { fatalError() }\n\n    var eventLoop: EventLoop {\n        EmbeddedEventLoop()\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/CircularBufferTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\nclass CircularBufferTests: XCTestCase {\n    func testTrivial() {\n        var ring = CircularBuffer<Int>(initialCapacity: 8)\n        ring.append(1)\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(1, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n    }\n\n    func testAddRemoveInALoop() {\n        var ring = CircularBuffer<Int>(initialCapacity: 8)\n        XCTAssertTrue(ring.isEmpty)\n        XCTAssertEqual(0, ring.count)\n\n        for f in 0..<1000 {\n            ring.append(f)\n            XCTAssertEqual(f, ring.removeFirst())\n            XCTAssertTrue(ring.isEmpty)\n            XCTAssertEqual(0, ring.count)\n        }\n    }\n\n    func testAddAllRemoveAll() {\n        var ring = CircularBuffer<Int>(initialCapacity: 8)\n        XCTAssertTrue(ring.isEmpty)\n        XCTAssertEqual(0, ring.count)\n\n        for f in 1..<100 {\n            ring.append(f)\n            XCTAssertEqual(f, ring.count)\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        for f in 1..<100 {\n            XCTAssertEqual(f, ring.removeFirst())\n            XCTAssertEqual(99 - f, ring.count)\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        XCTAssertTrue(ring.isEmpty)\n    }\n\n    func testRemoveAt() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<7 {\n            ring.prepend(idx)\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n\n        XCTAssertEqual(7, ring.count)\n        _ = ring.remove(at: ring.index(ring.startIndex, offsetBy: 1))\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(6, ring.count)\n        XCTAssertEqual(0, ring.last)\n    }\n\n    func testRemoveAtLastPosition() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<7 {\n            ring.prepend(idx)\n        }\n\n        let last = ring.remove(at: ring.index(ring.endIndex, offsetBy: -1))\n        XCTAssertEqual(0, last)\n        XCTAssertEqual(1, ring.last)\n    }\n\n    func testRemoveAtTailIdx0() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        ring.prepend(99)\n        ring.prepend(98)\n        XCTAssertEqual(2, ring.count)\n        XCTAssertEqual(99, ring.remove(at: ring.index(ring.endIndex, offsetBy: -1)))\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertFalse(ring.isEmpty)\n        XCTAssertEqual(1, ring.count)\n        XCTAssertEqual(98, ring.last)\n        XCTAssertEqual(98, ring.first)\n    }\n\n    func testRemoveAtFirstPosition() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<7 {\n            ring.prepend(idx)\n        }\n\n        let first = ring.remove(at: ring.startIndex)\n        XCTAssertEqual(6, first)\n        XCTAssertEqual(5, ring.first)\n    }\n\n    func collectAllIndices<Element>(ring: CircularBuffer<Element>) -> [CircularBuffer<Element>.Index] {\n        Array(ring.indices)\n    }\n\n    func collectAllIndices<Element>(\n        ring: CircularBuffer<Element>,\n        range: Range<CircularBuffer<Element>.Index>\n    ) -> [CircularBuffer<Element>.Index] {\n        var index: CircularBuffer<Element>.Index = range.lowerBound\n        var allIndices: [CircularBuffer<Element>.Index] = []\n        while index != range.upperBound {\n            allIndices.append(index)\n            index = ring.index(after: index)\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        return allIndices\n    }\n\n    func testHarderExpansion() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(ring: ring, range: ring.startIndex..<ring.startIndex)\n        )\n\n        ring.append(1)\n        XCTAssertEqual(ring.count, 1)\n        XCTAssertEqual(ring[ring.startIndex], 1)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 1\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        ring.append(2)\n        XCTAssertEqual(ring.count, 2)\n        XCTAssertEqual(ring[ring.startIndex], 1)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 1)], 2)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 2\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        ring.append(3)\n        XCTAssertEqual(ring.count, 3)\n        XCTAssertEqual(ring[ring.startIndex], 1)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 1)], 2)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 2)], 3)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 3\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        XCTAssertEqual(1, ring.removeFirst())\n        XCTAssertEqual(ring.count, 2)\n        XCTAssertEqual(ring[ring.startIndex], 2)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 1)], 3)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 2\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        XCTAssertEqual(2, ring.removeFirst())\n        XCTAssertEqual(ring.count, 1)\n        XCTAssertEqual(ring[ring.startIndex], 3)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 1\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        ring.append(5)\n        XCTAssertEqual(ring.count, 2)\n        XCTAssertEqual(ring[ring.startIndex], 3)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 1)], 5)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 2\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        ring.append(6)\n        XCTAssertEqual(ring.count, 3)\n        XCTAssertEqual(ring[ring.startIndex], 3)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 1)], 5)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 2)], 6)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 3\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        ring.append(7)\n        XCTAssertEqual(ring.count, 4)\n        XCTAssertEqual(ring[ring.startIndex], 3)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 1)], 5)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 2)], 6)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 3)], 7)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 4\n                    )\n            )\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n    }\n\n    func testCollection() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(ring: ring, range: ring.startIndex..<ring.startIndex)\n        )\n        XCTAssertEqual(0, ring.distance(from: ring.startIndex, to: ring.endIndex))\n        XCTAssertEqual(0, ring.distance(from: ring.startIndex, to: ring.startIndex))\n\n        for idx in 0..<5 {\n            ring.append(idx)\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n\n        XCTAssertFalse(ring.isEmpty)\n        XCTAssertEqual(5, ring.count)\n\n        XCTAssertEqual(\n            self.collectAllIndices(ring: ring),\n            self.collectAllIndices(\n                ring: ring,\n                range: ring\n                    .startIndex..<ring.index(\n                        ring.startIndex,\n                        offsetBy: 5\n                    )\n            )\n        )\n        XCTAssertEqual(ring.startIndex, ring.startIndex)\n        XCTAssertEqual(ring.endIndex, ring.index(ring.startIndex, offsetBy: 5))\n\n        XCTAssertEqual(\n            ring.index(after: ring.index(ring.startIndex, offsetBy: 1)),\n            ring.index(ring.startIndex, offsetBy: 2)\n        )\n        XCTAssertEqual(\n            ring.index(before: ring.index(ring.startIndex, offsetBy: 3)),\n            ring.index(ring.startIndex, offsetBy: 2)\n        )\n\n        let actualValues = [Int](ring)\n        let expectedValues = [0, 1, 2, 3, 4]\n        XCTAssertEqual(expectedValues, actualValues)\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n    }\n\n    func testReplaceSubrange5ElementsWith1() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<50 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(50, ring.count)\n        ring.replaceSubrange(\n            ring.index(ring.startIndex, offsetBy: 20)..<ring.index(ring.startIndex, offsetBy: 25),\n            with: [99]\n        )\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        XCTAssertEqual(ring.count, 46)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 19)], 30)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 20)], 99)\n        XCTAssertEqual(ring[ring.index(ring.startIndex, offsetBy: 21)], 24)\n    }\n\n    func testReplaceSubrangeAllElementsWithFewerElements() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<50 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(50, ring.count)\n\n        ring.replaceSubrange(ring.startIndex..<ring.endIndex, with: [3, 4])\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(2, ring.count)\n        XCTAssertEqual(3, ring.first)\n        XCTAssertEqual(4, ring.last)\n    }\n\n    func testReplaceSubrangeEmptyRange() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<50 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(50, ring.count)\n\n        ring.replaceSubrange(ring.startIndex..<ring.startIndex, with: [])\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(50, ring.count)\n    }\n\n    func testReplaceSubrangeWithSubrangeLargerThanTargetRange() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<5 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(5, ring.count)\n\n        ring.replaceSubrange(ring.startIndex..<ring.endIndex, with: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19])\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(10, ring.count)\n        XCTAssertEqual(10, ring.first)\n        XCTAssertEqual(19, ring.last)\n    }\n\n    func testReplaceSubrangeSameSize() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<5 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(5, ring.count)\n        XCTAssertEqual(4, ring.first)\n        XCTAssertEqual(0, ring.last)\n\n        var replacement = [Int]()\n        for idx in 0..<5 {\n            replacement.append(idx)\n        }\n        XCTAssertEqual(5, replacement.count)\n        XCTAssertEqual(0, replacement.first)\n        XCTAssertEqual(4, replacement.last)\n\n        ring.replaceSubrange(ring.startIndex..<ring.endIndex, with: replacement)\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(5, ring.count)\n        XCTAssertEqual(0, ring.first)\n        XCTAssertEqual(4, ring.last)\n    }\n\n    func testReplaceSubrangeReplaceBufferWithEmptyArray() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<5 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(5, ring.count)\n        XCTAssertEqual(4, ring.first)\n        XCTAssertEqual(0, ring.last)\n\n        ring.replaceSubrange(ring.startIndex..<ring.endIndex, with: [])\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertTrue(ring.isEmpty)\n    }\n\n    func testRangeSubscriptExpanding() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<5 {\n            ring.prepend(idx)\n        }\n        XCTAssertEqual(5, ring.count)\n\n        let index = ring.firstIndex(of: 1)!\n        let originalCount = ring.count\n        XCTAssertEqual(ring[index..<ring.endIndex].count, 2)\n        ring[index..<ring.endIndex] = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(originalCount + 8, ring.count)\n        XCTAssertEqual(4, ring.first)\n        XCTAssertEqual(19, ring.last)\n    }\n\n    func testWeCanDistinguishBetweenEmptyAndFull() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        XCTAssertTrue(ring.isEmpty)\n        for idx in 0..<4 {\n            ring.append(idx)\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        XCTAssertEqual(4, ring.count)\n        XCTAssertFalse(ring.isEmpty)\n    }\n\n    func testExpandZeroBasedRingWorks() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<5 {\n            ring.append(idx)\n        }\n        for idx in 0..<5 {\n            XCTAssertEqual(idx, ring[ring.index(ring.startIndex, offsetBy: idx)])\n        }\n    }\n\n    func testExpandNonZeroBasedRingWorks() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        for idx in 0..<4 {\n            ring.append(idx)\n        }\n        // the underlying buffer should now be filled from 0 to max\n        for idx in 0..<4 {\n            XCTAssertEqual(idx, ring[ring.index(ring.startIndex, offsetBy: idx)])\n        }\n        XCTAssertEqual(0, ring.removeFirst())\n        // now the first element is gone, ie. the ring starts at index 1 now\n        for idx in 0..<3 {\n            XCTAssertEqual(idx + 1, ring[ring.index(ring.startIndex, offsetBy: idx)])\n        }\n        ring.append(4)\n        XCTAssertEqual(1, ring.first!)\n        // now the last element should be at ring position 0\n        for idx in 0..<4 {\n            XCTAssertEqual(idx + 1, ring[ring.index(ring.startIndex, offsetBy: idx)])\n        }\n        // and now we'll make it expand\n        ring.append(5)\n        for idx in 0..<5 {\n            XCTAssertEqual(idx + 1, ring[ring.index(ring.startIndex, offsetBy: idx)])\n        }\n    }\n\n    func testEmptyingExpandedRingWorks() {\n        var ring = CircularBuffer<Int>(initialCapacity: 2)\n        for idx in 0..<4 {\n            ring.append(idx)\n        }\n        for idx in 0..<4 {\n            XCTAssertEqual(idx, ring[ring.index(ring.startIndex, offsetBy: idx)])\n        }\n        for idx in 0..<4 {\n            XCTAssertEqual(idx, ring.removeFirst())\n        }\n        XCTAssertTrue(ring.isEmpty)\n        XCTAssertNil(ring.first)\n    }\n\n    func testChangeElements() {\n        var ring = CircularBuffer<Int>(initialCapacity: 100)\n        for idx in 0..<50 {\n            ring.append(idx)\n        }\n        var changes: [(Int, Int)] = []\n        for (idx, element) in ring.enumerated() {\n            XCTAssertEqual(idx, element)\n            changes.append((idx, element * 2))\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        for change in changes {\n            ring[ring.index(ring.startIndex, offsetBy: change.0)] = change.1\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        for (idx, element) in ring.enumerated() {\n            XCTAssertEqual(idx * 2, element)\n        }\n    }\n\n    func testSliceTheRing() {\n        var ring = CircularBuffer<Int>(initialCapacity: 100)\n        for idx in 0..<50 {\n            ring.append(idx)\n        }\n\n        let slice = ring[ring.index(ring.startIndex, offsetBy: 25)..<ring.index(ring.startIndex, offsetBy: 30)]\n        for (idx, element) in slice.enumerated() {\n            XCTAssertEqual(\n                ring.index(ring.startIndex, offsetBy: idx + 25),\n                ring.index(ring.startIndex, offsetBy: element)\n            )\n        }\n    }\n\n    func testCount() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        ring.append(1)\n        XCTAssertEqual(1, ring.count)\n        ring.append(2)\n        XCTAssertEqual(2, ring.count)\n        XCTAssertEqual(1, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        ring.append(3)\n        XCTAssertEqual(2, ring.count)\n        XCTAssertEqual(2, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        ring.append(4)\n\n        XCTAssertEqual(2, ring.count)\n        XCTAssertEqual(3, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        ring.append(5)\n\n        XCTAssertEqual(3, ring.headBackingIndex)\n        XCTAssertEqual(1, ring.tailBackingIndex)\n        XCTAssertEqual(2, ring.count)\n        XCTAssertEqual(4, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(5, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(0, ring.count)\n        XCTAssertTrue(ring.isEmpty)\n    }\n\n    func testFirst() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        XCTAssertNil(ring.first)\n        ring.append(1)\n        XCTAssertEqual(1, ring.first)\n        XCTAssertEqual(1, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertNil(ring.first)\n    }\n\n    func testLast() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        XCTAssertNil(ring.last)\n        ring.prepend(1)\n        XCTAssertEqual(1, ring.last)\n        XCTAssertEqual(1, ring.removeLast())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertNil(ring.last)\n        XCTAssertEqual(0, ring.count)\n        XCTAssertTrue(ring.isEmpty)\n    }\n\n    func testRemoveLast() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        XCTAssertNil(ring.last)\n        ring.append(1)\n        ring.prepend(0)\n        XCTAssertEqual(1, ring.last)\n        XCTAssertEqual(1, ring.removeLast())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(0, ring.last)\n    }\n\n    func testRemoveLastCountElements() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        XCTAssertNil(ring.last)\n        ring.append(1)\n        ring.prepend(0)\n        XCTAssertEqual(1, ring.last)\n        ring.removeLast(2)\n        XCTAssertTrue(ring.isEmpty)\n    }\n\n    func testRemoveLastElements() {\n        var ring = CircularBuffer<Int>(initialCapacity: 10)\n        XCTAssertNil(ring.last)\n        for i in 0..<20 {\n            ring.prepend(i)\n        }\n        XCTAssertEqual(20, ring.count)\n        XCTAssertEqual(19, ring.first)\n        XCTAssertEqual(0, ring.last)\n        ring.removeLast(10)\n        XCTAssertEqual(10, ring.count)\n        XCTAssertEqual(19, ring.first)\n        XCTAssertEqual(10, ring.last)\n    }\n\n    func testOperateOnBothSides() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        XCTAssertNil(ring.last)\n        ring.prepend(1)\n        ring.prepend(2)\n\n        XCTAssertEqual(1, ring.last)\n        XCTAssertEqual(2, ring.first)\n\n        XCTAssertEqual(1, ring.removeLast())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(2, ring.removeFirst())\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n        XCTAssertNil(ring.last)\n        XCTAssertNil(ring.first)\n        XCTAssertEqual(0, ring.count)\n        XCTAssertTrue(ring.isEmpty)\n    }\n\n    func testPrependExpandBuffer() {\n        var ring = CircularBuffer<Int>(initialCapacity: 3)\n        for f in 1..<1000 {\n            ring.prepend(f)\n            XCTAssertEqual(f, ring.count)\n        }\n        for f in 1..<1000 {\n            XCTAssertEqual(f, ring.removeLast())\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        }\n        XCTAssertTrue(ring.isEmpty)\n        XCTAssertEqual(0, ring.count)\n    }\n\n    func testRemoveAllKeepingCapacity() {\n        var ring = CircularBuffer<Int>(initialCapacity: 2)\n        XCTAssertEqual(ring.capacity, 2)\n        ring.append(1)\n        ring.append(2)\n        // we're full so it will have doubled\n        XCTAssertEqual(ring.capacity, 4)\n        XCTAssertEqual(ring.count, 2)\n        ring.removeAll(keepingCapacity: true)\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(ring.capacity, 4)\n        XCTAssertEqual(ring.count, 0)\n    }\n\n    func testRemoveAllNotKeepingCapacity() {\n        var ring = CircularBuffer<Int>(initialCapacity: 2)\n        XCTAssertGreaterThanOrEqual(ring.capacity, 2)\n        ring.append(1)\n        ring.append(2)\n        // we're full so it will have doubled\n        XCTAssertEqual(ring.capacity, 4)\n        XCTAssertEqual(ring.count, 2)\n        ring.removeAll(keepingCapacity: false)\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        // 1 is the smallest capacity we have\n        XCTAssertEqual(ring.capacity, 1)\n        XCTAssertEqual(ring.count, 0)\n        ring.append(1)\n        XCTAssertEqual(ring.capacity, 2)\n        XCTAssertEqual(ring.count, 1)\n        ring.append(2)\n        XCTAssertEqual(ring.capacity, 4)\n        XCTAssertEqual(ring.count, 2)\n        ring.removeAll()  // default should not keep capacity\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(ring.capacity, 1)\n        XCTAssertEqual(ring.count, 0)\n    }\n\n    func testBufferManaged() {\n        var ring = CircularBuffer<Int>(initialCapacity: 2)\n        ring.append(1)\n        XCTAssertEqual(ring.capacity, 2)\n\n        // Now we want to replace the last subrange with two elements. This should\n        // force an increase in size.\n        ring.replaceSubrange(ring.startIndex..<ring.index(ring.startIndex, offsetBy: 1), with: [3, 4])\n        XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual(ring.capacity, 4)\n    }\n\n    func testDoesNotExpandCapacityNeedlesslyWhenInserting() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        let capacity0 = ring.capacity\n        XCTAssertGreaterThanOrEqual(capacity0, 4)\n        XCTAssertLessThan(capacity0, 16)\n\n        ring.insert(0, at: ring.startIndex)\n        let capacity1 = ring.capacity\n        XCTAssertEqual(capacity0, capacity1)\n\n        ring.insert(1, at: ring.startIndex)\n        let capacity2 = ring.capacity\n        XCTAssertEqual(capacity0, capacity2)\n\n        ring.insert(2, at: ring.startIndex)\n        let capacity3 = ring.capacity\n        XCTAssertEqual(capacity0, capacity3)\n    }\n\n    func testDoesNotExpandCapacityNeedlesslyWhenAppending() {\n        var ring = CircularBuffer<Int>(initialCapacity: 4)\n        let capacity0 = ring.capacity\n        XCTAssertGreaterThanOrEqual(capacity0, 4)\n        XCTAssertLessThan(capacity0, 16)\n\n        ring.append(0)\n        let capacity1 = ring.capacity\n        XCTAssertEqual(capacity0, capacity1)\n\n        ring.append(1)\n        let capacity2 = ring.capacity\n        XCTAssertEqual(capacity0, capacity2)\n\n        ring.append(2)\n        let capacity3 = ring.capacity\n        XCTAssertEqual(capacity0, capacity3)\n    }\n\n    func testExpandRemoveAllKeepingAndNotKeepingCapacityAndExpandAgain() {\n        for shouldKeepCapacity in [false, true] {\n            var ring = CircularBuffer<Int>(initialCapacity: 4)\n\n            for i in (0..<16) {\n                ring.append(i)\n            }\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n            for _ in (0..<4) {\n                _ = ring.removeFirst()\n            }\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n            for i in (16..<20) {\n                ring.append(i)\n            }\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n            XCTAssertEqual(Array(4..<20), Array(ring))\n\n            ring.removeAll(keepingCapacity: shouldKeepCapacity)\n\n            for i in (0..<8) {\n                ring.append(i)\n            }\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n            for _ in (0..<4) {\n                _ = ring.removeFirst()\n            }\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n            for i in (8..<64) {\n                ring.append(i)\n            }\n            XCTAssertTrue(ring.testOnly_verifyInvariantsForNonSlices())\n\n            XCTAssertEqual(Array(4..<64), Array(ring))\n        }\n    }\n\n    func testRemoveAllNilsOutTheContents() {\n        class Dummy {}\n\n        weak var dummy1: Dummy? = nil\n        weak var dummy2: Dummy? = nil\n        weak var dummy3: Dummy? = nil\n        weak var dummy4: Dummy? = nil\n        weak var dummy5: Dummy? = nil\n        weak var dummy6: Dummy? = nil\n        weak var dummy7: Dummy? = nil\n        weak var dummy8: Dummy? = nil\n\n        var ring: CircularBuffer<Dummy> = .init(initialCapacity: 4)\n\n        ({\n            for _ in 0..<2 {\n                ring.append(Dummy())\n            }\n\n            dummy1 = ring.dropFirst(0).first\n            dummy2 = ring.dropFirst(1).first\n\n            XCTAssertNotNil(dummy1)\n            XCTAssertNotNil(dummy2)\n\n            _ = ring.removeFirst()\n\n            for _ in 2..<8 {\n                ring.append(Dummy())\n            }\n\n            dummy3 = ring.dropFirst(1).first\n            dummy4 = ring.dropFirst(2).first\n            dummy5 = ring.dropFirst(3).first\n            dummy6 = ring.dropFirst(4).first\n            dummy7 = ring.dropFirst(5).first\n            dummy8 = ring.dropFirst(6).first\n\n            XCTAssertNotNil(dummy3)\n            XCTAssertNotNil(dummy4)\n            XCTAssertNotNil(dummy5)\n            XCTAssertNotNil(dummy6)\n            XCTAssertNotNil(dummy7)\n            XCTAssertNotNil(dummy8)\n        })()\n\n        XCTAssertNotNil(dummy2)\n        XCTAssertNotNil(dummy3)\n        XCTAssertNotNil(dummy4)\n        XCTAssertNotNil(dummy5)\n        XCTAssertNotNil(dummy6)\n        XCTAssertNotNil(dummy7)\n        XCTAssertNotNil(dummy8)\n\n        ring.removeAll(keepingCapacity: true)\n\n        assert(dummy1 == nil, within: .seconds(1))\n        assert(dummy2 == nil, within: .seconds(1))\n        assert(dummy3 == nil, within: .seconds(1))\n        assert(dummy4 == nil, within: .seconds(1))\n        assert(dummy5 == nil, within: .seconds(1))\n        assert(dummy6 == nil, within: .seconds(1))\n        assert(dummy7 == nil, within: .seconds(1))\n        assert(dummy8 == nil, within: .seconds(1))\n    }\n\n    func testIntIndexing() {\n        var ring = CircularBuffer<Int>()\n        for i in 0..<5 {\n            ring.append(i)\n            XCTAssertEqual(ring[offset: i], i)\n        }\n\n        XCTAssertEqual(ring[ring.startIndex], ring[offset: 0])\n        XCTAssertEqual(ring[ring.index(before: ring.endIndex)], ring[offset: 4])\n\n        ring[offset: 1] = 10\n        XCTAssertEqual(ring[ring.index(after: ring.startIndex)], 10)\n    }\n\n    func testIndexDistance() {\n        var bufferOfBackingSize4 = CircularBuffer<Int>(initialCapacity: 4)\n        XCTAssertEqual(3, bufferOfBackingSize4.indexBeforeHeadIdx())\n\n        let index1 = CircularBuffer<Int>.Index(backingIndex: 0, backingCount: 4, backingIndexOfHead: 0)\n        let index2 = CircularBuffer<Int>.Index(backingIndex: 1, backingCount: 4, backingIndexOfHead: 0)\n        XCTAssertEqual(bufferOfBackingSize4.distance(from: index1, to: index2), 1)\n\n        bufferOfBackingSize4.append(1)\n        XCTAssertEqual(1, bufferOfBackingSize4.removeFirst())\n        XCTAssertEqual(1, bufferOfBackingSize4.headBackingIndex)\n        let index3 = CircularBuffer<Int>.Index(backingIndex: 2, backingCount: 4, backingIndexOfHead: 1)\n        let index4 = CircularBuffer<Int>.Index(backingIndex: 0, backingCount: 4, backingIndexOfHead: 1)\n        XCTAssertEqual(bufferOfBackingSize4.distance(from: index3, to: index4), 2)\n\n        let index5 = CircularBuffer<Int>.Index(backingIndex: 0, backingCount: 4, backingIndexOfHead: 1)\n        let index6 = CircularBuffer<Int>.Index(backingIndex: 2, backingCount: 4, backingIndexOfHead: 1)\n        XCTAssertEqual(bufferOfBackingSize4.distance(from: index5, to: index6), -2)\n\n        bufferOfBackingSize4.append(2)\n        bufferOfBackingSize4.append(3)\n        XCTAssertEqual(2, bufferOfBackingSize4.removeFirst())\n        XCTAssertEqual(3, bufferOfBackingSize4.removeFirst())\n        XCTAssertEqual(3, bufferOfBackingSize4.headBackingIndex)\n        let index7 = CircularBuffer<Int>.Index(backingIndex: 0, backingCount: 4, backingIndexOfHead: 3)\n        let index8 = CircularBuffer<Int>.Index(backingIndex: 2, backingCount: 4, backingIndexOfHead: 3)\n        XCTAssertEqual(bufferOfBackingSize4.distance(from: index7, to: index8), 2)\n    }\n\n    func testIndexAdvancing() {\n        var bufferOfBackingSize4 = CircularBuffer<Int>(initialCapacity: 4)\n        XCTAssertEqual(3, bufferOfBackingSize4.indexBeforeHeadIdx())\n\n        let index1 = CircularBuffer<Int>.Index(backingIndex: 0, backingCount: 4, backingIndexOfHead: 0)\n        let index2 = bufferOfBackingSize4.index(after: index1)\n        XCTAssertEqual(index2.backingIndex, 1)\n        XCTAssertEqual(index2.isIndexGEQHeadIndex, true)\n\n        bufferOfBackingSize4.append(1)\n        bufferOfBackingSize4.append(2)\n        XCTAssertEqual(1, bufferOfBackingSize4.removeFirst())\n        XCTAssertEqual(2, bufferOfBackingSize4.removeFirst())\n        XCTAssertEqual(2, bufferOfBackingSize4.headBackingIndex)\n\n        let index3 = CircularBuffer<Int>.Index(backingIndex: 3, backingCount: 4, backingIndexOfHead: 2)\n        let index4 = bufferOfBackingSize4.index(after: index3)\n        XCTAssertEqual(index4.backingIndex, 0)\n        XCTAssertEqual(index4.isIndexGEQHeadIndex, false)\n\n        bufferOfBackingSize4.prepend(3)\n        XCTAssertEqual(1, bufferOfBackingSize4.headBackingIndex)\n        let index5 = CircularBuffer<Int>.Index(backingIndex: 0, backingCount: 4, backingIndexOfHead: 1)\n        let index6 = bufferOfBackingSize4.index(before: index5)\n        XCTAssertEqual(index6.backingIndex, 3)\n        XCTAssertEqual(index6.isIndexGEQHeadIndex, true)\n\n        let index7 = CircularBuffer<Int>.Index(backingIndex: 2, backingCount: 4, backingIndexOfHead: 1)\n        let index8 = bufferOfBackingSize4.index(before: index7)\n        XCTAssertEqual(index8.backingIndex, 1)\n        XCTAssertEqual(index8.isIndexGEQHeadIndex, true)\n    }\n\n    func testPopFirst() {\n        var buf = CircularBuffer([1, 2, 3])\n        if let element = buf.popFirst() {\n            XCTAssertEqual(1, element)\n        } else {\n            XCTFail(\"popFirst didn't find first element\")\n        }\n\n        if let element = buf.popFirst() {\n            XCTAssertEqual(2, element)\n        } else {\n            XCTFail(\"popFirst didn't find second element\")\n        }\n\n        if let element = buf.popFirst() {\n            XCTAssertEqual(3, element)\n        } else {\n            XCTFail(\"popFirst didn't find third element\")\n        }\n\n        XCTAssertNil(buf.popFirst())\n        XCTAssertTrue(buf.testOnly_verifyInvariantsForNonSlices())\n    }\n\n    func testSlicing() {\n        var buf = CircularBuffer<Int>()\n        for i in -4..<124 {\n            buf.append(i)\n        }\n        XCTAssertEqual(-4, buf.removeFirst())\n        XCTAssertEqual(-3, buf.removeFirst())\n        XCTAssertEqual(-2, buf.removeFirst())\n        XCTAssertEqual(-1, buf.removeFirst())\n        buf.append(124)\n        buf.append(125)\n        buf.append(126)\n        buf.append(127)\n\n        let buf2: CircularBuffer<Int> = buf[buf.index(buf.startIndex, offsetBy: 100)..<buf.endIndex]\n        XCTAssertEqual(Array(100..<128), Array(buf2))\n        XCTAssertEqual(Array(100..<128), Array(buf[buf2.startIndex..<buf2.endIndex]))\n    }\n\n    func testRemoveInMiddle() {\n        var buf = CircularBuffer<Int>(initialCapacity: 8)\n        for i in 0..<7 {\n            buf.append(i)\n        }\n        XCTAssertEqual(0, buf.removeFirst())\n        XCTAssertTrue(buf.testOnly_verifyInvariantsForNonSlices())\n        buf.append(7)\n        XCTAssertEqual(2, buf.remove(at: buf.index(buf.startIndex, offsetBy: 1)))\n        XCTAssertTrue(buf.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual([1, 3, 4, 5, 6, 7], Array(buf))\n        buf.removeAll(keepingCapacity: true)\n        XCTAssertTrue(buf.testOnly_verifyInvariantsForNonSlices())\n        XCTAssertEqual([], Array(buf))\n    }\n\n    func testLotsOfPrepending() {\n        var buf = CircularBuffer<Int>(initialCapacity: 8)\n\n        for i in (0..<128).reversed() {\n            buf.prepend(i)\n        }\n        XCTAssertEqual(Array(0..<128), Array(buf))\n    }\n\n    func testLotsOfInsertAtStart() {\n        var buf = CircularBuffer<Int>(initialCapacity: 8)\n\n        for i in (0..<128).reversed() {\n            buf.insert(i, at: buf.startIndex)\n        }\n        XCTAssertEqual(Array(0..<128), Array(buf))\n    }\n\n    func testLotsOfInsertAtEnd() {\n        var buf = CircularBuffer<Int>(initialCapacity: 8)\n\n        for i in (0..<128) {\n            buf.insert(i, at: buf.endIndex)\n        }\n        XCTAssertEqual(Array(0..<128), Array(buf))\n    }\n\n    func testPopLast() {\n        var buf = CircularBuffer<Int>(initialCapacity: 4)\n        buf.append(1)\n        XCTAssertEqual(1, buf.popLast())\n        XCTAssertNil(buf.popLast())\n\n        buf.append(1)\n        buf.append(2)\n        buf.append(3)\n        XCTAssertEqual(3, buf.popLast())\n        XCTAssertEqual(2, buf.popLast())\n        XCTAssertEqual(1, buf.popLast())\n        XCTAssertNil(buf.popLast())\n    }\n\n    func testModify() {\n        var buf = CircularBuffer<Int>(initialCapacity: 4)\n        buf.append(contentsOf: 0..<4)\n        XCTAssertEqual(Array(0..<4), Array(buf))\n\n        let secondIndex = buf.index(after: buf.startIndex)\n        buf.modify(secondIndex) { value in\n            XCTAssertEqual(value, 1)\n            value = 5\n        }\n        XCTAssertEqual([0, 5, 2, 3], Array(buf))\n    }\n\n    func testEquality() {\n        // Empty buffers\n        let emptyA = CircularBuffer<Int>()\n        let emptyB = CircularBuffer<Int>()\n        XCTAssertEqual(emptyA, emptyB)\n\n        var buffA = CircularBuffer<Int>()\n        var buffB = CircularBuffer<Int>()\n        var buffC = CircularBuffer<Int>()\n        var buffD = CircularBuffer<Int>()\n        buffA.append(contentsOf: 1...10)\n        buffB.append(contentsOf: 1...10)\n        buffC.append(contentsOf: 2...11)  // Same count different values\n        buffD.append(contentsOf: 1...2)  // Different count\n        XCTAssertEqual(buffA, buffB)\n        XCTAssertNotEqual(buffA, buffC)\n        XCTAssertNotEqual(buffA, buffD)\n\n        // Will make internal head/tail indexes different\n        var prependBuff = CircularBuffer<Int>()\n        var appendBuff = CircularBuffer<Int>()\n        for i in (1...100).reversed() {\n            prependBuff.prepend(i)\n        }\n        for i in 1...100 {\n            appendBuff.append(i)\n        }\n        // But the contents are still the same\n        XCTAssertEqual(prependBuff, appendBuff)\n    }\n\n    func testHash() {\n        let emptyA = CircularBuffer<Int>()\n        let emptyB = CircularBuffer<Int>()\n        XCTAssertEqual(Set([emptyA, emptyB]).count, 1)\n\n        var buffA = CircularBuffer<Int>()\n        var buffB = CircularBuffer<Int>()\n        buffA.append(contentsOf: 1...10)\n        buffB.append(contentsOf: 1...10)\n        XCTAssertEqual(Set([buffA, buffB]).count, 1)\n        buffB.append(123)\n        XCTAssertEqual(Set([buffA, buffB]).count, 2)\n        buffA.append(1)\n        XCTAssertEqual(Set([buffA, buffB]).count, 2)\n\n        // Will make internal head/tail indexes different\n        var prependBuff = CircularBuffer<Int>()\n        var appendBuff = CircularBuffer<Int>()\n        for i in (1...100).reversed() {\n            prependBuff.prepend(i)\n        }\n        for i in 1...100 {\n            appendBuff.append(i)\n        }\n        XCTAssertEqual(Set([prependBuff, appendBuff]).count, 1)\n    }\n\n    func testArrayLiteralInit() {\n        let empty: CircularBuffer<Int> = []\n        XCTAssert(empty.isEmpty)\n\n        let increasingInts: CircularBuffer = [1, 2, 3, 4, 5]\n        XCTAssertEqual(increasingInts.count, 5)\n        XCTAssert(zip(increasingInts, 1...5).allSatisfy(==))\n\n        let someIntsArray = [-9, 384, 2, 10, 0, 0, 0]\n        let someInts: CircularBuffer = [-9, 384, 2, 10, 0, 0, 0]\n        XCTAssertEqual(someInts.count, 7)\n        XCTAssert(zip(someInts, someIntsArray).allSatisfy(==))\n    }\n\n    func testFirstWorks() {\n        var buffer = CircularBuffer<Int>(initialCapacity: 4)\n        XCTAssertNil(buffer.first)\n\n        buffer.append(1)\n        XCTAssertEqual(1, buffer.first)\n        XCTAssertEqual(1, buffer.removeFirst())\n\n        XCTAssertNil(buffer.first)\n\n        for n in 0..<10 {\n            buffer.append(contentsOf: 0...n)\n\n            for i in 0...n {\n                XCTAssertEqual(i, buffer.first)\n                XCTAssertEqual(i, buffer.removeFirst())\n            }\n            XCTAssertNil(buffer.first)\n        }\n    }\n\n    func testReserveCapacityActuallyDoesSomething() {\n        var buffer = CircularBuffer<Int>(initialCapacity: 4)\n        XCTAssertEqual(buffer.capacity, 4)\n\n        buffer.reserveCapacity(16)\n        XCTAssertEqual(buffer.capacity, 16)\n\n        buffer.reserveCapacity(8)\n        XCTAssertEqual(buffer.capacity, 16)\n\n        buffer.reserveCapacity(20)\n        XCTAssertEqual(buffer.capacity, 32)\n\n        buffer.reserveCapacity(0)\n        XCTAssertEqual(buffer.capacity, 32)\n    }\n\n    func testCopyContents() {\n        var buffer = CircularBuffer<String>(initialCapacity: 4)\n\n        // Test with no elements.\n        XCTAssertEqual(buffer._buffer.count, 4)\n        XCTAssertEqual(Array(buffer), [])\n\n        // Test with head < tail.\n        buffer.append(contentsOf: [\"a\", \"b\", \"c\"])\n        XCTAssertEqual(buffer._buffer.count, 4)\n        XCTAssertEqual(buffer.count, 3)\n        XCTAssertLessThan(buffer.headBackingIndex, buffer.tailBackingIndex)\n        XCTAssertEqual(Array(buffer), [\"a\", \"b\", \"c\"])\n\n        // Test with head > tail.\n        buffer.removeFirst()\n        buffer.append(\"d\")\n        XCTAssertEqual(buffer._buffer.count, 4)\n        XCTAssertEqual(buffer.count, 3)\n        XCTAssertGreaterThan(buffer.headBackingIndex, buffer.tailBackingIndex)\n        XCTAssertEqual(Array(buffer), [\"b\", \"c\", \"d\"])\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/CustomChannelTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\nstruct NotImplementedError: Error {}\n\nstruct InvalidTypeError: Error {}\n\n/// A basic ChannelCore that expects write0 to receive a NIOAny containing an Int.\n///\n/// Everything else either throws or returns a failed future, except for things that cannot,\n/// which precondition instead.\nprivate class IntChannelCore: ChannelCore {\n    func localAddress0() throws -> SocketAddress {\n        throw NotImplementedError()\n    }\n\n    func remoteAddress0() throws -> SocketAddress {\n        throw NotImplementedError()\n    }\n\n    func register0(promise: EventLoopPromise<Void>?) {\n        promise?.fail(NotImplementedError())\n    }\n\n    func registerAlreadyConfigured0(promise: EventLoopPromise<Void>?) {\n        promise?.fail(NotImplementedError())\n    }\n\n    func bind0(to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        promise?.fail(NotImplementedError())\n    }\n\n    func connect0(to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        promise?.fail(NotImplementedError())\n    }\n\n    func write0(_ data: NIOAny, promise: EventLoopPromise<Void>?) {\n        _ = self.unwrapData(data, as: Int.self)\n        promise?.succeed(())\n    }\n\n    func flush0() {\n        preconditionFailure(\"Must not flush\")\n    }\n\n    func read0() {\n        preconditionFailure(\"Must not ew\")\n    }\n\n    func close0(error: Error, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        promise?.fail(NotImplementedError())\n    }\n\n    func triggerUserOutboundEvent0(_ event: Any, promise: EventLoopPromise<Void>?) {\n        promise?.fail(NotImplementedError())\n    }\n\n    func channelRead0(_ data: NIOAny) {\n        preconditionFailure(\"Must not call channelRead0\")\n    }\n\n    func errorCaught0(error: Error) {\n        preconditionFailure(\"Must not call errorCaught0\")\n    }\n}\n\nclass CustomChannelTests: XCTestCase {\n    func testWritingIntToSpecialChannel() throws {\n        let loop = EmbeddedEventLoop()\n        let intCore = IntChannelCore()\n        let writePromise = loop.makePromise(of: Void.self)\n\n        intCore.write0(NIOAny(5), promise: writePromise)\n        XCTAssertNoThrow(try writePromise.futureResult.wait())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/DispatchQueue+WithFutureTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport Dispatch\nimport NIOCore\nimport NIOEmbedded\nimport NIOPosix\nimport XCTest\n\nenum DispatchQueueTestError: Error {\n    case example\n}\n\nclass DispatchQueueWithFutureTest: XCTestCase {\n    func testDispatchQueueAsyncWithFuture() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let eventLoop = group.next()\n        let sem = DispatchSemaphore(value: 0)\n        let nonBlockingRan = ManagedAtomic(false)\n        let futureResult: EventLoopFuture<String> = DispatchQueue.global().asyncWithFuture(eventLoop: eventLoop) {\n            () -> String in\n            sem.wait()  // Block in callback\n            return \"hello\"\n        }\n        futureResult.whenSuccess { value in\n            XCTAssertEqual(value, \"hello\")\n            XCTAssertTrue(nonBlockingRan.load(ordering: .sequentiallyConsistent))\n        }\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.store(true, ordering: .sequentiallyConsistent)\n        }\n        p2.succeed(true)\n\n        sem.signal()\n    }\n\n    func testDispatchQueueAsyncWithFutureThrows() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let eventLoop = group.next()\n        let sem = DispatchSemaphore(value: 0)\n        let nonBlockingRan = ManagedAtomic(false)\n        let futureResult: EventLoopFuture<String> = DispatchQueue.global().asyncWithFuture(eventLoop: eventLoop) {\n            () -> String in\n            sem.wait()  // Block in callback\n            throw DispatchQueueTestError.example\n        }\n        futureResult.whenFailure { err in\n            XCTAssertEqual(err as! DispatchQueueTestError, DispatchQueueTestError.example)\n            XCTAssertTrue(nonBlockingRan.load(ordering: .sequentiallyConsistent))\n        }\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.store(true, ordering: .sequentiallyConsistent)\n        }\n        p2.succeed(true)\n\n        sem.signal()\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/IOErrorTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n//\nimport XCTest\n\n@testable import NIOCore\n\nclass IOErrorTest: XCTestCase {\n    func testMemoryLayoutBelowThreshold() {\n        XCTAssert(MemoryLayout<IOError>.size <= 24)\n    }\n\n    @available(*, deprecated, message: \"deprecated because it tests deprecated functionality\")\n    func testDeprecatedAPIStillFunctional() {\n        XCTAssertNoThrow(IOError(errnoCode: 1, function: \"anyFunc\"))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/IntegerTypesTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\npublic final class IntegerTypesTest: XCTestCase {\n    func testNextPowerOfOfTwoZero() {\n        XCTAssertEqual(1, (0 as UInt).nextPowerOf2())\n        XCTAssertEqual(1, (0 as UInt16).nextPowerOf2())\n        XCTAssertEqual(1, (0 as UInt32).nextPowerOf2())\n        XCTAssertEqual(1, (0 as UInt64).nextPowerOf2())\n        XCTAssertEqual(1, (0 as Int).nextPowerOf2())\n        XCTAssertEqual(1, (0 as Int16).nextPowerOf2())\n        XCTAssertEqual(1, (0 as Int32).nextPowerOf2())\n        XCTAssertEqual(1, (0 as Int64).nextPowerOf2())\n    }\n\n    func testNextPowerOfTwoOfOne() {\n        XCTAssertEqual(1, (1 as UInt).nextPowerOf2())\n        XCTAssertEqual(1, (1 as UInt16).nextPowerOf2())\n        XCTAssertEqual(1, (1 as UInt32).nextPowerOf2())\n        XCTAssertEqual(1, (1 as UInt64).nextPowerOf2())\n        XCTAssertEqual(1, (1 as Int).nextPowerOf2())\n        XCTAssertEqual(1, (1 as Int16).nextPowerOf2())\n        XCTAssertEqual(1, (1 as Int32).nextPowerOf2())\n        XCTAssertEqual(1, (1 as Int64).nextPowerOf2())\n    }\n\n    func testNextPowerOfTwoOfTwo() {\n        XCTAssertEqual(2, (2 as UInt).nextPowerOf2())\n        XCTAssertEqual(2, (2 as UInt16).nextPowerOf2())\n        XCTAssertEqual(2, (2 as UInt32).nextPowerOf2())\n        XCTAssertEqual(2, (2 as UInt64).nextPowerOf2())\n        XCTAssertEqual(2, (2 as Int).nextPowerOf2())\n        XCTAssertEqual(2, (2 as Int16).nextPowerOf2())\n        XCTAssertEqual(2, (2 as Int32).nextPowerOf2())\n        XCTAssertEqual(2, (2 as Int64).nextPowerOf2())\n    }\n\n    func testNextPowerOfTwoOfThree() {\n        XCTAssertEqual(4, (3 as UInt).nextPowerOf2())\n        XCTAssertEqual(4, (3 as UInt16).nextPowerOf2())\n        XCTAssertEqual(4, (3 as UInt32).nextPowerOf2())\n        XCTAssertEqual(4, (3 as UInt64).nextPowerOf2())\n        XCTAssertEqual(4, (3 as Int).nextPowerOf2())\n        XCTAssertEqual(4, (3 as Int16).nextPowerOf2())\n        XCTAssertEqual(4, (3 as Int32).nextPowerOf2())\n        XCTAssertEqual(4, (3 as Int64).nextPowerOf2())\n    }\n\n    func testNextPowerOfTwoOfFour() {\n        XCTAssertEqual(4, (4 as UInt).nextPowerOf2())\n        XCTAssertEqual(4, (4 as UInt16).nextPowerOf2())\n        XCTAssertEqual(4, (4 as UInt32).nextPowerOf2())\n        XCTAssertEqual(4, (4 as UInt64).nextPowerOf2())\n        XCTAssertEqual(4, (4 as Int).nextPowerOf2())\n        XCTAssertEqual(4, (4 as Int16).nextPowerOf2())\n        XCTAssertEqual(4, (4 as Int32).nextPowerOf2())\n        XCTAssertEqual(4, (4 as Int64).nextPowerOf2())\n    }\n\n    func testNextPowerOfTwoOfFive() {\n        XCTAssertEqual(8, (5 as UInt).nextPowerOf2())\n        XCTAssertEqual(8, (5 as UInt16).nextPowerOf2())\n        XCTAssertEqual(8, (5 as UInt32).nextPowerOf2())\n        XCTAssertEqual(8, (5 as UInt64).nextPowerOf2())\n        XCTAssertEqual(8, (5 as Int).nextPowerOf2())\n        XCTAssertEqual(8, (5 as Int16).nextPowerOf2())\n        XCTAssertEqual(8, (5 as Int32).nextPowerOf2())\n        XCTAssertEqual(8, (5 as Int64).nextPowerOf2())\n    }\n\n    func testDescriptionUInt24() {\n        XCTAssertEqual(\"0\", _UInt24.min.description)\n        XCTAssertEqual(\"16777215\", _UInt24.max.description)\n        XCTAssertEqual(\"12345678\", _UInt24(12_345_678 as UInt32).description)\n        XCTAssertEqual(\"1\", _UInt24(1).description)\n        XCTAssertEqual(\"8388608\", _UInt24(1 << 23).description)\n        XCTAssertEqual(\"66\", _UInt24(66).description)\n    }\n\n    func testDescriptionUInt56() {\n        XCTAssertEqual(\"0\", _UInt56.min.description)\n        XCTAssertEqual(\"72057594037927935\", _UInt56.max.description)\n        XCTAssertEqual(\"12345678901234567\", _UInt56(12_345_678_901_234_567 as UInt64).description)\n        XCTAssertEqual(\"1\", _UInt56(1).description)\n        XCTAssertEqual(\"66\", _UInt56(66).description)\n        XCTAssertEqual(\"36028797018963968\", _UInt56(UInt64(1) << 55).description)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/LinuxTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\nclass LinuxTest: XCTestCase {\n    func testCoreCountCgroup1RestrictionWithVariousIntegerFormats() throws {\n        #if os(Linux) || os(Android)\n        // Test various integer formats in cgroup files\n        let testCases = [\n            (\"42\", \"100000\", 1),  // Simple integer\n            (\"0\", \"100000\", nil),  // Zero should be rejected\n        ]\n\n        for (quotaContent, periodContent, expectedResult) in testCases {\n            try withTemporaryFile(content: quotaContent) { (_, quotaPath) -> Void in\n                try withTemporaryFile(content: periodContent) { (_, periodPath) -> Void in\n                    let result = Linux.coreCountCgroup1Restriction(quota: quotaPath, period: periodPath)\n                    XCTAssertEqual(result, expectedResult, \"Failed for quota '\\(quotaContent)'\")\n                }\n            }\n        }\n\n        // Test invalid integer cases\n        let invalidCases = [\"abc\", \"12abc\", \"\"]\n        for invalidContent in invalidCases {\n            try withTemporaryFile(content: invalidContent) { (_, quotaPath) -> Void in\n                try withTemporaryFile(content: \"100000\") { (_, periodPath) -> Void in\n                    let result = Linux.coreCountCgroup1Restriction(quota: quotaPath, period: periodPath)\n                    XCTAssertNil(result, \"Should return nil for invalid quota '\\(invalidContent)'\")\n                }\n            }\n        }\n        #endif\n    }\n\n    func testCoreCountWithMultipleRanges() throws {\n        #if os(Linux) || os(Android)\n        // Test coreCount function with multiple CPU ranges\n        let content = \"0,2,4-6\"  // Should count as 5 cores: 0,2,4,5,6\n        try withTemporaryFile(content: content) { (_, path) -> Void in\n            let result = Linux.coreCount(cpuset: path)\n            XCTAssertEqual(result, 5)\n        }\n        #endif\n    }\n\n    func testCoreCountWithSingleRange() throws {\n        #if os(Linux) || os(Android)\n        let content = \"0-3\"  // Should count as 4 cores\n        try withTemporaryFile(content: content) { (_, path) -> Void in\n            let result = Linux.coreCount(cpuset: path)\n            XCTAssertEqual(result, 4)\n        }\n        #endif\n    }\n\n    func testCoreCountWithEmptyFile() throws {\n        #if os(Linux) || os(Android)\n        try withTemporaryFile(content: \"\") { (_, path) -> Void in\n            let result = Linux.coreCount(cpuset: path)\n            XCTAssertNil(result)  // Empty file should return nil\n        }\n        #endif\n    }\n\n    func testCoreCountReadsOnlyFirstLine() throws {\n        #if os(Linux) || os(Android)\n        // Test that coreCount only processes the first line of the file\n        let content = \"0-1\\n2-3\\n4-5\"  // First line should be \"0-1\" = 2 cores\n        try withTemporaryFile(content: content) { (_, path) -> Void in\n            let result = Linux.coreCount(cpuset: path)\n            XCTAssertEqual(result, 2)  // Should only process first line\n        }\n        #endif\n    }\n\n    func testCoreCountWithSimpleCpuset() throws {\n        #if os(Linux) || os(Android)\n        // Test coreCount function with simple cpuset formats\n        let testCases = [\n            (\"0\", 1),  // Single core\n            (\"0-3\", 4),  // Range 0,1,2,3\n            (\"5-7\", 3),  // Range 5,6,7\n            (\"10-10\", 1),  // Single core as range\n        ]\n\n        for (input, expected) in testCases {\n            try withTemporaryFile(content: input) { (_, path) -> Void in\n                let result = Linux.coreCount(cpuset: path)\n                XCTAssertEqual(result, expected, \"Failed for input '\\(input)'\")\n            }\n        }\n        #endif\n    }\n\n    func testCoreCountWithComplexCpuset() throws {\n        #if os(Linux) || os(Android)\n        // Test more complex cpuset formats\n        let cpusets = [\n            (\"0\", 1),\n            (\"0,2\", 2),\n            (\"0-1,4-5\", 4),  // Two ranges: 0,1 and 4,5\n            (\"0,2-4,7,9-10\", 7),  // Mixed: 0, 2,3,4, 7, 9,10\n        ]\n        for (cpuset, count) in cpusets {\n            try withTemporaryFile(content: cpuset) { (_, path) -> Void in\n                XCTAssertEqual(Linux.coreCount(cpuset: path), count)\n            }\n        }\n        #endif\n    }\n\n    func testCoreCountQuota() throws {\n        #if os(Linux) || os(Android)\n        let coreCountQuoats = [\n            (\"50000\", \"100000\", 1),\n            (\"100000\", \"100000\", 1),\n            (\"100000\\n\", \"100000\", 1),\n            (\"100000\", \"100000\\n\", 1),\n            (\"150000\", \"100000\", 2),\n            (\"200000\", \"100000\", 2),\n            (\"-1\", \"100000\", nil),\n            (\"100000\", \"-1\", nil),\n            (\"\", \"100000\", nil),\n            (\"100000\", \"\", nil),\n            (\"100000\", \"0\", nil),\n        ]\n        for (quota, period, count) in coreCountQuoats {\n            try withTemporaryFile(content: quota) { (_, quotaPath) -> Void in\n                try withTemporaryFile(content: period) { (_, periodPath) -> Void in\n                    XCTAssertEqual(Linux.coreCountCgroup1Restriction(quota: quotaPath, period: periodPath), count)\n                }\n            }\n        }\n        #endif\n    }\n\n    func testCoreCountCpuset() throws {\n        #if os(Linux) || os(Android)\n        let cpusets = [\n            (\"0\", 1),\n            (\"0,3\", 2),\n            (\"0-3\", 4),\n            (\"0-3,7\", 5),\n            (\"0-3,7\\n\", 5),\n            (\"0,2-4,6,7,9-11\", 9),\n            (\"\", nil),\n        ]\n        for (cpuset, count) in cpusets {\n            try withTemporaryFile(content: cpuset) { (_, path) -> Void in\n                XCTAssertEqual(Linux.coreCount(cpuset: path), count)\n            }\n        }\n        #endif\n    }\n\n    func testCoreCountCgroup2() throws {\n        #if os(Linux) || os(Android)\n        let contents = [\n            (\"max 100000\", nil),\n            (\"75000 100000\", 1),\n            (\"200000 100000\", 2),\n        ]\n        for (content, count) in contents {\n            try withTemporaryFile(content: content) { (_, path) in\n                XCTAssertEqual(Linux.coreCountCgroup2Restriction(cpuMaxPath: path), count)\n            }\n        }\n        #endif\n    }\n\n    func testParseV2CgroupLine() throws {\n        #if os(Linux) || os(Android)\n        let testCases: [(String, String?)] = [\n            // Valid cgroup v2 formats\n            (\"0::/\", \"/\"),  // Root cgroup\n            (\"0::/user.slice\", \"/user.slice\"),  // User slice\n            (\"0::/docker/container123\", \"/docker/container123\"),  // Docker container\n            (\"0::/\", \"/\"),  // This should work with omittingEmptySubsequences: false\n            (\"0::///\", \"///\"),  // Multiple slashes should be preserved\n            (\"0::/a/b/c\", \"/a/b/c\"),  // Normal nested path\n            (\"0::/.hidden\", \"/.hidden\"),  // Hidden directory\n            (\"0::/path:extra\", \"/path:extra\"),  // Test we're limiting to 2 splits maximum\n\n            // Invalid formats that should return nil\n            (\"1::/\", nil),  // Not hierarchy 0\n            (\"0:name:/\", nil),  // Has cgroup name (v1 format)\n            (\"0\", nil),  // Missing colons\n            (\"0:\", nil),  // Missing second colon\n            (\":\", nil),  // Only one colon\n            (\"::/\", nil),  // Missing hierarchy number\n            (\"\", nil),  // Empty string\n        ]\n\n        for (input, expected) in testCases {\n            let result = Linux.parseV2CgroupLine(Substring(input))\n            XCTAssertEqual(\n                result,\n                expected,\n                \"Failed parsing '\\(input)' - expected '\\(expected ?? \"nil\")' but got '\\(result ?? \"nil\")'\"\n            )\n        }\n        #endif\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/MarkedCircularBufferTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nclass MarkedCircularBufferTests: XCTestCase {\n    func testEmptyMark() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 8)\n        XCTAssertFalse(buf.hasMark)\n        XCTAssertNil(buf.markedElement)\n        XCTAssertNil(buf.markedElementIndex)\n\n        buf.mark()\n        XCTAssertFalse(buf.hasMark)\n        XCTAssertNil(buf.markedElement)\n        XCTAssertNil(buf.markedElementIndex)\n    }\n\n    func testSimpleMark() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 8)\n\n        for i in 1...4 { buf.append(i) }\n        buf.mark()\n        for i in 5...8 { buf.append(i) }\n\n        XCTAssertTrue(buf.hasMark)\n        XCTAssertEqual(buf.markedElement, 4)\n        XCTAssertEqual(buf.markedElementIndex, buf.index(buf.startIndex, offsetBy: 3))\n\n        for i in 0..<3 { XCTAssertFalse(buf.isMarked(index: buf.index(buf.startIndex, offsetBy: i))) }\n        XCTAssertTrue(buf.isMarked(index: buf.index(buf.startIndex, offsetBy: 3)))\n        for i in 4..<8 { XCTAssertFalse(buf.isMarked(index: buf.index(buf.startIndex, offsetBy: i))) }\n    }\n\n    func testPassingTheMark() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 8)\n\n        for i in 1...4 { buf.append(i) }\n        buf.mark()\n        for i in 5...8 { buf.append(i) }\n\n        for j in 1...3 {\n            XCTAssertEqual(buf.removeFirst(), j)\n            XCTAssertTrue(buf.hasMark)\n            XCTAssertEqual(buf.markedElement, 4)\n            XCTAssertEqual(buf.markedElementIndex, buf.index(buf.startIndex, offsetBy: 3 - j))\n        }\n\n        XCTAssertEqual(buf.removeFirst(), 4)\n        XCTAssertFalse(buf.hasMark)\n        XCTAssertNil(buf.markedElement)\n        XCTAssertNil(buf.markedElementIndex)\n    }\n\n    func testMovingTheMark() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 8)\n\n        for i in 1...8 {\n            buf.append(i)\n            buf.mark()\n\n            XCTAssertTrue(buf.hasMark)\n            XCTAssertEqual(buf.markedElement, i)\n            XCTAssertEqual(buf.markedElementIndex, buf.index(buf.startIndex, offsetBy: i - 1))\n            XCTAssertTrue(buf.isMarked(index: buf.index(buf.startIndex, offsetBy: i - 1)))\n        }\n    }\n    func testIndices() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n\n        var allIndices: [MarkedCircularBuffer<Int>.Index] = []\n        var index = buf.startIndex\n        while index != buf.endIndex {\n            allIndices.append(index)\n            index = buf.index(after: index)\n        }\n        XCTAssertEqual(Array(buf.indices), allIndices)\n    }\n\n    func testFirst() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n        XCTAssertEqual(buf.first, 1)\n    }\n\n    func testCount() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n        XCTAssertEqual(buf.count, 4)\n    }\n\n    func testSubscript() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n        XCTAssertEqual(buf[buf.startIndex], 1)\n        XCTAssertEqual(buf[buf.index(buf.startIndex, offsetBy: 3)], 4)\n    }\n\n    func testRangeSubscript() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n        let range = buf.startIndex..<buf.index(buf.startIndex, offsetBy: 2)\n        XCTAssertEqual(buf[range].count, 2)\n        buf[range] = [0, 1]\n        XCTAssertEqual(buf.firstIndex(of: 2), nil)\n        XCTAssertEqual(buf.count, 4)\n    }\n\n    func testIsEmpty() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n        XCTAssertFalse(buf.isEmpty)\n        XCTAssertEqual(buf.removeFirst(), 1)\n        XCTAssertEqual(buf.removeFirst(), 2)\n        XCTAssertEqual(buf.removeFirst(), 3)\n        XCTAssertEqual(buf.removeFirst(), 4)\n        XCTAssertTrue(buf.isEmpty)\n    }\n\n    func testPopFirst() throws {\n        var buf = MarkedCircularBuffer<Int>(initialCapacity: 4)\n        for i in 1...4 {\n            buf.append(i)\n        }\n        XCTAssertFalse(buf.isEmpty)\n        XCTAssertEqual(buf.popFirst(), 1)\n        XCTAssertEqual(buf.popFirst(), 2)\n        XCTAssertEqual(buf.popFirst(), 3)\n        XCTAssertEqual(buf.popFirst(), 4)\n        XCTAssertNil(buf.popFirst())\n        XCTAssertTrue(buf.isEmpty)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/NIOAnyDebugTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nclass NIOAnyDebugTest: XCTestCase {\n\n    func testCustomStringConvertible() throws {\n        XCTAssertEqual(wrappedInNIOAnyBlock(\"string\").description, \"String: string\")\n        XCTAssertEqual(wrappedInNIOAnyBlock(123).description, \"Int: 123\")\n\n        let bb = ByteBuffer(string: \"byte buffer string\")\n        XCTAssertEqual(\n            wrappedInNIOAnyBlock(bb).description,\n            \"ByteBuffer: [627974652062756666657220737472696e67](18 bytes)\"\n        )\n\n        let fileHandle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: 1)\n        defer {\n            XCTAssertNoThrow(_ = try fileHandle.takeDescriptorOwnership())\n        }\n        let fileRegion = FileRegion(fileHandle: fileHandle, readerIndex: 1, endIndex: 5)\n        XCTAssertEqual(\n            wrappedInNIOAnyBlock(fileRegion).description,\n            \"\"\"\n            FileRegion: \\\n            FileRegion { \\\n            handle: \\\n            FileHandle \\\n            { descriptor: 1 \\\n            }, \\\n            readerIndex: \\(fileRegion.readerIndex), \\\n            endIndex: \\(fileRegion.endIndex) }\n            \"\"\"\n        )\n\n        let socketAddress = try SocketAddress(unixDomainSocketPath: \"socketAdress\")\n        let envelopeByteBuffer = ByteBuffer(string: \"envelope buffer\")\n        let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: socketAddress, data: envelopeByteBuffer)\n        XCTAssertEqual(\n            wrappedInNIOAnyBlock(envelope).description,\n            \"\"\"\n            AddressedEnvelope<ByteBuffer>: \\\n            AddressedEnvelope { \\\n            remoteAddress: \\(socketAddress), \\\n            data: \\(envelopeByteBuffer) }\n            \"\"\"\n        )\n    }\n\n    func testCustomDebugStringConvertible() {\n        XCTAssertEqual(wrappedInNIOAnyBlock(\"string\").debugDescription, \"(String: string)\")\n        let any = wrappedInNIOAnyBlock(\"test\")\n        XCTAssertEqual(any.debugDescription, \"(\\(any.description))\")\n    }\n\n    private func wrappedInNIOAnyBlock(_ item: Any) -> NIOAny {\n        NIOAny(item)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/NIOCloseOnErrorHandlerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\nfinal class DummyFailingHandler1: ChannelInboundHandler, Sendable {\n    typealias InboundIn = NIOAny\n\n    struct DummyError1: Error {}\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.fireErrorCaught(DummyError1())\n    }\n}\n\nclass NIOCloseOnErrorHandlerTest: XCTestCase {\n    private var eventLoop: EmbeddedEventLoop!\n    private var channel: EmbeddedChannel!\n\n    override func setUp() {\n        super.setUp()\n\n        self.eventLoop = EmbeddedEventLoop()\n        self.channel = EmbeddedChannel(loop: self.eventLoop)\n    }\n\n    override func tearDown() {\n        self.eventLoop = nil\n        if self.channel.isActive {\n            XCTAssertNoThrow(XCTAssertTrue(try self.channel.finish().isClean))\n        }\n\n        super.tearDown()\n    }\n\n    func testChannelCloseOnError() throws {\n        XCTAssertNoThrow(\n            self.channel.pipeline.addHandlers([\n                DummyFailingHandler1(),\n                NIOCloseOnErrorHandler(),\n            ])\n        )\n\n        XCTAssertNoThrow(try self.channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5)).wait())\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertThrowsError(try self.channel.writeInbound(\"Hello World\")) {\n            XCTAssertTrue($0 is DummyFailingHandler1.DummyError1)\n        }\n        XCTAssertFalse(self.channel.isActive)\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/NIODecodedAsyncSequenceTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport Testing\n\nstruct NIODecodedAsyncSequenceTests {\n    private final class ByteToInt32Decoder: NIOSingleStepByteToMessageDecoder {\n        typealias InboundOut = Int32\n\n        func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n            buffer.readInteger()\n        }\n\n        func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n            #expect(seenEOF)\n            return try self.decode(buffer: &buffer)\n        }\n    }\n\n    private final class ThrowingDecoder: NIOSingleStepByteToMessageDecoder {\n        typealias InboundOut = Int32\n\n        struct DecoderError: Error {}\n\n        func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n            throw DecoderError()\n        }\n\n        func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n            #expect(seenEOF)\n            return try self.decode(buffer: &buffer)\n        }\n    }\n\n    static let testingArguments = [\n        (elementCount: 100, chunkSize: 4),\n        (elementCount: 89, chunkSize: 4),\n        (elementCount: 77, chunkSize: 1),\n        (elementCount: 65, chunkSize: 3),\n        (elementCount: 61, chunkSize: 100),\n        (elementCount: 55, chunkSize: 15),\n    ]\n\n    @Test(arguments: Self.testingArguments)\n    func decodingWorks(elementCount: Int, chunkSize: Int) async throws {\n        var randomElements: [Int32] = (0..<elementCount).map {\n            _ in Int32.random(in: .min ... .max)\n        }\n\n        var buffer = ByteBuffer()\n        buffer.reserveCapacity(minimumWritableBytes: elementCount)\n        for element in randomElements {\n            buffer.writeInteger(element)\n        }\n\n        let stream = try self.makeFinishedAsyncStream(using: buffer, chunkSize: chunkSize)\n        let decodedSequence = stream.decode(using: ByteToInt32Decoder())\n\n        for try await element in decodedSequence {\n            #expect(element == randomElements.removeFirst())\n        }\n    }\n\n    @Test(arguments: Self.testingArguments)\n    func decodingThrowsWhenDecoderThrows(elementCount: Int, chunkSize: Int) async throws {\n        let randomElements: [Int32] = (0..<elementCount).map {\n            _ in Int32.random(in: .min ... .max)\n        }\n\n        var buffer = ByteBuffer()\n        buffer.reserveCapacity(minimumWritableBytes: elementCount)\n        for element in randomElements {\n            buffer.writeInteger(element)\n        }\n\n        let stream = try self.makeFinishedAsyncStream(using: buffer, chunkSize: chunkSize)\n        let decodedSequence = stream.decode(using: ThrowingDecoder())\n\n        await #expect(throws: ThrowingDecoder.DecoderError.self) {\n            for try await _ in decodedSequence {\n                Issue.record(\"Should not have reached here\")\n            }\n        }\n    }\n\n    @Test\n    func decodingThrowsWhenStreamThrows() async throws {\n        struct StreamError: Error {}\n\n        let baseSequence = AsyncThrowingStream<ByteBuffer, any Error>.makeStream()\n        baseSequence.continuation.finish(throwing: StreamError())\n\n        let decodedSequence = baseSequence.stream.decode(using: ByteToInt32Decoder())\n\n        await #expect(throws: StreamError.self) {\n            for try await _ in decodedSequence {\n                Issue.record(\"Should not have reached here\")\n            }\n        }\n    }\n\n    private func makeFinishedAsyncStream(\n        using buffer: ByteBuffer,\n        chunkSize: Int\n    ) throws -> AsyncStream<ByteBuffer> {\n        var buffer = buffer\n        let sequence = AsyncStream<ByteBuffer>.makeStream()\n        while buffer.readableBytes > 0 {\n            if Int.random(in: 0..<4) == 0 {\n                // Insert an empty buffer to test the behavior of the decoder.\n                sequence.continuation.yield(ByteBuffer())\n                continue\n            }\n            let length = min(buffer.readableBytes, chunkSize)\n            let _slice = buffer.readSlice(length: length)\n            let slice = try #require(_slice)\n            sequence.continuation.yield(slice)\n        }\n        sequence.continuation.finish()\n        return sequence.stream\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/NIOIsolatedEventLoopTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\nfinal class NIOIsolatedEventLoopTests: XCTestCase {\n    func withEmbeddedEventLoop(_ body: (EmbeddedEventLoop) throws -> Void) rethrows {\n        let loop = EmbeddedEventLoop()\n        defer { try! loop.syncShutdownGracefully() }\n        try body(loop)\n    }\n\n    func testMakeSucceededFuture() throws {\n        try self.withEmbeddedEventLoop { loop in\n            let future = loop.assumeIsolated().makeSucceededFuture(NotSendable())\n            XCTAssertNoThrow(try future.map { _ in }.wait())\n        }\n    }\n\n    func testMakeFailedFuture() throws {\n        try self.withEmbeddedEventLoop { loop in\n            let future: EventLoopFuture<NotSendable> = loop.assumeIsolated().makeFailedFuture(\n                ChannelError.alreadyClosed\n            )\n            XCTAssertThrowsError(try future.map { _ in }.wait())\n        }\n    }\n\n    func testMakeCompletedFuture() throws {\n        try self.withEmbeddedEventLoop { loop in\n            let result = Result<NotSendable, any Error>.success(NotSendable())\n            let future: EventLoopFuture<NotSendable> = loop.assumeIsolated().makeCompletedFuture(result)\n            XCTAssertNoThrow(try future.map { _ in }.wait())\n        }\n    }\n\n    func testMakeCompletedFutureWithResultOfClosure() throws {\n        try self.withEmbeddedEventLoop { loop in\n            let future = loop.assumeIsolated().makeCompletedFuture { NotSendable() }\n            XCTAssertNoThrow(try future.map { _ in }.wait())\n        }\n    }\n}\n\nprivate struct NotSendable {}\n\n@available(*, unavailable)\nextension NotSendable: Sendable {}\n"
  },
  {
    "path": "Tests/NIOCoreTests/NIOPooledRecvBufferAllocatorTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\ninternal final class NIOPooledRecvBufferAllocatorTests: XCTestCase {\n    func testPoolFillsToCapacity() {\n        let allocator = ByteBufferAllocator()\n        var pool = NIOPooledRecvBufferAllocator(\n            capacity: 3,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024)\n        )\n        XCTAssertEqual(pool.count, 0)\n        XCTAssertEqual(pool.capacity, 3)\n\n        // The pool recycles buffers which are unique. Store each buffer to ensure that's not the\n        // case.\n        let buffers: [ByteBuffer] = (1...pool.capacity).map { i in\n            let (buffer, _) = pool.buffer(allocator: allocator) {\n                XCTAssertEqual($0.readableBytes, 0)\n                XCTAssertEqual($0.writableBytes, 1024)\n            }\n            return buffer\n        }\n\n        let bufferIDs = Set(buffers.map { $0.storagePointerIntegerValue() })\n        XCTAssertEqual(buffers.count, bufferIDs.count)\n\n        // Keep the buffers alive.\n        withExtendedLifetime(buffers) {\n            for _ in 1...pool.capacity {\n                let (buffer, _) = pool.buffer(allocator: allocator) {\n                    XCTAssertEqual($0.readableBytes, 0)\n                    XCTAssertEqual($0.writableBytes, 1024)\n                }\n                XCTAssertEqual(pool.count, pool.capacity)\n                XCTAssertFalse(bufferIDs.contains(buffer.storagePointerIntegerValue()))\n            }\n        }\n    }\n\n    func testBuffersAreRecycled() {\n        let allocator = ByteBufferAllocator()\n        var pool = NIOPooledRecvBufferAllocator(\n            capacity: 5,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024)\n        )\n\n        let (_, storageID) = pool.buffer(allocator: allocator) { buffer in\n            buffer.storagePointerIntegerValue()\n        }\n\n        XCTAssertEqual(pool.count, 1)\n\n        for _ in 0..<100 {\n            _ = pool.buffer(allocator: allocator) { buffer in\n                XCTAssertEqual(buffer.storagePointerIntegerValue(), storageID)\n            }\n            XCTAssertEqual(pool.count, 1)\n        }\n    }\n\n    func testFirstAvailableBufferUsed() {\n        let allocator = ByteBufferAllocator()\n        var pool = NIOPooledRecvBufferAllocator(\n            capacity: 3,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024)\n        )\n\n        var buffers: [ByteBuffer] = (0..<pool.capacity).map { _ in\n            let (buffer, _) = pool.buffer(allocator: allocator) { _ in }\n            return buffer\n        }\n\n        let bufferIDs = Set(buffers.map { $0.storagePointerIntegerValue() })\n        XCTAssertEqual(bufferIDs.count, pool.capacity)\n\n        // Drop the ref to the middle buffer.\n        buffers.remove(at: 1)\n\n        _ = pool.buffer(allocator: allocator) { buffer in\n            XCTAssert(bufferIDs.contains(buffer.storagePointerIntegerValue()))\n        }\n    }\n\n    func testBuffersAreClearedBetweenCalls() {\n        let allocator = ByteBufferAllocator()\n        var pool = NIOPooledRecvBufferAllocator(\n            capacity: 3,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024)\n        )\n\n        // The pool recycles buffers which are unique. Store each buffer to ensure that's not the\n        // case.\n        var buffers: [ByteBuffer] = (1...pool.capacity).map { i in\n            let (buffer, _) = pool.buffer(allocator: allocator) {\n                $0.writeRepeatingByte(42, count: 1024)\n            }\n            return buffer\n        }\n\n        // Grab the storage pointers; check against them below.\n        var storagePointers = Set(buffers.map { $0.storagePointerIntegerValue() })\n        XCTAssertEqual(storagePointers.count, pool.capacity)\n\n        // Drop the buffer storage refs so they can be reused.\n        buffers.removeAll()\n\n        // Loop of the pool again.\n        var moreBuffers: [ByteBuffer] = storagePointers.map { pointerValue in\n            let (buffer, _) = pool.buffer(allocator: allocator) {\n                let storagePointer = $0.storagePointerIntegerValue()\n                XCTAssertNotNil(storagePointers.remove(storagePointer))\n                XCTAssertEqual($0.readerIndex, 0)\n                XCTAssertEqual($0.writerIndex, 0)\n            }\n            return buffer\n        }\n        moreBuffers.removeAll()\n    }\n\n    func testPoolCapacityIncrease() {\n        let allocator = ByteBufferAllocator()\n        var pool = NIOPooledRecvBufferAllocator(\n            capacity: 3,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024)\n        )\n\n        // Fill the pool.\n        let buffers: [ByteBuffer] = (0..<pool.capacity).map { _ in\n            let (buffer, _) = pool.buffer(allocator: allocator) { _ in }\n            return buffer\n        }\n        XCTAssertEqual(pool.capacity, 3)\n        XCTAssertEqual(pool.count, 3)\n\n        // Increase the capacity.\n        pool.updateCapacity(to: 8)\n        XCTAssertEqual(pool.capacity, 8)\n        XCTAssertEqual(pool.count, 3)\n\n        // Fill the pool.\n        let moreBuffers: [ByteBuffer] = (pool.count..<pool.capacity).map { _ in\n            let (buffer, _) = pool.buffer(allocator: allocator) { _ in }\n            return buffer\n        }\n\n        XCTAssertEqual(pool.count, 8)\n        XCTAssertEqual(pool.capacity, 8)\n\n        var ids = Set(buffers.map { $0.storagePointerIntegerValue() })\n        for buffer in moreBuffers {\n            ids.insert(buffer.storagePointerIntegerValue())\n        }\n        XCTAssertEqual(ids.count, pool.count)\n    }\n\n    func testPoolCapacityDecrease() {\n        let allocator = ByteBufferAllocator()\n        var pool = NIOPooledRecvBufferAllocator(\n            capacity: 5,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024)\n        )\n\n        // Fill the pool.\n        var buffers: [ByteBuffer] = []\n        for _ in (0..<pool.capacity) {\n            let (buffer, _) = pool.buffer(allocator: allocator) { _ in }\n            buffers.append(buffer)\n        }\n        XCTAssertEqual(pool.count, 5)\n        XCTAssertEqual(pool.capacity, 5)\n\n        // Reduce the capacity.\n        pool.updateCapacity(to: 3)\n        XCTAssertEqual(pool.count, 3)\n        XCTAssertEqual(pool.capacity, 3)\n    }\n}\n\nextension Array where Element == ByteBuffer {\n    fileprivate func allHaveUniqueStorage() -> Bool {\n        self.count == Set(self.map { $0.storagePointerIntegerValue() }).count\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/NIOSplitLinesMessageDecoderTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Testing\n\n@testable import NIOCore\n\nstruct NIOSplitLinesMessageDecoderTests {\n    @Test(\n        arguments: SplittingTextTestArgument.allHardcodedArguments\n            + SplittingTextTestArgument.allProducedUsingSTDLibSplitFunction\n    )\n    private func splittingTextWorksCorrectly(argument: SplittingTextTestArgument) async throws {\n        let buffer = ByteBuffer(string: argument.text)\n        let stream = try self.makeFinishedAsyncStream(using: buffer, chunkSize: argument.chunkSize)\n\n        let decodedSequence = stream.decode(\n            using: SplitMessageDecoder(\n                omittingEmptySubsequences: argument.omittingEmptySubsequences,\n                whereSeparator: { $0 == argument.separator }\n            )\n        )\n\n        var producedElements = [ByteBuffer]()\n        producedElements.reserveCapacity(argument.expectedElements.count)\n        for try await element in decodedSequence {\n            producedElements.append(element)\n        }\n\n        #expect(\n            producedElements == argument.expectedElements.map(ByteBuffer.init),\n            \"\"\"\n            Produced elements: \\(producedElements.map(String.init(buffer:)).debugDescription)\n            Expected elements: \\(argument.expectedElements.debugDescription)\n            \"\"\"\n        )\n    }\n\n    @Test(\n        arguments: SplittingLinesTestArgument.allHardcodedArguments\n            + SplittingLinesTestArgument.allProducedUsingSTDLibSplitFunction\n    )\n    private func splittingLinesWorksCorrectly(argument: SplittingLinesTestArgument) async throws {\n        let buffer = ByteBuffer(string: argument.text)\n        let stream = try self.makeFinishedAsyncStream(using: buffer, chunkSize: argument.chunkSize)\n\n        let decodedSequence = stream.splitLines(\n            omittingEmptySubsequences: argument.omittingEmptySubsequences\n        )\n\n        var producedElements = [ByteBuffer]()\n        producedElements.reserveCapacity(argument.expectedElements.count)\n        for try await element in decodedSequence {\n            producedElements.append(element)\n        }\n\n        #expect(\n            producedElements == argument.expectedElements.map(ByteBuffer.init),\n            \"\"\"\n            Produced elements: \\(producedElements.map(String.init(buffer:)).debugDescription)\n            Expected elements: \\(argument.expectedElements.debugDescription)\n            \"\"\"\n        )\n    }\n\n    @Test(\n        arguments: SplittingLinesTestArgument.allHardcodedArguments\n            + SplittingLinesTestArgument.allProducedUsingSTDLibSplitFunction\n    )\n    private func splittingUTF8LinesWorksCorrectly(argument: SplittingLinesTestArgument) async throws {\n        let buffer = ByteBuffer(string: argument.text)\n        let stream = try self.makeFinishedAsyncStream(using: buffer, chunkSize: argument.chunkSize)\n\n        let decodedSequence = stream.splitUTF8Lines(\n            omittingEmptySubsequences: argument.omittingEmptySubsequences\n        )\n\n        var producedElements = [String]()\n        producedElements.reserveCapacity(argument.expectedElements.count)\n        for try await element in decodedSequence {\n            producedElements.append(element)\n        }\n\n        #expect(producedElements == argument.expectedElements)\n    }\n\n    private func makeFinishedAsyncStream(\n        using buffer: ByteBuffer,\n        chunkSize: Int\n    ) throws -> AsyncStream<ByteBuffer> {\n        var buffer = buffer\n        let sequence = AsyncStream<ByteBuffer>.makeStream()\n        while buffer.readableBytes > 0 {\n            if Int.random(in: 0..<4) == 0 {\n                // Insert an empty buffer to test the behavior of the decoder.\n                sequence.continuation.yield(ByteBuffer())\n                continue\n            }\n            let length = min(buffer.readableBytes, chunkSize)\n            let _slice = buffer.readSlice(length: length)\n            let slice = try #require(_slice)\n            sequence.continuation.yield(slice)\n        }\n        sequence.continuation.finish()\n        return sequence.stream\n    }\n}\n\nprivate struct SplittingTextTestArgument {\n    let text: String\n    let separator: UInt8\n    let omittingEmptySubsequences: Bool\n    let chunkSize: Int\n    let expectedElements: [String]\n\n    static let text = \"\"\"\n           Here's to the   crazy    ones, th    e misfits, t he rebels, the troublemakers, \\\n        the   round . pegs in the square holes, the ones who    see   thi    ngs\n        differently .\n        \"\"\"\n    static let separators: [String] = [\"a\", \".\", \" \", \"\\n\", \",\", \"r\"]\n    static let chunkSizes: [Int] = [1, 2, 5, 8, 10, 15, 16, 20, 50, 100, 500]\n\n    static var allProducedUsingSTDLibSplitFunction: [Self] {\n        Self.separators.flatMap { separator -> [Self] in\n            [true, false].flatMap { omittingEmptySubsequences -> [Self] in\n                Self.chunkSizes.map { chunkSize -> Self in\n                    Self(\n                        text: Self.text,\n                        separator: separator.utf8.first!,\n                        omittingEmptySubsequences: omittingEmptySubsequences,\n                        chunkSize: chunkSize,\n                        expectedElements: Self.text.split(\n                            omittingEmptySubsequences: omittingEmptySubsequences,\n                            whereSeparator: { $0 == separator.first }\n                        ).map(String.init)\n                    )\n                }\n            }\n        }\n    }\n\n    /// These are hard-coded so we don't have a hard dependency on the standard library's `String.split` function.\n    /// Also so one can eyeball the whole argument if needed.\n    static var allHardcodedArguments: [Self] {\n        [\n            SplittingTextTestArgument(\n                text: Self.text,\n                separator: UInt8(ascii: \" \"),\n                omittingEmptySubsequences: true,\n                chunkSize: 50,\n                expectedElements: [\n                    \"Here\\'s\",\n                    \"to\",\n                    \"the\",\n                    \"crazy\",\n                    \"ones,\",\n                    \"th\",\n                    \"e\",\n                    \"misfits,\",\n                    \"t\",\n                    \"he\",\n                    \"rebels,\",\n                    \"the\",\n                    \"troublemakers,\",\n                    \"the\",\n                    \"round\",\n                    \".\",\n                    \"pegs\",\n                    \"in\",\n                    \"the\",\n                    \"square\",\n                    \"holes,\",\n                    \"the\",\n                    \"ones\",\n                    \"who\",\n                    \"see\",\n                    \"thi\",\n                    \"ngs\\ndifferently\",\n                    \".\",\n                ]\n            ),\n            SplittingTextTestArgument(\n                text: Self.text,\n                separator: UInt8(ascii: \" \"),\n                omittingEmptySubsequences: false,\n                chunkSize: 50,\n                expectedElements: [\n                    \"\", \"\", \"\",\n                    \"Here\\'s\",\n                    \"to\",\n                    \"the\",\n                    \"\", \"\",\n                    \"crazy\",\n                    \"\", \"\", \"\",\n                    \"ones,\",\n                    \"th\",\n                    \"\", \"\", \"\",\n                    \"e\",\n                    \"misfits,\",\n                    \"t\",\n                    \"he\",\n                    \"rebels,\",\n                    \"the\",\n                    \"troublemakers,\",\n                    \"the\",\n                    \"\", \"\",\n                    \"round\",\n                    \".\",\n                    \"pegs\",\n                    \"in\",\n                    \"the\",\n                    \"square\",\n                    \"holes,\",\n                    \"the\",\n                    \"ones\",\n                    \"who\",\n                    \"\", \"\", \"\",\n                    \"see\",\n                    \"\", \"\",\n                    \"thi\",\n                    \"\", \"\", \"\",\n                    \"ngs\\ndifferently\",\n                    \".\",\n                ]\n            ),\n        ]\n    }\n}\n\nprivate struct SplittingLinesTestArgument {\n    let text: String\n    let omittingEmptySubsequences: Bool\n    let chunkSize: Int\n    let expectedElements: [String]\n\n    /// A text with a lot of line breaks.\n    /// U+0009, U+000E are not considered line breaks, they are included since they are right\n    /// outside the line-break-byte boundaries (U+000A to U+000D).\n    static let text = \"\"\"\n           Here's to the  \\n\\r\\n\\u{000B}\\n\\r\\u{000C}\\n\\r\\n\\r\\n\\r\\n\\n\\r\\n\\r crazy    ones, th    e misfits, t he rebels,\n        the troublemakers, \\u{0009} the  \\u{000C} round \\u{000E}. pegs in \\u{000B}\\u{000C}\\r\\n\\r\\n\\r\\n\\r\\n\\rthe square holes, the ones\n        who  \\r\\n  see   thi \\n   ngs differently .\\u{000B}\n        \"\"\"\n    static let chunkSizes: [Int] = [1, 2, 5, 8, 10, 15, 16, 20, 50, 100, 500]\n\n    static var allProducedUsingSTDLibSplitFunction: [Self] {\n        [true, false].flatMap { omittingEmptySubsequences -> [Self] in\n            Self.chunkSizes.map { chunkSize -> Self in\n                Self(\n                    text: Self.text,\n                    omittingEmptySubsequences: omittingEmptySubsequences,\n                    chunkSize: chunkSize,\n                    expectedElements: Self.text.split(\n                        omittingEmptySubsequences: omittingEmptySubsequences,\n                        whereSeparator: \\.isNewline\n                    ).map(String.init)\n                )\n            }\n        }\n    }\n\n    /// These are hard-coded so we don't have a hard dependency on the standard library's `String.split` function.\n    /// Also so one can eyeball the whole argument if needed.\n    static var allHardcodedArguments: [Self] {\n        [\n            SplittingLinesTestArgument(\n                text: Self.text,\n                omittingEmptySubsequences: true,\n                chunkSize: 100,\n                expectedElements: [\n                    \"   Here\\'s to the  \",\n                    \" crazy    ones, th    e misfits, t he rebels,\",\n                    \"the troublemakers, \\t the  \",\n                    \" round \\u{0E}. pegs in \",\n                    \"the square holes, the ones\",\n                    \"who  \",\n                    \"  see   thi \",\n                    \"   ngs differently .\",\n                ]\n            ),\n            SplittingLinesTestArgument(\n                text: Self.text,\n                omittingEmptySubsequences: false,\n                chunkSize: 100,\n                expectedElements: [\n                    \"   Here\\'s to the  \",\n                    \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\",\n                    \" crazy    ones, th    e misfits, t he rebels,\",\n                    \"the troublemakers, \\t the  \",\n                    \" round \\u{0E}. pegs in \",\n                    \"\", \"\", \"\", \"\", \"\", \"\",\n                    \"the square holes, the ones\",\n                    \"who  \",\n                    \"  see   thi \",\n                    \"   ngs differently .\",\n                    \"\",\n                ]\n            ),\n        ]\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/RecvByteBufAllocatorTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nfinal class AdaptiveRecvByteBufferAllocatorTest: XCTestCase {\n    private let allocator = ByteBufferAllocator()\n    private var adaptive: AdaptiveRecvByteBufferAllocator!\n    private var fixed: FixedSizeRecvByteBufferAllocator!\n\n    override func setUp() {\n        self.adaptive = AdaptiveRecvByteBufferAllocator(minimum: 64, initial: 1024, maximum: 16 * 1024)\n        self.fixed = FixedSizeRecvByteBufferAllocator(capacity: 1024)\n    }\n\n    override func tearDown() {\n        self.adaptive = nil\n        self.fixed = nil\n    }\n\n    func testAdaptive() throws {\n        let buffer = adaptive.buffer(allocator: allocator)\n        XCTAssertEqual(1024, buffer.capacity)\n\n        // We double every time.\n        testActualReadBytes(mayGrow: true, actualReadBytes: 1024, expectedCapacity: 2048)\n        testActualReadBytes(mayGrow: true, actualReadBytes: 16384, expectedCapacity: 4096)\n        testActualReadBytes(mayGrow: true, actualReadBytes: 16384, expectedCapacity: 8192)\n        testActualReadBytes(mayGrow: true, actualReadBytes: 16384, expectedCapacity: 16384)\n\n        // Will never go over maximum\n        testActualReadBytes(mayGrow: false, actualReadBytes: 32768, expectedCapacity: 16384)\n\n        // Shrinks if two successive reads below half happen\n        testActualReadBytes(mayGrow: false, actualReadBytes: 4096, expectedCapacity: 16384)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 8192, expectedCapacity: 8192)\n\n        testActualReadBytes(mayGrow: false, actualReadBytes: 4096, expectedCapacity: 8192)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 4096, expectedCapacity: 4096)\n\n        // But not if an intermediate read is above half.\n        testActualReadBytes(mayGrow: false, actualReadBytes: 2048, expectedCapacity: 4096)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 2049, expectedCapacity: 4096)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 2048, expectedCapacity: 4096)\n\n        // Or if we grow in-between.\n        testActualReadBytes(mayGrow: true, actualReadBytes: 4096, expectedCapacity: 8192)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 4096, expectedCapacity: 8192)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 4096, expectedCapacity: 4096)\n\n        // Reads above half never shrink the capacity\n        for _ in 0..<10 {\n            testActualReadBytes(mayGrow: false, actualReadBytes: 2049, expectedCapacity: 4096)\n        }\n\n        // Consistently reading below half does shrink all the way down.\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 4096)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 2048)\n\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 2048)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 1024)\n\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 1024)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 512)\n\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 512)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 256)\n\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 256)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 128)\n\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 128)\n        testActualReadBytes(mayGrow: false, actualReadBytes: 64, expectedCapacity: 64)\n\n        // Until the bottom, where it stays forever.\n        for _ in 0..<10 {\n            testActualReadBytes(mayGrow: false, actualReadBytes: 1, expectedCapacity: 64)\n        }\n    }\n\n    private func testActualReadBytes(\n        mayGrow: Bool,\n        actualReadBytes: Int,\n        expectedCapacity: Int,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) {\n        XCTAssertEqual(\n            mayGrow,\n            adaptive.record(actualReadBytes: actualReadBytes),\n            \"unexpected value for mayGrow\",\n            file: file,\n            line: line\n        )\n        let buffer = adaptive.buffer(allocator: allocator)\n        XCTAssertEqual(expectedCapacity, buffer.capacity, \"unexpected capacity\", file: file, line: line)\n    }\n\n    func testFixed() throws {\n        var buffer = fixed.buffer(allocator: allocator)\n        XCTAssertEqual(fixed.capacity, buffer.capacity)\n        XCTAssert(!fixed.record(actualReadBytes: 32768))\n        buffer = fixed.buffer(allocator: allocator)\n        XCTAssertEqual(fixed.capacity, buffer.capacity)\n        XCTAssert(!fixed.record(actualReadBytes: 64))\n        buffer = fixed.buffer(allocator: allocator)\n        XCTAssertEqual(fixed.capacity, buffer.capacity)\n    }\n\n    func testMaxAllocSizeIsIntMax() {\n        // To find the max alloc size, we're going to search for a fixed point in resizing. To do that we're just going to\n        // keep saying we read max until we can't resize any longer.\n        self.adaptive = AdaptiveRecvByteBufferAllocator(minimum: 0, initial: .max / 2, maximum: .max)\n        var mayGrow = true\n        while mayGrow {\n            mayGrow = self.adaptive.record(actualReadBytes: .max)\n        }\n\n        let buffer = self.adaptive.buffer(allocator: self.allocator)\n        XCTAssertEqual(buffer.capacity, 1 << 30)\n        XCTAssertEqual(self.adaptive.maximum, 1 << 30)\n        XCTAssertEqual(self.adaptive.minimum, 0)\n    }\n\n    func testAdaptiveRoundsValues() {\n        let adaptive = AdaptiveRecvByteBufferAllocator(minimum: 9, initial: 677, maximum: 111111)\n        XCTAssertEqual(adaptive.minimum, 8)\n        XCTAssertEqual(adaptive.maximum, 131072)\n        XCTAssertEqual(adaptive.initial, 512)\n    }\n\n    func testSettingMinimumAboveMaxAllowed() {\n        guard let targetValue = Int(exactly: Int64.max / 2) else {\n            // On a 32-bit word platform, this test cannot do anything sensible.\n            return\n        }\n\n        let adaptive = AdaptiveRecvByteBufferAllocator(\n            minimum: targetValue,\n            initial: targetValue + 1,\n            maximum: targetValue + 2\n        )\n        XCTAssertEqual(adaptive.minimum, 1 << 30)\n        XCTAssertEqual(adaptive.maximum, 1 << 30)\n        XCTAssertEqual(adaptive.initial, 1 << 30)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/SingleStepByteToMessageDecoderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n\npublic final class NIOSingleStepByteToMessageDecoderTest: XCTestCase {\n    private final class ByteToInt32Decoder: NIOSingleStepByteToMessageDecoder {\n        typealias InboundOut = Int32\n\n        func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n            buffer.readInteger()\n        }\n\n        func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n            XCTAssertTrue(seenEOF)\n            return try self.decode(buffer: &buffer)\n        }\n    }\n\n    private final class LargeChunkDecoder: NIOSingleStepByteToMessageDecoder {\n        typealias InboundOut = ByteBuffer\n\n        func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n            buffer.readSlice(length: 512)\n        }\n\n        func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n            XCTAssertFalse(seenEOF)\n            return try self.decode(buffer: &buffer)\n        }\n    }\n\n    // A special case decoder that decodes only once there is 5,120 bytes in the buffer,\n    // at which point it decodes exactly 2kB of memory.\n    private final class OnceDecoder: NIOSingleStepByteToMessageDecoder {\n        typealias InboundOut = ByteBuffer\n\n        func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n            guard buffer.readableBytes >= 5120 else {\n                return nil\n            }\n\n            return buffer.readSlice(length: 2048)!\n        }\n\n        func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n            XCTAssertFalse(seenEOF)\n            return try self.decode(buffer: &buffer)\n        }\n    }\n\n    private final class PairOfBytesDecoder: NIOSingleStepByteToMessageDecoder {\n        typealias InboundOut = ByteBuffer\n\n        var decodeLastCalls = 0\n        var lastBuffer: ByteBuffer?\n\n        func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n            buffer.readSlice(length: 2)\n        }\n\n        func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n            self.decodeLastCalls += 1\n            XCTAssertEqual(1, self.decodeLastCalls)\n            self.lastBuffer = buffer\n            return nil\n        }\n    }\n\n    private final class MessageReceiver<InboundOut> {\n        var messages: CircularBuffer<InboundOut> = CircularBuffer()\n\n        func receiveMessage(message: InboundOut) {\n            messages.append(message)\n        }\n\n        var count: Int { messages.count }\n\n        func retrieveMessage() -> InboundOut? {\n            if messages.isEmpty {\n                return nil\n            }\n            return messages.removeFirst()\n        }\n    }\n\n    func testDecoder() throws {\n        let allocator = ByteBufferAllocator()\n        let processor = NIOSingleStepByteToMessageProcessor(ByteToInt32Decoder())\n        let messageReceiver: MessageReceiver<Int32> = MessageReceiver()\n\n        var buffer = allocator.buffer(capacity: 32)\n        buffer.writeInteger(Int32(1))\n        let writerIndex = buffer.writerIndex\n        buffer.moveWriterIndex(to: writerIndex - 1)\n\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertNil(messageReceiver.retrieveMessage())\n\n        buffer.moveWriterIndex(to: writerIndex)\n        XCTAssertNoThrow(\n            try processor.process(\n                buffer: buffer.getSlice(at: writerIndex - 1, length: 1)!,\n                messageReceiver.receiveMessage\n            )\n        )\n\n        var buffer2 = allocator.buffer(capacity: 32)\n        buffer2.writeInteger(Int32(2))\n        buffer2.writeInteger(Int32(3))\n        XCTAssertNoThrow(try processor.process(buffer: buffer2, messageReceiver.receiveMessage))\n\n        XCTAssertNoThrow(try processor.finishProcessing(seenEOF: true, messageReceiver.receiveMessage))\n\n        XCTAssertEqual(Int32(1), messageReceiver.retrieveMessage())\n        XCTAssertEqual(Int32(2), messageReceiver.retrieveMessage())\n        XCTAssertEqual(Int32(3), messageReceiver.retrieveMessage())\n        XCTAssertNil(messageReceiver.retrieveMessage())\n    }\n\n    func testMemoryIsReclaimedIfMostIsConsumed() throws {\n        let allocator = ByteBufferAllocator()\n        let processor = NIOSingleStepByteToMessageProcessor(LargeChunkDecoder())\n        let messageReceiver: MessageReceiver<ByteBuffer> = MessageReceiver()\n        defer {\n            XCTAssertNoThrow(try processor.finishProcessing(seenEOF: false, messageReceiver.receiveMessage))\n        }\n\n        // We're going to send in 513 bytes. This will cause a chunk to be passed on, and will leave\n        // a 512-byte empty region in a byte buffer with a capacity of 1024 bytes. Since 512 empty\n        // bytes are exactly 50% of the buffers capacity and not one tiny bit more, the empty space\n        // will not be reclaimed.\n        var buffer = allocator.buffer(capacity: 513)\n        buffer.writeBytes(Array(repeating: 0x04, count: 513))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n\n        XCTAssertEqual(512, messageReceiver.retrieveMessage()!.readableBytes)\n\n        XCTAssertEqual(processor._buffer!.capacity, 1024)\n        XCTAssertEqual(1, processor._buffer!.readableBytes)\n        XCTAssertEqual(512, processor._buffer!.readerIndex)\n\n        // Next we're going to send in another 513 bytes. This will cause another chunk to be passed\n        // into our decoder buffer, which has a capacity of 1024 bytes, before we pass in another\n        // 513 bytes. Since we already have written to 513 bytes, there isn't enough space in the\n        // buffer, which will cause a resize to a new underlying storage with 2048 bytes. Since the\n        // `LargeChunkDecoder` has consumed another 512 bytes, there are now two bytes left to read\n        // (513 + 513) - (512 + 512). The reader index is at 1024. The empty space has not been\n        // reclaimed: While the capacity is more than 1024 bytes (2048 bytes), the reader index is\n        // now at 1024. This means the buffer is exactly 50% consumed and not a tiny bit more, which\n        // means no space will be reclaimed.\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(512, messageReceiver.retrieveMessage()!.readableBytes)\n\n        XCTAssertEqual(processor._buffer!.capacity, 2048)\n        XCTAssertEqual(2, processor._buffer!.readableBytes)\n        XCTAssertEqual(1024, processor._buffer!.readerIndex)\n\n        // Finally we're going to send in another 513 bytes. This will cause another chunk to be\n        // passed into our decoder buffer, which has a capacity of 2048 bytes. Since the buffer has\n        // enough available space (1022 bytes) there will be no buffer resize before the decoding.\n        // After the decoding of another 512 bytes, the buffer will have 1536 empty bytes\n        // (3 * 512 bytes). This means that 75% of the buffer's capacity can now be reclaimed, which\n        // will lead to a reclaim. The resulting buffer will have a capacity of 2048 bytes (based\n        // on its previous growth), with 3 readable bytes remaining.\n\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(512, messageReceiver.retrieveMessage()!.readableBytes)\n\n        XCTAssertEqual(processor._buffer!.capacity, 2048)\n        XCTAssertEqual(3, processor._buffer!.readableBytes)\n        XCTAssertEqual(0, processor._buffer!.readerIndex)\n    }\n\n    func testMemoryIsReclaimedIfLotsIsAvailable() throws {\n        let allocator = ByteBufferAllocator()\n        let processor = NIOSingleStepByteToMessageProcessor(OnceDecoder())\n        let messageReceiver: MessageReceiver<ByteBuffer> = MessageReceiver()\n        defer {\n            XCTAssertNoThrow(try processor.finishProcessing(seenEOF: false, messageReceiver.receiveMessage))\n        }\n\n        // We're going to send in 5119 bytes. This will be held.\n        var buffer = allocator.buffer(capacity: 5119)\n        buffer.writeBytes(Array(repeating: 0x04, count: 5119))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(0, messageReceiver.count)\n\n        XCTAssertEqual(5119, processor._buffer!.readableBytes)\n        XCTAssertEqual(0, processor._buffer!.readerIndex)\n\n        // Now we're going to send in one more byte. This will cause a chunk to be passed on,\n        // shrinking the held memory to 3072 bytes. However, memory will be reclaimed.\n        XCTAssertNoThrow(\n            try processor.process(buffer: buffer.getSlice(at: 0, length: 1)!, messageReceiver.receiveMessage)\n        )\n        XCTAssertEqual(2048, messageReceiver.retrieveMessage()!.readableBytes)\n        XCTAssertEqual(3072, processor._buffer!.readableBytes)\n        XCTAssertEqual(0, processor._buffer!.readerIndex)\n    }\n\n    func testLeftOversMakeDecodeLastCalled() {\n        let allocator = ByteBufferAllocator()\n        let decoder = PairOfBytesDecoder()\n        let processor = NIOSingleStepByteToMessageProcessor(decoder)\n        let messageReceiver: MessageReceiver<ByteBuffer> = MessageReceiver()\n\n        var buffer = allocator.buffer(capacity: 16)\n        buffer.clear()\n        buffer.writeStaticString(\"1\")\n        XCTAssertEqual(processor.unprocessedBytes, 0)\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(processor.unprocessedBytes, 1)\n        buffer.clear()\n        buffer.writeStaticString(\"23\")\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(processor.unprocessedBytes, 1)\n        buffer.clear()\n        buffer.writeStaticString(\"4567890x\")\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(processor.unprocessedBytes, 1)\n        XCTAssertNoThrow(try processor.finishProcessing(seenEOF: false, messageReceiver.receiveMessage))\n        XCTAssertEqual(processor.unprocessedBytes, 1)\n\n        XCTAssertEqual(\n            \"12\",\n            messageReceiver.retrieveMessage().map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertEqual(\n            \"34\",\n            messageReceiver.retrieveMessage().map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertEqual(\n            \"56\",\n            messageReceiver.retrieveMessage().map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertEqual(\n            \"78\",\n            messageReceiver.retrieveMessage().map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertEqual(\n            \"90\",\n            messageReceiver.retrieveMessage().map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertNil(messageReceiver.retrieveMessage())\n\n        XCTAssertEqual(\n            \"x\",\n            decoder.lastBuffer.map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testStructsWorkAsOSBTMDecoders() {\n        struct WantsOneThenTwoOSBTMDecoder: NIOSingleStepByteToMessageDecoder {\n            typealias InboundOut = Int\n\n            var state: Int = 1\n\n            mutating func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n                if buffer.readSlice(length: self.state) != nil {\n                    defer {\n                        self.state += 1\n                    }\n                    return self.state\n                } else {\n                    return nil\n                }\n            }\n\n            mutating func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n                XCTAssertTrue(seenEOF)\n                if self.state > 0 {\n                    self.state = 0\n                    return buffer.readableBytes * -1\n                } else {\n                    return nil\n                }\n            }\n        }\n        let allocator = ByteBufferAllocator()\n        let processor = NIOSingleStepByteToMessageProcessor(WantsOneThenTwoOSBTMDecoder())\n        let messageReceiver: MessageReceiver<Int> = MessageReceiver()\n\n        var buffer = allocator.buffer(capacity: 16)\n        buffer.clear()\n        buffer.writeStaticString(\"1\")\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        buffer.clear()\n        buffer.writeStaticString(\"23\")\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        buffer.clear()\n        buffer.writeStaticString(\"4567890qwer\")\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n\n        XCTAssertEqual(1, messageReceiver.retrieveMessage())\n        XCTAssertEqual(2, messageReceiver.retrieveMessage())\n        XCTAssertEqual(3, messageReceiver.retrieveMessage())\n        XCTAssertEqual(4, messageReceiver.retrieveMessage())\n        XCTAssertNil(messageReceiver.retrieveMessage())\n\n        XCTAssertNoThrow(try processor.finishProcessing(seenEOF: true, messageReceiver.receiveMessage))\n\n        XCTAssertEqual(-4, messageReceiver.retrieveMessage())\n        XCTAssertNil(messageReceiver.retrieveMessage())\n    }\n\n    func testDecodeLastIsInvokedOnceEvenIfNothingEverArrivedOnChannelClosed() {\n        class Decoder: NIOSingleStepByteToMessageDecoder {\n            typealias InboundOut = ()\n            var decodeLastCalls = 0\n\n            public func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n                XCTFail(\"did not expect to see decode called\")\n                return nil\n            }\n\n            public func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n                XCTAssertTrue(seenEOF)\n                self.decodeLastCalls += 1\n                XCTAssertEqual(1, self.decodeLastCalls)\n                XCTAssertEqual(0, buffer.readableBytes)\n                return ()\n            }\n        }\n\n        let decoder = Decoder()\n        let processor = NIOSingleStepByteToMessageProcessor(decoder)\n        let messageReceiver: MessageReceiver<()> = MessageReceiver()\n\n        XCTAssertEqual(0, messageReceiver.count)\n\n        XCTAssertNoThrow(try processor.finishProcessing(seenEOF: true, messageReceiver.receiveMessage))\n        XCTAssertNotNil(messageReceiver.retrieveMessage())\n        XCTAssertNil(messageReceiver.retrieveMessage())\n\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testPayloadTooLarge() {\n        struct Decoder: NIOSingleStepByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n                nil\n            }\n\n            func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n                nil\n            }\n        }\n\n        let max = 100\n        let allocator = ByteBufferAllocator()\n        let processor = NIOSingleStepByteToMessageProcessor(Decoder(), maximumBufferSize: max)\n        let messageReceiver: MessageReceiver<Never> = MessageReceiver()\n\n        var buffer = allocator.buffer(capacity: max + 1)\n        buffer.writeString(String(repeating: \"*\", count: max + 1))\n        XCTAssertThrowsError(try processor.process(buffer: buffer, messageReceiver.receiveMessage)) { error in\n            XCTAssertTrue(error is ByteToMessageDecoderError.PayloadTooLargeError)\n        }\n    }\n\n    func testPayloadTooLargeButHandlerOk() {\n        class Decoder: NIOSingleStepByteToMessageDecoder {\n            typealias InboundOut = String\n\n            var decodeCalls = 0\n\n            func decode(buffer: inout ByteBuffer) throws -> InboundOut? {\n                self.decodeCalls += 1\n                return buffer.readString(length: buffer.readableBytes)\n            }\n\n            func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> InboundOut? {\n                try decode(buffer: &buffer)\n            }\n        }\n\n        let max = 100\n        let allocator = ByteBufferAllocator()\n        let decoder = Decoder()\n        let processor = NIOSingleStepByteToMessageProcessor(decoder, maximumBufferSize: max)\n        let messageReceiver: MessageReceiver<String> = MessageReceiver()\n\n        var buffer = allocator.buffer(capacity: max + 1)\n        buffer.writeString(String(repeating: \"*\", count: max + 1))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertNoThrow(try processor.finishProcessing(seenEOF: false, messageReceiver.receiveMessage))\n        XCTAssertEqual(0, processor._buffer!.readableBytes)\n        XCTAssertGreaterThan(decoder.decodeCalls, 0)\n    }\n\n    func testReentrancy() {\n        class ReentrantWriteProducingHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = String\n            var processor: NIOSingleStepByteToMessageProcessor<OneByteStringDecoder>? = nil\n            var produced = 0\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if self.processor == nil {\n                    self.processor = NIOSingleStepByteToMessageProcessor(OneByteStringDecoder())\n                }\n                do {\n                    try self.processor!.process(buffer: Self.unwrapInboundIn(data)) { message in\n                        self.produced += 1\n                        // Produce an extra write the first time we are called to test reentrancy\n                        if self.produced == 1 {\n                            let buf = ByteBuffer(string: \"X\")\n                            XCTAssertNoThrow(try (context.channel as! EmbeddedChannel).writeInbound(buf))\n                        }\n                        context.fireChannelRead(Self.wrapInboundOut(message))\n                    }\n                } catch {\n                    context.fireErrorCaught(error)\n                }\n            }\n        }\n\n        class OneByteStringDecoder: NIOSingleStepByteToMessageDecoder {\n            typealias InboundOut = String\n\n            func decode(buffer: inout ByteBuffer) throws -> String? {\n                buffer.readString(length: 1)\n            }\n\n            func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> String? {\n                XCTAssertTrue(seenEOF)\n                return try self.decode(buffer: &buffer)\n            }\n        }\n\n        let channel = EmbeddedChannel(handler: ReentrantWriteProducingHandler())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"a\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertEqual(\"X\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"a\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWeDoNotCallShouldReclaimMemoryAsLongAsFramesAreProduced() {\n        struct TestByteToMessageDecoder: NIOSingleStepByteToMessageDecoder {\n            typealias InboundOut = TestMessage\n\n            enum TestMessage: Equatable {\n                case foo\n            }\n\n            var lastByteBuffer: ByteBuffer?\n            var decodeHits = 0\n            var reclaimHits = 0\n\n            mutating func decode(buffer: inout ByteBuffer) throws -> TestMessage? {\n                XCTAssertEqual(self.decodeHits * 3, buffer.readerIndex)\n                self.decodeHits += 1\n                guard buffer.readableBytes >= 3 else {\n                    return nil\n                }\n                buffer.moveReaderIndex(forwardBy: 3)\n                return .foo\n            }\n\n            mutating func decodeLast(buffer: inout ByteBuffer, seenEOF: Bool) throws -> TestMessage? {\n                try self.decode(buffer: &buffer)\n            }\n\n            mutating func shouldReclaimBytes(buffer: ByteBuffer) -> Bool {\n                self.reclaimHits += 1\n                return true\n            }\n        }\n\n        let decoder = TestByteToMessageDecoder()\n        let processor = NIOSingleStepByteToMessageProcessor(decoder, maximumBufferSize: nil)\n\n        let buffer = ByteBuffer(repeating: 0, count: 3001)\n        var callbackCount = 0\n        XCTAssertNoThrow(\n            try processor.process(buffer: buffer) { _ in\n                callbackCount += 1\n            }\n        )\n\n        XCTAssertEqual(callbackCount, 1000)\n        XCTAssertEqual(processor.decoder.decodeHits, 1001)\n        XCTAssertEqual(processor.decoder.reclaimHits, 1)\n        XCTAssertEqual(processor._buffer!.readableBytes, 1)\n    }\n\n    func testUnprocessedBytes() {\n        let allocator = ByteBufferAllocator()\n        let processor = NIOSingleStepByteToMessageProcessor(LargeChunkDecoder())  // reads slices of 512 bytes\n        let messageReceiver: MessageReceiver<ByteBuffer> = MessageReceiver()\n\n        // We're going to send in 128 bytes. This will be held.\n        var buffer = allocator.buffer(capacity: 128)\n        buffer.writeBytes(Array(repeating: 0x04, count: 128))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(0, messageReceiver.count)\n        XCTAssertEqual(processor.unprocessedBytes, 128)\n\n        // Adding 513 bytes, will cause a message to be returned and an extra byte to be saved.\n        buffer.clear()\n        buffer.writeBytes(Array(repeating: 0x04, count: 513))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(1, messageReceiver.count)\n        XCTAssertEqual(processor.unprocessedBytes, 129)\n\n        // Adding 255 bytes, will cause 255 more bytes to be held.\n        buffer.clear()\n        buffer.writeBytes(Array(repeating: 0x04, count: 255))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(1, messageReceiver.count)\n        XCTAssertEqual(processor.unprocessedBytes, 384)\n\n        // Adding 128 bytes, will cause another message to be returned and the buffer to be empty.\n        buffer.clear()\n        buffer.writeBytes(Array(repeating: 0x04, count: 128))\n        XCTAssertNoThrow(try processor.process(buffer: buffer, messageReceiver.receiveMessage))\n        XCTAssertEqual(2, messageReceiver.count)\n        XCTAssertEqual(processor.unprocessedBytes, 0)\n    }\n\n    /// Tests re-entrancy by having a nested decoding operation empty the buffer and exit part way\n    /// through the outer processing step\n    func testErrorDuringNestedDecoding() {\n        class ThrowingOnLastDecoder: NIOSingleStepByteToMessageDecoder {\n            /// `ByteBuffer` is the expected type passed in.\n            public typealias InboundIn = ByteBuffer\n            /// `ByteBuffer`s will be passed to the next stage.\n            public typealias InboundOut = ByteBuffer\n\n            public init() {}\n\n            struct DecodeLastError: Error {}\n\n            func decodeLast(buffer: inout NIOCore.ByteBuffer, seenEOF: Bool) throws -> NIOCore.ByteBuffer? {\n                buffer = ByteBuffer()  // to allow the decode loop to exit\n                throw DecodeLastError()\n            }\n\n            func decode(buffer: inout NIOCore.ByteBuffer) throws -> NIOCore.ByteBuffer? {\n                ByteBuffer()\n            }\n        }\n\n        let decoder = ThrowingOnLastDecoder()\n        let b2mp = NIOSingleStepByteToMessageProcessor(decoder)\n        var errorObserved = false\n        XCTAssertNoThrow(\n            try b2mp.process(buffer: ByteBuffer(string: \"1\\n\\n2\\n3\\n\")) { line in\n                // We will throw an error to exit the decoding within the nested process call prematurely.\n                // Unless this is carefully handled we can be left in an inconsistent state which the outer call will encounter\n                do {\n                    try b2mp.finishProcessing(seenEOF: true) { _ in }\n                } catch _ as ThrowingOnLastDecoder.DecodeLastError {\n                    errorObserved = true\n                }\n            }\n        )\n        XCTAssertTrue(errorObserved)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/TimeAmount+DurationTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\nclass TimeAmountDurationTests: XCTestCase {\n    func testTimeAmountFromDurationConversion() throws {\n        guard #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) else {\n            throw XCTSkip(\"Required API is not available for this test.\")\n        }\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 0, attosecondsComponent: 0)),\n            .nanoseconds(0)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 0, attosecondsComponent: 1_000_000_001)),\n            .nanoseconds(1)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 0, attosecondsComponent: 999_999_999)),\n            .nanoseconds(0)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 42, attosecondsComponent: 1_000_000_001)),\n            .nanoseconds(42_000_000_001)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 42, attosecondsComponent: 999_999_999)),\n            .nanoseconds(42_000_000_000)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 0, attosecondsComponent: -1_000_000_000)),\n            .nanoseconds(-1)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 0, attosecondsComponent: -999_999_999)),\n            .nanoseconds(0)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 1, attosecondsComponent: -1_000_000_000_000_000_000)),\n            .nanoseconds(0)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 1, attosecondsComponent: -1_000_000_000_000_000_001)),\n            .nanoseconds(0)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration(secondsComponent: 1, attosecondsComponent: -1_000_000_001_000_000_000)),\n            .nanoseconds(-1)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration.nanoseconds(Int64.max)),\n            .nanoseconds(Int64.max)\n        )\n        XCTAssertEqual(\n            TimeAmount(Duration.nanoseconds(Int64.max) + .nanoseconds(1)),\n            .nanoseconds(Int64.max)\n        )\n    }\n\n    func testTimeAmountToDurationLosslessRountTrip() throws {\n        guard #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) else {\n            throw XCTSkip(\"Required API is not available for this test.\")\n        }\n        for amount in [\n            TimeAmount.zero,\n            TimeAmount.seconds(1),\n            TimeAmount.seconds(-1),\n            TimeAmount.nanoseconds(1),\n            TimeAmount.nanoseconds(-1),\n            TimeAmount.nanoseconds(.max),\n            TimeAmount.nanoseconds(.min),\n        ] {\n            XCTAssertEqual(TimeAmount(Duration(amount)), amount)\n        }\n    }\n\n    func testDurationToTimeAmountLossyRoundTrip() throws {\n        guard #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) else {\n            throw XCTSkip(\"Required API is not available for this test.\")\n        }\n        for duration in [\n            Duration.zero,\n            Duration.seconds(1),\n            Duration.seconds(-1),\n            Duration.nanoseconds(Int64.max),\n            Duration.nanoseconds(Int64.min),\n            Duration.nanoseconds(Int64.max) + Duration.nanoseconds(1),\n            Duration.nanoseconds(Int64.min) - Duration.nanoseconds(1),\n            Duration(secondsComponent: 0, attosecondsComponent: 1),\n            Duration(secondsComponent: 0, attosecondsComponent: 1_000_000_000),\n            Duration(secondsComponent: 0, attosecondsComponent: 1_500_000_000),\n            Duration(secondsComponent: 0, attosecondsComponent: 1_000_000_001),\n            Duration(secondsComponent: 0, attosecondsComponent: 0_999_999_999),\n            Duration(secondsComponent: 0, attosecondsComponent: -1),\n            Duration(secondsComponent: 0, attosecondsComponent: -1_000_000_000),\n            Duration(secondsComponent: 0, attosecondsComponent: -1_500_000_000),\n            Duration(secondsComponent: 0, attosecondsComponent: -1_000_000_001),\n            Duration(secondsComponent: 0, attosecondsComponent: -0_999_999_999),\n        ] {\n            let duration_ = Duration(TimeAmount(duration))\n            XCTAssertEqual(duration_.nanosecondsClamped, duration.nanosecondsClamped)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/TimeAmountTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOCore\n\nclass TimeAmountTests: XCTestCase {\n    func testTimeAmountConversion() {\n        XCTAssertEqual(TimeAmount.nanoseconds(3), .nanoseconds(3))\n        XCTAssertEqual(TimeAmount.microseconds(14), .nanoseconds(14_000))\n        XCTAssertEqual(TimeAmount.milliseconds(15), .nanoseconds(15_000_000))\n        XCTAssertEqual(TimeAmount.seconds(9), .nanoseconds(9_000_000_000))\n        XCTAssertEqual(TimeAmount.minutes(2), .nanoseconds(120_000_000_000))\n        XCTAssertEqual(TimeAmount.hours(6), .nanoseconds(21_600_000_000_000))\n        XCTAssertEqual(TimeAmount.zero, .nanoseconds(0))\n    }\n\n    func testTimeAmountIsHashable() {\n        let amounts: Set<TimeAmount> = [.seconds(1), .milliseconds(4), .seconds(1)]\n        XCTAssertEqual(amounts, [.seconds(1), .milliseconds(4)])\n    }\n\n    func testTimeAmountDoesAddTime() {\n        var lhs = TimeAmount.nanoseconds(0)\n        let rhs = TimeAmount.nanoseconds(5)\n        lhs += rhs\n        XCTAssertEqual(lhs, .nanoseconds(5))\n    }\n\n    func testTimeAmountDoesSubtractTime() {\n        var lhs = TimeAmount.nanoseconds(5)\n        let rhs = TimeAmount.nanoseconds(5)\n        lhs -= rhs\n        XCTAssertEqual(lhs, .nanoseconds(0))\n    }\n\n    func testTimeAmountCappedOverflow() {\n        let overflowCap = TimeAmount.nanoseconds(Int64.max)\n        XCTAssertEqual(TimeAmount.microseconds(.max), overflowCap)\n        XCTAssertEqual(TimeAmount.milliseconds(.max), overflowCap)\n        XCTAssertEqual(TimeAmount.seconds(.max), overflowCap)\n        XCTAssertEqual(TimeAmount.minutes(.max), overflowCap)\n        XCTAssertEqual(TimeAmount.hours(.max), overflowCap)\n    }\n\n    func testTimeAmountCappedUnderflow() {\n        let underflowCap = TimeAmount.nanoseconds(.min)\n        XCTAssertEqual(TimeAmount.microseconds(.min), underflowCap)\n        XCTAssertEqual(TimeAmount.milliseconds(.min), underflowCap)\n        XCTAssertEqual(TimeAmount.seconds(.min), underflowCap)\n        XCTAssertEqual(TimeAmount.minutes(.min), underflowCap)\n        XCTAssertEqual(TimeAmount.hours(.min), underflowCap)\n    }\n\n    func testTimeAmountParsing() throws {\n        // Test all supported hour formats\n        XCTAssertEqual(try TimeAmount(\"2h\"), .hours(2))\n        XCTAssertEqual(try TimeAmount(\"2hr\"), .hours(2))\n        XCTAssertEqual(try TimeAmount(\"2hrs\"), .hours(2))\n\n        // Test all supported minute formats\n        XCTAssertEqual(try TimeAmount(\"3m\"), .minutes(3))\n        XCTAssertEqual(try TimeAmount(\"3min\"), .minutes(3))\n\n        // Test all supported second formats\n        XCTAssertEqual(try TimeAmount(\"4s\"), .seconds(4))\n        XCTAssertEqual(try TimeAmount(\"4sec\"), .seconds(4))\n        XCTAssertEqual(try TimeAmount(\"4secs\"), .seconds(4))\n\n        // Test all supported millisecond formats\n        XCTAssertEqual(try TimeAmount(\"5ms\"), .milliseconds(5))\n        XCTAssertEqual(try TimeAmount(\"5millis\"), .milliseconds(5))\n\n        // Test all supported microsecond formats\n        XCTAssertEqual(try TimeAmount(\"6us\"), .microseconds(6))\n        XCTAssertEqual(try TimeAmount(\"6µs\"), .microseconds(6))\n        XCTAssertEqual(try TimeAmount(\"6micros\"), .microseconds(6))\n\n        // Test all supported nanosecond formats\n        XCTAssertEqual(try TimeAmount(\"7ns\"), .nanoseconds(7))\n        XCTAssertEqual(try TimeAmount(\"7nanos\"), .nanoseconds(7))\n    }\n\n    func testTimeAmountParsingWithWhitespace() throws {\n        XCTAssertEqual(try TimeAmount(\"5 s\"), .seconds(5))\n        XCTAssertEqual(try TimeAmount(\"100  ms\"), .milliseconds(100))\n        XCTAssertEqual(try TimeAmount(\"42    ns\"), .nanoseconds(42))\n        XCTAssertEqual(try TimeAmount(\" 5s \"), .seconds(5))\n    }\n\n    func testTimeAmountParsingCaseInsensitive() throws {\n        XCTAssertEqual(try TimeAmount(\"5S\"), .seconds(5))\n        XCTAssertEqual(try TimeAmount(\"100MS\"), .milliseconds(100))\n        XCTAssertEqual(try TimeAmount(\"1HR\"), .hours(1))\n        XCTAssertEqual(try TimeAmount(\"30MIN\"), .minutes(30))\n    }\n\n    func testTimeAmountParsingInvalidInput() throws {\n        // Empty string\n        XCTAssertThrowsError(try TimeAmount(\"\")) { error in\n            XCTAssertEqual(\n                error as? TimeAmount.ValidationError,\n                TimeAmount.ValidationError.invalidNumber(\"'' cannot be parsed as number and unit\")\n            )\n        }\n\n        // Invalid number\n        XCTAssertThrowsError(try TimeAmount(\"abc\")) { error in\n            XCTAssertEqual(\n                error as? TimeAmount.ValidationError,\n                TimeAmount.ValidationError.invalidNumber(\"'abc' cannot be parsed as number and unit\")\n            )\n        }\n\n        // Unknown unit\n        XCTAssertThrowsError(try TimeAmount(\"5x\")) { error in\n            XCTAssertEqual(\n                error as? TimeAmount.ValidationError,\n                TimeAmount.ValidationError.unsupportedUnit(\"Unknown unit 'x' in '5x'\")\n            )\n        }\n\n        // Missing number\n        XCTAssertThrowsError(try TimeAmount(\"ms\")) { error in\n            XCTAssertEqual(\n                error as? TimeAmount.ValidationError,\n                TimeAmount.ValidationError.invalidNumber(\"'ms' cannot be parsed as number and unit\")\n            )\n        }\n    }\n\n    func testTimeAmountPrettyPrint() {\n        // Basic formatting\n        XCTAssertEqual(TimeAmount.seconds(5).description, \"5 s\")\n        XCTAssertEqual(TimeAmount.milliseconds(100).description, \"100 ms\")\n        XCTAssertEqual(TimeAmount.microseconds(250).description, \"250 us\")\n        XCTAssertEqual(TimeAmount.nanoseconds(42).description, \"42 ns\")\n\n        // Unit selection based on value\n        XCTAssertEqual(TimeAmount.nanoseconds(1_000).description, \"1 us\")\n        XCTAssertEqual(TimeAmount.nanoseconds(1_000_000).description, \"1 ms\")\n        XCTAssertEqual(TimeAmount.nanoseconds(1_000_000_000).description, \"1 s\")\n\n        // Values with remainders\n        XCTAssertEqual(TimeAmount.nanoseconds(1_500).description, \"1500 ns\")\n        XCTAssertEqual(TimeAmount.nanoseconds(1_500_000).description, \"1500 us\")\n        XCTAssertEqual(TimeAmount.nanoseconds(1_500_000_000).description, \"1500 ms\")\n\n        // Negative values\n        XCTAssertEqual(TimeAmount.seconds(-5).description, \"-5 s\")\n        XCTAssertEqual(TimeAmount.milliseconds(-100).description, \"-100 ms\")\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/TypeAssistedChannelHandlerTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nclass TypeAssistedChannelHandlerTest: XCTestCase {\n    func testCanDefineBothInboundAndOutbound() throws {\n        class TestClass: ChannelDuplexHandler {\n            public typealias OutboundIn = ByteBuffer\n            public typealias OutboundOut = ByteBuffer\n            public typealias InboundIn = ByteBuffer\n            public typealias InboundOut = ByteBuffer\n        }\n\n        // This test really just confirms that compilation works: no need to run any code.\n        XCTAssert(true)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/UtilitiesTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nclass UtilitiesTest: XCTestCase {\n    func testCoreCountWorks() {\n        XCTAssertGreaterThan(System.coreCount, 0)\n    }\n\n    @available(*, deprecated)\n    func testEnumeratingInterfaces() throws {\n        // This is a tricky test, because we can't really assert much and expect this\n        // to pass on all systems. The best we can do is assume there is a loopback:\n        // maybe an IPv4 one, maybe an IPv6 one, but there will be one. We look for\n        // both.\n        let interfaces = try System.enumerateInterfaces()\n        XCTAssertGreaterThan(interfaces.count, 0)\n\n        var ipv4LoopbackPresent = false\n        var ipv6LoopbackPresent = false\n\n        for interface in interfaces {\n            if try interface.address == SocketAddress(ipAddress: \"127.0.0.1\", port: 0) {\n                ipv4LoopbackPresent = true\n                XCTAssertEqual(interface.netmask, try SocketAddress(ipAddress: \"255.0.0.0\", port: 0))\n                XCTAssertNil(interface.broadcastAddress)\n                XCTAssertNil(interface.pointToPointDestinationAddress)\n            } else if try interface.address == SocketAddress(ipAddress: \"::1\", port: 0) {\n                ipv6LoopbackPresent = true\n                XCTAssertEqual(\n                    interface.netmask,\n                    try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\", port: 0)\n                )\n                XCTAssertNil(interface.broadcastAddress)\n                XCTAssertNil(interface.pointToPointDestinationAddress)\n            }\n        }\n\n        XCTAssertTrue(ipv4LoopbackPresent || ipv6LoopbackPresent)\n    }\n\n    func testEnumeratingDevices() throws {\n        // This is a tricky test, because we can't really assert much and expect this\n        // to pass on all systems. The best we can do is assume there is a loopback:\n        // maybe an IPv4 one, maybe an IPv6 one, but there will be one. We look for\n        // both.\n        let devices = try System.enumerateDevices()\n        XCTAssertGreaterThan(devices.count, 0)\n\n        var ipv4LoopbackPresent = false\n        var ipv6LoopbackPresent = false\n\n        for device in devices {\n            if try device.address == SocketAddress(ipAddress: \"127.0.0.1\", port: 0) {\n                ipv4LoopbackPresent = true\n                XCTAssertEqual(device.netmask, try SocketAddress(ipAddress: \"255.0.0.0\", port: 0))\n                XCTAssertNil(device.broadcastAddress)\n                XCTAssertNil(device.pointToPointDestinationAddress)\n            } else if try device.address == SocketAddress(ipAddress: \"::1\", port: 0) {\n                ipv6LoopbackPresent = true\n                XCTAssertEqual(\n                    device.netmask,\n                    try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\", port: 0)\n                )\n                XCTAssertNil(device.broadcastAddress)\n                XCTAssertNil(device.pointToPointDestinationAddress)\n            }\n        }\n\n        XCTAssertTrue(ipv4LoopbackPresent || ipv6LoopbackPresent)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/XCTest+AsyncAwait.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the AsyncHTTPClient open source project\n//\n// Copyright (c) 2021 Apple Inc. and the AsyncHTTPClient project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//\n// Copyright 2021, gRPC Authors All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertThrowsError<T>(\n    _ expression: @autoclosure () async throws -> T,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    verify: (Error) -> Void = { _ in }\n) async {\n    do {\n        _ = try await expression()\n        XCTFail(\"Expression did not throw error\", file: file, line: line)\n    } catch {\n        verify(error)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertNoThrow<T>(\n    _ expression: @autoclosure () async throws -> T,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async {\n    do {\n        _ = try await expression()\n    } catch {\n        XCTFail(\"Expression did throw error\", file: file, line: line)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertNoThrowWithResult<Result>(\n    _ expression: @autoclosure () async throws -> Result,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async -> Result? {\n    do {\n        return try await expression()\n    } catch {\n        XCTFail(\"Expression did throw: \\(error)\", file: file, line: line)\n    }\n    return nil\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAsyncAssertNotNil(\n    _ expression: @autoclosure () async throws -> Any?,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let result = try await expression()\n    XCTAssertNotNil(result, file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAsyncAssertNil(\n    _ expression: @autoclosure () async throws -> Any?,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let result = try await expression()\n    XCTAssertNil(result, file: file, line: line)\n}\n"
  },
  {
    "path": "Tests/NIOCoreTests/XCTest+Extensions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n#if canImport(Android)\nimport Android\n#endif\n\nfunc assert(\n    _ condition: @autoclosure () -> Bool,\n    within time: TimeAmount,\n    testInterval: TimeAmount? = nil,\n    _ message: String = \"condition not satisfied in time\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let testInterval = testInterval ?? TimeAmount.nanoseconds(time.nanoseconds / 5)\n    let endTime = NIODeadline.now() + time\n\n    repeat {\n        if condition() { return }\n        usleep(UInt32(testInterval.nanoseconds / 1000))\n    } while NIODeadline.now() < endTime\n\n    if !condition() {\n        XCTFail(message, file: (file), line: line)\n    }\n}\n\nfunc assertNoThrowWithValue<T>(\n    _ body: @autoclosure () throws -> T,\n    defaultValue: T? = nil,\n    message: String? = nil,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws -> T {\n    do {\n        return try body()\n    } catch {\n        XCTFail(\"\\(message.map { $0 + \": \" } ?? \"\")unexpected error \\(error) thrown\", file: (file), line: line)\n        if let defaultValue = defaultValue {\n            return defaultValue\n        } else {\n            throw error\n        }\n    }\n}\n\nfunc withTemporaryFile<T>(content: String? = nil, _ body: (NIOCore.NIOFileHandle, String) throws -> T) throws -> T {\n    let temporaryFilePath = \"\\(temporaryDirectory)/nio_\\(UUID())\"\n    _ = FileManager.default.createFile(atPath: temporaryFilePath, contents: content?.data(using: .utf8))\n    defer {\n        XCTAssertNoThrow(try FileManager.default.removeItem(atPath: temporaryFilePath))\n    }\n\n    let fileHandle = try NIOFileHandle(_deprecatedPath: temporaryFilePath, mode: [.read, .write])\n    defer {\n        XCTAssertNoThrow(try fileHandle.close())\n    }\n\n    return try body(fileHandle, temporaryFilePath)\n}\n\nprivate var temporaryDirectory: String {\n    get {\n        #if targetEnvironment(simulator)\n        // Simulator temp directories are so long (and contain the user name) that they're not usable\n        // for UNIX Domain Socket paths (which are limited to 103 bytes).\n        return \"/tmp\"\n        #else\n        #if os(Linux)\n        return \"/tmp\"\n        #else\n        if #available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) {\n            return FileManager.default.temporaryDirectory.path\n        } else {\n            return \"/tmp\"\n        }\n        #endif  // os\n        #endif  // targetEnvironment\n    }\n}\n"
  },
  {
    "path": "Tests/NIODataStructuresTests/HeapTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2020 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import _NIODataStructures\n\npublic func getRandomNumbers(count: Int) -> [UInt8] {\n    (0..<count).map { _ in\n        UInt8.random(in: .min ... .max)\n    }\n}\n\nclass HeapTests: XCTestCase {\n    func testSimple() throws {\n        var h = Heap<Int>()\n        h.append(3)\n        h.append(1)\n        h.append(2)\n        XCTAssertEqual(1, h.removeRoot())\n        XCTAssertTrue(h.checkHeapProperty())\n    }\n\n    func testSortedDesc() throws {\n        var minHeap = Heap<Int>()\n\n        let inputs = [16, 14, 10, 9, 8, 7, 4, 3, 2, 1]\n        for input in inputs {\n            minHeap.append(input)\n            XCTAssertTrue(minHeap.checkHeapProperty())\n        }\n        var minHeapInputPtr = inputs.count - 1\n        while let minE = minHeap.removeRoot() {\n            XCTAssertEqual(minE, inputs[minHeapInputPtr])\n            minHeapInputPtr -= 1\n            XCTAssertTrue(minHeap.checkHeapProperty(), \"\\(minHeap.debugDescription)\")\n        }\n        XCTAssertEqual(-1, minHeapInputPtr)\n    }\n\n    func testSortedAsc() throws {\n        var minHeap = Heap<Int>()\n\n        let inputs = Array([16, 14, 10, 9, 8, 7, 4, 3, 2, 1].reversed())\n        for input in inputs {\n            minHeap.append(input)\n        }\n        var minHeapInputPtr = 0\n        while let minE = minHeap.removeRoot() {\n            XCTAssertEqual(minE, inputs[minHeapInputPtr])\n            minHeapInputPtr += 1\n        }\n        XCTAssertEqual(inputs.count, minHeapInputPtr)\n    }\n\n    func testAddAndRemoveRandomNumbers() throws {\n        var minHeap = Heap<UInt8>()\n        var minHeapLast = UInt8.min\n\n        let N = 10\n\n        for n in getRandomNumbers(count: N) {\n            minHeap.append(n)\n            XCTAssertTrue(minHeap.checkHeapProperty(), minHeap.debugDescription)\n\n            XCTAssertEqual(Array(minHeap.sorted()), Array(minHeap))\n        }\n\n        for _ in 0..<N / 2 {\n            let value = minHeap.removeRoot()!\n            XCTAssertGreaterThanOrEqual(value, minHeapLast)\n            minHeapLast = value\n\n            XCTAssertTrue(minHeap.checkHeapProperty())\n\n            XCTAssertEqual(Array(minHeap.sorted()), Array(minHeap))\n        }\n\n        minHeapLast = UInt8.min\n\n        for n in getRandomNumbers(count: N) {\n            minHeap.append(n)\n            XCTAssertTrue(minHeap.checkHeapProperty(), minHeap.debugDescription)\n        }\n\n        for _ in 0..<N / 2 + N {\n            let value = minHeap.removeRoot()!\n            XCTAssertGreaterThanOrEqual(value, minHeapLast)\n            minHeapLast = value\n\n            XCTAssertTrue(minHeap.checkHeapProperty())\n        }\n\n        XCTAssertEqual(0, minHeap.underestimatedCount)\n    }\n\n    func testRemoveElement() throws {\n        var h = Heap<Int>()\n        for f in [84, 22, 19, 21, 3, 10, 6, 5, 20] {\n            h.append(f)\n        }\n        _ = h.remove(value: 10)\n        XCTAssertTrue(h.checkHeapProperty(), \"\\(h.debugDescription)\")\n    }\n}\n\nextension Heap {\n    internal func checkHeapProperty() -> Bool {\n        func checkHeapProperty(index: Int) -> Bool {\n            let li = self.leftIndex(index)\n            let ri = self.rightIndex(index)\n            if index >= self.storage.count {\n                return true\n            } else {\n                let me = self.storage[index]\n                var lCond = true\n                var rCond = true\n                if li < self.storage.count {\n                    let l = self.storage[li]\n                    lCond = !self.comparator(l, me)\n                }\n                if ri < self.storage.count {\n                    let r = self.storage[ri]\n                    rCond = !self.comparator(r, me)\n                }\n                return lCond && rCond && checkHeapProperty(index: li) && checkHeapProperty(index: ri)\n            }\n        }\n        return checkHeapProperty(index: 0)\n    }\n}\n"
  },
  {
    "path": "Tests/NIODataStructuresTests/PriorityQueueTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport XCTest\nimport _NIODataStructures\n\nclass PriorityQueueTest: XCTestCase {\n    func testSomeStringsAsc() throws {\n        var pq = PriorityQueue<String>()\n        pq.push(\"foo\")\n        pq.push(\"bar\")\n        pq.push(\"buz\")\n        pq.push(\"qux\")\n\n        pq.remove(\"buz\")\n\n        XCTAssertEqual(\"bar\", pq.peek()!)\n        XCTAssertEqual(\"bar\", pq.pop()!)\n\n        pq.push(\"bar\")\n\n        XCTAssertEqual(\"bar\", pq.peek()!)\n        XCTAssertEqual(\"bar\", pq.pop()!)\n\n        XCTAssertEqual(\"foo\", pq.pop()!)\n        XCTAssertEqual(\"qux\", pq.pop()!)\n\n        XCTAssertTrue(pq.isEmpty)\n    }\n\n    func testRemoveNonExisting() throws {\n        var pq = PriorityQueue<String>()\n        pq.push(\"foo\")\n        pq.remove(\"bar\")\n        pq.remove(\"foo\")\n        XCTAssertNil(pq.pop())\n        XCTAssertNil(pq.peek())\n    }\n\n    func testRemoveFromEmpty() throws {\n        var pq = PriorityQueue<Int>()\n        pq.remove(234)\n        XCTAssertTrue(pq.isEmpty)\n    }\n\n    func testBuildAndRemoveFromRandomPriorityQueues() {\n        for size in 0...33 {\n            var pq = PriorityQueue<UInt8>()\n            let randoms = getRandomNumbers(count: size)\n            for number in randoms {\n                pq.push(number)\n            }\n\n            // remove one random member, add it back and assert we're still the same\n            for random in randoms {\n                var pq2 = pq\n                pq2.remove(random)\n                XCTAssertEqual(pq.count - 1, pq2.count)\n                XCTAssertNotEqual(pq, pq2)\n                pq2.push(random)\n                XCTAssertEqual(pq, pq2)\n            }\n\n            // remove up to `n` members and add them back at the end and check that the priority queues are still the same\n            for n in 1...5 where n <= size {\n                var pq2 = pq\n                let deleted = randoms.prefix(n).map { (random: UInt8) -> UInt8 in\n                    pq2.remove(random)\n                    return random\n                }\n                XCTAssertEqual(pq.count - n, pq2.count)\n                XCTAssertNotEqual(pq, pq2)\n                for number in deleted.reversed() {\n                    pq2.push(number)\n                }\n                XCTAssertEqual(pq, pq2, \"pq: \\(pq), pq2: \\(pq2), deleted: \\(deleted)\")\n            }\n        }\n    }\n\n    func testPartialOrder() {\n        let clearlyTheSmallest = SomePartiallyOrderedDataType(width: 0, height: 0)\n        let clearlyTheLargest = SomePartiallyOrderedDataType(width: 100, height: 100)\n        let inTheMiddles = zip(1...99, (1...99).reversed()).map { SomePartiallyOrderedDataType(width: $0, height: $1) }\n\n        // the four values are only partially ordered (from small (top) to large (bottom)):\n\n        //                   clearlyTheSmallest\n        //                  /         |        \\\n        //           inTheMiddle[0]   |    inTheMiddle[1...]\n        //                  \\         |        /\n        //                    clearlyTheLargest\n\n        var pq = PriorityQueue<SomePartiallyOrderedDataType>()\n        pq.push(clearlyTheLargest)\n        pq.push(inTheMiddles[0])\n        pq.push(clearlyTheSmallest)\n        for number in inTheMiddles[1...] {\n            pq.push(number)\n        }\n        let pop1 = pq.pop()\n        XCTAssertEqual(clearlyTheSmallest, pop1)\n        for _ in inTheMiddles {\n            let popN = pq.pop()!\n            XCTAssert(inTheMiddles.contains(popN))\n        }\n        XCTAssertEqual(clearlyTheLargest, pq.pop()!)\n        XCTAssert(pq.isEmpty)\n    }\n\n    func testDescription() {\n        let pq1 = PriorityQueue<Int>()\n        var pq2 = PriorityQueue<Int>()\n        pq2.push(1)\n        pq2.push(2)\n        pq2.push(3)\n        XCTAssertEqual(pq1.description, \"PriorityQueue(count: 0): \\(Array(pq1))\")\n        XCTAssertEqual(pq2.description, \"PriorityQueue(count: 3): \\(Array(pq2))\")\n    }\n}\n\n/// This data type is only partially ordered. Ie. from `a < b` and `a != b` we can't imply `a > b`.\nstruct SomePartiallyOrderedDataType: Comparable, CustomStringConvertible {\n    public static func < (lhs: SomePartiallyOrderedDataType, rhs: SomePartiallyOrderedDataType) -> Bool {\n        lhs.width < rhs.width && lhs.height < rhs.height\n    }\n\n    public static func == (lhs: SomePartiallyOrderedDataType, rhs: SomePartiallyOrderedDataType) -> Bool {\n        lhs.width == rhs.width && lhs.height == rhs.height\n    }\n\n    private let width: Int\n    private let height: Int\n    public init(width: Int, height: Int) {\n        self.width = width\n        self.height = height\n    }\n\n    public var description: String {\n        \"(w: \\(self.width), h: \\(self.height))\"\n    }\n}\n"
  },
  {
    "path": "Tests/NIOEmbeddedTests/AsyncTestingChannelTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOCore\nimport XCTest\n\n@testable import NIOEmbedded\n\n#if canImport(Android)\nimport Android\n#endif\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nclass AsyncTestingChannelTests: XCTestCase {\n    func testSingleHandlerInit() async throws {\n        final class Handler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n        }\n\n        let channel = await NIOAsyncTestingChannel(handler: Handler())\n        XCTAssertNoThrow(try channel.pipeline.handler(type: Handler.self).wait())\n    }\n\n    func testEmptyInit() throws {\n\n        class Handler: ChannelInboundHandler {\n            typealias InboundIn = Never\n        }\n\n        let channel = NIOAsyncTestingChannel()\n        XCTAssertThrowsError(try channel.pipeline.handler(type: Handler.self).map { _ in }.wait()) { e in\n            XCTAssertEqual(e as? ChannelPipelineError, .notFound)\n        }\n\n    }\n\n    func testMultipleHandlerInit() async throws {\n        final class Handler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n            typealias InboundIn = Never\n            let identifier: String\n\n            init(identifier: String) {\n                self.identifier = identifier\n            }\n        }\n\n        let channel = await NIOAsyncTestingChannel(\n            handlers: [Handler(identifier: \"0\"), Handler(identifier: \"1\"), Handler(identifier: \"2\")]\n        )\n        XCTAssertNoThrow(XCTAssertEqual(try channel.pipeline.handler(type: Handler.self).wait().identifier, \"0\"))\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"handler0\").wait())\n\n        XCTAssertNoThrow(XCTAssertEqual(try channel.pipeline.handler(type: Handler.self).wait().identifier, \"1\"))\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"handler1\").wait())\n\n        XCTAssertNoThrow(XCTAssertEqual(try channel.pipeline.handler(type: Handler.self).wait().identifier, \"2\"))\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"handler2\").wait())\n    }\n\n    func testClosureInit() async throws {\n        final class Handler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n        }\n\n        let channel = try await NIOAsyncTestingChannel {\n            try $0.pipeline.syncOperations.addHandler(Handler())\n        }\n        XCTAssertNoThrow(try channel.pipeline.handler(type: Handler.self).wait())\n    }\n\n    func testWaitForInboundWrite() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let task = Task {\n            try await XCTAsyncAssertEqual(try await channel.waitForInboundWrite(), 1)\n            try await XCTAsyncAssertEqual(try await channel.waitForInboundWrite(), 2)\n            try await XCTAsyncAssertEqual(try await channel.waitForInboundWrite(), 3)\n        }\n\n        try await channel.writeInbound(1)\n        try await channel.writeInbound(2)\n        try await channel.writeInbound(3)\n        try await task.value\n    }\n\n    func testWaitForMultipleInboundWritesInParallel() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let task = Task {\n            let task1 = Task { try await channel.waitForInboundWrite(as: Int.self) }\n            let task2 = Task { try await channel.waitForInboundWrite(as: Int.self) }\n            let task3 = Task { try await channel.waitForInboundWrite(as: Int.self) }\n            try await XCTAsyncAssertEqual(\n                Set([\n                    try await task1.value,\n                    try await task2.value,\n                    try await task3.value,\n                ]),\n                [1, 2, 3]\n            )\n        }\n\n        try await channel.writeInbound(1)\n        try await channel.writeInbound(2)\n        try await channel.writeInbound(3)\n        try await task.value\n    }\n\n    func testWaitForOutboundWrite() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let task = Task {\n            try await XCTAsyncAssertEqual(try await channel.waitForOutboundWrite(), 1)\n            try await XCTAsyncAssertEqual(try await channel.waitForOutboundWrite(), 2)\n            try await XCTAsyncAssertEqual(try await channel.waitForOutboundWrite(), 3)\n        }\n\n        try await channel.writeOutbound(1)\n        try await channel.writeOutbound(2)\n        try await channel.writeOutbound(3)\n        try await task.value\n    }\n\n    func testWaitForMultipleOutboundWritesInParallel() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let task = Task {\n            let task1 = Task { try await channel.waitForOutboundWrite(as: Int.self) }\n            let task2 = Task { try await channel.waitForOutboundWrite(as: Int.self) }\n            let task3 = Task { try await channel.waitForOutboundWrite(as: Int.self) }\n            try await XCTAsyncAssertEqual(\n                Set([\n                    try await task1.value,\n                    try await task2.value,\n                    try await task3.value,\n                ]),\n                [1, 2, 3]\n            )\n        }\n\n        try await channel.writeOutbound(1)\n        try await channel.writeOutbound(2)\n        try await channel.writeOutbound(3)\n        try await task.value\n    }\n\n    func testWriteOutboundByteBuffer() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        let isFull = try await channel.writeOutbound(buf).isFull\n        XCTAssertTrue(isFull)\n\n        let hasLeftovers = try await channel.finish().hasLeftOvers\n        XCTAssertTrue(hasLeftovers)\n\n        let read = try await channel.readOutbound(as: ByteBuffer.self)\n        XCTAssertNoThrow(XCTAssertEqual(buf, read))\n\n        let nextOutboundRead = try await channel.readOutbound(as: ByteBuffer.self)\n        let nextInboundRead = try await channel.readInbound(as: ByteBuffer.self)\n        XCTAssertNoThrow(XCTAssertNil(nextOutboundRead))\n        XCTAssertNoThrow(XCTAssertNil(nextInboundRead))\n    }\n\n    func testWriteOutboundByteBufferMultipleTimes() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        try await XCTAsyncAssertTrue(await channel.writeOutbound(buf).isFull)\n        try await XCTAsyncAssertEqual(buf, await channel.readOutbound())\n        try await XCTAsyncAssertNil(await channel.readOutbound(as: ByteBuffer.self))\n        try await XCTAsyncAssertNil(await channel.readInbound(as: ByteBuffer.self))\n\n        var bufB = channel.allocator.buffer(capacity: 1024)\n        bufB.writeString(\"again\")\n\n        try await XCTAsyncAssertTrue(await channel.writeOutbound(bufB).isFull)\n        try await XCTAsyncAssertTrue(await channel.finish().hasLeftOvers)\n        try await XCTAsyncAssertEqual(bufB, await channel.readOutbound())\n        try await XCTAsyncAssertNil(await channel.readOutbound(as: ByteBuffer.self))\n        try await XCTAsyncAssertNil(await channel.readInbound(as: ByteBuffer.self))\n    }\n\n    func testWriteInboundByteBuffer() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        try await XCTAsyncAssertTrue(await channel.writeInbound(buf).isFull)\n        try await XCTAsyncAssertTrue(await channel.finish().hasLeftOvers)\n        try await XCTAsyncAssertEqual(buf, await channel.readInbound())\n        try await XCTAsyncAssertNil(await channel.readInbound(as: ByteBuffer.self))\n        try await XCTAsyncAssertNil(await channel.readOutbound(as: ByteBuffer.self))\n    }\n\n    func testWriteInboundByteBufferMultipleTimes() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        try await XCTAsyncAssertTrue(await channel.writeInbound(buf).isFull)\n        try await XCTAsyncAssertEqual(buf, await channel.readInbound())\n        try await XCTAsyncAssertNil(await channel.readInbound(as: ByteBuffer.self))\n        try await XCTAsyncAssertNil(await channel.readOutbound(as: ByteBuffer.self))\n\n        var bufB = channel.allocator.buffer(capacity: 1024)\n        bufB.writeString(\"again\")\n\n        try await XCTAsyncAssertTrue(await channel.writeInbound(bufB).isFull)\n        try await XCTAsyncAssertTrue(await channel.finish().hasLeftOvers)\n        try await XCTAsyncAssertEqual(bufB, await channel.readInbound())\n        try await XCTAsyncAssertNil(await channel.readInbound(as: ByteBuffer.self))\n        try await XCTAsyncAssertNil(await channel.readOutbound(as: ByteBuffer.self))\n    }\n\n    func testWriteInboundByteBufferReThrow() async throws {\n        let channel = NIOAsyncTestingChannel()\n        XCTAssertNoThrow(try channel.pipeline.addHandler(ExceptionThrowingInboundHandler()).wait())\n        await XCTAsyncAssertThrowsError(try await channel.writeInbound(\"msg\")) { error in\n            XCTAssertEqual(ChannelError.operationUnsupported, error as? ChannelError)\n        }\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n    }\n\n    func testWriteOutboundByteBufferReThrow() async throws {\n        let channel = NIOAsyncTestingChannel()\n        XCTAssertNoThrow(try channel.pipeline.addHandler(ExceptionThrowingOutboundHandler()).wait())\n        await XCTAsyncAssertThrowsError(try await channel.writeOutbound(\"msg\")) { error in\n            XCTAssertEqual(ChannelError.operationUnsupported, error as? ChannelError)\n        }\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n    }\n\n    func testReadOutboundWrongTypeThrows() async throws {\n        let channel = NIOAsyncTestingChannel()\n        try await XCTAsyncAssertTrue(await channel.writeOutbound(\"hello\").isFull)\n        do {\n            _ = try await channel.readOutbound(as: Int.self)\n            XCTFail()\n        } catch let error as NIOAsyncTestingChannel.WrongTypeError {\n            let expectedError = NIOAsyncTestingChannel.WrongTypeError(expected: Int.self, actual: String.self)\n            XCTAssertEqual(error, expectedError)\n        } catch {\n            XCTFail()\n        }\n    }\n\n    func testReadInboundWrongTypeThrows() async throws {\n        let channel = NIOAsyncTestingChannel()\n        try await XCTAsyncAssertTrue(await channel.writeInbound(\"hello\").isFull)\n        do {\n            _ = try await channel.readInbound(as: Int.self)\n            XCTFail()\n        } catch let error as NIOAsyncTestingChannel.WrongTypeError {\n            let expectedError = NIOAsyncTestingChannel.WrongTypeError(expected: Int.self, actual: String.self)\n            XCTAssertEqual(error, expectedError)\n        } catch {\n            XCTFail()\n        }\n    }\n\n    func testWrongTypesWithFastpathTypes() async throws {\n        let channel = NIOAsyncTestingChannel()\n\n        let buffer = channel.allocator.buffer(capacity: 0)\n\n        try await XCTAsyncAssertTrue(await channel.writeOutbound(buffer).isFull)\n        try await XCTAsyncAssertTrue(\n            await channel.writeOutbound(\n                AddressedEnvelope<ByteBuffer>(\n                    remoteAddress: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678),\n                    data: buffer\n                )\n            ).isFull\n        )\n        try await XCTAsyncAssertTrue(await channel.writeOutbound(buffer).isFull)\n\n        try await XCTAsyncAssertTrue(await channel.writeInbound(buffer).isFull)\n        try await XCTAsyncAssertTrue(\n            await channel.writeInbound(\n                AddressedEnvelope<ByteBuffer>(\n                    remoteAddress: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678),\n                    data: buffer\n                )\n            ).isFull\n        )\n        try await XCTAsyncAssertTrue(await channel.writeInbound(buffer).isFull)\n\n        func check<Expected: Sendable, Actual>(\n            expected: Expected.Type,\n            actual: Actual.Type,\n            file: StaticString = #filePath,\n            line: UInt = #line\n        ) async {\n            do {\n                _ = try await channel.readOutbound(as: Expected.self)\n                XCTFail(\"this should have failed\", file: (file), line: line)\n            } catch let error as NIOAsyncTestingChannel.WrongTypeError {\n                let expectedError = NIOAsyncTestingChannel.WrongTypeError(expected: Expected.self, actual: Actual.self)\n                XCTAssertEqual(error, expectedError, file: (file), line: line)\n            } catch {\n                XCTFail(\"unexpected error: \\(error)\", file: (file), line: line)\n            }\n\n            do {\n                _ = try await channel.readInbound(as: Expected.self)\n                XCTFail(\"this should have failed\", file: (file), line: line)\n            } catch let error as NIOAsyncTestingChannel.WrongTypeError {\n                let expectedError = NIOAsyncTestingChannel.WrongTypeError(expected: Expected.self, actual: Actual.self)\n                XCTAssertEqual(error, expectedError, file: (file), line: line)\n            } catch {\n                XCTFail(\"unexpected error: \\(error)\", file: (file), line: line)\n            }\n        }\n\n        await check(expected: Never.self, actual: IOData.self)\n        await check(expected: ByteBuffer.self, actual: AddressedEnvelope<ByteBuffer>.self)\n        await check(expected: AddressedEnvelope<ByteBuffer>.self, actual: IOData.self)\n    }\n\n    func testCloseMultipleTimesThrows() async throws {\n        let channel = NIOAsyncTestingChannel()\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n\n        // Close a second time. This must fail.\n        do {\n            try await channel.close()\n            XCTFail(\"Second close succeeded\")\n        } catch ChannelError.alreadyClosed {\n            // Nothing to do here.\n        }\n    }\n\n    func testCloseOnInactiveIsOk() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let inactiveHandler = CloseInChannelInactiveHandler()\n        XCTAssertNoThrow(try channel.pipeline.addHandler(inactiveHandler).wait())\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n\n        // channelInactive should fire only once.\n        XCTAssertEqual(inactiveHandler.inactiveNotifications.load(ordering: .sequentiallyConsistent), 1)\n    }\n\n    func testEmbeddedLifecycle() async throws {\n        let handler = ChannelLifecycleHandler()\n        XCTAssertEqual(handler.currentState, .unregistered)\n\n        let channel = await NIOAsyncTestingChannel(handler: handler)\n\n        XCTAssertEqual(handler.currentState, .registered)\n        XCTAssertFalse(channel.isActive)\n\n        XCTAssertNoThrow(try channel.connect(to: try SocketAddress(unixDomainSocketPath: \"/fake\")).wait())\n        XCTAssertEqual(handler.currentState, .active)\n        XCTAssertTrue(channel.isActive)\n\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n        XCTAssertEqual(handler.currentState, .unregistered)\n        XCTAssertFalse(channel.isActive)\n    }\n\n    private final class ExceptionThrowingInboundHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = String\n\n        public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            context.fireErrorCaught(ChannelError.operationUnsupported)\n        }\n    }\n\n    private final class ExceptionThrowingOutboundHandler: ChannelOutboundHandler, Sendable {\n        typealias OutboundIn = String\n        typealias OutboundOut = Never\n\n        public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n            promise!.fail(ChannelError.operationUnsupported)\n        }\n    }\n\n    private final class CloseInChannelInactiveHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = ByteBuffer\n        public let inactiveNotifications = ManagedAtomic(0)\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            inactiveNotifications.wrappingIncrement(by: 1, ordering: .sequentiallyConsistent)\n            context.close(promise: nil)\n        }\n    }\n\n    func testEmbeddedChannelAndPipelineAndChannelCoreShareTheEventLoop() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let pipelineEventLoop = channel.pipeline.eventLoop\n        XCTAssert(pipelineEventLoop === channel.eventLoop)\n        XCTAssert(pipelineEventLoop === (channel._channelCore as! EmbeddedChannelCore).eventLoop)\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n    }\n\n    func testSendingAnythingOnEmbeddedChannel() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let buffer = ByteBufferAllocator().buffer(capacity: 5)\n        let socketAddress = try SocketAddress(unixDomainSocketPath: \"path\")\n\n        try await channel.writeAndFlush(1)\n        try await channel.writeAndFlush(\"1\")\n        try await channel.writeAndFlush(buffer)\n        try await channel.writeAndFlush(AddressedEnvelope(remoteAddress: socketAddress, data: buffer))\n    }\n\n    func testActiveWhenConnectPromiseFiresAndInactiveWhenClosePromiseFires() async throws {\n        let channel = NIOAsyncTestingChannel()\n        XCTAssertFalse(channel.isActive)\n        let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n        connectPromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            XCTAssertTrue(channel.isActive)\n        }\n        channel.connect(to: try SocketAddress(ipAddress: \"127.0.0.1\", port: 0), promise: connectPromise)\n        try await connectPromise.futureResult.get()\n\n        let closePromise = channel.eventLoop.makePromise(of: Void.self)\n        closePromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            XCTAssertFalse(channel.isActive)\n        }\n\n        channel.close(promise: closePromise)\n        try await closePromise.futureResult.get()\n    }\n\n    func testWriteWithoutFlushDoesNotWrite() async throws {\n        let channel = NIOAsyncTestingChannel()\n\n        let buf = ByteBuffer(bytes: [1])\n        let writeFuture = channel.write(buf)\n        try await XCTAsyncAssertNil(await channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertFalse(writeFuture.isFulfilled)\n        channel.flush()\n        try await XCTAsyncAssertNotNil(await channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertTrue(writeFuture.isFulfilled)\n        try await XCTAsyncAssertTrue(await channel.finish().isClean)\n    }\n\n    func testSetLocalAddressAfterSuccessfulBind() throws {\n        let channel = NIOAsyncTestingChannel()\n        let bindPromise = channel.eventLoop.makePromise(of: Void.self)\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        channel.bind(to: socketAddress, promise: bindPromise)\n        bindPromise.futureResult.whenComplete { _ in\n            XCTAssertEqual(channel.localAddress, socketAddress)\n        }\n        try bindPromise.futureResult.wait()\n    }\n\n    func testSetLocalAddressAfterSuccessfulBindWithoutPromise() throws {\n        let channel = NIOAsyncTestingChannel()\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        // Call bind on-loop so we know when to expect the result\n        try channel.testingEventLoop.submit {\n            channel.bind(to: socketAddress, promise: nil)\n        }.wait()\n        XCTAssertEqual(channel.localAddress, socketAddress)\n    }\n\n    func testSetRemoteAddressAfterSuccessfulConnect() throws {\n        let channel = NIOAsyncTestingChannel()\n        let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        channel.connect(to: socketAddress, promise: connectPromise)\n        connectPromise.futureResult.whenComplete { _ in\n            XCTAssertEqual(channel.remoteAddress, socketAddress)\n        }\n        try connectPromise.futureResult.wait()\n    }\n\n    func testSetRemoteAddressAfterSuccessfulConnectWithoutPromise() throws {\n        let channel = NIOAsyncTestingChannel()\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        // Call connect on-loop so we know when to expect the result\n        try channel.testingEventLoop.submit {\n            channel.connect(to: socketAddress, promise: nil)\n        }.wait()\n        XCTAssertEqual(channel.remoteAddress, socketAddress)\n    }\n\n    func testUnprocessedOutboundUserEventFailsOnEmbeddedChannel() throws {\n\n        let channel = NIOAsyncTestingChannel()\n        XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"event\").wait()) { (error: Error) in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.operationUnsupported, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n\n    }\n\n    func testEmbeddedChannelWritabilityIsWritable() throws {\n\n        let channel = NIOAsyncTestingChannel()\n        let opaqueChannel: Channel = channel\n        XCTAssertTrue(channel.isWritable)\n        XCTAssertTrue(opaqueChannel.isWritable)\n        channel.isWritable = false\n        XCTAssertFalse(channel.isWritable)\n        XCTAssertFalse(opaqueChannel.isWritable)\n\n    }\n\n    func testFinishWithRecursivelyScheduledTasks() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let invocations = AtomicCounter()\n\n        @Sendable func recursivelyScheduleAndIncrement() {\n            channel.pipeline.eventLoop.scheduleTask(deadline: .distantFuture) {\n                invocations.increment()\n                recursivelyScheduleAndIncrement()\n            }\n        }\n\n        recursivelyScheduleAndIncrement()\n\n        _ = try await channel.finish()\n        XCTAssertEqual(invocations.load(), 1)\n    }\n\n    func testSyncOptionsAreSupported() throws {\n        let channel = NIOAsyncTestingChannel()\n        try channel.testingEventLoop.submit {\n            let options = channel.syncOptions\n            XCTAssertNotNil(options)\n            // Unconditionally returns true.\n            XCTAssertEqual(try options?.getOption(.autoRead), true)\n            // (Setting options isn't supported.)\n        }.wait()\n    }\n\n    func testGetChannelOptionAutoReadIsSupported() throws {\n        let channel = NIOAsyncTestingChannel()\n        try channel.testingEventLoop.submit {\n            let options = channel.syncOptions\n            XCTAssertNotNil(options)\n            // Unconditionally returns true.\n            XCTAssertEqual(try options?.getOption(.autoRead), true)\n        }.wait()\n    }\n\n    func testSetGetChannelOptionAllowRemoteHalfClosureIsSupported() throws {\n        let channel = NIOAsyncTestingChannel()\n        try channel.testingEventLoop.submit {\n            let options = channel.syncOptions\n            XCTAssertNotNil(options)\n\n            // allowRemoteHalfClosure should be false by default\n            XCTAssertEqual(try options?.getOption(.allowRemoteHalfClosure), false)\n\n            channel.allowRemoteHalfClosure = true\n            XCTAssertEqual(try options?.getOption(.allowRemoteHalfClosure), true)\n\n            XCTAssertNoThrow(try options?.setOption(.allowRemoteHalfClosure, value: false))\n            XCTAssertEqual(try options?.getOption(.allowRemoteHalfClosure), false)\n        }.wait()\n    }\n\n    func testSecondFinishThrows() async throws {\n        let channel = NIOAsyncTestingChannel()\n        _ = try await channel.finish()\n        await XCTAsyncAssertThrowsError(try await channel.finish())\n    }\n\n    func testWriteOutboundEmptyBufferedByte() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buffered: ChannelOptions.Types.BufferedWritableBytesOption.Value = try await channel.getOption(\n            .bufferedWritableBytes\n        )\n        XCTAssertEqual(0, buffered)\n\n        let buf = channel.allocator.buffer(capacity: 10)\n\n        channel.write(buf, promise: nil)\n        buffered = try await channel.getOption(.bufferedWritableBytes)\n        XCTAssertEqual(0, buffered)\n\n        channel.flush()\n        buffered = try await channel.getOption(.bufferedWritableBytes)\n        XCTAssertEqual(0, buffered)\n\n        try await XCTAsyncAssertEqual(buf, try await channel.waitForOutboundWrite(as: ByteBuffer.self))\n        try await XCTAsyncAssertTrue(try await channel.finish().isClean)\n    }\n\n    func testWriteOutboundBufferedBytesSingleWrite() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n\n        channel.write(buf, promise: nil)\n        var buffered: ChannelOptions.Types.BufferedWritableBytesOption.Value = try await channel.getOption(\n            .bufferedWritableBytes\n        )\n        XCTAssertEqual(buf.readableBytes, buffered)\n        channel.flush()\n\n        buffered = try await channel.getOption(.bufferedWritableBytes).get()\n        XCTAssertEqual(0, buffered)\n        try await XCTAsyncAssertEqual(buf, try await channel.waitForOutboundWrite(as: ByteBuffer.self))\n        try await XCTAsyncAssertTrue(try await channel.finish().isClean)\n    }\n\n    func testWriteOuboundBufferedBytesMultipleWrites() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n        let totalCount = 5\n        for _ in 0..<totalCount {\n            channel.write(buf, promise: nil)\n        }\n        var buffered: ChannelOptions.Types.BufferedWritableBytesOption.Value = try await channel.getOption(\n            .bufferedWritableBytes\n        )\n        XCTAssertEqual(buf.readableBytes * totalCount, buffered)\n\n        channel.flush()\n        buffered = try await channel.getOption(.bufferedWritableBytes)\n        XCTAssertEqual(0, buffered)\n\n        for _ in 0..<totalCount {\n            try await XCTAsyncAssertEqual(buf, try await channel.waitForOutboundWrite(as: ByteBuffer.self))\n        }\n\n        try await XCTAsyncAssertTrue(try await channel.finish().isClean)\n    }\n\n    func testWriteOuboundBufferedBytesWriteAndFlushInterleaved() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n\n        channel.write(buf, promise: nil)\n        channel.write(buf, promise: nil)\n        channel.write(buf, promise: nil)\n        var buffered: ChannelOptions.Types.BufferedWritableBytesOption.Value = try await channel.getOption(\n            .bufferedWritableBytes\n        )\n        XCTAssertEqual(buf.readableBytes * 3, buffered)\n\n        channel.flush()\n        buffered = try await channel.getOption(.bufferedWritableBytes)\n        XCTAssertEqual(0, buffered)\n\n        channel.write(buf, promise: nil)\n        channel.write(buf, promise: nil)\n        buffered = try await channel.getOption(.bufferedWritableBytes)\n        XCTAssertEqual(buf.readableBytes * 2, buffered)\n        channel.flush()\n        buffered = try await channel.getOption(.bufferedWritableBytes)\n        XCTAssertEqual(0, buffered)\n\n        for _ in 0..<5 {\n            try await XCTAsyncAssertEqual(buf, try await channel.waitForOutboundWrite(as: ByteBuffer.self))\n        }\n\n        try await XCTAsyncAssertTrue(try await channel.finish().isClean)\n    }\n\n    func testWriteOutboundBufferedBytesWriteAndFlush() async throws {\n        let channel = NIOAsyncTestingChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n\n        try await XCTAsyncAssertTrue(await channel.writeOutbound(buf).isFull)\n        let buffered: ChannelOptions.Types.BufferedWritableBytesOption.Value = try await channel.getOption(\n            .bufferedWritableBytes\n        )\n        XCTAssertEqual(0, buffered)\n\n        try await XCTAsyncAssertEqual(buf, try await channel.waitForOutboundWrite(as: ByteBuffer.self))\n        try await XCTAsyncAssertTrue(try await channel.finish().isClean)\n    }\n\n    func testWaitingForWriteTerminatesAfterChannelClose() async throws {\n        let channel = NIOAsyncTestingChannel()\n\n        // Write some inbound and outbound data\n        for i in 1...3 {\n            try await channel.writeInbound(i)\n            try await channel.writeOutbound(i)\n        }\n\n        // We should successfully see the three inbound and outbound writes\n        for i in 1...3 {\n            try await XCTAsyncAssertEqual(try await channel.waitForInboundWrite(), i)\n            try await XCTAsyncAssertEqual(try await channel.waitForOutboundWrite(), i)\n        }\n\n        let task = Task {\n            // We close the channel after the third inbound/outbound write. Waiting again should result in a\n            // `ChannelError.ioOnClosedChannel` error.\n            await XCTAsyncAssertThrowsError(try await channel.waitForInboundWrite(as: Int.self)) {\n                XCTAssertEqual($0 as? ChannelError, ChannelError.ioOnClosedChannel)\n            }\n            await XCTAsyncAssertThrowsError(try await channel.waitForOutboundWrite(as: Int.self)) {\n                XCTAssertEqual($0 as? ChannelError, ChannelError.ioOnClosedChannel)\n            }\n        }\n\n        // Close the channel without performing any writes\n        try await channel.close()\n        try await task.value\n    }\n\n    func testEnqueueWriteConsumersBeforeChannelClosesWithoutAnyWrites() async throws {\n        let channel = NIOAsyncTestingChannel()\n\n        let task = Task {\n            // We don't write anything to the channel and simply just close it. Waiting for an inbound/outbound write\n            // should result in a `ChannelError.ioOnClosedChannel` when the channel closes.\n            await XCTAsyncAssertThrowsError(try await channel.waitForInboundWrite(as: Int.self)) {\n                XCTAssertEqual($0 as? ChannelError, ChannelError.ioOnClosedChannel)\n            }\n            await XCTAsyncAssertThrowsError(try await channel.waitForOutboundWrite(as: Int.self)) {\n                XCTAssertEqual($0 as? ChannelError, ChannelError.ioOnClosedChannel)\n            }\n        }\n\n        // Close the channel without performing any inbound or outbound writes\n        try await channel.close()\n        try await task.value\n    }\n\n    func testEnqueueWriteConsumersAfterChannelClosesWithoutAnyWrites() async throws {\n        let channel = NIOAsyncTestingChannel()\n        // Immediately close the channel without performing any inbound or outbound writes\n        try await channel.close()\n\n        // Now try to wait for an inbound/outbound write. This should result in a `ChannelError.ioOnClosedChannel`.\n        await XCTAsyncAssertThrowsError(try await channel.waitForInboundWrite(as: Int.self)) {\n            XCTAssertEqual($0 as? ChannelError, ChannelError.ioOnClosedChannel)\n        }\n        await XCTAsyncAssertThrowsError(try await channel.waitForOutboundWrite(as: Int.self)) {\n            XCTAssertEqual($0 as? ChannelError, ChannelError.ioOnClosedChannel)\n        }\n    }\n\n    func testGetSetOption() async throws {\n        let channel = NIOAsyncTestingChannel()\n        let option = ChannelOptions.socket(IPPROTO_IP, IP_TTL)\n        let _ = try await channel.setOption(option, value: 1).get()\n\n        let optionValue1 = try await channel.getOption(option).get()\n        XCTAssertEqual(1, optionValue1)\n\n        let _ = try await channel.setOption(option, value: 2).get()\n        let optionValue2 = try await channel.getOption(option).get()\n        XCTAssertEqual(2, optionValue2)\n    }\n\n    func testSocketAddressesOnContext() async throws {\n        final class Handler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                XCTAssertNotNil(context.localAddress)\n                XCTAssertNotNil(context.remoteAddress)\n            }\n        }\n\n        let channel = NIOAsyncTestingChannel()\n        channel.localAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 8080)\n        channel.remoteAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 9090)\n\n        try await channel.pipeline.addHandler(Handler())\n\n        XCTAssertNoThrow(try channel.pipeline.handler(type: Handler.self).wait())\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertTrue(\n    _ predicate: @autoclosure () async throws -> Bool,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let result = try await predicate()\n    XCTAssertTrue(result, file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertEqual<Element: Equatable>(\n    _ lhs: @autoclosure () async throws -> Element,\n    _ rhs: @autoclosure () async throws -> Element,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let lhsResult = try await lhs()\n    let rhsResult = try await rhs()\n    XCTAssertEqual(lhsResult, rhsResult, file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertThrowsError<ResultType>(\n    _ expression: @autoclosure () async throws -> ResultType,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ callback: ((Error) -> Void)? = nil\n) async {\n    do {\n        let _ = try await expression()\n        XCTFail(\"Did not throw\", file: file, line: line)\n    } catch {\n        callback?(error)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertNil(\n    _ expression: @autoclosure () async throws -> Any?,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let result = try await expression()\n    XCTAssertNil(result, file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertNotNil(\n    _ expression: @autoclosure () async throws -> Any?,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let result = try await expression()\n    XCTAssertNotNil(result, file: file, line: line)\n}\n\n/// A simple atomic counter.\nfinal class AtomicCounter: @unchecked Sendable {\n    // This class has to be `@unchecked Sendable` because ManagedAtomic\n    // is not sendable.\n    private let baseCounter = ManagedAtomic(0)\n\n    func increment() {\n        self.baseCounter.wrappingIncrement(ordering: .relaxed)\n    }\n\n    func load() -> Int {\n        self.baseCounter.load(ordering: .relaxed)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOEmbeddedTests/AsyncTestingEventLoopTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOEmbedded\n\nprivate final class EmbeddedTestError: Error {}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class NIOAsyncTestingEventLoopTests: XCTestCase {\n    func testExecuteDoesNotImmediatelyRunTasks() async throws {\n        let callbackRan = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        try await loop.executeInContext {\n            loop.execute { callbackRan.store(true, ordering: .relaxed) }\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n        await loop.run()\n        XCTAssertTrue(callbackRan.load(ordering: .relaxed))\n    }\n\n    func testExecuteWillRunAllTasks() async throws {\n        let runCount = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n        loop.execute { runCount.wrappingIncrement(ordering: .relaxed) }\n        loop.execute { runCount.wrappingIncrement(ordering: .relaxed) }\n        loop.execute { runCount.wrappingIncrement(ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertEqual(runCount.load(ordering: .relaxed), 3)\n        }\n        await loop.run()\n        try await loop.executeInContext {\n            XCTAssertEqual(runCount.load(ordering: .relaxed), 3)\n        }\n    }\n\n    func testExecuteWillRunTasksAddedRecursively() async throws {\n        let sentinel = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n\n        loop.execute {\n            // This should execute first.\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 0)\n            sentinel.store(1, ordering: .relaxed)\n            loop.execute {\n                // This should execute second\n                let loaded = sentinel.loadThenWrappingIncrement(ordering: .relaxed)\n                XCTAssertEqual(loaded, 1)\n            }\n        }\n        loop.execute {\n            // This should execute third\n            let loaded = sentinel.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(loaded, 2)\n        }\n\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 3)\n        }\n        await loop.run()\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 3)\n        }\n    }\n\n    func testExecuteRunsImmediately() async throws {\n        let callbackRan = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        loop.execute { callbackRan.store(true, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertTrue(callbackRan.load(ordering: .relaxed))\n        }\n        loop.execute { callbackRan.store(false, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n    }\n\n    func testTasksScheduledAfterRunDontRun() async throws {\n        let callbackRan = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        loop.scheduleTask(deadline: loop.now) { callbackRan.store(true, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n        await loop.run()\n        loop.scheduleTask(deadline: loop.now) { callbackRan.store(false, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertTrue(callbackRan.load(ordering: .relaxed))\n        }\n        await loop.run()\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n    }\n\n    func testSubmitRunsImmediately() async throws {\n        let callbackRan = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        _ = loop.submit { callbackRan.store(true, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertTrue(callbackRan.load(ordering: .relaxed))\n        }\n        _ = loop.submit { callbackRan.store(false, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n    }\n\n    func testSyncShutdownGracefullyRunsTasks() async throws {\n        let callbackRan = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        loop.scheduleTask(deadline: loop.now) { callbackRan.store(true, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n        XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        try await loop.executeInContext {\n            XCTAssertTrue(callbackRan.load(ordering: .relaxed))\n        }\n    }\n\n    func testShutdownGracefullyRunsTasks() async throws {\n        let callbackRan = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        loop.scheduleTask(deadline: loop.now) { callbackRan.store(true, ordering: .relaxed) }\n\n        try await loop.executeInContext {\n            XCTAssertFalse(callbackRan.load(ordering: .relaxed))\n        }\n        await loop.shutdownGracefully()\n        try await loop.executeInContext {\n            XCTAssertTrue(callbackRan.load(ordering: .relaxed))\n        }\n    }\n\n    func testCanControlTime() async throws {\n        let callbackCount = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            callbackCount.loadThenWrappingIncrement(ordering: .relaxed)\n        }\n\n        try await loop.executeInContext {\n            XCTAssertEqual(callbackCount.load(ordering: .relaxed), 0)\n        }\n        await loop.advanceTime(by: .nanoseconds(4))\n        try await loop.executeInContext {\n            XCTAssertEqual(callbackCount.load(ordering: .relaxed), 0)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(callbackCount.load(ordering: .relaxed), 1)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(callbackCount.load(ordering: .relaxed), 1)\n        }\n        await loop.advanceTime(by: .hours(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(callbackCount.load(ordering: .relaxed), 1)\n        }\n    }\n\n    func testCanScheduleMultipleTasks() async throws {\n        let sentinel = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n        for index in 1...10 {\n            _ = loop.scheduleTask(in: .nanoseconds(Int64(index))) {\n                sentinel.store(index, ordering: .relaxed)\n            }\n        }\n\n        for val in 1...10 {\n            try await loop.executeInContext {\n                XCTAssertEqual(sentinel.load(ordering: .relaxed), val - 1)\n            }\n            await loop.advanceTime(by: .nanoseconds(1))\n            try await loop.executeInContext {\n                XCTAssertEqual(sentinel.load(ordering: .relaxed), val)\n            }\n        }\n    }\n\n    func testExecutedTasksFromScheduledOnesAreRun() async throws {\n        let sentinel = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            sentinel.store(1, ordering: .relaxed)\n            loop.execute {\n                sentinel.store(2, ordering: .relaxed)\n            }\n        }\n\n        await loop.advanceTime(by: .nanoseconds(4))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 0)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 2)\n        }\n    }\n\n    func testScheduledTasksFromScheduledTasksProperlySchedule() async throws {\n        let sentinel = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            sentinel.store(1, ordering: .relaxed)\n            _ = loop.scheduleTask(in: .nanoseconds(3)) {\n                sentinel.store(2, ordering: .relaxed)\n            }\n            _ = loop.scheduleTask(in: .nanoseconds(5)) {\n                sentinel.store(3, ordering: .relaxed)\n            }\n        }\n\n        await loop.advanceTime(by: .nanoseconds(4))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 0)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 1)\n        }\n        await loop.advanceTime(by: .nanoseconds(2))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 1)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 2)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 2)\n        }\n        await loop.advanceTime(by: .nanoseconds(1))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 3)\n        }\n    }\n\n    func testScheduledTasksFromExecutedTasks() async throws {\n        let sentinel = ManagedAtomic(0)\n        let loop = NIOAsyncTestingEventLoop()\n        loop.execute {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 0)\n            _ = loop.scheduleTask(in: .nanoseconds(5)) {\n                XCTAssertEqual(sentinel.load(ordering: .relaxed), 1)\n                sentinel.store(2, ordering: .relaxed)\n            }\n            loop.execute { sentinel.store(1, ordering: .relaxed) }\n        }\n\n        await loop.advanceTime(by: .nanoseconds(5))\n        try await loop.executeInContext {\n            XCTAssertEqual(sentinel.load(ordering: .relaxed), 2)\n        }\n    }\n\n    func testCancellingScheduledTasks() async throws {\n        let loop = NIOAsyncTestingEventLoop()\n        let task = loop.scheduleTask(in: .nanoseconds(10), { XCTFail(\"Cancelled task ran\") })\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            task.cancel()\n        }\n\n        await loop.advanceTime(by: .nanoseconds(20))\n    }\n\n    func testScheduledTasksFuturesFire() async throws {\n        let fired = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        let task = loop.scheduleTask(in: .nanoseconds(5)) { true }\n        task.futureResult.whenSuccess { fired.store($0, ordering: .relaxed) }\n\n        await loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertFalse(fired.load(ordering: .relaxed))\n        await loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertTrue(fired.load(ordering: .relaxed))\n    }\n\n    func testScheduledTasksFuturesError() async throws {\n        let err = EmbeddedTestError()\n        let fired = ManagedAtomic(false)\n        let loop = NIOAsyncTestingEventLoop()\n        let task = loop.scheduleTask(in: .nanoseconds(5)) {\n            throw err\n        }\n        task.futureResult.map {\n            XCTFail(\"Scheduled future completed\")\n        }.recover { caughtErr in\n            XCTAssertTrue(err === caughtErr as? EmbeddedTestError)\n        }.whenComplete { (_: Result<Void, Error>) in\n            fired.store(true, ordering: .relaxed)\n        }\n\n        await loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertFalse(fired.load(ordering: .relaxed))\n        await loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertTrue(fired.load(ordering: .relaxed))\n    }\n\n    func testTaskOrdering() async throws {\n        // This test validates that the ordering of task firing on NIOAsyncTestingEventLoop via\n        // advanceTime(by:) is the same as on MultiThreadedEventLoopGroup: specifically, that tasks run via\n        // schedule that expire \"now\" all run at the same time, and that any work they schedule is run\n        // after all such tasks expire.\n        struct TestState {\n            var firstScheduled: Scheduled<Void>?\n            var secondScheduled: Scheduled<Void>?\n        }\n        let loop = NIOAsyncTestingEventLoop()\n        let lock = NIOLockedValueBox(TestState())\n        let orderingCounter = ManagedAtomic(0)\n\n        // Here's the setup. First, we'll set up two scheduled tasks to fire in 5 nanoseconds. Each of these\n        // will attempt to cancel the other, but the first one scheduled will fire first. Additionally, each will execute{} a single\n        // callback. Then we'll execute {} one other callback. Finally we'll schedule a task for 10ns, before\n        // we advance time. The ordering should be as follows:\n        //\n        // 1. The task executed by execute {} from this function.\n        // 2. The first scheduled task.\n        // 3. The second scheduled task  (note that the cancellation will fail).\n        // 4. The execute {} callback from the first scheduled task.\n        // 5. The execute {} callbacks from the second scheduled task.\n        // 6. The 10ns task.\n        //\n        // To validate the ordering, we'll use a counter.\n\n        lock.withLockedValue {\n            $0.firstScheduled = loop.scheduleTask(in: .nanoseconds(5)) {\n                let second = lock.withLockedValue {\n                    XCTAssertNotNil($0.firstScheduled)\n                    $0.firstScheduled = nil\n                    XCTAssertNotNil($0.secondScheduled)\n                    return $0.secondScheduled\n                }\n\n                if let partner = second {\n                    // Ok, this callback fired first. Cancel the other.\n                    partner.cancel()\n                } else {\n                    XCTFail(\"First callback executed second\")\n                }\n\n                XCTAssertCompareAndSwapSucceeds(storage: orderingCounter, expected: 1, desired: 2)\n\n                loop.execute {\n                    XCTAssertCompareAndSwapSucceeds(storage: orderingCounter, expected: 3, desired: 4)\n                }\n            }\n\n            $0.secondScheduled = loop.scheduleTask(in: .nanoseconds(5)) {\n                lock.withLockedValue {\n                    $0.secondScheduled = nil\n                    XCTAssertNil($0.firstScheduled)\n                    XCTAssertNil($0.secondScheduled)\n                }\n\n                XCTAssertCompareAndSwapSucceeds(storage: orderingCounter, expected: 2, desired: 3)\n\n                loop.execute {\n                    XCTAssertCompareAndSwapSucceeds(storage: orderingCounter, expected: 4, desired: 5)\n                }\n            }\n        }\n\n        // Ok, now we set one more task to execute.\n        loop.execute {\n            XCTAssertCompareAndSwapSucceeds(storage: orderingCounter, expected: 0, desired: 1)\n        }\n\n        // Finally schedule a task for 10ns.\n        _ = loop.scheduleTask(in: .nanoseconds(10)) {\n            XCTAssertCompareAndSwapSucceeds(storage: orderingCounter, expected: 5, desired: 6)\n        }\n\n        // Now we advance time by 10ns.\n        await loop.advanceTime(by: .nanoseconds(10))\n\n        // Now the final value should be 6.\n        XCTAssertEqual(orderingCounter.load(ordering: .relaxed), 6)\n    }\n\n    func testCancelledScheduledTasksDoNotHoldOnToRunClosure() async throws {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        defer {\n            XCTAssertNoThrow(try eventLoop.syncShutdownGracefully())\n        }\n\n        class Thing: @unchecked Sendable {\n            private let deallocated: ConditionLock<Int>\n\n            init(_ deallocated: ConditionLock<Int>) {\n                self.deallocated = deallocated\n            }\n\n            deinit {\n                self.deallocated.lock()\n                self.deallocated.unlock(withValue: 1)\n            }\n        }\n\n        func make(deallocated: ConditionLock<Int>) -> Scheduled<Never> {\n            let aThing = Thing(deallocated)\n            return eventLoop.next().scheduleTask(in: .hours(1)) {\n                preconditionFailure(\"this should definitely not run: \\(aThing)\")\n            }\n        }\n\n        let deallocated = ConditionLock(value: 0)\n        let scheduled = make(deallocated: deallocated)\n        scheduled.cancel()\n        if deallocated.lock(whenValue: 1, timeoutSeconds: 60) {\n            deallocated.unlock()\n        } else {\n            XCTFail(\"Timed out waiting for lock\")\n        }\n        await XCTAssertThrowsError(try await scheduled.futureResult.get()) { error in\n            XCTAssertEqual(EventLoopError.cancelled, error as? EventLoopError)\n        }\n    }\n\n    func testShutdownCancelsFutureScheduledTasks() async {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        let tasksRun = ManagedAtomic(0)\n\n        let a = eventLoop.scheduleTask(in: .seconds(1)) { tasksRun.wrappingIncrement(ordering: .relaxed) }\n        let b = eventLoop.scheduleTask(in: .seconds(2)) { tasksRun.wrappingIncrement(ordering: .relaxed) }\n\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 0)\n\n        await eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n\n        XCTAssertNoThrow(try eventLoop.syncShutdownGracefully())\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n\n        await eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n\n        await eventLoop.advanceTime(to: .distantFuture)\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n\n        XCTAssertNoThrow(try a.futureResult.wait())\n        await XCTAssertThrowsError(try await b.futureResult.get()) { error in\n            XCTAssertEqual(error as? EventLoopError, .cancelled)\n            XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n        }\n    }\n\n    func testTasksScheduledDuringShutdownAreAutomaticallyCancelledOrNotScheduled() async throws {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        let tasksRun = ManagedAtomic(0)\n\n        @Sendable\n        func scheduleRecursiveTask(\n            at taskStartTime: NIODeadline,\n            andChildTaskAfter childTaskStartDelay: TimeAmount\n        ) -> Scheduled<Void> {\n            eventLoop.scheduleTask(deadline: taskStartTime) {\n                tasksRun.wrappingIncrement(ordering: .releasing)\n                _ = scheduleRecursiveTask(\n                    at: eventLoop.now + childTaskStartDelay,\n                    andChildTaskAfter: childTaskStartDelay\n                )\n            }\n        }\n\n        _ = scheduleRecursiveTask(at: .uptimeNanoseconds(1), andChildTaskAfter: .zero)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                try await Task.sleep(nanoseconds: 10_000_000)\n                await eventLoop.shutdownGracefully()\n            }\n\n            await eventLoop.advanceTime(to: .uptimeNanoseconds(1))\n            try await group.waitForAll()\n        }\n\n        try await eventLoop.executeInContext {\n            XCTAssertGreaterThan(tasksRun.load(ordering: .acquiring), 0)\n        }\n    }\n\n    func testShutdownCancelsRemainingScheduledTasks() async {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        let tasksRun = ManagedAtomic(0)\n\n        let a = eventLoop.scheduleTask(in: .seconds(1)) {\n            tasksRun.wrappingIncrement(ordering: .sequentiallyConsistent)\n        }\n        let b = eventLoop.scheduleTask(in: .seconds(2)) {\n            tasksRun.wrappingIncrement(ordering: .sequentiallyConsistent)\n        }\n\n        XCTAssertEqual(tasksRun.load(ordering: .sequentiallyConsistent), 0)\n\n        await eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(tasksRun.load(ordering: .sequentiallyConsistent), 1)\n\n        XCTAssertNoThrow(try eventLoop.syncShutdownGracefully())\n        XCTAssertEqual(tasksRun.load(ordering: .sequentiallyConsistent), 1)\n\n        await eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(tasksRun.load(ordering: .sequentiallyConsistent), 1)\n\n        await eventLoop.advanceTime(to: .distantFuture)\n        XCTAssertEqual(tasksRun.load(ordering: .sequentiallyConsistent), 1)\n\n        XCTAssertNoThrow(try a.futureResult.wait())\n        await XCTAssertThrowsError(try await b.futureResult.get()) { error in\n            XCTAssertEqual(error as? EventLoopError, .cancelled)\n            XCTAssertEqual(tasksRun.load(ordering: .sequentiallyConsistent), 1)\n        }\n    }\n\n    func testAdvanceTimeToDeadline() async throws {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        let deadline = NIODeadline.uptimeNanoseconds(0) + .seconds(42)\n\n        let tasksRun = ManagedAtomic(0)\n        eventLoop.scheduleTask(deadline: deadline) {\n            tasksRun.loadThenWrappingIncrement(ordering: .relaxed)\n        }\n\n        await eventLoop.advanceTime(to: deadline)\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n    }\n\n    func testWeCantTimeTravelByAdvancingTimeToThePast() async throws {\n        let eventLoop = NIOAsyncTestingEventLoop()\n\n        let tasksRun = ManagedAtomic(0)\n        eventLoop.scheduleTask(deadline: .uptimeNanoseconds(0) + .seconds(42)) {\n            tasksRun.loadThenWrappingIncrement(ordering: .relaxed)\n        }\n\n        // t=40s\n        await eventLoop.advanceTime(to: .uptimeNanoseconds(0) + .seconds(40))\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 0)\n\n        // t=40s (still)\n        await eventLoop.advanceTime(to: .distantPast)\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 0)\n\n        // t=42s\n        await eventLoop.advanceTime(by: .seconds(2))\n        XCTAssertEqual(tasksRun.load(ordering: .relaxed), 1)\n    }\n\n    func testExecuteInOrder() async throws {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        let counter = ManagedAtomic(0)\n\n        eventLoop.execute {\n            let original = counter.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(original, 0)\n        }\n\n        eventLoop.execute {\n            let original = counter.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(original, 1)\n        }\n\n        eventLoop.execute {\n            let original = counter.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(original, 2)\n        }\n\n        await eventLoop.run()\n        XCTAssertEqual(counter.load(ordering: .relaxed), 3)\n    }\n\n    func testScheduledTasksInOrder() async throws {\n        let eventLoop = NIOAsyncTestingEventLoop()\n        let counter = ManagedAtomic(0)\n\n        eventLoop.scheduleTask(in: .seconds(1)) {\n            let original = counter.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(original, 1)\n        }\n\n        eventLoop.scheduleTask(in: .milliseconds(1)) {\n            let original = counter.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(original, 0)\n        }\n\n        eventLoop.scheduleTask(in: .seconds(1)) {\n            let original = counter.loadThenWrappingIncrement(ordering: .relaxed)\n            XCTAssertEqual(original, 2)\n        }\n\n        await eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(counter.load(ordering: .relaxed), 3)\n    }\n\n    func testCurrentTime() async {\n        let eventLoop = NIOAsyncTestingEventLoop()\n\n        await eventLoop.advanceTime(to: .uptimeNanoseconds(42))\n        XCTAssertEqual(eventLoop.now, .uptimeNanoseconds(42))\n\n        await eventLoop.advanceTime(by: .nanoseconds(42))\n        XCTAssertEqual(eventLoop.now, .uptimeNanoseconds(84))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOEmbeddedTests/EmbeddedChannelTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOEmbedded\n\n#if canImport(Android)\nimport Android\n#endif\n\nfinal class ChannelLifecycleHandler: ChannelInboundHandler, Sendable {\n    public typealias InboundIn = Any\n\n    public enum ChannelState {\n        case unregistered\n        case registered\n        case inactive\n        case active\n    }\n\n    public var currentState: ChannelState {\n        get {\n            self._state.withLockedValue { $0.currentState }\n        }\n    }\n    public var stateHistory: [ChannelState] {\n        get {\n            self._state.withLockedValue { $0.stateHistory }\n        }\n    }\n\n    private let _state: NIOLockedValueBox<(currentState: ChannelState, stateHistory: [ChannelState])>\n\n    public init() {\n        self._state = NIOLockedValueBox((currentState: .unregistered, stateHistory: [.unregistered]))\n    }\n\n    private func updateState(_ state: ChannelState) {\n        self._state.withLockedValue {\n            $0.currentState = state\n            $0.stateHistory.append(state)\n        }\n    }\n\n    public func channelRegistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .unregistered)\n        XCTAssertFalse(context.channel.isActive)\n        updateState(.registered)\n        context.fireChannelRegistered()\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .registered)\n        XCTAssertTrue(context.channel.isActive)\n        updateState(.active)\n        context.fireChannelActive()\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .active)\n        XCTAssertFalse(context.channel.isActive)\n        updateState(.inactive)\n        context.fireChannelInactive()\n    }\n\n    public func channelUnregistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .inactive)\n        XCTAssertFalse(context.channel.isActive)\n        updateState(.unregistered)\n        context.fireChannelUnregistered()\n    }\n}\n\nclass EmbeddedChannelTest: XCTestCase {\n\n    func testSingleHandlerInit() {\n        class Handler: ChannelInboundHandler {\n            typealias InboundIn = Never\n        }\n\n        let channel = EmbeddedChannel(handler: Handler())\n        XCTAssertNoThrow(try channel.pipeline.handler(type: Handler.self).map { _ in }.wait())\n    }\n\n    func testSingleHandlerInitNil() {\n        class Handler: ChannelInboundHandler {\n            typealias InboundIn = Never\n        }\n\n        let channel = EmbeddedChannel(handler: nil)\n        XCTAssertThrowsError(try channel.pipeline.handler(type: Handler.self).map { _ in }.wait()) { e in\n            XCTAssertEqual(e as? ChannelPipelineError, .notFound)\n        }\n    }\n\n    func testMultipleHandlerInit() {\n        class Handler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n            let identifier: String\n\n            init(identifier: String) {\n                self.identifier = identifier\n            }\n        }\n\n        let channel = EmbeddedChannel(\n            handlers: [Handler(identifier: \"0\"), Handler(identifier: \"1\"), Handler(identifier: \"2\")]\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(try channel.pipeline.handler(type: Handler.self).map { $0.identifier }.wait(), \"0\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"handler0\").wait())\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(try channel.pipeline.handler(type: Handler.self).map { $0.identifier }.wait(), \"1\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"handler1\").wait())\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(try channel.pipeline.handler(type: Handler.self).map { $0.identifier }.wait(), \"2\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"handler2\").wait())\n    }\n\n    func testWriteOutboundByteBuffer() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        XCTAssertTrue(try channel.writeOutbound(buf).isFull)\n        XCTAssertTrue(try channel.finish().hasLeftOvers)\n        XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testWriteOutboundByteBufferMultipleTimes() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        XCTAssertTrue(try channel.writeOutbound(buf).isFull)\n        XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        var bufB = channel.allocator.buffer(capacity: 1024)\n        bufB.writeString(\"again\")\n\n        XCTAssertTrue(try channel.writeOutbound(bufB).isFull)\n        XCTAssertTrue(try channel.finish().hasLeftOvers)\n        XCTAssertNoThrow(XCTAssertEqual(bufB, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testWriteInboundByteBuffer() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        XCTAssertTrue(try channel.writeInbound(buf).isFull)\n        XCTAssertTrue(try channel.finish().hasLeftOvers)\n        XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n    }\n\n    func testWriteInboundByteBufferMultipleTimes() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        XCTAssertTrue(try channel.writeInbound(buf).isFull)\n        XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n\n        var bufB = channel.allocator.buffer(capacity: 1024)\n        bufB.writeString(\"again\")\n\n        XCTAssertTrue(try channel.writeInbound(bufB).isFull)\n        XCTAssertTrue(try channel.finish().hasLeftOvers)\n        XCTAssertNoThrow(XCTAssertEqual(bufB, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n    }\n\n    func testWriteInboundByteBufferReThrow() {\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ExceptionThrowingInboundHandler()))\n        XCTAssertThrowsError(try channel.writeInbound(\"msg\")) { error in\n            XCTAssertEqual(ChannelError.operationUnsupported, error as? ChannelError)\n        }\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWriteOutboundByteBufferReThrow() {\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ExceptionThrowingOutboundHandler()))\n        XCTAssertThrowsError(try channel.writeOutbound(\"msg\")) { error in\n            XCTAssertEqual(ChannelError.operationUnsupported, error as? ChannelError)\n        }\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testReadOutboundWrongTypeThrows() {\n        let channel = EmbeddedChannel()\n        XCTAssertTrue(try channel.writeOutbound(\"hello\").isFull)\n        do {\n            _ = try channel.readOutbound(as: Int.self)\n            XCTFail()\n        } catch let error as EmbeddedChannel.WrongTypeError {\n            let expectedError = EmbeddedChannel.WrongTypeError(expected: Int.self, actual: String.self)\n            XCTAssertEqual(error, expectedError)\n        } catch {\n            XCTFail()\n        }\n    }\n\n    func testReadInboundWrongTypeThrows() {\n        let channel = EmbeddedChannel()\n        XCTAssertTrue(try channel.writeInbound(\"hello\").isFull)\n        do {\n            _ = try channel.readInbound(as: Int.self)\n            XCTFail()\n        } catch let error as EmbeddedChannel.WrongTypeError {\n            let expectedError = EmbeddedChannel.WrongTypeError(expected: Int.self, actual: String.self)\n            XCTAssertEqual(error, expectedError)\n        } catch {\n            XCTFail()\n        }\n    }\n\n    func testWrongTypesWithFastpathTypes() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        let buffer = channel.allocator.buffer(capacity: 0)\n        let ioData = IOData.byteBuffer(buffer)\n        let fileHandle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n        let fileRegion = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 0)\n        defer {\n            XCTAssertNoThrow(_ = try fileHandle.takeDescriptorOwnership())\n        }\n\n        XCTAssertTrue(try channel.writeOutbound(buffer).isFull)\n        XCTAssertTrue(try channel.writeOutbound(ioData).isFull)\n        XCTAssertTrue(try channel.writeOutbound(fileHandle).isFull)\n        XCTAssertTrue(try channel.writeOutbound(fileRegion).isFull)\n        XCTAssertTrue(\n            try channel.writeOutbound(\n                AddressedEnvelope<ByteBuffer>(\n                    remoteAddress: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678),\n                    data: buffer\n                )\n            ).isFull\n        )\n        XCTAssertTrue(try channel.writeOutbound(buffer).isFull)\n        XCTAssertTrue(try channel.writeOutbound(ioData).isFull)\n        XCTAssertTrue(try channel.writeOutbound(fileRegion).isFull)\n\n        XCTAssertTrue(try channel.writeInbound(buffer).isFull)\n        XCTAssertTrue(try channel.writeInbound(ioData).isFull)\n        XCTAssertTrue(try channel.writeInbound(fileHandle).isFull)\n        XCTAssertTrue(try channel.writeInbound(fileRegion).isFull)\n        XCTAssertTrue(\n            try channel.writeInbound(\n                AddressedEnvelope<ByteBuffer>(\n                    remoteAddress: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678),\n                    data: buffer\n                )\n            ).isFull\n        )\n        XCTAssertTrue(try channel.writeInbound(buffer).isFull)\n        XCTAssertTrue(try channel.writeInbound(ioData).isFull)\n        XCTAssertTrue(try channel.writeInbound(fileRegion).isFull)\n\n        func check<Expected, Actual>(\n            expected: Expected.Type,\n            actual: Actual.Type,\n            file: StaticString = #filePath,\n            line: UInt = #line\n        ) {\n            do {\n                _ = try channel.readOutbound(as: Expected.self)\n                XCTFail(\"this should have failed\", file: (file), line: line)\n            } catch let error as EmbeddedChannel.WrongTypeError {\n                let expectedError = EmbeddedChannel.WrongTypeError(expected: Expected.self, actual: Actual.self)\n                XCTAssertEqual(error, expectedError, file: (file), line: line)\n            } catch {\n                XCTFail(\"unexpected error: \\(error)\", file: (file), line: line)\n            }\n\n            do {\n                _ = try channel.readInbound(as: Expected.self)\n                XCTFail(\"this should have failed\", file: (file), line: line)\n            } catch let error as EmbeddedChannel.WrongTypeError {\n                let expectedError = EmbeddedChannel.WrongTypeError(expected: Expected.self, actual: Actual.self)\n                XCTAssertEqual(error, expectedError, file: (file), line: line)\n            } catch {\n                XCTFail(\"unexpected error: \\(error)\", file: (file), line: line)\n            }\n        }\n\n        check(expected: Never.self, actual: IOData.self)\n        check(expected: Never.self, actual: IOData.self)\n        check(expected: Never.self, actual: NIOFileHandle.self)\n        check(expected: Never.self, actual: IOData.self)\n        check(expected: Never.self, actual: AddressedEnvelope<ByteBuffer>.self)\n        check(expected: NIOFileHandle.self, actual: IOData.self)\n        check(expected: NIOFileHandle.self, actual: IOData.self)\n        check(expected: ByteBuffer.self, actual: IOData.self)\n    }\n\n    func testCloseMultipleTimesThrows() throws {\n        let channel = EmbeddedChannel()\n        XCTAssertTrue(try channel.finish().isClean)\n\n        // Close a second time. This must fail.\n        do {\n            try channel.close().wait()\n            XCTFail(\"Second close succeeded\")\n        } catch ChannelError.alreadyClosed {\n            // Nothing to do here.\n        }\n    }\n\n    func testCloseOnInactiveIsOk() throws {\n        let channel = EmbeddedChannel()\n        let inactiveHandler = CloseInChannelInactiveHandler()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(inactiveHandler))\n        XCTAssertTrue(try channel.finish().isClean)\n\n        // channelInactive should fire only once.\n        XCTAssertEqual(inactiveHandler.inactiveNotifications, 1)\n    }\n\n    func testEmbeddedLifecycle() throws {\n        let handler = ChannelLifecycleHandler()\n        XCTAssertEqual(handler.currentState, .unregistered)\n\n        let channel = EmbeddedChannel(handler: handler)\n\n        XCTAssertEqual(handler.currentState, .registered)\n        XCTAssertFalse(channel.isActive)\n\n        XCTAssertNoThrow(try channel.connect(to: try SocketAddress(unixDomainSocketPath: \"/fake\")).wait())\n        XCTAssertEqual(handler.currentState, .active)\n        XCTAssertTrue(channel.isActive)\n\n        XCTAssertTrue(try channel.finish().isClean)\n        XCTAssertEqual(handler.currentState, .unregistered)\n        XCTAssertFalse(channel.isActive)\n    }\n\n    private final class ExceptionThrowingInboundHandler: ChannelInboundHandler {\n        typealias InboundIn = String\n\n        public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            context.fireErrorCaught(ChannelError.operationUnsupported)\n        }\n    }\n\n    private final class ExceptionThrowingOutboundHandler: ChannelOutboundHandler {\n        typealias OutboundIn = String\n        typealias OutboundOut = Never\n\n        public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n            promise!.fail(ChannelError.operationUnsupported)\n        }\n    }\n\n    private final class CloseInChannelInactiveHandler: ChannelInboundHandler {\n        typealias InboundIn = ByteBuffer\n        public var inactiveNotifications = 0\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            inactiveNotifications += 1\n            context.close(promise: nil)\n        }\n    }\n\n    func testEmbeddedChannelAndPipelineAndChannelCoreShareTheEventLoop() {\n        let channel = EmbeddedChannel()\n        let pipelineEventLoop = channel.pipeline.eventLoop\n        XCTAssert(pipelineEventLoop === channel.eventLoop)\n        XCTAssert(pipelineEventLoop === (channel._channelCore as! EmbeddedChannelCore).eventLoop)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSendingAnythingOnEmbeddedChannel() throws {\n        let channel = EmbeddedChannel()\n        let buffer = ByteBufferAllocator().buffer(capacity: 5)\n        let socketAddress = try SocketAddress(unixDomainSocketPath: \"path\")\n        let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: 1)\n        let fileRegion = FileRegion(fileHandle: handle, readerIndex: 1, endIndex: 2)\n        defer {\n            // fake descriptor, so shouldn't be closed.\n            XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n        }\n        try channel.writeAndFlush(1).wait()\n        try channel.writeAndFlush(\"1\").wait()\n        try channel.writeAndFlush(buffer).wait()\n        try channel.writeOutbound(IOData.byteBuffer(buffer))\n        try channel.writeOutbound(IOData.fileRegion(fileRegion))\n        try channel.writeAndFlush(AddressedEnvelope(remoteAddress: socketAddress, data: buffer)).wait()\n    }\n\n    func testActiveWhenConnectPromiseFiresAndInactiveWhenClosePromiseFires() throws {\n        let channel = EmbeddedChannel()\n        XCTAssertFalse(channel.isActive)\n        let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n        connectPromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            XCTAssertTrue(channel.isActive)\n        }\n        channel.connect(to: try SocketAddress(ipAddress: \"127.0.0.1\", port: 0), promise: connectPromise)\n        try connectPromise.futureResult.wait()\n\n        let closePromise = channel.eventLoop.makePromise(of: Void.self)\n        closePromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            XCTAssertFalse(channel.isActive)\n        }\n\n        channel.close(promise: closePromise)\n        try closePromise.futureResult.wait()\n    }\n\n    func testWriteWithoutFlushDoesNotWrite() throws {\n        let channel = EmbeddedChannel()\n\n        let buf = ByteBuffer(bytes: [1])\n        let writeFuture = channel.write(buf)\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertFalse(writeFuture.isFulfilled)\n        channel.flush()\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertTrue(writeFuture.isFulfilled)\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testSetLocalAddressAfterSuccessfulBind() throws {\n        let channel = EmbeddedChannel()\n        let bindPromise = channel.eventLoop.makePromise(of: Void.self)\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        channel.bind(to: socketAddress, promise: bindPromise)\n        bindPromise.futureResult.whenComplete { _ in\n            XCTAssertEqual(channel.localAddress, socketAddress)\n        }\n        try bindPromise.futureResult.wait()\n    }\n\n    func testSetLocalAddressAfterSuccessfulBindWithoutPromise() throws {\n        let channel = EmbeddedChannel()\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        channel.bind(to: socketAddress, promise: nil)\n        XCTAssertEqual(channel.localAddress, socketAddress)\n    }\n\n    func testSetRemoteAddressAfterSuccessfulConnect() throws {\n        let channel = EmbeddedChannel()\n        let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        channel.connect(to: socketAddress, promise: connectPromise)\n        connectPromise.futureResult.whenComplete { _ in\n            XCTAssertEqual(channel.remoteAddress, socketAddress)\n        }\n        try connectPromise.futureResult.wait()\n    }\n\n    func testSetRemoteAddressAfterSuccessfulConnectWithoutPromise() throws {\n        let channel = EmbeddedChannel()\n        let socketAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 0)\n        channel.connect(to: socketAddress, promise: nil)\n        XCTAssertEqual(channel.remoteAddress, socketAddress)\n    }\n\n    func testUnprocessedOutboundUserEventFailsOnEmbeddedChannel() {\n        let channel = EmbeddedChannel()\n        XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"event\").wait()) { (error: Error) in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.operationUnsupported, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testEmbeddedChannelWritabilityIsWritable() {\n        let channel = EmbeddedChannel()\n        let opaqueChannel: Channel = channel\n        XCTAssertTrue(channel.isWritable)\n        XCTAssertTrue(opaqueChannel.isWritable)\n        channel.isWritable = false\n        XCTAssertFalse(channel.isWritable)\n        XCTAssertFalse(opaqueChannel.isWritable)\n    }\n\n    func testFinishWithRecursivelyScheduledTasks() throws {\n        let channel = EmbeddedChannel()\n        let tasks: NIOLoopBoundBox<[Scheduled<Void>]> = NIOLoopBoundBox([], eventLoop: channel.eventLoop)\n        let invocations = ManagedAtomic(0)\n\n        @Sendable\n        func recursivelyScheduleAndIncrement() {\n            let task = channel.pipeline.eventLoop.scheduleTask(deadline: .distantFuture) {\n                invocations.wrappingIncrement(ordering: .sequentiallyConsistent)\n                recursivelyScheduleAndIncrement()\n            }\n            tasks.value.append(task)\n        }\n\n        recursivelyScheduleAndIncrement()\n\n        try XCTAssertNoThrow(channel.finish())\n\n        // None of the tasks should have been executed, they were scheduled for distant future.\n        XCTAssertEqual(invocations.load(ordering: .sequentiallyConsistent), 0)\n\n        // Because the root task didn't run, it should be the onnly one scheduled.\n        XCTAssertEqual(tasks.value.count, 1)\n\n        // Check the task was failed with cancelled error.\n        let taskChecked = expectation(description: \"task future fulfilled\")\n        tasks.value.first?.futureResult.whenComplete { result in\n            switch result {\n            case .success: XCTFail(\"Expected task to be cancelled, not run.\")\n            case .failure(let error): XCTAssertEqual(error as? EventLoopError, .cancelled)\n            }\n            taskChecked.fulfill()\n        }\n        wait(for: [taskChecked], timeout: 0)\n    }\n\n    func testGetChannelOptionAutoReadIsSupported() {\n        let channel = EmbeddedChannel()\n        let options = channel.syncOptions\n        XCTAssertNotNil(options)\n        // Unconditionally returns true.\n        XCTAssertEqual(try options?.getOption(.autoRead), true)\n    }\n\n    func testSetGetChannelOptionAllowRemoteHalfClosureIsSupported() {\n        let channel = EmbeddedChannel()\n        let options = channel.syncOptions\n        XCTAssertNotNil(options)\n\n        // allowRemoteHalfClosure should be false by default\n        XCTAssertEqual(try options?.getOption(.allowRemoteHalfClosure), false)\n\n        channel.allowRemoteHalfClosure = true\n        XCTAssertEqual(try options?.getOption(.allowRemoteHalfClosure), true)\n\n        XCTAssertNoThrow(try options?.setOption(.allowRemoteHalfClosure, value: false))\n        XCTAssertEqual(try options?.getOption(.allowRemoteHalfClosure), false)\n    }\n\n    func testLocalAddress0() throws {\n        let channel = EmbeddedChannel()\n\n        XCTAssertThrowsError(try channel._channelCore.localAddress0()) { error in\n            XCTAssertEqual(error as? ChannelError, ChannelError.operationUnsupported)\n        }\n\n        let localAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 1234)\n        channel.localAddress = localAddress\n\n        XCTAssertEqual(try channel._channelCore.localAddress0(), localAddress)\n    }\n\n    func testRemoteAddress0() throws {\n        let channel = EmbeddedChannel()\n\n        XCTAssertThrowsError(try channel._channelCore.remoteAddress0()) { error in\n            XCTAssertEqual(error as? ChannelError, ChannelError.operationUnsupported)\n        }\n\n        let remoteAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 1234)\n        channel.remoteAddress = remoteAddress\n\n        XCTAssertEqual(try channel._channelCore.remoteAddress0(), remoteAddress)\n    }\n\n    func testWriteOutboundEmptyBufferedByte() throws {\n        let channel = EmbeddedChannel()\n        var buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n\n        let buf = channel.allocator.buffer(capacity: 10)\n\n        channel.write(buf, promise: nil)\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n\n        channel.flush()\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n        XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWriteOutboundBufferedByteSingleWrite() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n\n        channel.write(buf, promise: nil)\n        var buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(buf.readableBytes, buffered)\n        channel.flush()\n\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n        XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWriteOuboundBufferedBytesMultipleWrites() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n        let totalCount = 5\n        for _ in 0..<totalCount {\n            channel.write(buf, promise: nil)\n        }\n\n        var buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(buf.readableBytes * totalCount, buffered)\n\n        channel.flush()\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n        for _ in 0..<totalCount {\n            XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readOutbound()))\n        }\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWriteOuboundBufferedBytesWriteAndFlushInterleaved() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n\n        channel.write(buf, promise: nil)\n        channel.write(buf, promise: nil)\n        channel.write(buf, promise: nil)\n        var buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(buf.readableBytes * 3, buffered)\n\n        channel.flush()\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n\n        channel.write(buf, promise: nil)\n        channel.write(buf, promise: nil)\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(buf.readableBytes * 2, buffered)\n        channel.flush()\n        buffered = try channel.getOption(ChannelOptions.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n\n        for _ in 0..<5 {\n            XCTAssertNoThrow(XCTAssertEqual(buf, try channel.readOutbound()))\n        }\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWriteOutboundBufferedBytesWriteAndFlush() throws {\n        let channel = EmbeddedChannel()\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n\n        try XCTAssertTrue(channel.writeOutbound(buf).isFull)\n        let buffered = try channel.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(0, buffered)\n\n        XCTAssertEqual(buf, try channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testWriteInboundBufferConsumer() throws {\n        let channel = EmbeddedChannel()\n        let invocationPromise = channel.eventLoop.makePromise(of: Void.self)\n\n        channel.channelcore._enqueueInboundBufferConsumer { element in\n            invocationPromise.succeed()\n            switch element {\n            case .success(let result):\n                XCTAssertEqual(\n                    channel.channelcore.tryUnwrapData(result, as: ByteBuffer.self),\n                    ByteBuffer(string: \"hello\")\n                )\n            case .failure(let error):\n                XCTFail(\"Unexpectedly received an error: \\(error)\")\n            }\n        }\n\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n        try channel.writeInbound(buf)\n\n        XCTAssertTrue(invocationPromise.futureResult.isFulfilled)\n    }\n\n    func testWriteOutboundBufferConsumer() throws {\n        let channel = EmbeddedChannel()\n        let invocationPromise = channel.eventLoop.makePromise(of: Void.self)\n\n        channel.channelcore._enqueueOutboundBufferConsumer { element in\n            invocationPromise.succeed()\n            switch element {\n            case .success(let result):\n                XCTAssertEqual(\n                    channel.channelcore.tryUnwrapData(result, as: ByteBuffer.self),\n                    ByteBuffer(string: \"hello\")\n                )\n            case .failure(let error):\n                XCTFail(\"Unexpectedly received an error: \\(error)\")\n            }\n        }\n\n        var buf = channel.allocator.buffer(capacity: 10)\n        buf.writeString(\"hello\")\n        channel.write(buf, promise: nil)\n        channel.flush()\n\n        XCTAssertTrue(invocationPromise.futureResult.isFulfilled)\n    }\n\n    func testQueueMultipleInboundAndOutboundBufferConsumersBeforeChannelClose() async throws {\n        let channel = EmbeddedChannel()\n        let inboundInvocationPromises = [EventLoopPromise<Void>](\n            repeating: channel.eventLoop.makePromise(of: Void.self),\n            count: 3\n        )\n        let outboundInvocationPromises = [EventLoopPromise<Void>](\n            repeating: channel.eventLoop.makePromise(of: Void.self),\n            count: 3\n        )\n\n        // Enqueue 3 inbound and outbound consumers\n        for i in 0..<3 {\n            // Since the channel closes, all queued consumers should get a `ChannelError.ioOnClosedChannel`\n            channel.channelcore._enqueueInboundBufferConsumer { element in\n                inboundInvocationPromises[i].succeed()\n                switch element {\n                case .failure(let failure):\n                    XCTAssertEqual(failure as? ChannelError, ChannelError.ioOnClosedChannel)\n                case .success:\n                    XCTFail(\"Unexpectedly received a successful result: no writes were performed on the channel.\")\n                }\n            }\n\n            channel.channelcore._enqueueOutboundBufferConsumer { element in\n                outboundInvocationPromises[i].succeed()\n                switch element {\n                case .failure(let failure):\n                    XCTAssertEqual(failure as? ChannelError, ChannelError.ioOnClosedChannel)\n                case .success:\n                    XCTFail(\"Unexpectedly received a successful result: no writes were performed on the channel.\")\n                }\n            }\n        }\n\n        // Close the channel without performing any writes\n        try await channel.close()\n        XCTAssertEqual(channel.channelcore.isOpen, false)\n\n        // Check that all consumer closures were invoked\n        XCTAssertTrue(inboundInvocationPromises.map(\\.futureResult.isFulfilled).allSatisfy { $0 })\n        XCTAssertTrue(outboundInvocationPromises.map(\\.futureResult.isFulfilled).allSatisfy { $0 })\n    }\n\n    func testQueueInboundAndOutboundBufferConsumerAfterChannelClose() async throws {\n        let channel = EmbeddedChannel()\n        let inboundInvocationPromise = channel.eventLoop.makePromise(of: Void.self)\n        let outboundInvocationPromise = channel.eventLoop.makePromise(of: Void.self)\n\n        // Close the channel immediately\n        try await channel.close()\n        XCTAssertEqual(channel.channelcore.isOpen, false)\n\n        // Since the consumers are enqueued after the channel closed, they should get a `ChannelError.ioOnClosedChannel`\n        channel.channelcore._enqueueInboundBufferConsumer { element in\n            inboundInvocationPromise.succeed()\n            switch element {\n            case .failure(let failure):\n                XCTAssertEqual(failure as? ChannelError, ChannelError.ioOnClosedChannel)\n            case .success:\n                XCTFail(\"Unexpectedly received a successful result: no writes were performed on the channel.\")\n            }\n        }\n\n        channel.channelcore._enqueueOutboundBufferConsumer { element in\n            outboundInvocationPromise.succeed()\n            switch element {\n            case .failure(let failure):\n                XCTAssertEqual(failure as? ChannelError, ChannelError.ioOnClosedChannel)\n            case .success:\n                XCTFail(\"Unexpectedly received a successful result: no writes were performed on the channel.\")\n            }\n        }\n\n        XCTAssertTrue(inboundInvocationPromise.futureResult.isFulfilled)\n        XCTAssertTrue(outboundInvocationPromise.futureResult.isFulfilled)\n    }\n\n    func testGetSetOption() throws {\n        let channel = EmbeddedChannel()\n        let option = ChannelOptions.socket(IPPROTO_IP, IP_TTL)\n        let _ = channel.setOption(option, value: 1)\n\n        let optionValue1 = try channel.getOption(option).wait()\n        XCTAssertEqual(1, optionValue1)\n\n        let _ = channel.setOption(option, value: 2)\n        let optionValue2 = try channel.getOption(option).wait()\n        XCTAssertEqual(2, optionValue2)\n    }\n\n    func testGetSetOptionOptInThrowing() {\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.close().wait())\n\n        XCTAssert(channel.allowOptionsWhenClosed)\n        XCTAssertNoThrow(try channel.setOption(.connectTimeout, value: .milliseconds(42)).wait())\n        XCTAssertNoThrow(XCTAssertEqual(try channel.getOption(.connectTimeout).wait(), .milliseconds(42)))\n\n        channel.allowOptionsWhenClosed = false\n        XCTAssertThrowsError(try channel.setOption(.connectTimeout, value: .milliseconds(42)).wait())\n        XCTAssertThrowsError(try channel.getOption(.connectTimeout).wait())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOEmbeddedTests/EmbeddedEventLoopTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOEmbedded\n\nprivate final class EmbeddedTestError: Error {}\n\npublic final class EmbeddedEventLoopTest: XCTestCase {\n    func testExecuteDoesNotImmediatelyRunTasks() throws {\n        var callbackRan = false\n        let loop = EmbeddedEventLoop()\n        loop.execute { callbackRan = true }\n\n        XCTAssertFalse(callbackRan)\n        loop.run()\n        XCTAssertTrue(callbackRan)\n    }\n\n    func testExecuteWillRunAllTasks() throws {\n        var runCount = 0\n        let loop = EmbeddedEventLoop()\n        loop.execute { runCount += 1 }\n        loop.execute { runCount += 1 }\n        loop.execute { runCount += 1 }\n\n        XCTAssertEqual(runCount, 0)\n        loop.run()\n        XCTAssertEqual(runCount, 3)\n    }\n\n    func testExecuteWillRunTasksAddedRecursively() throws {\n        var sentinel = 0\n        let loop = EmbeddedEventLoop()\n\n        loop.execute {\n            // This should execute first.\n            XCTAssertEqual(sentinel, 0)\n            sentinel = 1\n            loop.execute {\n                // This should execute third.\n                XCTAssertEqual(sentinel, 2)\n                sentinel = 3\n            }\n        }\n        loop.execute {\n            // This should execute second.\n            XCTAssertEqual(sentinel, 1)\n            sentinel = 2\n        }\n\n        XCTAssertEqual(sentinel, 0)\n        loop.run()\n        XCTAssertEqual(sentinel, 3)\n    }\n\n    func testTasksSubmittedAfterRunDontRun() throws {\n        var callbackRan = false\n        let loop = EmbeddedEventLoop()\n        loop.execute { callbackRan = true }\n\n        XCTAssertFalse(callbackRan)\n        loop.run()\n        loop.execute { callbackRan = false }\n        XCTAssertTrue(callbackRan)\n        loop.run()\n        XCTAssertFalse(callbackRan)\n    }\n\n    func testShutdownGracefullyRunsTasks() throws {\n        var callbackRan = false\n        let loop = EmbeddedEventLoop()\n        loop.execute { callbackRan = true }\n\n        XCTAssertFalse(callbackRan)\n        XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        XCTAssertTrue(callbackRan)\n    }\n\n    func testCanControlTime() throws {\n        var callbackCount = 0\n        let loop = EmbeddedEventLoop()\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            callbackCount += 1\n        }\n\n        XCTAssertEqual(callbackCount, 0)\n        loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertEqual(callbackCount, 0)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(callbackCount, 1)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(callbackCount, 1)\n        loop.advanceTime(by: .hours(1))\n        XCTAssertEqual(callbackCount, 1)\n    }\n\n    func testCanScheduleMultipleTasks() throws {\n        var sentinel = 0\n        let loop = EmbeddedEventLoop()\n        for index in 1...10 {\n            _ = loop.scheduleTask(in: .nanoseconds(Int64(index))) {\n                sentinel = index\n            }\n        }\n\n        for val in 1...10 {\n            XCTAssertEqual(sentinel, val - 1)\n            loop.advanceTime(by: .nanoseconds(1))\n            XCTAssertEqual(sentinel, val)\n        }\n    }\n\n    func testExecutedTasksFromScheduledOnesAreRun() throws {\n        var sentinel = 0\n        let loop = EmbeddedEventLoop()\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            sentinel = 1\n            loop.execute {\n                sentinel = 2\n            }\n        }\n\n        loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertEqual(sentinel, 0)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(sentinel, 2)\n    }\n\n    func testScheduledTasksFromScheduledTasksProperlySchedule() throws {\n        var sentinel = 0\n        let loop = EmbeddedEventLoop()\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            sentinel = 1\n            _ = loop.scheduleTask(in: .nanoseconds(3)) {\n                sentinel = 2\n            }\n            _ = loop.scheduleTask(in: .nanoseconds(5)) {\n                sentinel = 3\n            }\n        }\n\n        loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertEqual(sentinel, 0)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(sentinel, 1)\n        loop.advanceTime(by: .nanoseconds(2))\n        XCTAssertEqual(sentinel, 1)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(sentinel, 2)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(sentinel, 2)\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertEqual(sentinel, 3)\n    }\n\n    func testScheduledTasksFromExecutedTasks() throws {\n        var sentinel = 0\n        let loop = EmbeddedEventLoop()\n        loop.execute {\n            XCTAssertEqual(sentinel, 0)\n            _ = loop.scheduleTask(in: .nanoseconds(5)) {\n                XCTAssertEqual(sentinel, 1)\n                sentinel = 2\n            }\n            loop.execute { sentinel = 1 }\n        }\n\n        loop.advanceTime(by: .nanoseconds(5))\n        XCTAssertEqual(sentinel, 2)\n    }\n\n    func testCancellingScheduledTasks() throws {\n        let loop = EmbeddedEventLoop()\n        let task = loop.scheduleTask(in: .nanoseconds(10), { XCTFail(\"Cancelled task ran\") })\n        _ = loop.scheduleTask(in: .nanoseconds(5)) {\n            task.cancel()\n        }\n\n        loop.advanceTime(by: .nanoseconds(20))\n    }\n\n    func testScheduledTasksFuturesFire() throws {\n        let fired = ManagedAtomic(false)\n        let loop = EmbeddedEventLoop()\n        let task = loop.scheduleTask(in: .nanoseconds(5)) { true }\n        task.futureResult.whenSuccess { fired.store($0, ordering: .sequentiallyConsistent) }\n\n        loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertFalse(fired.load(ordering: .sequentiallyConsistent))\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertTrue(fired.load(ordering: .sequentiallyConsistent))\n    }\n\n    func testScheduledTasksFuturesError() throws {\n        let err: NIOLockedValueBox<EmbeddedTestError?> = NIOLockedValueBox(nil)\n        let fired = ManagedAtomic(false)\n        let loop = EmbeddedEventLoop()\n        let task = loop.scheduleTask(in: .nanoseconds(5)) {\n            let localErr = EmbeddedTestError()\n            err.withLockedValue { $0 = localErr }\n            throw localErr\n        }\n        task.futureResult.map {\n            XCTFail(\"Scheduled future completed\")\n        }.recover { caughtErr in\n            XCTAssertTrue(err.withLockedValue { $0 === caughtErr as? EmbeddedTestError })\n        }.whenComplete { (_: Result<Void, Error>) in\n            fired.store(true, ordering: .sequentiallyConsistent)\n        }\n\n        loop.advanceTime(by: .nanoseconds(4))\n        XCTAssertFalse(fired.load(ordering: .sequentiallyConsistent))\n        loop.advanceTime(by: .nanoseconds(1))\n        XCTAssertTrue(fired.load(ordering: .sequentiallyConsistent))\n    }\n\n    func testTaskOrdering() {\n        // This test validates that the ordering of task firing on EmbeddedEventLoop via\n        // advanceTime(by:) is the same as on MultiThreadedEventLoopGroup: specifically, that tasks run via\n        // schedule that expire \"now\" all run at the same time, and that any work they schedule is run\n        // after all such tasks expire.\n        let loop = EmbeddedEventLoop()\n        var firstScheduled: Scheduled<Void>? = nil\n        var secondScheduled: Scheduled<Void>? = nil\n        var orderingCounter = 0\n\n        // Here's the setup. First, we'll set up two scheduled tasks to fire in 5 nanoseconds. Each of these\n        // will attempt to cancel the other, whichever fires first. Additionally, each will execute{} a single\n        // callback. Then we'll execute {} one other callback. Finally we'll schedule a task for 10ns, before\n        // we advance time. The ordering should be as follows:\n        //\n        // 1. The task executed by execute {} from this function.\n        // 2. One of the first scheduled tasks.\n        // 3. The other first scheduled task  (note that the cancellation will fail).\n        // 4. One of the execute {} callbacks from a scheduled task.\n        // 5. The other execute {} callbacks from the scheduled task.\n        // 6. The 10ns task.\n        //\n        // To validate the ordering, we'll use a counter.\n\n        func delayedExecute() {\n            // The acceptable value for the delayed execute callbacks is 3 or 4.\n            XCTAssertTrue(orderingCounter == 3 || orderingCounter == 4, \"Invalid counter value \\(orderingCounter)\")\n            orderingCounter += 1\n        }\n\n        firstScheduled = loop.scheduleTask(in: .nanoseconds(5)) {\n            firstScheduled = nil\n\n            let expected: Int\n            if let partner = secondScheduled {\n                // Ok, this callback fired first. Cancel the other, then set the expected current\n                // counter value to 1.\n                partner.cancel()\n                expected = 1\n            } else {\n                // This callback fired second.\n                expected = 2\n            }\n\n            XCTAssertEqual(orderingCounter, expected)\n            orderingCounter = expected + 1\n            loop.execute(delayedExecute)\n        }\n\n        secondScheduled = loop.scheduleTask(in: .nanoseconds(5)) {\n            secondScheduled = nil\n\n            let expected: Int\n            if let partner = firstScheduled {\n                // Ok, this callback fired first. Cancel the other, then set the expected current\n                // counter value to 1.\n                partner.cancel()\n                expected = 1\n            } else {\n                // This callback fired second.\n                expected = 2\n            }\n\n            XCTAssertEqual(orderingCounter, expected)\n            orderingCounter = expected + 1\n            loop.execute(delayedExecute)\n        }\n\n        // Ok, now we set one more task to execute.\n        loop.execute {\n            XCTAssertEqual(orderingCounter, 0)\n            orderingCounter = 1\n        }\n\n        // Finally schedule a task for 10ns.\n        _ = loop.scheduleTask(in: .nanoseconds(10)) {\n            XCTAssertEqual(orderingCounter, 5)\n            orderingCounter = 6\n        }\n\n        // Now we advance time by 10ns.\n        loop.advanceTime(by: .nanoseconds(10))\n\n        // Now the final value should be 6.\n        XCTAssertEqual(orderingCounter, 6)\n    }\n\n    func testCancelledScheduledTasksDoNotHoldOnToRunClosure() {\n        let eventLoop = EmbeddedEventLoop()\n        defer {\n            XCTAssertNoThrow(try eventLoop.syncShutdownGracefully())\n        }\n\n        class Thing: @unchecked Sendable {\n            private let deallocated: ConditionLock<Int>\n\n            init(_ deallocated: ConditionLock<Int>) {\n                self.deallocated = deallocated\n            }\n\n            deinit {\n                self.deallocated.lock()\n                self.deallocated.unlock(withValue: 1)\n            }\n        }\n\n        func make(deallocated: ConditionLock<Int>) -> Scheduled<Never> {\n            let aThing = Thing(deallocated)\n            return eventLoop.next().scheduleTask(in: .hours(1)) {\n                preconditionFailure(\"this should definitely not run: \\(aThing)\")\n            }\n        }\n\n        let deallocated = ConditionLock(value: 0)\n        let scheduled = make(deallocated: deallocated)\n        scheduled.cancel()\n        if deallocated.lock(whenValue: 1, timeoutSeconds: 60) {\n            deallocated.unlock()\n        } else {\n            XCTFail(\"Timed out waiting for lock\")\n        }\n        XCTAssertThrowsError(try scheduled.futureResult.wait()) { error in\n            XCTAssertEqual(EventLoopError.cancelled, error as? EventLoopError)\n        }\n    }\n\n    func testShutdownCancelsFutureScheduledTasks() {\n        let eventLoop = EmbeddedEventLoop()\n        var tasksRun = 0\n\n        let a = eventLoop.scheduleTask(in: .seconds(1)) { tasksRun += 1 }\n        let b = eventLoop.scheduleTask(in: .seconds(2)) { tasksRun += 1 }\n\n        XCTAssertEqual(tasksRun, 0)\n\n        eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(tasksRun, 1)\n\n        XCTAssertNoThrow(try eventLoop.syncShutdownGracefully())\n        XCTAssertEqual(tasksRun, 1)\n\n        eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(tasksRun, 1)\n\n        eventLoop.advanceTime(to: .distantFuture)\n        XCTAssertEqual(tasksRun, 1)\n\n        XCTAssertNoThrow(try a.futureResult.wait())\n        XCTAssertThrowsError(try b.futureResult.wait()) { error in\n            XCTAssertEqual(error as? EventLoopError, .cancelled)\n            XCTAssertEqual(tasksRun, 1)\n        }\n    }\n\n    func testTasksScheduledDuringShutdownAreAutomaticallyCancelled() throws {\n        let eventLoop = EmbeddedEventLoop()\n        var tasksRun = 0\n        var childTasks: [Scheduled<Void>] = []\n\n        func scheduleRecursiveTask(\n            at taskStartTime: NIODeadline,\n            andChildTaskAfter childTaskStartDelay: TimeAmount\n        ) -> Scheduled<Void> {\n            eventLoop.scheduleTask(deadline: taskStartTime) {\n                tasksRun += 1\n                try eventLoop.syncShutdownGracefully()\n                childTasks.append(\n                    scheduleRecursiveTask(\n                        at: eventLoop.now + childTaskStartDelay,\n                        andChildTaskAfter: childTaskStartDelay\n                    )\n                )\n            }\n        }\n\n        let rootTask = scheduleRecursiveTask(at: .uptimeNanoseconds(1), andChildTaskAfter: .zero)\n\n        eventLoop.advanceTime(to: .uptimeNanoseconds(1))\n\n        XCTAssertEqual(tasksRun, 1)\n        XCTAssertNoThrow(try rootTask.futureResult.wait())\n\n        for childTask in childTasks {\n            XCTAssertThrowsError(try childTask.futureResult.wait()) { error in\n                XCTAssertEqual(error as? EventLoopError, .cancelled)\n                XCTAssertEqual(tasksRun, 1)\n            }\n        }\n    }\n\n    func testAdvanceTimeToDeadline() {\n        let eventLoop = EmbeddedEventLoop()\n        let deadline = NIODeadline.uptimeNanoseconds(0) + .seconds(42)\n\n        var tasksRun = 0\n        eventLoop.scheduleTask(deadline: deadline) {\n            tasksRun += 1\n        }\n\n        eventLoop.advanceTime(to: deadline)\n        XCTAssertEqual(tasksRun, 1)\n    }\n\n    func testWeCantTimeTravelByAdvancingTimeToThePast() {\n        let eventLoop = EmbeddedEventLoop()\n\n        var tasksRun = 0\n        eventLoop.scheduleTask(deadline: .uptimeNanoseconds(0) + .seconds(42)) {\n            tasksRun += 1\n        }\n\n        // t=40s\n        eventLoop.advanceTime(to: .uptimeNanoseconds(0) + .seconds(40))\n        XCTAssertEqual(tasksRun, 0)\n\n        // t=40s (still)\n        eventLoop.advanceTime(to: .distantPast)\n        XCTAssertEqual(tasksRun, 0)\n\n        // t=42s\n        eventLoop.advanceTime(by: .seconds(2))\n        XCTAssertEqual(tasksRun, 1)\n    }\n\n    func testExecuteInOrder() {\n        let eventLoop = EmbeddedEventLoop()\n        var counter = 0\n\n        eventLoop.execute {\n            XCTAssertEqual(counter, 0)\n            counter += 1\n        }\n\n        eventLoop.execute {\n            XCTAssertEqual(counter, 1)\n            counter += 1\n        }\n\n        eventLoop.execute {\n            XCTAssertEqual(counter, 2)\n            counter += 1\n        }\n\n        eventLoop.run()\n        XCTAssertEqual(counter, 3)\n    }\n\n    func testScheduledTasksInOrder() {\n        let eventLoop = EmbeddedEventLoop()\n        var counter = 0\n\n        eventLoop.scheduleTask(in: .seconds(1)) {\n            XCTAssertEqual(counter, 1)\n            counter += 1\n        }\n\n        eventLoop.scheduleTask(in: .milliseconds(1)) {\n            XCTAssertEqual(counter, 0)\n            counter += 1\n        }\n\n        eventLoop.scheduleTask(in: .seconds(1)) {\n            XCTAssertEqual(counter, 2)\n            counter += 1\n        }\n\n        eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(counter, 3)\n    }\n\n    func testCurrentTime() {\n        let eventLoop = EmbeddedEventLoop()\n\n        eventLoop.advanceTime(to: .uptimeNanoseconds(42))\n        XCTAssertEqual(eventLoop.now, .uptimeNanoseconds(42))\n\n        eventLoop.advanceTime(by: .nanoseconds(42))\n        XCTAssertEqual(eventLoop.now, .uptimeNanoseconds(84))\n    }\n\n    func testScheduleRepeatedTask() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let counter = ManagedAtomic(0)\n        eventLoop.scheduleRepeatedTask(initialDelay: .seconds(1), delay: .seconds(1)) { repeatedTask in\n            guard counter.load(ordering: .sequentiallyConsistent) < 10 else {\n                repeatedTask.cancel()\n                return\n            }\n            counter.wrappingIncrement(ordering: .sequentiallyConsistent)\n        }\n\n        XCTAssertEqual(counter.load(ordering: .sequentiallyConsistent), 0)\n\n        eventLoop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(counter.load(ordering: .sequentiallyConsistent), 1)\n\n        eventLoop.advanceTime(by: .seconds(9))\n        XCTAssertEqual(counter.load(ordering: .sequentiallyConsistent), 10)\n    }\n}\n\n@available(*, unavailable)\nextension EmbeddedEventLoopTest: Sendable {}\n"
  },
  {
    "path": "Tests/NIOEmbeddedTests/TestUtils.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport Atomics\nimport Foundation\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n#if canImport(Android)\nimport Android\n#endif\n\n// FIXME: Duplicated with NIO\nfunc assert(\n    _ condition: @autoclosure () -> Bool,\n    within time: TimeAmount,\n    testInterval: TimeAmount? = nil,\n    _ message: String = \"condition not satisfied in time\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let testInterval = testInterval ?? TimeAmount.nanoseconds(time.nanoseconds / 5)\n    let endTime = NIODeadline.now() + time\n\n    repeat {\n        if condition() { return }\n        usleep(UInt32(testInterval.nanoseconds / 1000))\n    } while NIODeadline.now() < endTime\n\n    if !condition() {\n        XCTFail(message, file: (file), line: line)\n    }\n}\n\nextension EventLoopFuture {\n    var isFulfilled: Bool {\n        if self.eventLoop.inEventLoop {\n            // Easy, we're on the EventLoop. Let's just use our knowledge that we run completed future callbacks\n            // immediately.\n            let fulfilled = NIOLoopBoundBox(false, eventLoop: self.eventLoop)\n            self.whenComplete { _ in\n                fulfilled.value = true\n            }\n            return fulfilled.value\n        } else {\n            let fulfilled = NIOLockedValueBox(false)\n            let group = DispatchGroup()\n\n            group.enter()\n            self.eventLoop.execute {\n                let isFulfilled = self.isFulfilled  // This will now enter the above branch.\n                fulfilled.withLockedValue {\n                    $0 = isFulfilled\n                }\n                group.leave()\n            }\n            group.wait()  // this is very nasty but this is for tests only, so...\n            return fulfilled.withLockedValue { $0 }\n        }\n    }\n}\n\ninternal func XCTAssertCompareAndSwapSucceeds<Type: AtomicValue>(\n    storage: ManagedAtomic<Type>,\n    expected: Type,\n    desired: Type,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let result = storage.compareExchange(expected: expected, desired: desired, ordering: .relaxed)\n    XCTAssertTrue(result.exchanged, file: file, line: line)\n}\n"
  },
  {
    "path": "Tests/NIOEmbeddedTests/XCTest+AsyncAwait.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the AsyncHTTPClient open source project\n//\n// Copyright (c) 2021 Apple Inc. and the AsyncHTTPClient project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//\n// Copyright 2021, gRPC Authors All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertThrowsError<T>(\n    _ expression: @autoclosure () async throws -> T,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    verify: (Error) -> Void = { _ in }\n) async {\n    do {\n        _ = try await expression()\n        XCTFail(\"Expression did not throw error\", file: file, line: line)\n    } catch {\n        verify(error)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertNoThrowWithResult<Result>(\n    _ expression: @autoclosure () async throws -> Result,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async -> Result? {\n    do {\n        return try await expression()\n    } catch {\n        XCTFail(\"Expression did throw: \\(error)\", file: file, line: line)\n    }\n    return nil\n}\n"
  },
  {
    "path": "Tests/NIOFSFoundationCompatTests/FileSystemFoundationCompatTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOFS\nimport NIOFSFoundationCompat\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    func temporaryFilePath(\n        _ function: String = #function,\n        inTemporaryDirectory: Bool = true\n    ) async throws -> NIOFilePath {\n        if inTemporaryDirectory {\n            let directory = try await self.temporaryDirectory\n            return self.temporaryFilePath(function, inDirectory: directory)\n        } else {\n            return self.temporaryFilePath(function, inDirectory: nil)\n        }\n    }\n\n    func temporaryFilePath(\n        _ function: String = #function,\n        inDirectory directory: NIOFilePath?\n    ) -> NIOFilePath {\n        let index = function.firstIndex(of: \"(\")!\n        let functionName = function.prefix(upTo: index)\n        let random = UInt32.random(in: .min ... .max)\n        let fileName = \"\\(functionName)-\\(random)\"\n\n        if let directory = directory {\n            return NIOFilePath(FilePath(directory).appending(fileName))\n        } else {\n            return NIOFilePath(fileName)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class FileSystemBytesConformanceTests: XCTestCase {\n    func testTimepecToDate() async throws {\n        XCTAssertEqual(\n            FileInfo.Timespec(seconds: 0, nanoseconds: 0).date,\n            Date(timeIntervalSince1970: 0)\n        )\n        XCTAssertEqual(\n            FileInfo.Timespec(seconds: 1, nanoseconds: 0).date,\n            Date(timeIntervalSince1970: 1)\n        )\n        XCTAssertEqual(\n            FileInfo.Timespec(seconds: 1, nanoseconds: 1).date,\n            Date(timeIntervalSince1970: 1.000000001)\n        )\n    }\n\n    func testReadFileIntoData() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(forReadingAndWritingAt: path) { fileHandle in\n            _ = try await fileHandle.write(contentsOf: [0, 1, 2], toAbsoluteOffset: 0)\n        }\n\n        let contents = try await Data(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n\n        XCTAssertEqual(contents, Data([0, 1, 2]))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/BufferedReaderTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class BufferedReaderTests: XCTestCase {\n    func testBufferedReaderSizeAndCapacity() async throws {\n        let fs = FileSystem.shared\n        try await fs.withFileHandle(forReadingAt: #filePath) { handle in\n            var reader = handle.bufferedReader(capacity: .bytes(128 * 1024))\n            XCTAssertEqual(reader.count, 0)\n            XCTAssertEqual(reader.capacity, 128 * 1024)\n\n            let byte = try await reader.read(.bytes(1))\n            XCTAssertEqual(byte.readableBytes, 1)\n\n            // Buffer should be non-empty; there's more than one byte in this file.\n            XCTAssertGreaterThan(reader.count, 0)\n            // It should be no greater than the buffer capacity, however.\n            XCTAssertLessThanOrEqual(reader.count, reader.capacity)\n        }\n    }\n\n    func testBufferedReaderReadFixedSize() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            var writer = handle.bufferedWriter()\n            try await writer.write(contentsOf: repeatElement(0, count: 1024 * 1024))\n            try await writer.flush()\n        }\n\n        try await fs.withFileHandle(forReadingAt: path) { handle in\n            var reader = handle.bufferedReader()\n            let allTheBytes = try await reader.read(.bytes(1024 * 1024))\n            XCTAssertEqual(allTheBytes.readableBytes, 1024 * 1024)\n\n            let noBytes = try await reader.read(.bytes(1024))\n            XCTAssertEqual(noBytes.readableBytes, 0)\n        }\n    }\n\n    func testBufferedReaderMultipleReads() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            var writer = handle.bufferedWriter()\n            try await writer.write(contentsOf: repeatElement(0, count: 1024 * 1024))\n            try await writer.flush()\n        }\n\n        try await fs.withFileHandle(forReadingAt: path) { handle in\n            var reader = handle.bufferedReader()\n            var allTheBytes = [UInt8]()\n\n            while true {\n                let byte = try await reader.read(.bytes(100))\n                if byte.readableBytes == 0 { break }\n                allTheBytes.append(contentsOf: byte.readableBytesView)\n            }\n\n            XCTAssertEqual(allTheBytes.count, 1024 * 1024)\n        }\n    }\n\n    func testBufferedReaderReadingShort() async throws {\n        let fs = FileSystem.shared\n        try await fs.withFileHandle(forReadingAt: #filePath) { handle in\n            var reader = handle.bufferedReader(capacity: .bytes(128))\n            var buffer = ByteBuffer()\n            while true {\n                let chunk = try await reader.read(.bytes(128))\n                buffer.writeImmutableBuffer(chunk)\n                if chunk.readableBytes < 128 { break }\n            }\n\n            let info = try await handle.info()\n            XCTAssertEqual(Int64(buffer.readableBytes), info.size)\n        }\n    }\n\n    func testBufferedReaderReadWhile() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            var writer = handle.bufferedWriter()\n            for byte in UInt8.min...UInt8.max {\n                try await writer.write(contentsOf: repeatElement(byte, count: 1024))\n            }\n            try await writer.flush()\n        }\n\n        try await fs.withFileHandle(forReadingAt: path) { handle in\n            var reader = handle.bufferedReader()\n            let (zeros, isEOFZeros) = try await reader.read { $0 == 0 }\n            XCTAssertEqual(zeros, ByteBuffer(bytes: Array(repeating: 0, count: 1024)))\n            XCTAssertFalse(isEOFZeros)\n\n            let (onesAndTwos, isEOFOnesAndTwos) = try await reader.read { $0 < 3 }\n            var expectedOnesAndTwos = ByteBuffer()\n            expectedOnesAndTwos.writeRepeatingByte(1, count: 1024)\n            expectedOnesAndTwos.writeRepeatingByte(2, count: 1024)\n\n            XCTAssertEqual(onesAndTwos, expectedOnesAndTwos)\n            XCTAssertFalse(isEOFOnesAndTwos)\n\n            let (threesThroughNines, isEOFThreesThroughNines) = try await reader.read { $0 < 10 }\n            var expectedThreesThroughNines = ByteBuffer()\n            for byte in UInt8(3)...9 {\n                expectedThreesThroughNines.writeRepeatingByte(byte, count: 1024)\n            }\n            XCTAssertEqual(threesThroughNines, expectedThreesThroughNines)\n            XCTAssertFalse(isEOFThreesThroughNines)\n\n            let (theRest, isEOFTheRest) = try await reader.read { _ in true }\n            XCTAssertEqual(theRest.readableBytes, 246 * 1024)\n            XCTAssertTrue(isEOFTheRest)\n        }\n    }\n\n    func testBufferedReaderDropFixedSize() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            var writer = handle.bufferedWriter()\n            for byte in UInt8.min...UInt8.max {\n                try await writer.write(contentsOf: repeatElement(byte, count: 1000))\n            }\n            try await writer.flush()\n        }\n\n        try await fs.withFileHandle(forReadingAt: path) { handle in\n            var reader = handle.bufferedReader()\n            try await reader.drop(1000)\n            let ones = try await reader.read(.bytes(1000))\n            XCTAssertEqual(ones, ByteBuffer(repeating: 1, count: 1000))\n\n            try await reader.drop(1500)\n            let threes = try await reader.read(.bytes(500))\n            XCTAssertEqual(threes, ByteBuffer(repeating: 3, count: 500))\n\n            // More than remains in the file.\n            try await reader.drop(1_000_000)\n            let empty = try await reader.read(.bytes(1000))\n            XCTAssertEqual(empty.readableBytes, 0)\n        }\n    }\n\n    func testBufferedReaderDropWhile() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            var writer = handle.bufferedWriter()\n            for byte in UInt8.min...UInt8.max {\n                try await writer.write(contentsOf: repeatElement(byte, count: 1024))\n            }\n            try await writer.flush()\n        }\n\n        try await fs.withFileHandle(forReadingAt: path) { handle in\n            var reader = handle.bufferedReader()\n            try await reader.drop(while: { $0 < 255 })\n            let bytes = try await reader.read(.bytes(1024))\n            XCTAssertEqual(bytes, ByteBuffer(repeating: 255, count: 1024))\n\n            let empty = try await reader.read(.bytes(1))\n            XCTAssertEqual(empty.readableBytes, 0)\n        }\n    }\n\n    func testBufferedReaderReadingText() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            let text = \"\"\"\n                Here's to the crazy ones, the misfits, the rebels, the troublemakers, \\\n                the round pegs in the square holes, the ones who see things differently.\n                \"\"\"\n\n            var writer = handle.bufferedWriter()\n            try await writer.write(contentsOf: text.utf8)\n            try await writer.flush()\n        }\n\n        try await fs.withFileHandle(forReadingAt: path) { file in\n            var reader = file.bufferedReader()\n            var words = [String]()\n\n            func isWordIsh(_ byte: UInt8) -> Bool {\n                switch byte {\n                case UInt8(ascii: \"a\")...UInt8(ascii: \"z\"),\n                    UInt8(ascii: \"A\")...UInt8(ascii: \"Z\"),\n                    UInt8(ascii: \"'\"):\n                    return true\n                default:\n                    return false\n                }\n            }\n\n            repeat {\n                // Gobble up whitespace etc..\n                try await reader.drop(while: { !isWordIsh($0) })\n                // Read the next word.\n                var (characters, _) = try await reader.read(while: isWordIsh(_:))\n\n                if characters.readableBytes == 0 {\n                    break  // Done.\n                } else {\n                    words.append(characters.readString(length: characters.readableBytes)!)\n                }\n            } while true\n\n            let expected: [String] = [\n                \"Here's\",\n                \"to\",\n                \"the\",\n                \"crazy\",\n                \"ones\",\n                \"the\",\n                \"misfits\",\n                \"the\",\n                \"rebels\",\n                \"the\",\n                \"troublemakers\",\n                \"the\",\n                \"round\",\n                \"pegs\",\n                \"in\",\n                \"the\",\n                \"square\",\n                \"holes\",\n                \"the\",\n                \"ones\",\n                \"who\",\n                \"see\",\n                \"things\",\n                \"differently\",\n            ]\n\n            XCTAssertEqual(words, expected)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/BufferedWriterTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n@_spi(Testing) import NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class BufferedWriterTests: XCTestCase {\n    func testBufferedWriter() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let bufferSize = 8192\n            var writer = file.bufferedWriter(capacity: .bytes(Int64(bufferSize)))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Write a full buffers worth of bytes, should be flushed immediately.\n            try await writer.write(contentsOf: repeatElement(0, count: bufferSize))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Write just under a buffer.\n            try await writer.write(contentsOf: repeatElement(1, count: bufferSize - 1))\n            XCTAssertEqual(writer.bufferedBytes, bufferSize - 1)\n\n            // Try to read the as-yet-unwritten bytes.\n            let emptyChunk = try await file.readChunk(\n                fromAbsoluteOffset: Int64(bufferSize),\n                length: .bytes(Int64(bufferSize - 1))\n            )\n            XCTAssertEqual(emptyChunk.readableBytes, 0)\n\n            // Write one more byte to flush out the buffer.\n            try await writer.write(contentsOf: repeatElement(1, count: 1))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Try to read now that the bytes have been finished.\n            let chunk = try await file.readChunk(\n                fromAbsoluteOffset: Int64(bufferSize),\n                length: .bytes(Int64(bufferSize))\n            )\n            XCTAssertEqual(chunk, ByteBuffer(repeating: 1, count: bufferSize))\n        }\n    }\n\n    func testBufferedWriterByteBuffer() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let bufferSize = 8192\n            var writer = file.bufferedWriter(capacity: .bytes(Int64(bufferSize)))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Write a full buffers worth of bytes, should be flushed immediately.\n            try await writer.write(contentsOf: ByteBuffer(repeating: 0, count: bufferSize))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Write just under a buffer.\n            try await writer.write(contentsOf: ByteBuffer(repeating: 1, count: bufferSize - 1))\n            XCTAssertEqual(writer.bufferedBytes, bufferSize - 1)\n\n            // Try to read the as-yet-unwritten bytes.\n            let emptyChunk = try await file.readChunk(\n                fromAbsoluteOffset: Int64(bufferSize),\n                length: .bytes(Int64(bufferSize - 1))\n            )\n            XCTAssertEqual(emptyChunk.readableBytes, 0)\n\n            // Write one more byte to flush out the buffer.\n            try await writer.write(contentsOf: ByteBuffer(repeating: 1, count: 1))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Try to read now that the bytes have been finished.\n            let chunk = try await file.readChunk(\n                fromAbsoluteOffset: Int64(bufferSize),\n                length: .bytes(Int64(bufferSize))\n            )\n            XCTAssertEqual(chunk, ByteBuffer(repeating: 1, count: bufferSize))\n        }\n    }\n\n    func testBufferedWriterAsyncSequenceOfByteBuffer() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        let buffers = AsyncStream<ByteBuffer> { continuation in\n            continuation.yield(ByteBuffer(repeating: 0, count: 1024))\n            continuation.yield(ByteBuffer(repeating: 1, count: 1024))\n            continuation.yield(ByteBuffer(repeating: 2, count: 1024))\n            continuation.finish()\n        }\n\n        try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let bufferSize = 8192\n            var writer = file.bufferedWriter(capacity: .bytes(Int64(bufferSize)))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            // Write the buffers.\n            try await writer.write(contentsOf: buffers)\n            XCTAssertEqual(writer.bufferedBytes, 1024 * 3)\n\n            // Try to read the as-yet-unwritten bytes.\n            let emptyChunk = try await file.readChunk(\n                fromAbsoluteOffset: 0,\n                length: .bytes(Int64(1024 * 3))\n            )\n            XCTAssertEqual(emptyChunk.readableBytes, 0)\n\n            // Flush the buffer.\n            try await writer.flush()\n\n            // Try to read now that the bytes have been finished.\n            var chunk = try await file.readChunk(fromAbsoluteOffset: 0, length: .bytes(1024 * 3))\n            XCTAssertEqual(chunk.readableBytes, 1024 * 3)\n            XCTAssertEqual(chunk.readSlice(length: 1024), ByteBuffer(repeating: 0, count: 1024))\n            XCTAssertEqual(chunk.readSlice(length: 1024), ByteBuffer(repeating: 1, count: 1024))\n            XCTAssertEqual(chunk.readSlice(length: 1024), ByteBuffer(repeating: 2, count: 1024))\n            XCTAssertEqual(chunk.readableBytes, 0)\n        }\n    }\n\n    func testBufferedWriterAsyncSequenceOfBytes() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let bufferSize = 8192\n            var writer = file.bufferedWriter(capacity: .bytes(Int64(bufferSize)))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            let streamOfBytes = AsyncStream(UInt8.self) { continuation in\n                for _ in 0..<16384 {\n                    continuation.yield(0)\n                }\n                continuation.finish()\n            }\n\n            var written = try await writer.write(contentsOf: streamOfBytes)\n            XCTAssertEqual(written, 16384)\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            let streamOfChunks = AsyncStream([UInt8].self) { continuation in\n                for _ in stride(from: 0, to: 16384, by: 1024) {\n                    continuation.yield(Array(repeating: 0, count: 1024))\n                }\n                continuation.finish()\n            }\n\n            written = try await writer.write(contentsOf: streamOfChunks)\n            XCTAssertEqual(written, 16384)\n            XCTAssertEqual(writer.bufferedBytes, 0)\n\n            let bytes = try await file.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n            XCTAssertEqual(bytes.readableBytes, 16384 * 2)\n            XCTAssertTrue(bytes.readableBytesView.allSatisfy { $0 == 0 })\n        }\n    }\n\n    func testBufferedWriterManualFlushing() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            var writer = file.bufferedWriter(capacity: .bytes(1024))\n            try await writer.write(contentsOf: Array(repeating: 0, count: 128))\n            XCTAssertEqual(writer.bufferedBytes, 128)\n\n            try await writer.flush()\n            XCTAssertEqual(writer.bufferedBytes, 0)\n        }\n    }\n\n    // Tests the 'withBufferedWriter()' convenience method.\n    func testBufferedWriterAutomaticFlushing() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        let writtenBytes = try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            try await file.withBufferedWriter(\n                capacity: .bytes(1024),\n                execute: { writer in\n                    try await writer.write(\n                        contentsOf: Array(repeating: 0, count: 128)\n                    )\n                }\n            )\n        }\n        XCTAssertEqual(writtenBytes, 128)\n\n        guard let fileInfo = try await fs.info(forFileAt: path) else {\n            XCTFail()\n            return\n        }\n\n        // Test that the newly created file contains all the 128 characters.\n        XCTAssertEqual(fileInfo.size, 128)\n    }\n\n    func testBufferedWriterReclaimsStorageAfterLargeWrite() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n\n        try await fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let bufferSize = 128\n            var writer = file.bufferedWriter(capacity: .bytes(Int64(bufferSize)))\n            XCTAssertEqual(writer.bufferCapacity, 0)\n\n            // Fill up the buffer. The capacity should be >= the buffer size.\n            try await writer.write(contentsOf: Array(repeating: 0, count: bufferSize))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n            XCTAssertGreaterThanOrEqual(writer.bufferCapacity, bufferSize)\n\n            // Writes which take its internal buffer capacity over double its configured capacity\n            // will result in memory being reclaimed.\n            let doubleSize = bufferSize * 2\n            try await writer.write(contentsOf: Array(repeating: 1, count: doubleSize + 1))\n            XCTAssertEqual(writer.bufferedBytes, 0)\n            XCTAssertEqual(writer.bufferCapacity, 0)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/ConvenienceTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class ConvenienceTests: XCTestCase {\n    static let fs = FileSystem.shared\n\n    func testWriteStringToFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        let bytesWritten = try await \"some text\".write(toFileAt: path)\n        XCTAssertEqual(bytesWritten, 9)\n\n        let bytes = try await ByteBuffer(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n        XCTAssertEqual(bytes, ByteBuffer(string: \"some text\"))\n    }\n\n    func testWriteSequenceToFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        let byteSequence = stride(from: UInt8(0), to: UInt8(64), by: 1)\n        let bytesWritten = try await byteSequence.write(toFileAt: path)\n        XCTAssertEqual(bytesWritten, 64)\n\n        let bytes = try await ByteBuffer(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n        XCTAssertEqual(bytes, ByteBuffer(bytes: byteSequence))\n    }\n\n    func testWriteAsyncSequenceOfBytesToFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        let stream = AsyncStream(UInt8.self) { continuation in\n            for byte in UInt8(0)..<64 {\n                continuation.yield(byte)\n            }\n            continuation.finish()\n        }\n\n        let bytesWritten = try await stream.write(toFileAt: path)\n        XCTAssertEqual(bytesWritten, 64)\n\n        let bytes = try await ByteBuffer(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n        XCTAssertEqual(bytes, ByteBuffer(bytes: Array(0..<64)))\n    }\n\n    func testWriteAsyncSequenceOfChunksToFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        let stream = AsyncStream([UInt8].self) { continuation in\n            for lowerByte in stride(from: UInt8(0), to: 64, by: 8) {\n                continuation.yield(Array(lowerByte..<lowerByte + 8))\n            }\n            continuation.finish()\n        }\n\n        let bytesWritten = try await stream.write(toFileAt: path)\n        XCTAssertEqual(bytesWritten, 64)\n\n        let bytes = try await ByteBuffer(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n        XCTAssertEqual(bytes, ByteBuffer(bytes: Array(0..<64)))\n    }\n\n    // MARK: - String + FileSystem\n\n    func testStringFromFullFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        try await \"some text\".write(toFileAt: path)\n\n        let string = try await String(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n        XCTAssertEqual(string, \"some text\")\n    }\n\n    func testStringFromPartOfAFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        try await \"some text\".write(toFileAt: path)\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await String(contentsOf: path, maximumSizeAllowed: .bytes(4))\n        }\n    }\n\n    // MARK: - Array + FileSystem\n    func testArrayFromFullFile() async throws {\n        let path = try await Self.fs.temporaryFilePath()\n        try await Array(\"some text\".utf8).write(toFileAt: path)\n        let array = try await Array(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n        XCTAssertEqual(array, Array(\"some text\".utf8))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/FileHandleTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n@_spi(Testing) import NIOFS\nimport NIOFoundationCompat\nimport NIOPosix\nimport XCTest\n\n@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)\nfinal class FileHandleTests: XCTestCase {\n    static let thisFile = FilePath(#filePath)\n    static let testData = FilePath(#filePath)\n        .removingLastComponent()  // FileHandleTests.swift\n        .appending(\"Test Data\")\n        .lexicallyNormalized()\n\n    private static func temporaryFileName() -> FilePath {\n        FilePath(\"swift-filesystem-tests-\\(UInt64.random(in: .min ... .max))\")\n    }\n\n    func withTemporaryFile(\n        autoClose: Bool = true,\n        _ execute: @Sendable (SystemFileHandle) async throws -> Void\n    ) async throws {\n        let path = try await FilePath(\"\\(FileSystem.shared.temporaryDirectory)/\\(Self.temporaryFileName())\")\n        defer {\n            // Remove the file when we're done.\n            XCTAssertNoThrow(try Libc.remove(path).get())\n        }\n\n        try await withHandle(\n            forFileAtPath: path,\n            accessMode: .readWrite,\n            options: [.create, .exclusiveCreate],\n            permissions: .ownerReadWrite,\n            autoClose: autoClose\n        ) { handle in\n            try await execute(handle)\n        }\n    }\n\n    func withTestDataDirectory(\n        autoClose: Bool = true,\n        _ execute: @Sendable (SystemFileHandle) async throws -> Void\n    ) async throws {\n        try await self.withHandle(\n            forFileAtPath: Self.testData,\n            accessMode: .readOnly,\n            options: [.directory, .nonBlocking],\n            autoClose: autoClose\n        ) {\n            try await execute($0)\n        }\n    }\n\n    private static func removeFile(atPath path: FilePath) {\n        XCTAssertNoThrow(try Libc.remove(path).get())\n    }\n\n    func withHandle(\n        forFileAtPath path: FilePath,\n        accessMode: FileDescriptor.AccessMode = .readOnly,\n        options: FileDescriptor.OpenOptions = [],\n        permissions: FilePermissions? = nil,\n        autoClose: Bool = true,\n        _ execute: @Sendable (SystemFileHandle) async throws -> Void\n    ) async throws {\n        let descriptor = try FileDescriptor.open(\n            path,\n            accessMode,\n            options: options,\n            permissions: permissions\n        )\n        let handle = SystemFileHandle(\n            takingOwnershipOf: descriptor,\n            path: path,\n            threadPool: .singleton\n        )\n\n        do {\n            try await execute(handle)\n            if autoClose {\n                try? await handle.close()\n            }\n        } catch let skip as XCTSkip {\n            try? await handle.close()\n            throw skip\n        } catch {\n            XCTFail(\"Test threw error: '\\(error)'\")\n            // Always close on error.\n            try await handle.close()\n        }\n    }\n\n    func testInfo() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            let info = try await handle.info()\n            // It's hard to make more assertions than this...\n            XCTAssertEqual(info.type, .regular)\n            XCTAssertGreaterThan(info.size, 1024)\n        }\n\n        try await self.withTemporaryFile { handle in\n            let info = try await handle.info()\n            // It's hard to make more assertions than this...\n            XCTAssertEqual(info.type, .regular)\n            XCTAssertEqual(info.size, 0)\n        }\n    }\n\n    func testExtendedAttributes() async throws {\n        let attribute = \"attribute-name\"\n        try await self.withTemporaryFile { handle in\n            do {\n                // We just created this but we can't assert that there won't be any attributes\n                // (who knows what the filesystem will do?) so we'll use this number as a baseline.\n                var originalAttributes = try await handle.attributeNames()\n                originalAttributes.sort()\n\n                // There should be no value for this attribute, yet.\n                let value = try await handle.valueForAttribute(attribute)\n                XCTAssertEqual(value, [])\n\n                // Set a value.\n                let someBytes = Array(\"hello, world\".utf8)\n                try await handle.updateValueForAttribute(someBytes, attribute: attribute)\n\n                // Retrieve it again.\n                let retrieved = try await handle.valueForAttribute(attribute)\n                XCTAssertEqual(retrieved, someBytes)\n\n                // There should be an attribute now.\n                let attributes = try await handle.attributeNames()\n                XCTAssert(Set(attributes).isSuperset(of: originalAttributes))\n\n                // Remove it.\n                try await handle.removeValueForAttribute(attribute)\n\n                // Should be back to the original values.\n                var maybeOriginalAttributes = try await handle.attributeNames()\n                maybeOriginalAttributes.sort()\n                XCTAssertEqual(originalAttributes, maybeOriginalAttributes)\n            } catch let error as FileSystemError where error.code == .unsupported {\n                throw XCTSkip(\"Extended attributes are not supported on this platform.\")\n            }\n        }\n    }\n\n    func testListExtendedAttributes() async throws {\n        try await self.withTemporaryFile { handle in\n            do {\n                // Set some attributes.\n                let attributeNames = Set((0..<5).map { \"attr-\\($0)\" })\n                for attribute in attributeNames {\n                    try await handle.updateValueForAttribute([0, 1, 2], attribute: attribute)\n                }\n\n                // List the attributes.\n                let attributes = try await handle.attributeNames()\n                XCTAssert(Set(attributes).isSuperset(of: attributeNames))\n            } catch let error as FileSystemError where error.code == .unsupported {\n                throw XCTSkip(\"Extended attributes are not supported on this platform.\")\n            }\n        }\n    }\n\n    func testUpdatePermissions() async throws {\n        try await self.withTemporaryFile { handle in\n            let info = try await handle.info()\n            // Default permissions we use for temporary files.\n            XCTAssertEqual(info.permissions, .ownerReadWrite)\n\n            try await handle.replacePermissions(.ownerReadWriteExecute)\n            let actual = try await handle.info().permissions\n            XCTAssertEqual(actual, .ownerReadWriteExecute)\n        }\n    }\n\n    func testAddPermissions() async throws {\n        try await self.withTemporaryFile { handle in\n            let info = try await handle.info()\n            // Default permissions we use for temporary files.\n            XCTAssertEqual(info.permissions, .ownerReadWrite)\n\n            let computed = try await handle.addPermissions(.ownerExecute)\n            let actual = try await handle.info().permissions\n            XCTAssertEqual(computed, actual)\n            XCTAssertEqual(computed, .ownerReadWriteExecute)\n        }\n    }\n\n    func testRemovePermissions() async throws {\n        try await self.withTemporaryFile { handle in\n            let info = try await handle.info()\n            // Default permissions we use for temporary files.\n            XCTAssertEqual(info.permissions, .ownerReadWrite)\n\n            // Set execute so we can remove it.\n            try await handle.replacePermissions(.ownerReadWriteExecute)\n\n            // Remove owner execute.\n            let computed = try await handle.removePermissions(.ownerExecute)\n            let actual = try await handle.info().permissions\n            XCTAssertEqual(computed, actual)\n            XCTAssertEqual(computed, .ownerReadWrite)\n        }\n    }\n\n    func testWithUnsafeDescriptor() async throws {\n        try await self.withTemporaryFile { handle in\n            // Check we can successfully return a value.\n            let value = try await handle.withUnsafeDescriptor { descriptor in\n                42\n            }\n            XCTAssertEqual(value, 42)\n        }\n    }\n\n    func testDetach() async throws {\n        try await self.withTemporaryFile(autoClose: false) { handle in\n            let descriptor = try handle.detachUnsafeFileDescriptor()\n            // We don't need this: just close it.\n            XCTAssertNoThrow(try descriptor.close())\n            // Closing a detached handle is a no-op.\n            try await handle.close()\n            // All other methods should throw.\n            try await Self.testAllMethodsThrowClosed(handle)\n        }\n    }\n\n    func testClose() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile, autoClose: false) { handle in\n            // Close.\n            try await handle.close()\n            // Closing is idempotent: this is fine.\n            try await handle.close()\n            // All other methods should throw.\n            try await Self.testAllMethodsThrowClosed(handle)\n        }\n    }\n\n    func testReadChunk() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            do {\n                // Zero offset.\n                let bytes = try await handle.readChunk(fromAbsoluteOffset: 0, length: .bytes(80))\n                let line = String(buffer: bytes)\n                XCTAssertEqual(line, \"//===----------------------------------------------------------------------===//\")\n            }\n\n            do {\n                // Non-zero offset.\n                let bytes = try await handle.readChunk(fromAbsoluteOffset: 5, length: .bytes(10))\n                let line = String(buffer: bytes)\n                XCTAssertEqual(line, \"----------\")\n            }\n\n            do {\n                // Length longer than file.\n                let info = try await handle.info()\n                let bytes = try await handle.readChunk(\n                    fromAbsoluteOffset: 0,\n                    length: .bytes(info.size + 10)\n                )\n                // Bytes should not be larger than the file.\n                XCTAssertEqual(bytes.readableBytes, Int(info.size))\n            }\n        }\n    }\n\n    func testReadWholeFile() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            // Check errors are thrown if we don't allow enough bytes.\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await handle.readToEnd(maximumSizeAllowed: .bytes(0))\n            } onError: { error in\n                XCTAssertEqual(error.code, .resourceExhausted)\n            }\n\n            // Validate that we can read the whole file when at the limit.\n            let info = try await handle.info()\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(info.size))\n            // Compare against the data as read by Foundation.\n            let readByFoundation = try Data(contentsOf: URL(fileURLWithPath: Self.thisFile.string))\n            XCTAssertEqual(\n                contents,\n                ByteBuffer(data: readByFoundation),\n                \"Contents of \\(Self.thisFile) differ to that read by Foundation\"\n            )\n        }\n    }\n\n    func testWriteAndReadUnseekableFile() async throws {\n        let privateTempDirPath = try await FileSystem.shared.createTemporaryDirectory(template: \"test-XXX\")\n        self.addTeardownBlock {\n            try await FileSystem.shared.removeItem(at: privateTempDirPath, recursively: true)\n        }\n\n        let fifoPath = FilePath(privateTempDirPath).appending(\"fifo\")\n        guard mkfifo(fifoPath.string, 0o644) == 0 else {\n            XCTFail(\"Error calling mkfifo.\")\n            return\n        }\n\n        try await self.withHandle(forFileAtPath: fifoPath, accessMode: .readWrite) {\n            handle in\n            let someBytes = ByteBuffer(repeating: 42, count: 1546)\n            try await handle.write(contentsOf: someBytes.readableBytesView, toAbsoluteOffset: 0)\n\n            let readSomeBytes = try await handle.readToEnd(maximumSizeAllowed: .bytes(1546))\n            XCTAssertEqual(readSomeBytes, someBytes)\n        }\n    }\n\n    func testWriteAndReadUnseekableFileOverMaximumSizeAllowedThrowsError() async throws {\n        let privateTempDirPath = try await FileSystem.shared.createTemporaryDirectory(template: \"test-XXX\")\n        self.addTeardownBlock {\n            try await FileSystem.shared.removeItem(at: privateTempDirPath, recursively: true)\n        }\n\n        let fifoPath = FilePath(privateTempDirPath).appending(\"fifo\")\n        guard mkfifo(fifoPath.string, 0o644) == 0 else {\n            XCTFail(\"Error calling mkfifo.\")\n            return\n        }\n\n        try await self.withHandle(forFileAtPath: fifoPath, accessMode: .readWrite) {\n            handle in\n            let someBytes = [UInt8](repeating: 42, count: 10)\n            try await handle.write(contentsOf: someBytes, toAbsoluteOffset: 0)\n\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await handle.readToEnd(maximumSizeAllowed: .bytes(9))\n            } onError: { error in\n                XCTAssertEqual(error.code, .resourceExhausted)\n            }\n        }\n    }\n\n    func testWriteAndReadUnseekableFileWithOffsetsThrows() async throws {\n        let privateTempDirPath = try await FileSystem.shared.createTemporaryDirectory(template: \"test-XXX\")\n        self.addTeardownBlock {\n            try await FileSystem.shared.removeItem(at: privateTempDirPath, recursively: true)\n        }\n\n        let fifoPath = FilePath(privateTempDirPath).appending(\"fifo\")\n        guard mkfifo(fifoPath.string, 0o644) == 0 else {\n            XCTFail(\"Error calling mkfifo.\")\n            return\n        }\n\n        try await self.withHandle(forFileAtPath: fifoPath, accessMode: .readWrite) {\n            handle in\n            let someBytes = [UInt8](repeating: 42, count: 1546)\n\n            await XCTAssertThrowsErrorAsync {\n                try await handle.write(contentsOf: someBytes, toAbsoluteOffset: 42)\n                XCTFail(\"Should have thrown\")\n            } onError: { error in\n                let fileSystemError = error as! FileSystemError\n                XCTAssertEqual(fileSystemError.code, .unsupported)\n                XCTAssertEqual(fileSystemError.message, \"File is unseekable.\")\n            }\n\n            await XCTAssertThrowsErrorAsync {\n                _ = try await handle.readToEnd(fromAbsoluteOffset: 42, maximumSizeAllowed: .bytes(1))\n                XCTFail(\"Should have thrown\")\n            } onError: { error in\n                let fileSystemError = error as! FileSystemError\n                XCTAssertEqual(fileSystemError.code, .unsupported)\n                XCTAssertEqual(fileSystemError.message, \"File is unseekable.\")\n            }\n        }\n    }\n\n    func testReadWholeFileWithOffsets() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            let info = try await handle.info()\n\n            // We should be able to do a zero-length read at the end of the file with a max size\n            // allowed of zero.\n            let empty = try await handle.readToEnd(\n                fromAbsoluteOffset: info.size,\n                maximumSizeAllowed: .bytes(0)\n            )\n            XCTAssertEqual(empty.readableBytes, 0)\n\n            // Read the last 100 bytes.\n            let bytes = try await handle.readToEnd(\n                fromAbsoluteOffset: info.size - 100,\n                maximumSizeAllowed: .bytes(100)\n            )\n\n            // Compare against the data as read by Foundation.\n            let readByFoundation = try Data(contentsOf: URL(fileURLWithPath: Self.thisFile.string))\n            let tail = readByFoundation.dropFirst(readByFoundation.count - 100)\n            XCTAssertEqual(\n                bytes,\n                ByteBuffer(data: tail),\n                \"Contents of \\(Self.thisFile) differ to that read by Foundation\"\n            )\n        }\n    }\n\n    func testReadFileAsChunks() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            var bytes = ByteBuffer()\n\n            for try await chunk in handle.readChunks(in: ..., chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n\n            var contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n            XCTAssertEqual(\n                bytes,\n                contents,\n                \"\"\"\n                Read \\(bytes.readableBytes) which were different to the \\(contents.readableBytes) expected bytes.\n                \"\"\"\n            )\n\n            // Read from an offset.\n            bytes.clear()\n            for try await chunk in handle.readChunks(in: 100..., chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n\n            contents.moveReaderIndex(forwardBy: 100)\n            XCTAssertEqual(\n                bytes,\n                contents,\n                \"\"\"\n                Read \\(bytes.readableBytes) which were different to the \\(contents.readableBytes) \\\n                expected bytes.\n                \"\"\"\n            )\n        }\n    }\n\n    func testReadEmptyRange() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            // No bytes should be read.\n            for try await _ in handle.readChunks(in: 0..<0, chunkLength: .bytes(128)) {\n                XCTFail(\"We shouldn't read any chunks.\")\n            }\n\n            // No bytes should be read.\n            for try await _ in handle.readChunks(in: 100..<100, chunkLength: .bytes(128)) {\n                XCTFail(\"We shouldn't read any chunks.\")\n            }\n        }\n    }\n\n    enum RangeType {\n        case closed(ClosedRange<Int64>)\n        case partialThrough(PartialRangeThrough<Int64>)\n        case partialUpTo(PartialRangeUpTo<Int64>)\n    }\n\n    static func testReadEndOffsetExceedsEOF(range: RangeType, handle: SystemFileHandle) async throws {\n        var bytes = ByteBuffer()\n        let fileChunks: FileChunks\n\n        switch range {\n        case .closed(let offsets):\n            fileChunks = handle.readChunks(in: offsets, chunkLength: .bytes(128))\n        case .partialUpTo(let offsets):\n            fileChunks = handle.readChunks(in: offsets, chunkLength: .bytes(128))\n        case .partialThrough(let offsets):\n            fileChunks = handle.readChunks(in: offsets, chunkLength: .bytes(128))\n        }\n\n        for try await chunk in fileChunks {\n            XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n            bytes.writeImmutableBuffer(chunk)\n        }\n\n        // We should read bytes only before the EOF.\n        let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n        XCTAssertEqual(bytes, contents)\n    }\n\n    func testReadEndOffsetExceedsEOFClosedrange() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            let info = try await handle.info()\n            try await Self.testReadEndOffsetExceedsEOF(\n                range: .closed(0...(info.size + 3)),\n                handle: handle\n            )\n        }\n    }\n\n    func testReadEndOffsetExceedsEOFPartialThrough() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            let info = try await handle.info()\n            try await Self.testReadEndOffsetExceedsEOF(\n                range: .partialThrough(...(info.size + 3)),\n                handle: handle\n            )\n        }\n    }\n\n    func testReadEndOffsetExceedsEOFPartialUpTo() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            let info = try await handle.info()\n            try await Self.testReadEndOffsetExceedsEOF(\n                range: .partialUpTo(..<(info.size + 3)),\n                handle: handle\n            )\n        }\n    }\n\n    func testReadRangeShorterThanChunklength() async throws {\n        // Reading chunks of bytes from within a range that is shorter than the chunklength\n        // and the length of the file.\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            var bytes = ByteBuffer()\n            for try await chunk in handle.readChunks(in: 0...120, chunkLength: .bytes(128)) {\n                XCTAssertEqual(chunk.readableBytes, 121)\n                bytes.writeImmutableBuffer(chunk)\n            }\n\n            // We should only read bytes from within the range.\n            XCTAssertEqual(\n                bytes.readableBytes,\n                121,\n                \"\"\"\n                Read \\(bytes.readableBytes) which were different to the 121 \\\n                expected bytes.\n                \"\"\"\n            )\n        }\n    }\n\n    func testReadRangeLongerThanChunkAndNotMultipleOfChunkLength() async throws {\n        // Reading chunks of bytes from within a range longer than the chunklength\n        // and with size not a multiple of the chunklength.\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            var bytes = ByteBuffer()\n            for try await chunk in handle.readChunks(in: 0...200, chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n\n            // We should only read bytes from within the range.\n            XCTAssertEqual(\n                bytes.readableBytes,\n                201,\n                \"\"\"\n                Read \\(bytes.readableBytes) which were different to the 201 \\\n                expected bytes.\n                \"\"\"\n            )\n        }\n    }\n\n    func testReadPartialFromRange() async throws {\n        // Reading chunks of bytes from a PartialRangeFrom.\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            var bytes = ByteBuffer()\n            for try await chunk in handle.readChunks(in: 0..., chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n\n            // We should read bytes until EOF.\n            XCTAssertEqual(\n                bytes.readableBytes,\n                contents.readableBytes,\n                \"\"\"\n                Read \\(bytes.readableBytes) which were different to the \\(contents.readableBytes) \\\n                expected bytes.\n                \"\"\"\n            )\n        }\n    }\n\n    func testUnboundedRange() async throws {\n        // Reading chunks of bytes from an UnboundedRange.\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            var bytes = ByteBuffer()\n            for try await chunk in handle.readChunks(in: ..., chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n\n            // We should read bytes until EOF.\n            XCTAssertEqual(\n                bytes.readableBytes,\n                contents.readableBytes,\n                \"\"\"\n                Read \\(bytes.readableBytes) which were different to the \\(contents.readableBytes) \\\n                expected bytes.\n                \"\"\"\n            )\n        }\n    }\n\n    func testReadPartialRange() async throws {\n        // Reading chunks of bytes from a PartialRangeThrough with the upper bound inside the file.\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            var bytes = ByteBuffer()\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n\n            for try await chunk in handle.readChunks(in: ...200, chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n\n            // We should read the first bytes from the beginning of the file, until reaching the\n            // upper bound of the range (inclusive).\n            XCTAssertEqual(bytes, contents.getSlice(at: contents.readerIndex, length: 201))\n\n            bytes.clear()\n\n            for try await chunk in handle.readChunks(in: ..<200, chunkLength: .bytes(128)) {\n                XCTAssertLessThanOrEqual(chunk.readableBytes, 128)\n                bytes.writeImmutableBuffer(chunk)\n            }\n\n            // We should read the first bytes from the beginning of the file, until reaching the\n            // upper bound of the range (inclusive).\n            XCTAssertEqual(bytes, contents.getSlice(at: contents.readerIndex, length: 200))\n        }\n    }\n\n    func testReadChunksOverloadAmbiguity() async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile) { handle in\n            // Seven possibilities for range:\n            // 1. ...\n            // 2. x...y\n            // 3. x..<y\n            // 4. x...\n            // 5. ..<y\n            // 6. ...y\n            // 7. no value (i.e. default)\n            //\n            // Two possibilities for chunk length:\n            // 1. value\n            // 2. no value (i.e. default)\n            //\n            // Two possibilities for type:\n            // 1. value\n            // 2. no value (i.e. default)\n            //\n            // This makes 28 combinations which should all be representable.\n\n            // Unbounded range.\n            _ = handle.readChunks(in: ..., chunkLength: .mebibytes(1))\n            _ = handle.readChunks(in: ...)\n\n            // Closed range.\n            _ = handle.readChunks(in: 0...1, chunkLength: .mebibytes(1))\n            _ = handle.readChunks(in: 0...1)\n\n            // Range.\n            _ = handle.readChunks(in: 0..<1, chunkLength: .mebibytes(1))\n            _ = handle.readChunks(in: 0..<1)\n\n            // Partial range from.\n            _ = handle.readChunks(in: 0..., chunkLength: .mebibytes(1))\n            _ = handle.readChunks(in: 0...)\n\n            // Partial range up to.\n            _ = handle.readChunks(in: ..<1, chunkLength: .mebibytes(1))\n            _ = handle.readChunks(in: ..<1)\n\n            // Partial range through.\n            _ = handle.readChunks(in: ...1, chunkLength: .mebibytes(1))\n            _ = handle.readChunks(in: ...1)\n\n            // No range.\n            _ = handle.readChunks(chunkLength: .mebibytes(1))\n            _ = handle.readChunks()\n        }\n    }\n\n    func testCloseWhileReadingFromFile() async throws {\n        try await self.testCloseOrDetachMidRead(close: true)\n    }\n\n    func testDetachWhileReadingFromFile() async throws {\n        try await self.testCloseOrDetachMidRead(close: false)\n    }\n\n    func testCloseBeforeReadingFromFile() async throws {\n        try await self.testCloseOrDetachBeforeRead(close: true)\n    }\n\n    func testDetachBeforeReadingFromFile() async throws {\n        try await self.testCloseOrDetachBeforeRead(close: false)\n    }\n\n    private func testCloseOrDetachMidRead(close: Bool) async throws {\n        func testCloseWhileReadingFromFile() async throws {\n            try await self.withHandle(forFileAtPath: Self.thisFile, autoClose: false) { handle in\n                var bytes = ByteBuffer()\n                var iterator = handle.readChunks(chunkLength: .bytes(1)).makeAsyncIterator()\n                // Read the first 10 bytes.\n                for _ in 0..<10 {\n                    if let chunk = try await iterator.next() {\n                        bytes.writeImmutableBuffer(chunk)\n                    }\n                }\n\n                XCTAssertEqual(bytes.readableBytes, 10)\n\n                // Closing (or detaching) mid-read is weird but we should tolerate it.\n                if close {\n                    try await handle.close()\n                } else {\n                    let descriptor = try handle.detachUnsafeFileDescriptor()\n                    try descriptor.close()\n                }\n\n                // Resume iteration: we will be able to read any buffered bytes before the iterator\n                // eventually throws as it tries to read more from a closed file. We tolerate any number\n                // of buffered chunks (including zero).\n                do {\n                    while let next = try await iterator.next() {\n                        bytes.writeImmutableBuffer(next)\n                    }\n                    XCTFail(\"Iterator did not eventually throw for closed file.\")\n                } catch let error as FileSystemError {\n                    XCTAssertEqual(error.code, .closed)\n                    // The cause *shouldn't* be a system call failure: we should catch the close in\n                    // user space rather than the kernel trying to read from an already closed\n                    // descriptor (the descriptor value may be reused by a newly opened file).\n                    XCTAssertFalse(error.cause is FileSystemError.SystemCallError)\n                }\n            }\n        }\n    }\n\n    private func testCloseOrDetachBeforeRead(close: Bool) async throws {\n        try await self.withHandle(forFileAtPath: Self.thisFile, autoClose: false) { handle in\n            if close {\n                try await handle.close()\n            } else {\n                let descriptor = try handle.detachUnsafeFileDescriptor()\n                try descriptor.close()\n            }\n\n            var iterator = handle.readChunks().makeAsyncIterator()\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await iterator.next()\n            } onError: { error in\n                XCTAssertEqual(error.code, .closed)\n            }\n        }\n    }\n\n    func testWriteBytes() async throws {\n        try await withTemporaryFile { handle in\n            let someBytes = ByteBuffer(repeating: 42, count: 1024)\n            try await handle.write(contentsOf: someBytes.readableBytesView, toAbsoluteOffset: 0)\n\n            let readSomeBytes = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(readSomeBytes, someBytes)\n\n            let moreBytes = ByteBuffer(repeating: 13, count: 1024)\n            try await handle.write(contentsOf: moreBytes.readableBytesView, toAbsoluteOffset: 512)\n\n            let readMoreBytes = try await handle.readToEnd(\n                fromAbsoluteOffset: 512,\n                maximumSizeAllowed: .bytes(1024)\n            )\n            XCTAssertEqual(readMoreBytes, moreBytes)\n\n            var allTheBytes = try await handle.readToEnd(maximumSizeAllowed: .bytes(1536))\n            let firstBytes = allTheBytes.readSlice(length: 512)!\n            XCTAssertTrue(firstBytes.readableBytesView.allSatisfy({ $0 == 42 }))\n            XCTAssertTrue(allTheBytes.readableBytesView.allSatisfy({ $0 == 13 }))\n        }\n    }\n\n    func testWriteByteBuffer() async throws {\n        try await withTemporaryFile { handle in\n            let someBytes = ByteBuffer(repeating: 42, count: 1024)\n            try await handle.write(contentsOf: someBytes, toAbsoluteOffset: 0)\n\n            let readSomeBytes = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(readSomeBytes, someBytes)\n\n            let moreBytes = ByteBuffer(repeating: 13, count: 1024)\n            try await handle.write(contentsOf: moreBytes, toAbsoluteOffset: 512)\n\n            let readMoreBytes = try await handle.readToEnd(\n                fromAbsoluteOffset: 512,\n                maximumSizeAllowed: .bytes(1024)\n            )\n            XCTAssertEqual(readMoreBytes, moreBytes)\n\n            var allTheBytes = try await handle.readToEnd(maximumSizeAllowed: .bytes(1536))\n            let firstBytes = allTheBytes.readSlice(length: 512)!\n            XCTAssertTrue(firstBytes.readableBytesView.allSatisfy({ $0 == 42 }))\n            XCTAssertTrue(allTheBytes.readableBytesView.allSatisfy({ $0 == 13 }))\n        }\n    }\n\n    func testWriteSequenceOfBytes() async throws {\n        try await withTemporaryFile { handle in\n            let byteSequence = UInt8(0)..<UInt8(64)\n            var offset = Int64(0)\n            offset += try await Int64(\n                handle.write(contentsOf: byteSequence, toAbsoluteOffset: offset)\n            )\n            XCTAssertEqual(offset, 64)\n            offset += try await Int64(\n                handle.write(contentsOf: byteSequence, toAbsoluteOffset: offset)\n            )\n            XCTAssertEqual(offset, 128)\n\n            let bytes = try await handle.readToEnd(maximumSizeAllowed: .bytes(128))\n            XCTAssertEqual(bytes, ByteBuffer(bytes: Array(byteSequence) + Array(byteSequence)))\n        }\n    }\n\n    private static func testAllMethodsThrowClosed(_ handle: SystemFileHandle) async throws {\n        // All other operations should fail.\n        try await assertThrowsErrorClosed { try await handle.info() }\n        try await assertThrowsErrorClosed { try await handle.withUnsafeDescriptor { _ in } }\n        try await assertThrowsErrorClosed { try handle.detachUnsafeFileDescriptor() }\n        try await assertThrowsErrorClosed { try await handle.synchronize() }\n\n        // Extended attributes\n        try await assertThrowsErrorClosed { try await handle.attributeNames() }\n        try await assertThrowsErrorClosed { try await handle.valueForAttribute(\"foo\") }\n        try await assertThrowsErrorClosed {\n            try await handle.updateValueForAttribute([], attribute: \"foo\")\n        }\n        try await assertThrowsErrorClosed { try await handle.removeValueForAttribute(\"foo\") }\n\n        // Permissions\n        let perms = FilePermissions.ownerReadWrite\n        try await assertThrowsErrorClosed { try await handle.replacePermissions(perms) }\n        try await assertThrowsErrorClosed { try await handle.addPermissions(perms) }\n        try await assertThrowsErrorClosed { try await handle.removePermissions(perms) }\n    }\n\n    func testListContents() async throws {\n        try await self.withTestDataDirectory { handle in\n            let entries = try await handle.listContents()\n                .reduce(into: []) { $0.append($1) }\n            Self.verifyContentsOfTestData(entries)\n        }\n    }\n\n    func testListContentsRecursively() async throws {\n        try await self.withTestDataDirectory { handle in\n            let entries = try await handle.listContents(recursive: true)\n                .reduce(into: []) { $0.append($1) }\n            Self.verifyContentsOfTestData(entries, recursive: true)\n        }\n    }\n\n    func testListContentsBatched() async throws {\n        try await self.withTestDataDirectory { handle in\n            let entries = try await handle.listContents()\n                .batched()\n                .reduce(into: []) { $0.append(contentsOf: $1) }\n            Self.verifyContentsOfTestData(entries)\n        }\n    }\n\n    func testListContentsRecursivelyBatched() async throws {\n        try await self.withTestDataDirectory { handle in\n            let entries = try await handle.listContents(recursive: true)\n                .batched()\n                .reduce(into: []) { $0.append(contentsOf: $1) }\n            Self.verifyContentsOfTestData(entries, recursive: true)\n        }\n    }\n\n    private static func verifyContentsOfTestData(\n        _ entries: [DirectoryEntry],\n        recursive: Bool = false\n    ) {\n        var expected: [DirectoryEntry] = [\n            .init(path: NIOFilePath(Self.testData.appending(\"README.md\")), type: .regular)!,\n            .init(path: NIOFilePath(Self.testData.appending(\"Foo\")), type: .directory)!,\n            .init(path: NIOFilePath(Self.testData.appending(\"README.md.symlink\")), type: .symlink)!,\n            .init(path: NIOFilePath(Self.testData.appending(\"Foo.symlink\")), type: .symlink)!,\n        ]\n\n        if recursive {\n            let path = Self.testData.appending([\"Foo\", \"README.txt\"])\n            expected.append(.init(path: NIOFilePath(path), type: .regular)!)\n        }\n\n        for entry in expected {\n            XCTAssert(entries.contains(entry), \"Did not find expected entry '\\(entry)'\")\n        }\n    }\n\n    func testOpenRelativeDirectory() async throws {\n        try await self.withTestDataDirectory { testData in\n            for path in [\"Foo\", \"Foo.symlink\"] {\n                // Open a subdirectory.\n                try await testData.withDirectoryHandle(atPath: NIOFilePath(path)) { foo in\n                    let fooInfo = try await foo.info()\n                    XCTAssertEqual(fooInfo.type, .directory)\n\n                    // Open its parent, i.e. back to \"Test Data\".\n                    try await foo.withDirectoryHandle(atPath: \"..\") { fooParent in\n                        let fooParentInfo = try await fooParent.info()\n                        XCTAssertEqual(fooParentInfo.type, .directory)\n\n                        let entries = try await fooParent.listContents()\n                            .reduce(into: []) { $0.append($1) }\n\n                        Self.verifyContentsOfTestData(entries)\n                    }\n                }\n            }\n        }\n    }\n\n    func testOpenRelativeFile() async throws {\n        try await self.withTestDataDirectory { testData in\n            // Open a regular file.\n            let contents = try await testData.withFileHandle(forReadingAt: \"README.md\") { file in\n                let info = try await file.info()\n                XCTAssertEqual(info.type, .regular)\n                return try await file.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n            }\n\n            // Open the symlink should open the target.\n            try await testData.withFileHandle(forReadingAt: \"README.md.symlink\") { file in\n                let info = try await file.info()\n                XCTAssertEqual(info.type, .regular)\n\n                let other = try await file.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n                XCTAssertEqual(contents, other)\n            }\n        }\n    }\n\n    func testOpenCreateForFileWhichExists() async throws {\n        try await self.withTestDataDirectory { dir in\n            try await dir.withFileHandle(\n                forWritingAt: \"README.md\",\n                options: .modifyFile(createIfNecessary: true)\n            ) { file in\n                let info = try await file.info()\n                XCTAssertEqual(info.type, .regular)\n                XCTAssertGreaterThan(info.size, 0)\n            }\n        }\n    }\n\n    func testOpenCreateForFileWhichDoesNotExist() async throws {\n        try await self.withTestDataDirectory { dir in\n            let path = Self.temporaryFileName()\n            defer {\n                Self.removeFile(atPath: Self.testData.appending(path.string))\n            }\n\n            try await dir.withFileHandle(\n                forWritingAt: NIOFilePath(path),\n                options: .modifyFile(createIfNecessary: true)\n            ) { handle in\n                let info = try await handle.info()\n                XCTAssertEqual(info.size, 0)\n                XCTAssertEqual(info.type, .regular)\n            }\n        }\n    }\n\n    func testOpenExclusiveCreateForFileWhichExists() async throws {\n        try await self.withTestDataDirectory { dir in\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await dir.withFileHandle(\n                    forWritingAt: \"README.md\",\n                    options: .newFile(replaceExisting: false)\n                ) { _ in\n                }\n            } onError: { error in\n                XCTAssertEqual(error.code, .fileAlreadyExists)\n            }\n        }\n    }\n\n    func testOpenExclusiveCreateForFileWhichExistsWithoutOTMPFILE() async throws {\n        // Takes the path where 'O_TMPFILE' doesn't exist, so materializing the file is done via\n        // creating a temporary file and then renaming it using 'renamex_np'/'renameat2' (Darwin/Linux).\n        let temporaryDirectory = try await FileSystem.shared.temporaryDirectory\n        let path = FilePath(temporaryDirectory).appending(Self.temporaryFileName().components)\n        let handle = try SystemFileHandle.syncOpenWithMaterialization(\n            atPath: path,\n            mode: .writeOnly,\n            options: [.exclusiveCreate, .create],\n            permissions: .ownerReadWrite,\n            threadPool: .singleton,\n            useTemporaryFileIfPossible: false\n        ).get()\n\n        // Closing shouldn't throw and the file should now be visible.\n        try await handle.close()\n        let info = try await FileSystem.shared.info(forFileAt: NIOFilePath(path))\n        XCTAssertNotNil(info)\n    }\n\n    func testOpenExclusiveCreateForFileWhichExistsWithoutOTMPFILEOrRenameat2() async throws {\n        // Takes the path where 'O_TMPFILE' doesn't exist, so materializing the file is done via\n        // creating a temporary file and then renaming it using 'renameat2' and then takes a further\n        // fallback path where 'renameat2' returns EINVAL so the 'rename' is used in combination\n        // with 'stat'. This path is only reachable on Linux.\n        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        let temporaryDirectory = FilePath(try await FileSystem.shared.temporaryDirectory)\n        let path = temporaryDirectory.appending(Self.temporaryFileName().components)\n        let handle = try SystemFileHandle.syncOpenWithMaterialization(\n            atPath: path,\n            mode: .writeOnly,\n            options: [.exclusiveCreate, .create],\n            permissions: .ownerReadWrite,\n            threadPool: .singleton,\n            useTemporaryFileIfPossible: false\n        ).get()\n\n        // Close, but take the path where 'renameat2' fails with EINVAL. This shouldn't throw and\n        // the file should be available.\n        let result = handle.sendableView._close(materialize: true, failRenameat2WithEINVAL: true)\n        try result.get()\n\n        let info = try await FileSystem.shared.info(forFileAt: NIOFilePath(path))\n        XCTAssertNotNil(info)\n        #else\n        throw XCTSkip(\"This test requires 'renameat2' which isn't supported on this platform\")\n        #endif\n    }\n\n    func testOpenExclusiveCreateForFileWhichDoesNotExist() async throws {\n        try await self.withTestDataDirectory { dir in\n            let path = Self.temporaryFileName()\n            defer {\n                Self.removeFile(atPath: Self.testData.appending(path.string))\n            }\n\n            try await dir.withFileHandle(\n                forWritingAt: NIOFilePath(path),\n                options: .newFile(replaceExisting: false)\n            ) { handle in\n                let info = try await handle.info()\n                XCTAssertEqual(info.size, 0)\n                XCTAssertEqual(info.type, .regular)\n            }\n        }\n    }\n\n    func testOpenCreateOrTruncateForFileWhichExists() async throws {\n        try await self.withTestDataDirectory { dir in\n            let path = Self.temporaryFileName()\n            defer {\n                Self.removeFile(atPath: Self.testData.appending(path.string))\n            }\n\n            // Create a file and write some junk to it. We need to truncate it in a moment.\n            try await dir.withFileHandle(\n                forWritingAt: NIOFilePath(path),\n                options: .newFile(replaceExisting: false)\n            ) { handle in\n                try await handle.write(\n                    contentsOf: Array(repeating: 0, count: 1024),\n                    toAbsoluteOffset: 0\n                )\n                let info = try await handle.info()\n                XCTAssertEqual(info.size, 1024)\n            }\n\n            // Already exists; shouldn't throw.\n            try await dir.withFileHandle(\n                forWritingAt: NIOFilePath(path),\n                options: .newFile(replaceExisting: true)\n            ) { file in\n                let info = try await file.info()\n                XCTAssertEqual(info.type, .regular)\n                XCTAssertGreaterThanOrEqual(info.size, 0)\n            }\n        }\n    }\n\n    func testOpenCreateOrTruncateForFileWhichDoesNotExist() async throws {\n        try await self.withTestDataDirectory { dir in\n            let path = Self.temporaryFileName()\n            defer {\n                Self.removeFile(atPath: Self.testData.appending(path.string))\n            }\n\n            // Should not exist, should not throw.\n            try await dir.withFileHandle(\n                forWritingAt: NIOFilePath(path),\n                options: .newFile(replaceExisting: true)\n            ) { file in\n                let info = try await file.info()\n                XCTAssertEqual(info.type, .regular)\n                XCTAssertGreaterThanOrEqual(info.size, 0)\n            }\n        }\n    }\n\n    func testOpenMustExistForFileWhichExists() async throws {\n        try await self.withTestDataDirectory { dir in\n            // Exists, must not throw.\n            try await dir.withFileHandle(\n                forWritingAt: \"README.md\",\n                options: .modifyFile(createIfNecessary: false)\n            ) { file in\n                let info = try await file.info()\n                XCTAssertEqual(info.type, .regular)\n                XCTAssertGreaterThanOrEqual(info.size, 0)\n            }\n        }\n    }\n\n    func testOpenMustExistForFileWhichDoesNotExist() async throws {\n        try await self.withTestDataDirectory { dir in\n            let path = Self.temporaryFileName()\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await dir.withFileHandle(\n                    forWritingAt: NIOFilePath(path),\n                    options: .modifyFile(createIfNecessary: false)\n                ) { file in\n                    XCTFail(\"Unexpectedly opened \\(path)\")\n                }\n            } onError: { error in\n                XCTAssertEqual(error.code, .notFound)\n            }\n        }\n    }\n\n    func testResizeFile() async throws {\n        try await self.withTemporaryFile { handle in\n            try await handle.write(\n                contentsOf: Array(repeating: 0, count: 1024),\n                toAbsoluteOffset: 0\n            )\n\n            try await handle.resize(to: .bytes(1000))\n            let newSize1 = try await handle.info().size\n            XCTAssertEqual(newSize1, 1000)\n\n            try await handle.resize(to: .bytes(1025))\n            let newSize2 = try await handle.info().size\n            XCTAssertEqual(newSize2, 1025)\n\n            try await handle.resize(to: .bytes(0))\n            let newSize3 = try await handle.info().size\n            XCTAssertEqual(newSize3, 0)\n        }\n    }\n\n    func testResizeFileErrors() async throws {\n        try await self.withTemporaryFile { handle in\n            try await handle.write(\n                contentsOf: Array(repeating: 0, count: 1024),\n                toAbsoluteOffset: 0\n            )\n\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await handle.resize(to: .bytes(-2))\n            } onError: { error in\n                XCTAssertEqual(error.code, .invalidArgument)\n            }\n        }\n    }\n\n    func testSetLastAccesTime() async throws {\n        try await self.withTemporaryFile { handle in\n            let originalLastDataModificationTime = try await handle.info().lastDataModificationTime\n            let originalLastAccessTime = try await handle.info().lastAccessTime\n\n            try await handle.setTimes(\n                lastAccess: FileInfo.Timespec(seconds: 10, nanoseconds: 5),\n                lastDataModification: nil\n            )\n\n            let actualLastAccessTime = try await handle.info().lastAccessTime\n            XCTAssertEqual(actualLastAccessTime, FileInfo.Timespec(seconds: 10, nanoseconds: 5))\n            XCTAssertNotEqual(actualLastAccessTime, originalLastAccessTime)\n\n            let actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime, originalLastDataModificationTime)\n        }\n    }\n\n    func testSetLastDataModificationTime() async throws {\n        try await self.withTemporaryFile { handle in\n            let originalLastDataModificationTime = try await handle.info().lastDataModificationTime\n            let originalLastAccessTime = try await handle.info().lastAccessTime\n\n            try await handle.setTimes(\n                lastAccess: nil,\n                lastDataModification: FileInfo.Timespec(seconds: 10, nanoseconds: 5)\n            )\n\n            let actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime, FileInfo.Timespec(seconds: 10, nanoseconds: 5))\n            XCTAssertNotEqual(actualLastDataModificationTime, originalLastDataModificationTime)\n\n            let actualLastAccessTime = try await handle.info().lastAccessTime\n            XCTAssertEqual(actualLastAccessTime, originalLastAccessTime)\n        }\n    }\n\n    func testSetLastAccessAndLastDataModificationTimes() async throws {\n        try await self.withTemporaryFile { handle in\n            let originalLastDataModificationTime = try await handle.info().lastDataModificationTime\n            let originalLastAccessTime = try await handle.info().lastAccessTime\n\n            try await handle.setTimes(\n                lastAccess: FileInfo.Timespec(seconds: 20, nanoseconds: 25),\n                lastDataModification: FileInfo.Timespec(seconds: 10, nanoseconds: 5)\n            )\n\n            let actualLastAccessTime = try await handle.info().lastAccessTime\n            XCTAssertEqual(actualLastAccessTime, FileInfo.Timespec(seconds: 20, nanoseconds: 25))\n            XCTAssertNotEqual(actualLastAccessTime, originalLastAccessTime)\n\n            let actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime, FileInfo.Timespec(seconds: 10, nanoseconds: 5))\n            XCTAssertNotEqual(actualLastDataModificationTime, originalLastDataModificationTime)\n        }\n    }\n\n    func testSetLastAccessAndLastDataModificationTimesToNil() async throws {\n        try await self.withTemporaryFile { handle in\n            // Set some random value for both times, only to be overwritten by the current time\n            // right after.\n            try await handle.setTimes(\n                lastAccess: FileInfo.Timespec(seconds: 1, nanoseconds: 0),\n                lastDataModification: FileInfo.Timespec(seconds: 1, nanoseconds: 0)\n            )\n\n            var actualLastAccessTime = try await handle.info().lastAccessTime\n            XCTAssertEqual(actualLastAccessTime, FileInfo.Timespec(seconds: 1, nanoseconds: 0))\n\n            var actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime, FileInfo.Timespec(seconds: 1, nanoseconds: 0))\n\n            try await handle.setTimes(\n                lastAccess: nil,\n                lastDataModification: nil\n            )\n            let estimatedCurrentTimeInSeconds = Date.now.timeIntervalSince1970\n\n            // Assert that the times are equal to the current time, with up to a second difference\n            // to avoid timing flakiness. Both the last accessed and last modification times should\n            // also equal each other.\n            actualLastAccessTime = try await handle.info().lastAccessTime\n            let actualLastAccessTimeNanosecondsInSeconds = Double(actualLastAccessTime.nanoseconds) / 1e+9\n            let actualLastAccessTimeInSeconds =\n                Double(actualLastAccessTime.seconds) + actualLastAccessTimeNanosecondsInSeconds\n            XCTAssertEqual(actualLastAccessTimeInSeconds, estimatedCurrentTimeInSeconds, accuracy: 1)\n            actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime.seconds, actualLastAccessTime.seconds)\n        }\n    }\n\n    func testTouchFile() async throws {\n        try await self.withTemporaryFile { handle in\n            // Set some random value for both times, only to be overwritten by the current time\n            // right after.\n            try await handle.setTimes(\n                lastAccess: FileInfo.Timespec(seconds: 1, nanoseconds: 0),\n                lastDataModification: FileInfo.Timespec(seconds: 1, nanoseconds: 0)\n            )\n\n            var actualLastAccessTime = try await handle.info().lastAccessTime\n            XCTAssertEqual(actualLastAccessTime, FileInfo.Timespec(seconds: 1, nanoseconds: 0))\n\n            var actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime, FileInfo.Timespec(seconds: 1, nanoseconds: 0))\n\n            try await handle.touch()\n            let estimatedCurrentTimeInSeconds = Date.now.timeIntervalSince1970\n\n            // Assert that the times are equal to the current time, with up to a second difference\n            // to avoid timing flakiness. Both the last accessed and last modification times should\n            // also equal each other.\n            actualLastAccessTime = try await handle.info().lastAccessTime\n            let actualLastAccessTimeNanosecondsInSeconds = Double(actualLastAccessTime.nanoseconds) / 1e+9\n            let actualLastAccessTimeInSeconds =\n                Double(actualLastAccessTime.seconds) + actualLastAccessTimeNanosecondsInSeconds\n            XCTAssertEqual(actualLastAccessTimeInSeconds, estimatedCurrentTimeInSeconds, accuracy: 1)\n            actualLastDataModificationTime = try await handle.info().lastDataModificationTime\n            XCTAssertEqual(actualLastDataModificationTime.seconds, actualLastAccessTime.seconds)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func assertThrowsErrorClosed<R>(\n    line: UInt = #line,\n    _ expression: () async throws -> R\n) async throws {\n    await XCTAssertThrowsFileSystemErrorAsync {\n        try await expression()\n    } onError: { error in\n        XCTAssertEqual(error.code, .closed)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/FileSystemTests+SPI.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_spi(Testing) import NIOFS\nimport SystemPackage\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemTests {\n    func testRemoveOneItemIgnoresNonExistentFile() async throws {\n        let fs = FileSystem.shared\n        let path = try await fs.temporaryFilePath()\n        let removed = try await fs.removeOneItem(at: FilePath(path))\n        XCTAssertEqual(removed, 0)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/FileSystemTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\n@_spi(Testing) @testable import NIOFS\nimport SystemPackage\nimport XCTest\n\nextension NIOFilePath {\n    static let testData = NIOFilePath(\n        FilePath(#filePath)\n            .removingLastComponent()  // FileHandleTests.swift\n            .appending(\"Test Data\")\n            .lexicallyNormalized()\n    )\n\n    static let testDataReadme = NIOFilePath(Self.testData.underlying.appending(\"README.md\"))\n    static let testDataReadmeSymlink = NIOFilePath(Self.testData.underlying.appending(\"README.md.symlink\"))\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystem {\n    func temporaryFilePath(\n        _ function: String = #function,\n        inTemporaryDirectory: Bool = true\n    ) async throws -> NIOFilePath {\n        if inTemporaryDirectory {\n            let directory = (try await self.temporaryDirectory).underlying\n            return self.temporaryFilePath(function, inDirectory: directory)\n        } else {\n            return self.temporaryFilePath(function, inDirectory: nil)\n        }\n    }\n\n    func temporaryFilePath(\n        _ function: String = #function,\n        inDirectory directory: FilePath?\n    ) -> NIOFilePath {\n        let index = function.firstIndex(of: \"(\")!\n        let functionName = function.prefix(upTo: index)\n        let random = UInt32.random(in: .min ... .max)\n        let fileName = \"\\(functionName)-\\(random)\"\n\n        if let directory = directory {\n            return NIOFilePath(directory.appending(fileName))\n        } else {\n            return NIOFilePath(fileName)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class FileSystemTests: XCTestCase {\n    var fs: FileSystem { .shared }\n\n    func testOpenFileForReading() async throws {\n        try await self.fs.withFileHandle(forReadingAt: .testDataReadme) { file in\n            let info = try await file.info()\n            XCTAssertEqual(info.type, .regular)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testOpenFileForReadingFollowsSymlink() async throws {\n        try await self.fs.withFileHandle(forReadingAt: .testDataReadmeSymlink) { file in\n            let info = try await file.info()\n            XCTAssertEqual(info.type, .regular)\n        }\n    }\n\n    func testOpenSymlinkForReadingWithoutFollow() async throws {\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withFileHandle(\n                forReadingAt: .testDataReadmeSymlink,\n                options: OpenOptions.Read(followSymbolicLinks: false)\n            ) { _ in\n            }\n        } onError: { error in\n            XCTAssertEqual(error.code, .invalidArgument)\n        }\n    }\n\n    func testOpenNonExistentFileForReading() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withFileHandle(forReadingAt: path) { _ in }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testOpenFileWhereIntermediateIsNotADirectory() async throws {\n        let path = NIOFilePath(FilePath(#filePath).appending(\"foobar\"))\n\n        // For reading:\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withFileHandle(forReadingAt: path) { _ in\n                XCTFail(\"File unexpectedly opened\")\n            }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n\n        // For writing:\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withFileHandle(forWritingAt: path) { _ in\n                XCTFail(\"File unexpectedly opened\")\n            }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n\n        // As a directory:\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withDirectoryHandle(atPath: path) { _ in\n                XCTFail(\"File unexpectedly opened\")\n            }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testOpenFileForWriting() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            let info = try await file.info()\n            XCTAssertEqual(info.type, .regular)\n            XCTAssertEqual(info.size, 0)\n        }\n    }\n\n    func testOpenNonExistentFileForWritingWithoutCreating() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withFileHandle(\n                forWritingAt: path,\n                options: .modifyFile(createIfNecessary: false)\n            ) { _ in }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testOpenForWritingFollowingSymlink() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n\n        let link = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: link, withDestination: path)\n\n        // Open via the link and write.\n        try await self.fs.withFileHandle(\n            forWritingAt: link,\n            options: .modifyFile(createIfNecessary: false)\n        ) { file in\n            let info = try await file.info()\n            XCTAssertEqual(info.type, .regular)\n\n            try await file.write(contentsOf: [0, 1, 2], toAbsoluteOffset: 0)\n        }\n\n        let contents = try await ByteBuffer(\n            contentsOf: path,\n            maximumSizeAllowed: .bytes(1024),\n            fileSystem: self.fs\n        )\n        XCTAssertEqual(contents, ByteBuffer(bytes: [0, 1, 2]))\n    }\n\n    func testOpenNonExistentFileForWritingWithMaterialization() async throws {\n        for isAbsolute in [true, false] {\n            let path = try await self.fs.temporaryFilePath(inTemporaryDirectory: isAbsolute)\n            XCTAssertEqual(path.underlying.isAbsolute, isAbsolute)\n\n            await XCTAssertThrowsErrorAsync {\n                try await self.fs.withFileHandle(\n                    forWritingAt: path,\n                    options: .newFile(replaceExisting: false)\n                ) { file in\n                    // The file hasn't materialized yet, so no file at the expected path\n                    // should exist.\n                    let info = try await self.fs.info(forFileAt: path)\n                    XCTAssertNil(info)\n\n                    try await file.write(\n                        contentsOf: repeatElement(0, count: 1024),\n                        toAbsoluteOffset: 0\n                    )\n                    throw CancellationError()\n                }\n            } onError: { error in\n                XCTAssert(error is CancellationError)\n            }\n\n            // Threw in the 'with' block; the file shouldn't exist anymore.\n            let info = try await self.fs.info(forFileAt: path)\n            XCTAssertNil(info)\n        }\n    }\n\n    func testOpenExistingFileForWritingWithMaterialization() async throws {\n        for isAbsolute in [true, false] {\n            let path = try await self.fs.temporaryFilePath(inTemporaryDirectory: isAbsolute)\n            XCTAssertEqual(path.underlying.isAbsolute, isAbsolute)\n\n            // Avoid dirtying the current working directory.\n            if path.underlying.isRelative {\n                self.addTeardownBlock { [fileSystem = self.fs] in\n                    try await fileSystem.removeItem(at: path, strategy: .platformDefault)\n                }\n            }\n\n            // Create a file and write some data to it.\n            try await self.fs.withFileHandle(\n                forWritingAt: path,\n                options: .newFile(replaceExisting: false)\n            ) { file in\n                _ = try await file.write(contentsOf: [0, 1, 2], toAbsoluteOffset: 0)\n            }\n\n            // File must exist now.\n            let info = try await self.fs.info(forFileAt: path)\n            XCTAssertNotNil(info)\n\n            // Open the existing file and truncate it. Write different bytes to it but then throw an\n            // error. The changes shouldn't persist because of the error.\n            await XCTAssertThrowsErrorAsync {\n                try await self.fs.withFileHandle(\n                    forWritingAt: path,\n                    options: .newFile(replaceExisting: true)\n                ) { file in\n                    try await file.write(contentsOf: [3, 4, 5], toAbsoluteOffset: 0)\n                    throw CancellationError()\n                }\n            } onError: { error in\n                XCTAssert(error is CancellationError)\n            }\n\n            // Read the file again, it should contain the original bytes.\n            let bytes = try await ByteBuffer(contentsOf: path, maximumSizeAllowed: .megabytes(1))\n            XCTAssertEqual(bytes, ByteBuffer(bytes: [0, 1, 2]))\n        }\n    }\n\n    func testDetachUnsafeDescriptorForFileOpenedWithMaterialization() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        let descriptor = try await self.fs.withFileHandle(forWritingAt: path) { handle in\n            _ = try await handle.withBufferedWriter { writer in\n                try await writer.write(contentsOf: repeatElement(0, count: 1024))\n            }\n\n            return try handle.detachUnsafeFileDescriptor()\n        }\n\n        try descriptor.writeAll(toAbsoluteOffset: 1024, repeatElement(1, count: 1024))\n\n        var buffer = try await ByteBuffer(\n            contentsOf: path,\n            maximumSizeAllowed: .mebibytes(2),\n            fileSystem: self.fs\n        )\n\n        XCTAssertEqual(buffer.readBytes(length: 1024), Array(repeating: 0, count: 1024))\n        XCTAssertEqual(buffer.readBytes(length: 1024), Array(repeating: 1, count: 1024))\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testOpenFileForReadingAndWriting() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forReadingAndWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) {\n            file in\n            let info = try await file.info()\n            XCTAssertEqual(info.type, .regular)\n            XCTAssertEqual(info.size, 0)\n        }\n    }\n\n    func testOpenNonExistentFileForReadingAndWritingWithoutCreating() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withFileHandle(\n                forReadingAndWritingAt: path,\n                options: .modifyFile(createIfNecessary: false)\n            ) {\n                _ in\n            }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testOpenDirectory() async throws {\n        try await self.fs.withDirectoryHandle(atPath: .testData) { dir in\n            let info = try await dir.info()\n            XCTAssertEqual(info.type, .directory)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testOpenNonExistentDirectory() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.withDirectoryHandle(atPath: path) { _ in }\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testOpenDirectoryFollowingSymlink() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(at: path, withIntermediateDirectories: true)\n\n        let link = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: link, withDestination: path)\n\n        try await self.fs.withDirectoryHandle(atPath: link) { dir in\n            let info = try await dir.info()\n            XCTAssertEqual(info.type, .directory)\n        }\n    }\n\n    func testOpenNonExistentFileForWritingRelativeToDirectoryWithMaterialization() async throws {\n        // (false, false) isn't supported.\n        let isPathAbsolute: [(Bool, Bool)] = [(true, true), (true, false), (false, true)]\n\n        for (isDirectoryAbsolute, isFileAbsolute) in isPathAbsolute {\n            let directoryPath = try await self.fs.temporaryFilePath(\n                inTemporaryDirectory: isDirectoryAbsolute\n            )\n            XCTAssertEqual(directoryPath.underlying.isAbsolute, isDirectoryAbsolute)\n\n            // Avoid dirtying the current working directory.\n            if directoryPath.underlying.isRelative {\n                self.addTeardownBlock { [fileSystem = self.fs] in\n                    try await fileSystem.removeItem(at: directoryPath, strategy: .platformDefault)\n                }\n            }\n\n            // Create the directory and open it\n            try await self.fs.createDirectory(at: directoryPath, withIntermediateDirectories: true)\n            try await self.fs.withDirectoryHandle(atPath: directoryPath) { directory in\n                let filePath = try await self.fs.temporaryFilePath(\n                    inTemporaryDirectory: isFileAbsolute\n                )\n\n                XCTAssertEqual(filePath.underlying.isAbsolute, isFileAbsolute)\n\n                // Create the file and throw.\n                await XCTAssertThrowsErrorAsync {\n                    try await directory.withFileHandle(\n                        forWritingAt: filePath,\n                        options: .newFile(replaceExisting: false)\n                    ) { handle in\n                        throw CancellationError()\n                    }\n                } onError: { error in\n                    XCTAssert(error is CancellationError)\n                }\n\n                // The file shouldn't exist.\n                await XCTAssertThrowsFileSystemErrorAsync {\n                    try await directory.withFileHandle(forReadingAt: filePath) { _ in }\n                } onError: { error in\n                    XCTAssertEqual(error.code, .notFound)\n                }\n            }\n        }\n    }\n\n    func testOpenExistingFileForWritingRelativeToDirectoryWithMaterialization() async throws {\n        // (false, false) isn't supported.\n        let isPathAbsolute: [(Bool, Bool)] = [(true, true), (true, false), (false, true)]\n\n        for (isDirectoryAbsolute, isFileAbsolute) in isPathAbsolute {\n            let directoryPath = try await self.fs.temporaryFilePath(\n                inTemporaryDirectory: isDirectoryAbsolute\n            )\n\n            XCTAssertEqual(directoryPath.underlying.isAbsolute, isDirectoryAbsolute)\n\n            if directoryPath.underlying.isRelative {\n                self.addTeardownBlock { [fileSystem = self.fs] in\n                    try await fileSystem.removeItem(at: directoryPath, strategy: .platformDefault, recursively: true)\n                }\n            }\n\n            // Create the directory and open it\n            try await self.fs.createDirectory(at: directoryPath, withIntermediateDirectories: true)\n            try await self.fs.withDirectoryHandle(atPath: directoryPath) { directory in\n                let filePath = try await self.fs.temporaryFilePath(\n                    inTemporaryDirectory: isFileAbsolute\n                )\n\n                XCTAssertEqual(filePath.underlying.isAbsolute, isFileAbsolute)\n\n                // Create the file and write some bytes.\n                try await directory.withFileHandle(\n                    forWritingAt: filePath,\n                    options: .newFile(replaceExisting: false)\n                ) { file in\n                    _ = try await file.write(\n                        contentsOf: repeatElement(0, count: 1024),\n                        toAbsoluteOffset: 0\n                    )\n                }\n\n                // Create the file and throw.\n                await XCTAssertThrowsErrorAsync {\n                    try await directory.withFileHandle(\n                        forWritingAt: filePath,\n                        options: .newFile(replaceExisting: true)\n                    ) { handle in\n                        throw CancellationError()\n                    }\n                } onError: { error in\n                    XCTAssert(error is CancellationError)\n                }\n\n                // The file should contain the original bytes.\n                try await directory.withFileHandle(forReadingAt: filePath) { file in\n                    let bytes = try await file.readToEnd(maximumSizeAllowed: .megabytes(1))\n                    XCTAssertEqual(bytes, ByteBuffer(repeating: 0, count: 1024))\n                }\n            }\n        }\n    }\n\n    func testCreateDirectory() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(\n            at: path,\n            withIntermediateDirectories: false,\n            permissions: nil\n        )\n\n        try await self.fs.withDirectoryHandle(atPath: path) { dir in\n            let info = try await dir.info()\n            XCTAssertEqual(info.type, .directory)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testCreateDirectoryWithIntermediatePaths() async throws {\n        var path = try await self.fs.temporaryFilePath().underlying\n        for i in 0..<100 {\n            path.append(\"\\(i)\")\n        }\n\n        try await self.fs.createDirectory(\n            at: NIOFilePath(path),\n            withIntermediateDirectories: true,\n            permissions: nil\n        )\n\n        try await self.fs.withDirectoryHandle(atPath: NIOFilePath(path)) { dir in\n            let info = try await dir.info()\n            XCTAssertEqual(info.type, .directory)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testCreateDirectoryAtPathWhichExists() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.createDirectory(at: path, withIntermediateDirectories: true)\n        } onError: { error in\n            XCTAssertEqual(error.code, .fileAlreadyExists)\n        }\n    }\n\n    func testCreateDirectoryAtPathWhereParentDoesNotExist() async throws {\n        let parent = try await self.fs.temporaryFilePath().underlying\n        let path = NIOFilePath(parent.appending(\"path\"))\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.createDirectory(at: path, withIntermediateDirectories: false)\n        } onError: { error in\n            XCTAssertEqual(error.code, .invalidArgument)\n        }\n    }\n\n    func testCreateDirectoryIsIdempotentWhenAlreadyExists() async throws {\n        let path = try await self.fs.temporaryFilePath()\n\n        try await self.fs.createDirectory(at: path, withIntermediateDirectories: false)\n\n        try await self.fs.createDirectory(at: path, withIntermediateDirectories: false)\n        try await self.fs.createDirectory(at: path, withIntermediateDirectories: true)\n\n        try await self.fs.withDirectoryHandle(atPath: path) { dir in\n            let info = try await dir.info()\n            XCTAssertEqual(info.type, .directory)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testCreateDirectoryThroughSymlinkToExistingDirectoryIsIdempotent() async throws {\n        let realDir = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(at: realDir, withIntermediateDirectories: false)\n\n        let linkPath = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: linkPath, withDestination: realDir)\n\n        try await self.fs.createDirectory(at: linkPath, withIntermediateDirectories: false)\n\n        try await self.fs.withDirectoryHandle(atPath: linkPath) { dir in\n            let info = try await dir.info()\n            XCTAssertEqual(info.type, .directory)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testCurrentWorkingDirectory() async throws {\n        let directory = try await self.fs.currentWorkingDirectory\n        XCTAssert(!directory.underlying.isEmpty)\n        XCTAssert(directory.underlying.isAbsolute)\n    }\n\n    func testTemporaryDirectory() async throws {\n        let directory = try await self.fs.temporaryDirectory\n        XCTAssert(!directory.underlying.isEmpty)\n        XCTAssert(directory.underlying.isAbsolute)\n    }\n\n    func testHomeDirectory() async throws {\n        let directory = try await self.fs.homeDirectory\n        XCTAssert(!directory.underlying.isEmpty)\n        XCTAssert(directory.underlying.isAbsolute)\n        let info = try await self.fs.info(forFileAt: directory, infoAboutSymbolicLink: false)\n        XCTAssertEqual(info?.type, .directory)\n    }\n\n    func testHomeDirectoryFromEnvironment() async throws {\n        // Should return a value when HOME is set (which it typically is)\n        if let path = Libc.homeDirectoryFromEnvironment() {\n            XCTAssert(!path.isEmpty)\n            XCTAssert(path.isAbsolute)\n\n            // Verify it matches the high-level API\n            let fsHome = try await self.fs.homeDirectory\n            XCTAssertEqual(path, fsHome.underlying)\n        } else {\n            // If it returns nil, then HOME check should fail\n            let home = getenv(\"HOME\")\n            XCTAssertTrue(home == nil || home!.pointee == 0, \"Expected HOME to be unset or empty\")\n\n            #if os(Windows)\n            let profile = getenv(\"USERPROFILE\")\n            XCTAssertTrue(profile == nil || profile!.pointee == 0, \"Expected USERPROFILE to be unset or empty\")\n            #endif\n        }\n    }\n\n    #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Android)\n    func testHomeDirectoryFromPasswd() throws {\n        #if targetEnvironment(simulator)\n        // Simulators don't have a passwd database entry for the current user.\n        throw XCTSkip(\"getpwuid_r has no passwd entry in simulator environments\")\n        #else\n        // Should always succeed on Unix-like systems for the current user\n        let result = Libc.homeDirectoryFromPasswd()\n        switch result {\n        case .success(let path):\n            XCTAssert(!path.isEmpty)\n            XCTAssert(path.isAbsolute)\n        case .failure(let errno):\n            XCTFail(\"Expected success, got error: \\(errno)\")\n        }\n        #endif\n    }\n    #endif\n\n    func testInfo() async throws {\n        let info = try await self.fs.info(forFileAt: .testDataReadme, infoAboutSymbolicLink: false)\n        XCTAssertEqual(info?.type, .regular)\n        XCTAssertGreaterThan(info?.size ?? -1, Int64(0))\n    }\n\n    func testInfoResolvingSymbolicLinks() async throws {\n        let info = try await self.fs.info(\n            forFileAt: .testDataReadmeSymlink,\n            infoAboutSymbolicLink: false\n        )\n        XCTAssertEqual(info?.type, .regular)\n        XCTAssertGreaterThan(info?.size ?? -1, Int64(0))\n    }\n\n    func testInfoWithoutResolvingSymbolicLinks() async throws {\n        let info = try await self.fs.info(\n            forFileAt: .testDataReadmeSymlink,\n            infoAboutSymbolicLink: true\n        )\n        XCTAssertEqual(info?.type, .symlink)\n        XCTAssertGreaterThan(info?.size ?? -1, Int64(0))\n    }\n\n    func testCreateSymbolicLink() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        let destination = NIOFilePath.testDataReadme\n\n        try await self.fs.createSymbolicLink(at: path, withDestination: destination)\n        let info = try await self.fs.info(forFileAt: destination, infoAboutSymbolicLink: true)\n        let infoViaLink = try await self.fs.info(forFileAt: path, infoAboutSymbolicLink: false)\n        XCTAssertEqual(info, infoViaLink)\n    }\n\n    func testDestinationOfSymbolicLink() async throws {\n        do {\n            // Relative symbolic link.\n            let destination = try await self.fs.destinationOfSymbolicLink(\n                at: .testDataReadmeSymlink\n            )\n            XCTAssertEqual(destination, \"README.md\")\n        }\n\n        do {\n            // Absolute symbolic link.\n            let path = try await self.fs.temporaryFilePath()\n            try await self.fs.createSymbolicLink(at: path, withDestination: .testDataReadme)\n            let destination = try await self.fs.destinationOfSymbolicLink(at: path)\n            XCTAssertEqual(destination, .testDataReadme)\n        }\n    }\n\n    func testCopySingleFile() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.copyItem(at: .testDataReadme, to: path)\n\n        try await self.fs.withFileHandle(forReadingAt: path) { copy in\n            try await self.fs.withFileHandle(forReadingAt: .testDataReadme) { original in\n                let originalContents = try await original.readToEnd(\n                    maximumSizeAllowed: .bytes(1024 * 1024)\n                )\n                let copyContents = try await copy.readToEnd(maximumSizeAllowed: .bytes(1024 * 1024))\n                XCTAssertEqual(originalContents, copyContents)\n            }\n        }\n    }\n\n    func testCopyLargeFile() async throws {\n        let sourcePath = try await self.fs.temporaryFilePath()\n        let destPath = try await self.fs.temporaryFilePath()\n        self.addTeardownBlock { [fs] in\n            _ = try? await fs.removeItem(at: sourcePath, strategy: .platformDefault)\n            _ = try? await fs.removeItem(at: destPath, strategy: .platformDefault)\n        }\n\n        let sourceInfo = try await self.fs.withFileHandle(\n            forWritingAt: sourcePath,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            // On Linux we use sendfile to copy which has a limit of 2GB; write at least that much\n            // to much sure we handle files above that size correctly.\n            var bytesToWrite: Int64 = 3 * 1024 * 1024 * 1024\n            var offset: Int64 = 0\n            // Write a blob a handful of times to avoid consuming too much memory in one go.\n            let blob = [UInt8](repeating: 0, count: 1024 * 1024 * 32)  // 32MB\n            while bytesToWrite > 0 {\n                try await file.write(contentsOf: blob, toAbsoluteOffset: offset)\n                offset += Int64(blob.count)\n                bytesToWrite -= Int64(blob.count)\n            }\n\n            return try await file.info()\n        }\n\n        try await self.fs.copyItem(at: sourcePath, to: destPath)\n        let destInfo = try await self.fs.info(forFileAt: destPath)\n        XCTAssertEqual(destInfo?.size, sourceInfo.size)\n    }\n\n    func testCopySingleFileCopiesAttributesAndPermissions() async throws {\n        let original = try await self.fs.temporaryFilePath()\n        let copy = try await self.fs.temporaryFilePath()\n\n        try await self.fs.withFileHandle(\n            forWritingAt: original,\n            options: .newFile(replaceExisting: false, permissions: .ownerReadWrite)\n        ) { file1 in\n            do {\n                try await file1.updateValueForAttribute([0, 1, 2, 3], attribute: \"foo\")\n            } catch let error as FileSystemError where error.code == .unsupported {\n                // Extended attributes are not always supported; swallow the error if we hit it.\n            }\n        }\n\n        try await self.fs.copyItem(at: original, to: copy)\n\n        try await self.fs.withFileHandle(forReadingAt: copy) { file2 in\n            let info = try await file2.info()\n            XCTAssertEqual(info.permissions, [.ownerReadWrite])\n\n            do {\n                let value = try await file2.valueForAttribute(\"foo\")\n                XCTAssertEqual(value, [0, 1, 2, 3])\n            } catch let error as FileSystemError where error.code == .unsupported {\n                // Extended attributes are not always supported; swallow the error if we hit it.\n            }\n        }\n    }\n\n    func testCopySymlink() async throws {\n        let copy = try await self.fs.temporaryFilePath()\n        try await self.fs.copyItem(at: .testDataReadmeSymlink, to: copy)\n\n        let info = try await self.fs.info(forFileAt: copy, infoAboutSymbolicLink: true)\n        XCTAssertEqual(info?.type, .symlink)\n\n        let destination = try await self.fs.destinationOfSymbolicLink(at: copy)\n        XCTAssertEqual(destination, \"README.md\")\n    }\n\n    /// This is is not quite the same as sequential, different code paths are used.\n    /// Tests using this ensure use of the parallel paths (which are more complex) while keeping actual\n    /// parallelism to minimal levels to make debugging simpler.\n    private static let minimalParallel: CopyStrategy = try! .parallel(maxDescriptors: 2)\n\n    func testCopyEmptyDirectorySequential() async throws {\n        try await testCopyEmptyDirectory(.sequential)\n    }\n\n    func testCopyEmptyDirectoryParallelMinimal() async throws {\n        try await testCopyEmptyDirectory(Self.minimalParallel)\n    }\n\n    func testCopyEmptyDirectoryParallelDefault() async throws {\n        try await testCopyEmptyDirectory(.platformDefault)\n    }\n\n    private func testCopyEmptyDirectory(\n        _ copyStrategy: CopyStrategy\n    ) async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(at: path, withIntermediateDirectories: false)\n\n        let copy = try await self.fs.temporaryFilePath()\n        try await self.fs.copyItem(at: path, to: copy, strategy: copyStrategy)\n\n        try await self.checkDirectoriesMatch(path, copy)\n    }\n\n    func testCopyDirectoryToExistingDestinationSequential() async throws {\n        try await self.testCopyDirectoryToExistingDestination(.sequential)\n    }\n\n    func testCopyDirectoryToExistingDestinationParallelMinimal() async throws {\n        try await self.testCopyDirectoryToExistingDestination(Self.minimalParallel)\n    }\n\n    func testCopyDirectoryToExistingDestinationParallelDefault() async throws {\n        try await self.testCopyDirectoryToExistingDestination(.platformDefault)\n    }\n\n    private func testCopyDirectoryToExistingDestination(\n        _ strategy: CopyStrategy\n    ) async throws {\n        let path1 = try await self.fs.temporaryFilePath()\n        let path2 = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(at: path1, withIntermediateDirectories: false)\n        try await self.fs.createDirectory(at: path2, withIntermediateDirectories: false)\n\n        await XCTAssertThrowsErrorAsync {\n            try await self.fs.copyItem(at: path1, to: path2, strategy: strategy)\n        }\n    }\n\n    func testCopyOnGeneratedTreeStructureSequential() async throws {\n        try await testAnyCopyStrategyOnGeneratedTreeStructure(.sequential)\n    }\n\n    func testCopyOnGeneratedTreeStructureParallelMinimal() async throws {\n        try await testAnyCopyStrategyOnGeneratedTreeStructure(Self.minimalParallel)\n    }\n\n    func testCopyOnGeneratedTreeStructureParallelDefault() async throws {\n        try await testAnyCopyStrategyOnGeneratedTreeStructure(.platformDefault)\n    }\n\n    private func testAnyCopyStrategyOnGeneratedTreeStructure(\n        _ copyStrategy: CopyStrategy,\n        line: UInt = #line\n    ) async throws {\n        let path = try await self.fs.temporaryFilePath()\n        let items = try await self.generateDirectoryStructure(\n            root: path,\n            maxDepth: 4,\n            maxFilesPerDirectory: 10\n        )\n\n        let copy = try await self.fs.temporaryFilePath()\n        do {\n            try await self.fs.copyItem(at: path, to: copy, strategy: copyStrategy)\n        } catch {\n            // Leave breadcrumbs to make debugging easier.\n            XCTFail(\n                \"Using \\(copyStrategy) failed to copy \\(items) from '\\(path)' to '\\(copy)'\",\n                line: line\n            )\n            throw error\n        }\n\n        do {\n            try await self.checkDirectoriesMatch(path, copy)\n        } catch {\n            // Leave breadcrumbs to make debugging easier.\n            XCTFail(\n                \"Using \\(copyStrategy) failed to validate \\(items) copied from '\\(path)' to '\\(copy)'\",\n                line: line\n            )\n            throw error\n        }\n    }\n\n    func testCopySelectivelySequential() async throws {\n        try await testCopySelectively(.sequential)\n    }\n\n    func testCopySelectivelyParallelMinimal() async throws {\n        try await testCopySelectively(Self.minimalParallel)\n    }\n\n    func testCopySelectivelyParallelDefault() async throws {\n        try await testCopySelectively(.platformDefault)\n    }\n\n    private func testCopySelectively(\n        _ copyStrategy: CopyStrategy,\n        line: UInt = #line\n    ) async throws {\n        let path = try await self.fs.temporaryFilePath()\n\n        // Only generate regular files. They'll be in the format 'file-N-regular'.\n        let _ = try await self.generateDirectoryStructure(\n            root: path,\n            maxDepth: 1,\n            maxFilesPerDirectory: 10,\n            directoryProbability: 0.0,\n            symbolicLinkProbability: 0.0\n        )\n\n        let copyPath = try await self.fs.temporaryFilePath()\n        try await self.fs.copyItem(at: path, to: copyPath, strategy: copyStrategy, replaceExisting: false) { _, error in\n            throw error\n        } shouldCopyItem: { source, destination in\n            // Copy the directory and 'file-1-regular'\n            (source.path == path) || (source.path.underlying.lastComponent!.string == \"file-0-regular\")\n        }\n\n        let paths = try await self.fs.withDirectoryHandle(atPath: copyPath) { dir in\n            try await dir.listContents().reduce(into: []) { $0.append($1) }\n        }\n\n        XCTAssertEqual(paths.count, 1)\n        XCTAssertEqual(paths.first?.name, \"file-0-regular\")\n    }\n\n    func testCopyCancelledPartWayThroughSequential() async throws {\n        try await testCopyCancelledPartWayThrough(.sequential)\n    }\n\n    func testCopyCancelledPartWayThroughParallelMinimal() async throws {\n        try await testCopyCancelledPartWayThrough(Self.minimalParallel)\n    }\n\n    func testCopyCancelledPartWayThroughParallelDefault() async throws {\n        try await testCopyCancelledPartWayThrough(.platformDefault)\n    }\n\n    private func testCopyCancelledPartWayThrough(\n        _ copyStrategy: CopyStrategy,\n        line: UInt = #line\n    ) async throws {\n        // Whitebox testing to cover specific scenarios\n        switch copyStrategy.wrapped {\n        case let .parallel(maxDescriptors):\n            // The use of nested directories here allows us to rely on deterministic ordering\n            // of the shouldCopy calls that are used to trigger the cancel. If we used files then directory\n            // listing is not deterministic in general and that could make tests unreliable.\n            // If maxDescriptors gets too high the resulting recursion might result in the test failing.\n            // At that stage the tests would need some rework, but it's not viewed as likely given that\n            // the maxDescriptors defaults should remain small.\n\n            // Each dir consumes two descriptors, so this source can cover all scenarios.\n            let depth = maxDescriptors + 1\n            let path = try await self.fs.temporaryFilePath()\n            try await self.generateDeterministicDirectoryStructure(\n                root: path,\n                structure: TestFileStructure.makeNestedDirs(depth) {\n                    .init(\"dir-\\(depth - $0)\")!\n                }\n            )\n\n            // This covers cancelling before/at the point we reach the limit.\n            // If the maxDescriptors is sufficiently low we simply can't trigger\n            // inside that phase so don't try.\n            if maxDescriptors >= 4 {\n                try await testCopyCancelledPartWayThrough(copyStrategy, \"early_complete\", path) {\n                    $0.name == \"dir-0\"\n                }\n            }\n\n            // This covers completing after we reach the steady state phase.\n            let triggerAt = \"dir-\\(maxDescriptors / 2 + 1)\"\n            try await testCopyCancelledPartWayThrough(copyStrategy, \"late_complete\", path) {\n                $0.name == triggerAt\n            }\n        case .sequential:\n            // nothing much to whitebox test here\n            break\n        }\n        // Keep doing random ones as a sort of fuzzing, it previously highlighted some interesting cases\n        // that are now covered in the whitebox tests above\n        let randomPath = try await self.fs.temporaryFilePath()\n        let _ = try await self.generateDirectoryStructure(\n            root: randomPath,\n            // Ensure:\n            // - Parallelism is possible in directory scans.\n            // - There are sub directories underneath the point we trigger cancel\n            maxDepth: 4,\n            maxFilesPerDirectory: 10,\n            directoryProbability: 1.0,\n            symbolicLinkProbability: 0.0\n        )\n        try await testCopyCancelledPartWayThrough(\n            copyStrategy,\n            \"randomly generated\",\n            randomPath\n        ) { source in\n            source.path != randomPath && NIOFilePath(source.path.underlying.removingLastComponent()) != randomPath\n        }\n    }\n\n    private func testCopyCancelledPartWayThrough(\n        _ copyStrategy: CopyStrategy,\n        _ description: String,\n        _ path: NIOFilePath,\n        triggerCancel: @escaping @Sendable (DirectoryEntry) -> Bool,\n        line: UInt = #line\n    ) async throws {\n\n        let copyPath = try await self.fs.temporaryFilePath()\n\n        let requestedCancel = NIOLockedValueBox<Bool>(false)\n        let cancelRequested = expectation(description: \"cancel requested\")\n\n        let task = Task { [fs] in\n            try await fs.copyItem(at: path, to: copyPath, strategy: copyStrategy, replaceExisting: false) { _, error in\n                throw error\n            } shouldCopyItem: { source, destination in\n                // Abuse shouldCopy to trigger the cancellation after getting some way in.\n                if triggerCancel(source) {\n                    let shouldSleep = requestedCancel.withLockedValue { requested in\n                        if !requested {\n                            requested = true\n                            cancelRequested.fulfill()\n                            return true\n                        }\n\n                        return requested\n                    }\n                    // Give the cancellation time to kick in, this should be more than plenty.\n                    if shouldSleep {\n                        do {\n                            try await Task.sleep(nanoseconds: 3_000_000_000)\n                            XCTFail(\"\\(description) Should have been cancelled by now!\")\n                        } catch is CancellationError {\n                            // This is fine - we got cancelled as desired, let the rest of the in flight\n                            // logic wind down cleanly (we hope/assert)\n                        } catch let error {\n                            XCTFail(\"\\(description) just expected a cancellation error not \\(error)\")\n                        }\n                    }\n                }\n                return true\n            }\n\n            return \"completed the copy\"\n        }\n\n        // Timeout notes: locally this should be fine as a second but on a loaded\n        // CI instance this test can be flaky at that level.\n        // Since testing cancellation is deemed highly desirable this is retained at\n        // quite relaxed thresholds.\n        // If this threshold remains insufficient for stable use then this test is likely\n        // not tenable to run in CI\n        await fulfillment(of: [cancelRequested], timeout: 5)\n        task.cancel()\n        let result = await task.result\n        switch result {\n        case let .success(msg):\n            XCTFail(\"\\(description) expected the cancellation to have happened : \\(msg)\")\n\n        case let .failure(err):\n            if err is CancellationError {\n                // success\n            } else {\n                XCTFail(\"\\(description) expected CancellationError not \\(err)\")\n            }\n        }\n        // We can't assert anything about the state of the copy,\n        // it might happen to all finish in time depending on scheduling.\n    }\n\n    func testCopyNonExistentFileSequential() async throws {\n        try await testCopyNonExistentFile(.sequential)\n    }\n\n    func testCopyNonExistentFileParallelMinimal() async throws {\n        try await testCopyNonExistentFile(Self.minimalParallel)\n    }\n\n    func testCopyNonExistentFileParallelDefault() async throws {\n        try await testCopyNonExistentFile(.platformDefault)\n    }\n\n    private func testCopyNonExistentFile(\n        _ copyStrategy: CopyStrategy,\n        line: UInt = #line\n    ) async throws {\n        let source = try await self.fs.temporaryFilePath()\n        let destination = try await self.fs.temporaryFilePath()\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.copyItem(at: source, to: destination, strategy: copyStrategy)\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testCopyToExistingDestinationSequential() async throws {\n        try await testCopyToExistingDestination(.sequential)\n    }\n\n    func testCopyToExistingDestinationParallelMinimal() async throws {\n        try await testCopyToExistingDestination(Self.minimalParallel)\n    }\n\n    func testCopyToExistingDestinationParallelDefault() async throws {\n        try await testCopyToExistingDestination(.platformDefault)\n    }\n\n    private func testCopyToExistingDestination(\n        _ copyStrategy: CopyStrategy,\n        line: UInt = #line\n    ) async throws {\n        let source = try await self.fs.temporaryFilePath()\n        let destination = try await self.fs.temporaryFilePath()\n\n        // Touch both files.\n        for path in [source, destination] {\n            try await self.fs.withFileHandle(\n                forWritingAt: path,\n                options: .newFile(replaceExisting: false)\n            ) { _ in }\n        }\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.copyItem(at: source, to: destination, strategy: copyStrategy)\n        } onError: { error in\n            XCTAssertEqual(error.code, .fileAlreadyExists)\n        }\n    }\n\n    func testRemoveSingleFile() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n\n        let infoAfterCreation = try await self.fs.info(forFileAt: path)\n        XCTAssertNotNil(infoAfterCreation)\n\n        let removed = try await self.fs.removeItem(at: path, strategy: .platformDefault)\n        XCTAssertEqual(removed, 1)\n\n        let infoAfterRemoval = try await self.fs.info(forFileAt: path)\n        XCTAssertNil(infoAfterRemoval)\n    }\n\n    func testRemoveNonExistentFile() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        let info = try await self.fs.info(forFileAt: path)\n        XCTAssertNil(info)\n        let removed = try await self.fs.removeItem(at: path, strategy: .platformDefault)\n        XCTAssertEqual(removed, 0)\n    }\n\n    func testRemoveDirectorySequentially() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        let created = try await self.generateDirectoryStructure(\n            root: path,\n            maxDepth: 3,\n            maxFilesPerDirectory: 10\n        )\n\n        let infoAfterCreation = try await self.fs.info(forFileAt: path)\n        XCTAssertNotNil(infoAfterCreation)\n\n        // Removing a non-empty directory recursively should throw 'notEmpty'\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.removeItem(at: path, strategy: .sequential, recursively: false)\n        } onError: { error in\n            XCTAssertEqual(error.code, .notEmpty)\n        }\n\n        let removed = try await self.fs.removeItem(at: path, strategy: .sequential)\n        XCTAssertEqual(created, removed)\n\n        let infoAfterRemoval = try await self.fs.info(forFileAt: path)\n        XCTAssertNil(infoAfterRemoval)\n    }\n\n    func testRemoveDirectoryConcurrently() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        let created = try await self.generateDirectoryStructure(\n            root: path,\n            maxDepth: 3,\n            maxFilesPerDirectory: 10\n        )\n\n        let infoAfterCreation = try await self.fs.info(forFileAt: path)\n        XCTAssertNotNil(infoAfterCreation)\n\n        // Removing a non-empty directory recursively should throw 'notEmpty'\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.removeItem(at: path, strategy: .parallel(maxDescriptors: 2), recursively: false)\n        } onError: { error in\n            XCTAssertEqual(error.code, .notEmpty)\n        }\n\n        let removed = try await self.fs.removeItem(at: path, strategy: .parallel(maxDescriptors: 2))\n        XCTAssertEqual(created, removed)\n\n        let infoAfterRemoval = try await self.fs.info(forFileAt: path)\n        XCTAssertNil(infoAfterRemoval)\n    }\n\n    func testMoveRegularFile() async throws {\n        let source = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let destination = try await self.fs.temporaryFilePath()\n\n        do {\n            let sourceInfo = try await self.fs.info(forFileAt: source)\n            XCTAssertNotNil(sourceInfo)\n            let destinationInfo = try await self.fs.info(forFileAt: destination)\n            XCTAssertNil(destinationInfo)\n        }\n\n        try await self.fs.moveItem(at: source, to: destination)\n\n        do {\n            let sourceInfo = try await self.fs.info(forFileAt: source)\n            XCTAssertNil(sourceInfo)\n            let destinationInfo = try await self.fs.info(forFileAt: destination)\n            XCTAssertNotNil(destinationInfo)\n        }\n    }\n\n    func testMoveSymbolicLink() async throws {\n        let source = try await self.fs.temporaryFilePath()\n        let destination = try await self.fs.temporaryFilePath()\n\n        try await self.fs.createSymbolicLink(at: source, withDestination: .testDataReadme)\n\n        do {\n            let sourceInfo = try await self.fs.info(forFileAt: source, infoAboutSymbolicLink: true)\n            XCTAssertNotNil(sourceInfo)\n            XCTAssertEqual(sourceInfo?.type, .symlink)\n            let destinationInfo = try await self.fs.info(forFileAt: destination)\n            XCTAssertNil(destinationInfo)\n        }\n\n        try await self.fs.moveItem(at: source, to: destination)\n\n        do {\n            let sourceInfo = try await self.fs.info(forFileAt: source)\n            XCTAssertNil(sourceInfo)\n            let destinationInfo = try await self.fs.info(\n                forFileAt: destination,\n                infoAboutSymbolicLink: true\n            )\n            XCTAssertNotNil(destinationInfo)\n            XCTAssertEqual(destinationInfo?.type, .symlink)\n        }\n\n        let linkDestination = try await self.fs.destinationOfSymbolicLink(at: destination)\n        XCTAssertEqual(linkDestination, .testDataReadme)\n    }\n\n    func testMoveDirectory() async throws {\n        let source = try await self.fs.temporaryFilePath()\n        let destination = try await self.fs.temporaryFilePath()\n\n        try await self.fs.createDirectory(at: source, withIntermediateDirectories: true)\n        try await self.fs.withFileHandle(\n            forWritingAt: NIOFilePath(source.underlying.appending(\"foo\")),\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n\n        do {\n            let sourceInfo = try await self.fs.info(forFileAt: source, infoAboutSymbolicLink: false)\n            XCTAssertNotNil(sourceInfo)\n            XCTAssertEqual(sourceInfo?.type, .directory)\n            let destinationInfo = try await self.fs.info(forFileAt: destination)\n            XCTAssertNil(destinationInfo)\n        }\n\n        try await self.fs.moveItem(at: source, to: destination)\n\n        let sourceInfo = try await self.fs.info(forFileAt: source)\n        XCTAssertNil(sourceInfo)\n\n        let items = try await self.fs.withDirectoryHandle(atPath: destination) { directory in\n            try await directory.listContents().reduce(into: []) { $0.append($1) }\n        }\n\n        XCTAssertEqual(items.count, 1)\n        XCTAssertEqual(items.first?.name, \"foo\")\n    }\n\n    func testMoveWhenSourceDoesNotExist() async throws {\n        let source = try await self.fs.temporaryFilePath()\n        let destination = try await self.fs.temporaryFilePath()\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.moveItem(at: source, to: destination)\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testMoveWhenDestinationAlreadyExists() async throws {\n        let source = try await self.fs.temporaryFilePath()\n        let destination = try await self.fs.temporaryFilePath()\n        for path in [source, destination] {\n            try await self.fs.withFileHandle(\n                forWritingAt: path,\n                options: .newFile(replaceExisting: false)\n            ) { _ in }\n        }\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.moveItem(at: source, to: destination)\n        } onError: { error in\n            XCTAssertEqual(error.code, .fileAlreadyExists)\n        }\n    }\n\n    func testReplaceFile(_ existingType: FileType?, with replacementType: FileType) async throws {\n        func makeRegularFile(at path: NIOFilePath) async throws {\n            try await self.fs.withFileHandle(\n                forWritingAt: path,\n                options: .newFile(replaceExisting: false)\n            ) { _ in }\n        }\n\n        func makeSymbolicLink(at path: NIOFilePath) async throws {\n            try await self.fs.createSymbolicLink(at: path, withDestination: \"/whatever\")\n        }\n\n        func makeDirectory(at path: NIOFilePath) async throws {\n            try await self.fs.createDirectory(at: path, withIntermediateDirectories: true)\n        }\n\n        func makeFile(ofType type: FileType, at path: NIOFilePath) async throws {\n            switch type {\n            case .regular:\n                try await makeRegularFile(at: path)\n            case .symlink:\n                try await makeSymbolicLink(at: path)\n            case .directory:\n                try await makeDirectory(at: path)\n            default:\n                XCTFail(\"Unexpected file type '\\(type)'\")\n            }\n        }\n\n        let existingPath = try await self.fs.temporaryFilePath()\n        let replacementPath = try await self.fs.temporaryFilePath()\n        if let existingType = existingType {\n            try await makeFile(ofType: existingType, at: existingPath)\n        }\n        try await makeFile(ofType: replacementType, at: replacementPath)\n\n        try await self.fs.replaceItem(at: existingPath, withItemAt: replacementPath)\n\n        let sourceInfo = try await self.fs.info(\n            forFileAt: existingPath,\n            infoAboutSymbolicLink: true\n        )\n        XCTAssertNotNil(sourceInfo)\n        XCTAssertEqual(sourceInfo?.type, replacementType)\n\n        let destinationInfo = try await self.fs.info(\n            forFileAt: replacementPath,\n            infoAboutSymbolicLink: true\n        )\n        XCTAssertNil(destinationInfo)\n    }\n\n    func testReplaceRegularFileWithRegularFile() async throws {\n        try await self.testReplaceFile(.regular, with: .regular)\n    }\n\n    func testReplaceRegularFileWithSymbolicLink() async throws {\n        try await self.testReplaceFile(.regular, with: .symlink)\n    }\n\n    func testReplaceRegularFileWithDirectory() async throws {\n        try await self.testReplaceFile(.regular, with: .directory)\n    }\n\n    func testReplaceSymbolicLinkWithRegularFile() async throws {\n        try await self.testReplaceFile(.symlink, with: .regular)\n    }\n\n    func testReplaceSymbolicLinkWithSymbolicLink() async throws {\n        try await self.testReplaceFile(.symlink, with: .symlink)\n    }\n\n    func testReplaceSymbolicLinkWithDirectory() async throws {\n        try await self.testReplaceFile(.symlink, with: .directory)\n    }\n\n    func testReplaceDirectoryWithRegularFile() async throws {\n        try await self.testReplaceFile(.directory, with: .regular)\n    }\n\n    func testReplaceDirectoryWithSymbolicLink() async throws {\n        try await self.testReplaceFile(.directory, with: .symlink)\n    }\n\n    func testReplaceDirectoryWithDirectory() async throws {\n        try await self.testReplaceFile(.directory, with: .directory)\n    }\n\n    func testReplaceNothingWithRegularFile() async throws {\n        try await self.testReplaceFile(.none, with: .regular)\n    }\n\n    func testReplaceNothingWithSymbolicLink() async throws {\n        try await self.testReplaceFile(.none, with: .symlink)\n    }\n\n    func testReplaceNothingWithDirectory() async throws {\n        try await self.testReplaceFile(.none, with: .directory)\n    }\n\n    func testReplaceWhenExistingFileDoesNotExist() async throws {\n        let existing = try await self.fs.temporaryFilePath()\n        let replacement = try await self.fs.temporaryFilePath()\n\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.replaceItem(at: replacement, withItemAt: existing)\n        } onError: { error in\n            XCTAssertEqual(error.code, .notFound)\n        }\n    }\n\n    func testWithFileSystem() async throws {\n        try await withFileSystem(numberOfThreads: 1) { fs in\n            let info = try await fs.info(forFileAt: .testDataReadme)\n            XCTAssertEqual(info?.type, .regular)\n        }\n    }\n\n    func testListContentsOfLargeDirectory() async throws {\n        let path = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(at: path, withIntermediateDirectories: true)\n\n        try await self.fs.withDirectoryHandle(atPath: path) { handle in\n            for i in 0..<1024 {\n                try await self.fs.withFileHandle(\n                    forWritingAt: NIOFilePath(path.underlying.appending(\"\\(i)\")),\n                    options: .newFile(replaceExisting: false)\n                ) { _ in }\n            }\n\n            let names = try await handle.listContents().reduce(into: []) {\n                $0.append($1.name)\n            }\n\n            let expected = (0..<1024).map {\n                String($0)\n            }\n\n            XCTAssertEqual(names.sorted(), expected.sorted())\n        }\n    }\n\n    func testWithTemporaryDirectory() async throws {\n        let fs = FileSystem.shared\n\n        let createdPath = try await fs.withTemporaryDirectory { directory, path in\n            let root = try await fs.temporaryDirectory\n            XCTAssert(path.underlying.starts(with: root.underlying))\n            return path\n        }\n\n        // Directory shouldn't exist any more.\n        let info = try await fs.info(forFileAt: createdPath)\n        XCTAssertNil(info)\n    }\n\n    func testWithTemporaryDirectoryPrefix() async throws {\n        let fs = FileSystem.shared\n        let prefix = try await fs.currentWorkingDirectory\n\n        let createdPath = try await fs.withTemporaryDirectory(prefix: prefix) { directory, path in\n            XCTAssert(path.underlying.starts(with: prefix.underlying))\n            return path\n        }\n\n        // Directory shouldn't exist any more.\n        let info = try await fs.info(forFileAt: createdPath)\n        XCTAssertNil(info)\n    }\n\n    func testWithTemporaryDirectoryRemovesContents() async throws {\n        let fs = FileSystem.shared\n        let createdPath = try await fs.withTemporaryDirectory { directory, path in\n            for name in [\"foo\", \"bar\", \"baz\"] {\n                try await directory.withFileHandle(forWritingAt: NIOFilePath(name)) { fh in\n                    _ = try await fh.write(contentsOf: [1, 2, 3], toAbsoluteOffset: 0)\n                }\n            }\n\n            let entries = try await directory.listContents().reduce(into: []) { $0.append($1) }\n            let names = entries.map { $0.name }\n            XCTAssertEqual(names.sorted(), [\"bar\", \"baz\", \"foo\"])\n\n            return path\n        }\n\n        // Directory shouldn't exist any more.\n        let info = try await fs.info(forFileAt: createdPath)\n        XCTAssertNil(info)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension FileSystemTests {\n    private func checkDirectoriesMatch(_ root1: NIOFilePath, _ root2: NIOFilePath) async throws {\n        func namesAndTypes(_ root: NIOFilePath) async throws -> [(String, FileType)] {\n            try await self.fs.withDirectoryHandle(atPath: root) { dir in\n                try await dir.listContents()\n                    .reduce(into: []) { $0.append($1) }\n                    .map { ($0.name, $0.type) }\n                    .sorted(by: { lhs, rhs in lhs.0 < rhs.0 })\n            }\n        }\n\n        // Check if all named entries and types match.\n        let root1Entries = try await namesAndTypes(root1)\n        let root2Entries = try await namesAndTypes(root2)\n        XCTAssertEqual(root1Entries.map { $0.0 }, root2Entries.map { $0.0 })\n        XCTAssertEqual(root1Entries.map { $0.1 }, root2Entries.map { $0.1 })\n\n        // Now look at regular files: are they all the same?\n        for (path, type) in root1Entries where type == .regular {\n            try await self.checkRegularFilesMatch(\n                NIOFilePath(root1.underlying.appending(path)),\n                NIOFilePath(root2.underlying.appending(path))\n            )\n        }\n\n        // Are symbolic links all the same?\n        for (path, type) in root1Entries where type == .symlink {\n            try await self.checkSymbolicLinksMatch(\n                NIOFilePath(root1.underlying.appending(path)),\n                NIOFilePath(root2.underlying.appending(path))\n            )\n        }\n\n        // Finally, check directories.\n        for (path, type) in root1Entries where type == .directory {\n            try await self.checkDirectoriesMatch(\n                NIOFilePath(root1.underlying.appending(path)),\n                NIOFilePath(root2.underlying.appending(path))\n            )\n        }\n    }\n\n    private func checkRegularFilesMatch(_ path1: NIOFilePath, _ path2: NIOFilePath) async throws {\n        try await self.fs.withFileHandle(forReadingAt: path1) { file1 in\n            try await self.fs.withFileHandle(forReadingAt: path2) { file2 in\n                let info1 = try await file1.info()\n                let info2 = try await file2.info()\n                XCTAssertEqual(info1.type, info2.type)\n                XCTAssertEqual(info1.size, info2.size)\n                XCTAssertEqual(info1.permissions, info2.permissions)\n\n                let file1Contents = try await file1.readToEnd(\n                    maximumSizeAllowed: .bytes(1024 * 1024)\n                )\n                let file2Contents = try await file2.readToEnd(\n                    maximumSizeAllowed: .bytes(1024 * 1024)\n                )\n                XCTAssertEqual(file1Contents, file2Contents)\n\n                do {\n                    let file1Attributes = try await file1.attributeNames().sorted()\n                    let file2Attributes = try await file2.attributeNames().sorted()\n                    XCTAssertEqual(file1Attributes, file2Attributes)\n\n                    for attribute in file1Attributes {\n                        let value1 = try await file1.valueForAttribute(attribute)\n                        let value2 = try await file2.valueForAttribute(attribute)\n                        XCTAssertEqual(value1, value2)\n                    }\n                } catch let error as FileSystemError where error.code == .unsupported {\n                    // Extended attributes aren't supported on all platforms, so swallow any\n                    // unavailable errors.\n                }\n            }\n        }\n    }\n\n    private func checkSymbolicLinksMatch(_ path1: NIOFilePath, _ path2: NIOFilePath) async throws {\n        let destination1 = try await self.fs.destinationOfSymbolicLink(at: path1)\n        let destination2 = try await self.fs.destinationOfSymbolicLink(at: path2)\n        XCTAssertEqual(destination1, destination2)\n    }\n\n    /// Declare a directory structure in code to make with ``generateDeterministicDirectoryStructure``\n    fileprivate enum TestFileStructure {\n        case dir(_ name: FilePath.Component, _ contents: [TestFileStructure] = [])\n        case file(_ name: FilePath.Component)\n        // don't care about the destination yet\n        case symbolicLink(_ name: FilePath.Component)\n\n        static func makeNestedDirs(\n            _ depth: Int,\n            namer: (Int) -> FilePath.Component = { .init(\"dir-\\($0)\")! }\n        ) -> [TestFileStructure] {\n            let name = namer(depth)\n            guard depth > 0 else {\n                return []\n            }\n            return [.dir(name, makeNestedDirs(depth - 1, namer: namer))]\n        }\n\n        static func makeManyFiles(\n            _ num: Int,\n            namer: (Int) -> FilePath.Component = { .init(\"file-\\($0)\")! }\n        ) -> [TestFileStructure] {\n            (0..<num).map { .file(namer($0)) }\n        }\n    }\n\n    /// This generates a directory structure to cover specific scenarios easily\n    private func generateDeterministicDirectoryStructure(\n        root: NIOFilePath,\n        structure: [TestFileStructure]\n    ) async throws {\n        // always make root\n        try await self.fs.createDirectory(\n            at: root,\n            withIntermediateDirectories: false,\n            permissions: nil\n        )\n\n        for item in structure {\n            switch item {\n            case let .dir(name, contents):\n                try await self.generateDeterministicDirectoryStructure(\n                    root: NIOFilePath(root.underlying.appending(name)),\n                    structure: contents\n                )\n            case let .file(name):\n                try await self.makeTestFile(NIOFilePath(root.underlying.appending(name)))\n            case let .symbolicLink(name):\n                try await self.fs.createSymbolicLink(\n                    at: NIOFilePath(root.underlying.appending(name)),\n                    withDestination: \"nonexistent-destination\"\n                )\n            }\n        }\n    }\n\n    fileprivate func makeTestFile(\n        _ path: NIOFilePath,\n        tryAddAttribute: String? = .none\n    ) async throws {\n        try await self.fs.withFileHandle(\n            forWritingAt: path,\n            options: .newFile(replaceExisting: false)\n        ) { file in\n            if let tryAddAttribute {\n                let byteCount = (32...128).randomElement()!\n                do {\n                    try await file.updateValueForAttribute(\n                        Array(repeating: 0, count: byteCount),\n                        attribute: tryAddAttribute\n                    )\n                } catch let error as FileSystemError where error.code == .unsupported {\n                    // Extended attributes are not supported on all platforms. Ignore\n                    // errors if that's the case.\n                    ()\n                }\n            }\n\n            let byteCount = (512...1024).randomElement()!\n            try await file.write(\n                contentsOf: Array(repeating: 0, count: byteCount),\n                toAbsoluteOffset: 0\n            )\n        }\n    }\n\n    private func generateDirectoryStructure(\n        root: NIOFilePath,\n        maxDepth: Int,\n        maxFilesPerDirectory: Int,\n        directoryProbability: Double = 0.3,\n        symbolicLinkProbability: Double = 0.2\n    ) async throws -> Int {\n        guard maxDepth > 0 else { return 0 }\n\n        func makeDirectory() -> Bool {\n            Double.random(in: 0..<1.0) <= directoryProbability\n        }\n\n        func makeSymbolicLink() -> Bool {\n            Double.random(in: 0..<1.0) <= symbolicLinkProbability\n        }\n\n        try await self.fs.createDirectory(\n            at: root,\n            withIntermediateDirectories: false,\n            permissions: nil\n        )\n\n        let itemsInThisDir = Int.random(in: 1...maxFilesPerDirectory)\n        var itemsCreated = 1\n\n        guard itemsInThisDir > 0 else {\n            return itemsCreated\n        }\n\n        let dirsToMake = try await self.fs.withDirectoryHandle(atPath: root) { dir in\n            var directoriesToMake = [FilePath]()\n\n            for i in 0..<itemsInThisDir {\n                if makeDirectory() {\n                    directoriesToMake.append(root.underlying.appending(\"file-\\(i)-directory\"))\n                } else if makeSymbolicLink() {\n                    let path = \"file-\\(i)-symlink\"\n                    try await self.fs.createSymbolicLink(\n                        at: NIOFilePath(root.underlying.appending(path)),\n                        withDestination: \"nonexistent-destination\"\n                    )\n                    itemsCreated += 1\n                } else {\n                    let path = root.underlying.appending(\"file-\\(i)-regular\")\n                    let attribute: String? = Bool.random() ? .some(\"attribute-{\\(i)}\") : .none\n                    try await makeTestFile(NIOFilePath(path), tryAddAttribute: attribute)\n                    itemsCreated += 1\n                }\n            }\n\n            return directoriesToMake\n        }\n\n        for path in dirsToMake {\n            itemsCreated += try await self.generateDirectoryStructure(\n                root: NIOFilePath(path),\n                maxDepth: maxDepth - 1,\n                maxFilesPerDirectory: maxFilesPerDirectory,\n                directoryProbability: directoryProbability,\n                symbolicLinkProbability: symbolicLinkProbability\n            )\n        }\n\n        return itemsCreated\n    }\n\n    func testCreateTemporaryDirectory() async throws {\n        let validTemporaryDirectoryTemplates = [\n            \"ValidTemporaryDirectoryXXX\", \"ValidTemporaryDirectoryXXXX\",\n            \"ValidTemporaryDirectoryXXXXX\", \"ValidTemporaryDirectoryXXXXXX\",\n            \"XXXXX\", \"fooXbarXXXX\", \"foo.barXXXX\",\n        ]\n\n        for templateString in validTemporaryDirectoryTemplates {\n            let template = NIOFilePath(templateString)\n\n            // A random ending consisting only of 'X's could be generated, making the template\n            // equal to the generated file path, but the probability of this happening three\n            // times in a row is very low.\n            var temporaryDirectoryPath: NIOFilePath?\n\n            attempt: for _ in 1...3 {\n                do {\n                    temporaryDirectoryPath = try await self.fs.createTemporaryDirectory(\n                        template: template\n                    )\n                    break attempt\n                } catch let error as FileSystemError where error.code == .fileAlreadyExists {\n                    // Try again.\n                    continue\n                } catch {\n                    XCTFail(\"Unexpected error creating temporary file\")\n                    return\n                }\n            }\n\n            guard let temporaryDirectoryPath = temporaryDirectoryPath else {\n                return XCTFail(\"Ran out of attempts to create a unique temporary directory\")\n            }\n\n            // Clean up after ourselves.\n            self.addTeardownBlock { [fileSystem = self.fs] in\n                try await fileSystem.removeItem(at: temporaryDirectoryPath, strategy: .platformDefault)\n            }\n\n            guard let info = try await self.fs.info(forFileAt: temporaryDirectoryPath) else {\n                return XCTFail(\"The temporary directory could not be accessed.\")\n            }\n\n            XCTAssertEqual(info.type, .directory)\n            XCTAssertGreaterThan(info.size, 0)\n        }\n    }\n\n    func testCreateTemporaryDirectoryInvalidTemplate() async throws {\n        let invalidTemporaryDirectoryTemplates = [\n            \"\", \"InalidTemporaryDirectory\", \"InvalidTemporaryDirectoryX\",\n            \"InvalidTemporaryDirectoryXX\", \"Invalidxxx\", \"InvalidXxX\",\n        ]\n        for templateString in invalidTemporaryDirectoryTemplates {\n            let template = NIOFilePath(templateString)\n            await XCTAssertThrowsFileSystemErrorAsync {\n                try await self.fs.createTemporaryDirectory(template: template)\n            } onError: { error in\n                XCTAssertEqual(error.code, .invalidArgument)\n            }\n        }\n    }\n\n    func testCreateTemporaryDirectoryWithIntermediatePaths() async throws {\n        let templateString = \"\\(#function)\"\n        let templateRoot = FilePath(templateString)\n        var template = templateRoot\n        for i in 0..<10 {\n            template.append(\"\\(i)\")\n        }\n        template.append(\"pattern-XXXXXX\")\n        let temporaryDirectoryPath = try await self.fs.createTemporaryDirectory(\n            template: NIOFilePath(template)\n        )\n\n        self.addTeardownBlock { [fileSystem = self.fs] in\n            try await fileSystem.removeItem(\n                at: NIOFilePath(templateRoot),\n                strategy: .platformDefault,\n                recursively: true\n            )\n        }\n\n        guard\n            let info = try await self.fs.info(\n                forFileAt: temporaryDirectoryPath,\n                infoAboutSymbolicLink: false\n            )\n        else {\n            XCTFail(\"The temporary directory could not be accessed.\")\n            return\n        }\n        XCTAssertEqual(info.type, .directory)\n        XCTAssertGreaterThan(info.size, 0)\n    }\n\n    func testTemporaryDirectoryRespectsEnvironment() async throws {\n        if let envTmpDir = getenv(\"TMPDIR\") {\n            let envTmpDirString = String(cString: envTmpDir)\n            let fsTempDirectory = try await fs.temporaryDirectory\n            XCTAssertEqual(fsTempDirectory.underlying, FilePath(envTmpDirString))\n        }\n    }\n\n    func testReadChunksRange() async throws {\n        try await self.fs.withFileHandle(forReadingAt: NIOFilePath(#filePath)) { handle in\n            let info = try await handle.info()\n            let size = info.size\n            let endIndex = size + 1\n\n            let ranges: [(Range<Int64>, Int)] = [\n                (0..<0, 0),\n                (0..<1, 1),\n                (0..<endIndex, Int(size)),\n                (1..<endIndex, Int(size - 1)),\n                (0..<endIndex + 1, Int(size)),\n                (1..<endIndex + 1, Int(size - 1)),\n                (0..<Int64.max, Int(size)),\n            ]\n\n            for (range, expected) in ranges {\n                let byteCount = try await handle.readChunks(in: range).reduce(into: 0) {\n                    $0 += $1.readableBytes\n                }\n\n                XCTAssertEqual(byteCount, expected)\n            }\n        }\n    }\n\n    func testReadChunksClosedRange() async throws {\n        try await self.fs.withFileHandle(forReadingAt: NIOFilePath(#filePath)) { handle in\n            let info = try await handle.info()\n            let size = info.size\n            let endIndex = size + 1\n\n            let ranges: [(ClosedRange<Int64>, Int)] = [\n                (0...0, 1),\n                (0...1, 2),\n                // Clamped to file size.\n                (0...endIndex, Int(info.size)),\n                (0...(endIndex - 1), Int(info.size)),\n                // Short one byte.\n                (1...(endIndex - 1), Int(info.size - 1)),\n                (1...endIndex, Int(info.size - 1)),\n                (0...(Int64.max - 1), Int(size)),\n            ]\n\n            for (range, expected) in ranges {\n                let byteCount = try await handle.readChunks(in: range).reduce(into: 0) {\n                    $0 += $1.readableBytes\n                }\n                XCTAssertEqual(byteCount, expected)\n            }\n        }\n    }\n\n    func testReadChunksPartialRangeUpTo() async throws {\n        try await self.fs.withFileHandle(forReadingAt: NIOFilePath(#filePath)) { handle in\n            let info = try await handle.info()\n            let size = info.size\n            let endIndex = size + 1\n\n            let ranges: [(PartialRangeUpTo<Int64>, Int)] = [\n                (..<0, 0),\n                (..<1, 1),\n                // Clamped to file size.\n                (..<endIndex, Int(info.size)),\n                // Exactly the file size.\n                (..<(endIndex - 1), Int(info.size)),\n                // One byte short.\n                (..<(endIndex - 2), Int(info.size - 1)),\n                (..<Int64.max, Int(size)),\n            ]\n\n            for (range, expected) in ranges {\n                let byteCount = try await handle.readChunks(in: range).reduce(into: 0) {\n                    $0 += $1.readableBytes\n                }\n\n                XCTAssertEqual(byteCount, expected)\n            }\n        }\n    }\n\n    func testReadChunksPartialRangeThrough() async throws {\n        try await self.fs.withFileHandle(forReadingAt: NIOFilePath(#filePath)) { handle in\n            let info = try await handle.info()\n            let size = info.size\n            let endIndex = size + 1\n\n            let ranges: [(PartialRangeThrough<Int64>, Int)] = [\n                (...0, 1),\n                (...1, 2),\n                // Clamped to size.\n                (...endIndex, Int(info.size)),\n                (...(endIndex - 1), Int(info.size)),\n                // Exact size.\n                (...(endIndex - 2), Int(info.size)),\n                // One byte short\n                (...(endIndex - 3), Int(info.size - 1)),\n                (...(Int64.max - 1), Int(size)),\n            ]\n\n            for (range, expected) in ranges {\n                let byteCount = try await handle.readChunks(in: range).reduce(into: 0) {\n                    $0 += $1.readableBytes\n                }\n\n                XCTAssertEqual(byteCount, expected)\n            }\n        }\n    }\n\n    func testReadChunksPartialRangeFrom() async throws {\n        try await self.fs.withFileHandle(forReadingAt: NIOFilePath(#filePath)) { handle in\n            let info = try await handle.info()\n            let size = info.size\n            let endIndex = size + 1\n\n            let ranges: [(PartialRangeFrom<Int64>, Int)] = [\n                (0..., Int(size)),\n                (1..., Int(size - 1)),\n                (endIndex..., 0),\n                ((endIndex - 1)..., 0),\n                ((endIndex - 2)..., 1),\n            ]\n\n            for (range, expected) in ranges {\n                let byteCount = try await handle.readChunks(in: range).reduce(into: 0) {\n                    $0 += $1.readableBytes\n                }\n\n                XCTAssertEqual(byteCount, expected, \"\\(range)\")\n            }\n        }\n    }\n\n    func testReadChunksUnboundedRange() async throws {\n        try await self.fs.withFileHandle(forReadingAt: NIOFilePath(#filePath)) { handle in\n            let info = try await handle.info()\n            let size = info.size\n\n            let byteCount = try await handle.readChunks(in: ...).reduce(into: 0) {\n                $0 += $1.readableBytes\n            }\n\n            XCTAssertEqual(byteCount, Int(size))\n        }\n    }\n\n    func testReadMoreThanByteBufferCapacity() async throws {\n        let path = try await self.fs.temporaryFilePath()\n\n        try await self.fs.withFileHandle(forReadingAndWritingAt: path) { fileHandle in\n            await XCTAssertThrowsFileSystemErrorAsync {\n                // Set `maximumSizeAllowed` to 1 byte more than can be written to `ByteBuffer`.\n                try await fileHandle.readToEnd(\n                    maximumSizeAllowed: .byteBufferCapacity + .bytes(1)\n                )\n            } onError: { error in\n                XCTAssertEqual(error.code, .resourceExhausted)\n            }\n        }\n    }\n\n    func testReadWithUnlimitedMaximumSizeAllowed() async throws {\n        let path = try await self.fs.temporaryFilePath()\n\n        try await self.fs.withFileHandle(forReadingAndWritingAt: path) { fileHandle in\n            await XCTAssertNoThrowAsync(\n                try await fileHandle.readToEnd(maximumSizeAllowed: .unlimited)\n            )\n        }\n    }\n\n    func testReadIntoArray() async throws {\n        let path = try await self.fs.temporaryFilePath()\n\n        try await self.fs.withFileHandle(forReadingAndWritingAt: path) { fileHandle in\n            _ = try await fileHandle.write(contentsOf: [0, 1, 2], toAbsoluteOffset: 0)\n        }\n\n        let contents = try await Array(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n\n        XCTAssertEqual(contents, [0, 1, 2])\n    }\n\n    func testReadIntoArraySlice() async throws {\n        let path = try await self.fs.temporaryFilePath()\n\n        try await self.fs.withFileHandle(forReadingAndWritingAt: path) { fileHandle in\n            _ = try await fileHandle.write(contentsOf: [0, 1, 2], toAbsoluteOffset: 0)\n        }\n\n        let contents = try await ArraySlice(contentsOf: path, maximumSizeAllowed: .bytes(1024))\n\n        XCTAssertEqual(contents, [0, 1, 2])\n    }\n\n    func testCopyFileReplacingExistingFileSucceeds() async throws {\n        // Use a dedicated subdirectory so the temp file check isn't polluted by\n        // concurrent tests or other processes writing to the shared temp directory.\n        let testDirectory = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(\n            at: testDirectory,\n            withIntermediateDirectories: false,\n            permissions: .ownerReadWriteExecute\n        )\n        let fs = self.fs\n\n        self.addTeardownBlock {\n            // clean up the test directory\n            _ = try await fs.removeItem(\n                at: testDirectory,\n                strategy: .platformDefault,\n                recursively: true\n            )\n        }\n\n        let sourceFileContent: [UInt8] = [1, 2, 3]\n        let source = self.fs.temporaryFilePath(inDirectory: testDirectory.underlying)\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false, permissions: .ownerReadWrite)\n        ) { handle in\n            try await handle.write(\n                contentsOf: sourceFileContent,\n                toAbsoluteOffset: 0\n            )\n        }\n\n        let existingFileContent: [UInt8] = [4, 5, 6]\n        let destination = self.fs.temporaryFilePath(inDirectory: testDirectory.underlying)\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: destination,\n            options: .newFile(replaceExisting: false, permissions: .ownerReadWriteExecute)\n        ) { handle in\n            try await handle.write(\n                contentsOf: existingFileContent,\n                toAbsoluteOffset: 0\n            )\n        }\n\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in\n                throw error\n            },\n            shouldCopyItem: { _, _ in\n                true\n            }\n        )\n\n        // verify destination now has source content and permissions\n        let destInfo = try await self.fs.info(forFileAt: destination)\n        XCTAssertEqual(destInfo?.permissions, .ownerReadWrite)\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceFileContent)\n        }\n\n        // verify source still exists with original content and permissions\n        let sourceInfo = try await self.fs.info(forFileAt: source)\n        XCTAssertEqual(sourceInfo?.permissions, .ownerReadWrite)\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceFileContent)\n        }\n\n        // verify no temp files are left (Linux only - Darwin uses COPYFILE_UNLINK)\n        #if canImport(Glibc) || canImport(Musl) || canImport(Bionic)\n        let temporaryFiles = try await self.fs.withDirectoryHandle(atPath: testDirectory) { dir in\n            var temporaryFiles: [String] = []\n            for try await batch in dir.listContents().batched() {\n                for entry in batch where entry.name.hasPrefix(\".tmp-\") {\n                    temporaryFiles.append(entry.name)\n                }\n            }\n            return temporaryFiles\n        }\n        XCTAssertTrue(temporaryFiles.isEmpty, \"Found temp files: \\(temporaryFiles)\")\n        #endif\n    }\n\n    func testCopyFileToNonExistingDestinationSucceeds() async throws {\n        let sourceFileContent: [UInt8] = [7, 8, 9]\n        let source = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(\n                contentsOf: sourceFileContent,\n                toAbsoluteOffset: 0\n            )\n        }\n\n        // destination doesn't exist\n        let destination = try await self.fs.temporaryFilePath()\n\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination now exists with expected content\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceFileContent)\n        }\n\n        // verify source still exists with original content\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceFileContent)\n        }\n    }\n\n    func testCopySymlinkReplacingExistingSymlinkSucceeds() async throws {\n        // Use a dedicated subdirectory so the temp symlink check isn't polluted by\n        // concurrent tests or other processes writing to the shared temp directory.\n        let testDirectory = try await self.fs.temporaryFilePath()\n        try await self.fs.createDirectory(\n            at: testDirectory,\n            withIntermediateDirectories: false,\n            permissions: .ownerReadWriteExecute\n        )\n        let fs = self.fs\n        self.addTeardownBlock {\n            // clean up the test directory\n            _ = try await fs.removeItem(\n                at: testDirectory,\n                strategy: .platformDefault,\n                recursively: true\n            )\n        }\n\n        let sourceTarget = self.fs.temporaryFilePath(inDirectory: testDirectory.underlying)\n        try await self.fs.withFileHandle(\n            forWritingAt: sourceTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let sourceSymlink = self.fs.temporaryFilePath(inDirectory: testDirectory.underlying)\n        try await self.fs.createSymbolicLink(\n            at: sourceSymlink,\n            withDestination: sourceTarget\n        )\n\n        let destinationTarget = self.fs.temporaryFilePath(inDirectory: testDirectory.underlying)\n        try await self.fs.withFileHandle(\n            forWritingAt: destinationTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let destinationSymlink = self.fs.temporaryFilePath(inDirectory: testDirectory.underlying)\n        try await self.fs.createSymbolicLink(\n            at: destinationSymlink,\n            withDestination: destinationTarget\n        )\n\n        try await self.fs.copyItem(\n            at: sourceSymlink,\n            to: destinationSymlink,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination symlink now points to source's target\n        let destinationTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: destinationSymlink)\n        XCTAssertEqual(destinationTargetAfterCopy, sourceTarget)\n\n        // verify source symlink has not changed\n        let sourceTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: sourceSymlink)\n        XCTAssertEqual(sourceTargetAfterCopy, sourceTarget)\n\n        // verify no temp symlinks are left\n        let temporarySymlinks = try await self.fs.withDirectoryHandle(atPath: testDirectory) { dir in\n            var temporarySymlinks: [String] = []\n            for try await batch in dir.listContents().batched() {\n                for entry in batch where entry.name.hasPrefix(\".tmp-link-\") {\n                    temporarySymlinks.append(entry.name)\n                }\n            }\n            return temporarySymlinks\n        }\n        XCTAssertTrue(temporarySymlinks.isEmpty, \"Found temp symlinks: \\(temporarySymlinks)\")\n    }\n\n    func testCopySymlinkToNonExistingDestinationSucceeds() async throws {\n        let sourceTarget = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: sourceTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let sourceSymlink = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(\n            at: sourceSymlink,\n            withDestination: sourceTarget\n        )\n\n        // destination symlink doesn't exist\n        let destinationSymlink = try await self.fs.temporaryFilePath()\n\n        try await self.fs.copyItem(\n            at: sourceSymlink,\n            to: destinationSymlink,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination symlink now exists and points to source's target\n        let destinationTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: destinationSymlink)\n        XCTAssertEqual(destinationTargetAfterCopy, sourceTarget)\n\n        // verify source symlink has not changed\n        let sourceTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: sourceSymlink)\n        XCTAssertEqual(sourceTargetAfterCopy, sourceTarget)\n    }\n\n    func testCopySymlinkToExistingDestinationFailsWithoutReplaceExisting() async throws {\n        let sourceTarget = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: sourceTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let sourceSymlink = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: sourceSymlink, withDestination: sourceTarget)\n\n        let destinationTarget = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: destinationTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let destinationSymlink = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: destinationSymlink, withDestination: destinationTarget)\n\n        // should fail with `fileAlreadyExists`\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.copyItem(\n                at: sourceSymlink,\n                to: destinationSymlink,\n                strategy: .platformDefault,\n                replaceExisting: false,\n                shouldProceedAfterError: { _, error in throw error },\n                shouldCopyItem: { _, _ in true }\n            )\n        } onError: { error in\n            XCTAssertEqual(error.code, .fileAlreadyExists)\n        }\n\n        // verify destination symlink is unchanged\n        let destinationTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: destinationSymlink)\n        XCTAssertEqual(destinationTargetAfterCopy, destinationTarget)\n\n        // verify source symlink is unchanged\n        let sourceTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: sourceSymlink)\n        XCTAssertEqual(sourceTargetAfterCopy, sourceTarget)\n    }\n\n    func testCopyFileToExistingDestinationFailsWithoutReplaceExisting() async throws {\n        let sourceContent: [UInt8] = [1, 2, 3]\n        let source = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: sourceContent, toAbsoluteOffset: 0)\n        }\n\n        let destinationContent: [UInt8] = [4, 5, 6]\n        let destination = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: destination,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: destinationContent, toAbsoluteOffset: 0)\n        }\n\n        // should fail with `fileAlreadyExists`\n        await XCTAssertThrowsFileSystemErrorAsync {\n            try await self.fs.copyItem(\n                at: source,\n                to: destination,\n                strategy: .platformDefault,\n                replaceExisting: false,\n                shouldProceedAfterError: { _, error in throw error },\n                shouldCopyItem: { _, _ in true }\n            )\n        } onError: { error in\n            XCTAssertEqual(error.code, .fileAlreadyExists)\n        }\n\n        // verify the destination is unchanged\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), destinationContent)\n        }\n\n        // verify the source is unchanged\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n    }\n\n    func testCopyFileReplacingExistingSymlinkSucceeds() async throws {\n        let sourceContent: [UInt8] = [10, 20, 30]\n        let source = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: sourceContent, toAbsoluteOffset: 0)\n        }\n\n        let symlinkTarget = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: symlinkTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n\n        let destination = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: destination, withDestination: symlinkTarget)\n\n        // verify destination is a symlink before copy\n        let infoBefore = try await self.fs.info(forFileAt: destination, infoAboutSymbolicLink: true)\n        XCTAssertEqual(infoBefore?.type, .symlink)\n\n        // overwrite symlink with regular file\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination is now a regular file\n        let infoAfter = try await self.fs.info(forFileAt: destination, infoAboutSymbolicLink: true)\n        XCTAssertEqual(infoAfter?.type, .regular)\n\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n\n        // verify source is unchanged\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n    }\n\n    func testCopySymlinkReplacingExistingFileSucceeds() async throws {\n        let destinationContent: [UInt8] = [40, 50, 60]\n        let destination = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: destination,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: destinationContent, toAbsoluteOffset: 0)\n        }\n\n        let symlinkTarget = try await self.fs.temporaryFilePath()\n        try await self.fs.withFileHandle(\n            forWritingAt: symlinkTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        let sourceSymlink = try await self.fs.temporaryFilePath()\n        try await self.fs.createSymbolicLink(at: sourceSymlink, withDestination: symlinkTarget)\n\n        // verify destination is a regular file before copy\n        let infoBefore = try await self.fs.info(forFileAt: destination, infoAboutSymbolicLink: true)\n        XCTAssertEqual(infoBefore?.type, .regular)\n\n        // overwrite regular file with symlink\n        try await self.fs.copyItem(\n            at: sourceSymlink,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination is now a symlink pointing to correct target\n        let infoAfter = try await self.fs.info(forFileAt: destination, infoAboutSymbolicLink: true)\n        XCTAssertEqual(infoAfter?.type, .symlink)\n\n        let target = try await self.fs.destinationOfSymbolicLink(at: destination)\n        XCTAssertEqual(target, symlinkTarget)\n\n        // verify source symlink is unchanged\n        let sourceTarget = try await self.fs.destinationOfSymbolicLink(at: sourceSymlink)\n        XCTAssertEqual(sourceTarget, symlinkTarget)\n    }\n\n    func testCopyDanglingSymlinkSucceeds() async throws {\n        let nonExistentTarget = try await self.fs.temporaryFilePath()\n        let sourceSymlink = try await self.fs.temporaryFilePath()\n\n        // dangling symbolic link\n        try await self.fs.createSymbolicLink(at: sourceSymlink, withDestination: nonExistentTarget)\n        let targetInfo = try await self.fs.info(forFileAt: nonExistentTarget)\n        XCTAssertNil(targetInfo)\n\n        let destinationSymlink = try await self.fs.temporaryFilePath()\n\n        try await self.fs.copyItem(\n            at: sourceSymlink,\n            to: destinationSymlink,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination symlink exists and points to same (non-existent) target\n        let destTarget = try await self.fs.destinationOfSymbolicLink(at: destinationSymlink)\n        XCTAssertEqual(destTarget, nonExistentTarget)\n\n        let destInfo = try await self.fs.info(forFileAt: destinationSymlink, infoAboutSymbolicLink: false)\n        XCTAssertNil(destInfo)\n\n        // verify source symlink is unchanged\n        let sourceTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: sourceSymlink)\n        XCTAssertEqual(sourceTargetAfterCopy, nonExistentTarget)\n    }\n\n    func testCopyFileReplacingExistingFileWithLargerSourceSucceeds() async throws {\n        let sourceContent: [UInt8] = Array(repeating: 0xAB, count: 1024)\n        let source = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: sourceContent, toAbsoluteOffset: 0)\n        }\n\n        let destinationContent: [UInt8] = [1, 2, 3]\n        let destination = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: destination,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: destinationContent, toAbsoluteOffset: 0)\n        }\n\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination now has source content\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(2048))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n\n        // verify source is unchanged\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(2048))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n    }\n\n    func testCopyFileReplacingExistingFileWithSmallerSourceSucceeds() async throws {\n        let sourceContent: [UInt8] = [1, 2, 3]\n        let source = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: sourceContent, toAbsoluteOffset: 0)\n        }\n\n        let destinationContent: [UInt8] = Array(repeating: 0xAB, count: 1024)\n        let destination = try await self.fs.temporaryFilePath()\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: destination,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: destinationContent, toAbsoluteOffset: 0)\n        }\n\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        // verify destination now has source content\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(2048))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n\n        // verify source is unchanged\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let contents = try await handle.readToEnd(maximumSizeAllowed: .bytes(2048))\n            XCTAssertEqual(Array(buffer: contents), sourceContent)\n        }\n    }\n\n    func testCopyFileWithRelativePathsSucceeds() async throws {\n        let source = NIOFilePath(\"source\")\n        let destination = NIOFilePath(\"destination\")\n        let sourceContent: [UInt8] = [1, 2, 3, 4, 5]\n        let destinationContent: [UInt8] = [9, 9, 9, 9, 9]\n\n        self.addTeardownBlock { [fs] in\n            _ = try? await fs.removeItem(at: source, strategy: .platformDefault)\n            _ = try? await fs.removeItem(at: destination, strategy: .platformDefault)\n        }\n\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: source,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: sourceContent, toAbsoluteOffset: 0)\n        }\n        _ = try await self.fs.withFileHandle(\n            forWritingAt: destination,\n            options: .newFile(replaceExisting: false)\n        ) { handle in\n            try await handle.write(contentsOf: destinationContent, toAbsoluteOffset: 0)\n        }\n\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        try await self.fs.withFileHandle(forReadingAt: destination) { handle in\n            let destinationContentAfterCopy = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: destinationContentAfterCopy), sourceContent)\n        }\n\n        try await self.fs.withFileHandle(forReadingAt: source) { handle in\n            let sourceContentAfterCopy = try await handle.readToEnd(maximumSizeAllowed: .bytes(1024))\n            XCTAssertEqual(Array(buffer: sourceContentAfterCopy), sourceContent)\n        }\n    }\n\n    func testCopySymlinkWithRelativePathsSucceeds() async throws {\n        let sourceTarget = NIOFilePath(\"source-target\")\n        let source = NIOFilePath(\"source-link\")\n        let destinationTarget = NIOFilePath(\"destination-target\")\n        let destination = NIOFilePath(\"destination-link\")\n\n        self.addTeardownBlock { [fs] in\n            _ = try? await fs.removeItem(at: sourceTarget, strategy: .platformDefault)\n            _ = try? await fs.removeItem(at: destinationTarget, strategy: .platformDefault)\n            _ = try? await fs.removeItem(at: source, strategy: .platformDefault)\n            _ = try? await fs.removeItem(at: destination, strategy: .platformDefault)\n        }\n\n        try await self.fs.withFileHandle(\n            forWritingAt: sourceTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        try await self.fs.withFileHandle(\n            forWritingAt: destinationTarget,\n            options: .newFile(replaceExisting: false)\n        ) { _ in }\n        try await self.fs.createSymbolicLink(at: source, withDestination: sourceTarget)\n        try await self.fs.createSymbolicLink(at: destination, withDestination: destinationTarget)\n\n        try await self.fs.copyItem(\n            at: source,\n            to: destination,\n            strategy: .platformDefault,\n            replaceExisting: true,\n            shouldProceedAfterError: { _, error in throw error },\n            shouldCopyItem: { _, _ in true }\n        )\n\n        let destinationTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: destination)\n        XCTAssertEqual(destinationTargetAfterCopy, sourceTarget)\n\n        let sourceTargetAfterCopy = try await self.fs.destinationOfSymbolicLink(at: source)\n        XCTAssertEqual(sourceTargetAfterCopy, sourceTarget)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/Test Data/Foo/README.txt",
    "content": "This file exists so that the containing directory is not empty.\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/Test Data/README.md",
    "content": "# Test Data\n\nThis directory contains known files and directories for integration testing. This avoids having to\nrely on APIs for creating files and directories in order to test APIs which read files and\ndirectories.\n"
  },
  {
    "path": "Tests/NIOFSIntegrationTests/XCTestExtensions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfunc XCTAssertThrowsErrorAsync<R>(\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    expression: () async throws -> R,\n    onError: (Error) -> Void = { _ in }\n) async {\n    do {\n        _ = try await expression()\n        XCTFail(\"expression did not throw\", file: file, line: line)\n    } catch {\n        onError(error)\n    }\n}\n\nfunc XCTAssertThrowsFileSystemError<R>(\n    _ expression: @autoclosure () throws -> R,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ onError: (FileSystemError) -> Void = { _ in }\n) {\n    XCTAssertThrowsError(try expression(), file: file, line: line) { error in\n        if let fsError = error as? FileSystemError {\n            onError(fsError)\n        } else {\n            XCTFail(\n                \"Expected 'FileSystemError' but found '\\(type(of: error))'\",\n                file: file,\n                line: line\n            )\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfunc XCTAssertThrowsFileSystemErrorAsync<R>(\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ expression: () async throws -> R,\n    onError: (FileSystemError) -> Void = { _ in }\n) async {\n    await XCTAssertThrowsErrorAsync(file: file, line: line, expression: expression) { error in\n        if let fsError = error as? FileSystemError {\n            onError(fsError)\n        } else {\n            XCTFail(\n                \"Expected 'FileSystemError' but found '\\(type(of: error))'\",\n                file: file,\n                line: line\n            )\n        }\n    }\n}\n\nfunc XCTAssertNoThrowAsync<T>(\n    _ expression: @autoclosure () async throws -> T,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async {\n    do {\n        _ = try await expression()\n    } catch {\n        XCTFail(\"Expression did throw: \\(error)\", file: file, line: line)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/ByteCountTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOFS\nimport XCTest\n\nclass ByteCountTests: XCTestCase {\n    func testByteCountBytes() {\n        let byteCount = ByteCount.bytes(10)\n        XCTAssertEqual(byteCount.bytes, 10)\n    }\n\n    func testByteCountKilobytes() {\n        let byteCount = ByteCount.kilobytes(10)\n        XCTAssertEqual(byteCount.bytes, 10_000)\n    }\n\n    func testByteCountMegabytes() {\n        let byteCount = ByteCount.megabytes(10)\n        XCTAssertEqual(byteCount.bytes, 10_000_000)\n    }\n\n    func testByteCountGigabytes() {\n        let byteCount = ByteCount.gigabytes(10)\n        XCTAssertEqual(byteCount.bytes, 10_000_000_000)\n    }\n\n    func testByteCountKibibytes() {\n        let byteCount = ByteCount.kibibytes(10)\n        XCTAssertEqual(byteCount.bytes, 10_240)\n    }\n\n    func testByteCountMebibytes() {\n        let byteCount = ByteCount.mebibytes(10)\n        XCTAssertEqual(byteCount.bytes, 10_485_760)\n    }\n\n    func testByteCountGibibytes() {\n        let byteCount = ByteCount.gibibytes(10)\n        XCTAssertEqual(byteCount.bytes, 10_737_418_240)\n    }\n\n    func testByteCountUnlimited() {\n        let byteCount = ByteCount.unlimited\n        XCTAssertEqual(byteCount.bytes, .max)\n    }\n\n    func testByteCountEquality() {\n        let byteCount1 = ByteCount.bytes(10)\n        let byteCount2 = ByteCount.bytes(20)\n        XCTAssertEqual(byteCount1, byteCount1)\n        XCTAssertNotEqual(byteCount1, byteCount2)\n    }\n\n    func testByteCountZero() {\n        let byteCount = ByteCount.zero\n        XCTAssertEqual(byteCount.bytes, 0)\n    }\n\n    func testByteCountAddition() {\n        let byteCount1 = ByteCount.bytes(10)\n        let byteCount2 = ByteCount.bytes(20)\n        let sum = byteCount1 + byteCount2\n        XCTAssertEqual(sum.bytes, 30)\n    }\n\n    func testByteCountSubtraction() {\n        let byteCount1 = ByteCount.bytes(30)\n        let byteCount2 = ByteCount.bytes(20)\n        let difference = byteCount1 - byteCount2\n        XCTAssertEqual(difference.bytes, 10)\n    }\n\n    func testByteCountComparison() {\n        let byteCount1 = ByteCount.bytes(10)\n        let byteCount2 = ByteCount.bytes(20)\n        XCTAssertLessThan(byteCount1, byteCount2)\n        XCTAssertGreaterThan(byteCount2, byteCount1)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/DirectoryEntriesTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class DirectoryEntriesTests: XCTestCase {\n    func testDirectoryEntriesWrapsAsyncStream() async throws {\n        let stream = AsyncThrowingStream<[DirectoryEntry], Error> {\n            $0.yield([DirectoryEntry(path: \"foo\", type: .regular)!])\n            $0.yield(\n                [\n                    DirectoryEntry(path: \"bar\", type: .block)!,\n                    DirectoryEntry(path: \"baz\", type: .character)!,\n                ]\n            )\n            $0.finish()\n        }\n\n        let directoryEntries = DirectoryEntries(wrapping: stream)\n        var iterator = directoryEntries.makeAsyncIterator()\n        let entry0 = try await iterator.next()\n        XCTAssertEqual(entry0, DirectoryEntry(path: \"foo\", type: .regular))\n        let entry1 = try await iterator.next()\n        XCTAssertEqual(entry1, DirectoryEntry(path: \"bar\", type: .block))\n        let entry2 = try await iterator.next()\n        XCTAssertEqual(entry2, DirectoryEntry(path: \"baz\", type: .character))\n        let end = try await iterator.next()\n        XCTAssertNil(end)\n    }\n\n    func testDirectoryEntriesBatchesWrapsAsyncStream() async throws {\n        let stream = AsyncThrowingStream<[DirectoryEntry], Error> {\n            $0.yield([DirectoryEntry(path: \"foo\", type: .regular)!])\n            $0.yield(\n                [\n                    DirectoryEntry(path: \"bar\", type: .block)!,\n                    DirectoryEntry(path: \"baz\", type: .character)!,\n                ]\n            )\n            $0.finish()\n        }\n\n        let directoryEntries = DirectoryEntries(wrapping: stream)\n        var iterator = directoryEntries.batched().makeAsyncIterator()\n        let entry0 = try await iterator.next()\n        XCTAssertEqual(entry0, [DirectoryEntry(path: \"foo\", type: .regular)!])\n\n        let entry1 = try await iterator.next()\n        XCTAssertEqual(\n            entry1,\n            [\n                DirectoryEntry(path: \"bar\", type: .block)!,\n                DirectoryEntry(path: \"baz\", type: .character)!,\n            ]\n        )\n        let end = try await iterator.next()\n        XCTAssertNil(end)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/FileChunksTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class FileChunksTests: XCTestCase {\n    func testFileChunksWrapsAsyncStream() async throws {\n        let stream = AsyncThrowingStream<ByteBuffer, Error> {\n            $0.yield(ByteBuffer(bytes: [0, 1, 2]))\n            $0.yield(ByteBuffer(bytes: [3, 4, 5]))\n            $0.yield(ByteBuffer(bytes: [6, 7, 8]))\n            $0.finish()\n        }\n\n        let fileChunks = FileChunks(wrapping: stream)\n        var iterator = fileChunks.makeAsyncIterator()\n        let chunk0 = try await iterator.next()\n        XCTAssertEqual(chunk0, ByteBuffer(bytes: [0, 1, 2]))\n        let chunk1 = try await iterator.next()\n        XCTAssertEqual(chunk1, ByteBuffer(bytes: [3, 4, 5]))\n        let chunk2 = try await iterator.next()\n        XCTAssertEqual(chunk2, ByteBuffer(bytes: [6, 7, 8]))\n        let end = try await iterator.next()\n        XCTAssertNil(end)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/FileHandleTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_spi(Testing) import NIOFS\nimport NIOPosix\nimport XCTest\n\n#if ENABLE_MOCKING\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal final class FileHandleTests: XCTestCase {\n    private func withHandleForMocking(\n        path: FilePath = \"/probably/does/not/exist\",\n        _ execute: (SystemFileHandle, MockingDriver) throws -> Void\n    ) async throws {\n        #if ENABLE_MOCKING\n        // The executor is required to create the handle, we won't do any async work if we're\n        // mocking as the driver requires synchronous code (as it uses thread local storage).\n        let threadPool = NIOThreadPool(numberOfThreads: 1)\n        try! await threadPool.shutdownGracefully()\n\n        // Not a real descriptor.\n        let descriptor = FileDescriptor(rawValue: -1)\n        let handle = SystemFileHandle(takingOwnershipOf: descriptor, path: path, threadPool: threadPool)\n        defer {\n            // Not a 'real' descriptor so just detach to avoid \"leaking\" the descriptor and\n            // trapping in the deinit of handle.\n            XCTAssertNoThrow(try handle.detachUnsafeFileDescriptor())\n        }\n\n        try MockingDriver.withMockingEnabled { driver in\n            try execute(handle, driver)\n        }\n        #else\n        throw XCTSkip(\"Mocking is not enabled (via 'ENABLE_MOCKING')\")\n        #endif\n    }\n\n    /// A test case which mocks system calls made by the a file handle.\n    private struct MockHandleTest {\n        /// The function to run which makes a system call.\n        var fn: (SystemFileHandle) throws -> Void\n\n        /// The name of the system call being made. This is used to verify information provided\n        /// in expected errors.\n        var systemCall: String\n\n        /// Errnos which when emitted by the system are not expected to result in errors being\n        /// thrown.\n        var nonThrowingErrnos: [Errno]\n\n        /// Errnos which map to known file system error codes.\n        var knownErrnos: [Errno: FileSystemError.Code]\n\n        /// Errnos with no known mapping to file system error codes.\n        var unknownErrnos: [Errno]\n\n        init<R>(\n            expectedSystemCall: String,\n            nonThrowingErrnos: [Errno] = [],\n            knownErrnos: [Errno: FileSystemError.Code] = [:],\n            unknownErrnos: [Errno] = [],\n            expression: @escaping (SystemFileHandle) throws -> R\n        ) {\n            self.systemCall = expectedSystemCall\n            self.nonThrowingErrnos = nonThrowingErrnos\n            self.knownErrnos = knownErrnos\n            self.unknownErrnos = unknownErrnos\n            self.fn = { _ = try expression($0) }\n\n            // Verify that EBADF results in the '.closed' status.\n            let existing = self.knownErrnos.updateValue(.closed, forKey: .badFileDescriptor)\n            assert(existing == nil)\n        }\n    }\n\n    private func run(_ test: MockHandleTest) async throws {\n        try await self.withHandleForMocking { handle, driver in\n            // No errno should not throw an error.\n            try driver.testNoErrnoDoesNotThrow(try test.fn(handle))\n\n            // Some errnos are safe to ignore and should not throw.\n            for errno in test.nonThrowingErrnos {\n                try driver.testNoErrnoDoesNotThrow(errno)\n            }\n\n            // Each of these should result in an known status code.\n            for (errno, code) in test.knownErrnos {\n                try driver.testErrnoThrowsError(errno, try test.fn(handle)) { error in\n                    XCTAssertEqual(\n                        error.code,\n                        code,\n                        \"\"\"\n                        \\(test.systemCall) throwing \\(errno) resulted in '\\(error.code)',\\\n                        expected '\\(code)'.\n                        \"\"\"\n                    )\n                    XCTAssertSystemCallError(error.cause, name: test.systemCall, errno: errno)\n                }\n            }\n\n            // Each of these should result in an unknown status code.\n            for errno in test.unknownErrnos {\n                try driver.testErrnoThrowsError(errno, try test.fn(handle)) { error in\n                    XCTAssertEqual(error.code, .unknown)\n                    XCTAssertEqual(\n                        error.code,\n                        .unknown,\n                        \"\"\"\n                        \\(test.systemCall) throwing \\(errno) resulted in '\\(error.code)',\\\n                        expected 'unknown'.\n                        \"\"\"\n                    )\n                    XCTAssertSystemCallError(error.cause, name: test.systemCall, errno: errno)\n                }\n            }\n        }\n    }\n\n    func testInfo() async throws {\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"fstat\",\n            unknownErrnos: [.deadlock, .ioError]\n        ) { handle in\n            try handle.sendableView._info().get()\n        }\n\n        try await self.run(testCase)\n    }\n\n    func testReplacePermissions() async throws {\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"fchmod\",\n            knownErrnos: [\n                .invalidArgument: .invalidArgument,\n                .notPermitted: .permissionDenied,\n            ],\n            unknownErrnos: [.deadlock, .ioError]\n        ) { handle in\n            try handle.sendableView._replacePermissions(.groupRead)\n        }\n\n        try await self.run(testCase)\n    }\n\n    func testListAttributeNames() async throws {\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"flistxattr\",\n            knownErrnos: [\n                .notSupported: .unsupported,\n                .notPermitted: .unsupported,\n                .permissionDenied: .permissionDenied,\n            ],\n            unknownErrnos: [.deadlock, .ioError]\n        ) { handle in\n            try handle.sendableView._attributeNames()\n        }\n\n        try await self.run(testCase)\n    }\n\n    func testValueForAttribute() async throws {\n        var nonThrowingErrnos: [Errno] = [.noData]\n        var knownErrnos: [Errno: FileSystemError.Code] = [.notSupported: .unsupported]\n        #if canImport(Darwin)\n        nonThrowingErrnos.append(.attributeNotFound)\n        knownErrnos[.fileNameTooLong] = .invalidArgument\n        #endif\n\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"fgetxattr\",\n            nonThrowingErrnos: nonThrowingErrnos,\n            knownErrnos: knownErrnos,\n            unknownErrnos: [.deadlock, .ioError]\n        ) { handle in\n            try handle.sendableView._valueForAttribute(\"foobar\")\n        }\n\n        try await self.run(testCase)\n    }\n\n    func testSynchronize() async throws {\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"fsync\",\n            knownErrnos: [.ioError: .io],\n            unknownErrnos: [.deadlock, .addressInUse]\n        ) { handle in\n            try handle.sendableView._synchronize()\n        }\n\n        try await self.run(testCase)\n    }\n\n    func testUpdateValueForAttribute() async throws {\n        var knownErrnos: [Errno: FileSystemError.Code] = [\n            .notSupported: .unsupported,\n            .invalidArgument: .invalidArgument,\n        ]\n        #if canImport(Darwin)\n        knownErrnos[.fileNameTooLong] = .invalidArgument\n        #endif\n\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"fsetxattr\",\n            knownErrnos: knownErrnos,\n            unknownErrnos: [.deadlock, .ioError]\n        ) { handle in\n            try handle.sendableView._updateValueForAttribute([0, 1, 2, 4], attribute: \"foobar\")\n        }\n\n        try await self.run(testCase)\n    }\n\n    func testRemoveValueForAttribute() async throws {\n        var knownErrnos: [Errno: FileSystemError.Code] = [.notSupported: .unsupported]\n        #if canImport(Darwin)\n        knownErrnos[.fileNameTooLong] = .invalidArgument\n        #endif\n\n        let testCase = MockHandleTest(\n            expectedSystemCall: \"fremovexattr\",\n            knownErrnos: knownErrnos,\n            unknownErrnos: [.deadlock, .ioError]\n        ) { handle in\n            try handle.sendableView._removeValueForAttribute(\"foobar\")\n        }\n\n        try await self.run(testCase)\n    }\n}\n\nextension MockingDriver {\n    fileprivate func testNoErrnoDoesNotThrow<R>(\n        _ expression: @autoclosure () throws -> R,\n        line: UInt = #line\n    ) throws {\n        self.forceErrno = .none\n        XCTAssertNoThrow(try expression(), line: line)\n    }\n\n    fileprivate func testErrnoDoesNotThrowError<R>(\n        _ errno: Errno,\n        _ expression: @autoclosure () throws -> R,\n        line: UInt = #line\n    ) throws {\n        self.forceErrno = .always(errno: errno.rawValue)\n        XCTAssertNoThrow(try expression(), line: line)\n    }\n\n    fileprivate func testErrnoThrowsError<R>(\n        _ errno: Errno,\n        _ expression: @autoclosure () throws -> R,\n        line: UInt = #line,\n        onError: (FileSystemError) -> Void\n    ) throws {\n        self.forceErrno = .always(errno: errno.rawValue)\n        XCTAssertThrowsFileSystemError(try expression(), line: line) { error in\n            onError(error)\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Tests/NIOFSTests/FileInfoTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\nimport NIOFS\nimport XCTest\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\nimport Glibc\n#elseif canImport(Android)\nimport Android\n#endif\n\n#if canImport(Darwin)\nprivate let S_IFREG = Darwin.S_IFREG\n#elseif canImport(Glibc)\nprivate let S_IFREG = Glibc.S_IFREG\n#elseif canImport(Musl)\nprivate let S_IFREG = Musl.S_IFREG\n#endif\n\nfinal class FileInfoTests: XCTestCase {\n    private var status: CInterop.Stat {\n        var status = CInterop.Stat()\n        status.st_dev = 1\n        status.st_mode = .init(S_IFREG | 0o777)\n        status.st_nlink = 3\n        status.st_ino = 4\n        status.st_uid = 5\n        status.st_gid = 6\n        status.st_rdev = 7\n        status.st_size = 8\n        status.st_blocks = 9\n        status.st_blksize = 10\n\n        #if canImport(Darwin)\n        status.st_atimespec = timespec(tv_sec: 0, tv_nsec: 0)\n        status.st_mtimespec = timespec(tv_sec: 1, tv_nsec: 0)\n        status.st_ctimespec = timespec(tv_sec: 2, tv_nsec: 0)\n        status.st_birthtimespec = timespec(tv_sec: 3, tv_nsec: 0)\n        status.st_flags = 11\n        status.st_gen = 12\n        #elseif canImport(Glibc) || canImport(Android)\n        status.st_atim = timespec(tv_sec: 0, tv_nsec: 0)\n        status.st_mtim = timespec(tv_sec: 1, tv_nsec: 0)\n        status.st_ctim = timespec(tv_sec: 2, tv_nsec: 0)\n        #endif\n\n        return status\n    }\n\n    func testConversionFromStat() {\n        let info = FileInfo(platformSpecificStatus: self.status)\n        XCTAssertEqual(info.type, .regular)\n        XCTAssertEqual(\n            info.permissions,\n            [.groupReadWriteExecute, .ownerReadWriteExecute, .otherReadWriteExecute]\n        )\n        XCTAssertEqual(info.userID, FileInfo.UserID(rawValue: 5))\n        XCTAssertEqual(info.groupID, FileInfo.GroupID(rawValue: 6))\n        XCTAssertEqual(info.size, 8)\n\n        XCTAssertEqual(info.lastAccessTime, FileInfo.Timespec(seconds: 0, nanoseconds: 0))\n        XCTAssertEqual(info.lastDataModificationTime, FileInfo.Timespec(seconds: 1, nanoseconds: 0))\n        XCTAssertEqual(info.lastStatusChangeTime, FileInfo.Timespec(seconds: 2, nanoseconds: 0))\n    }\n\n    func testEquatableConformance() {\n        let info = FileInfo(platformSpecificStatus: self.status)\n        let other = FileInfo(platformSpecificStatus: self.status)\n        XCTAssertEqual(info, other)\n\n        func assertNotEqualAfterMutation(line: UInt = #line, _ mutate: (inout FileInfo) -> Void) {\n            var modified = info\n            mutate(&modified)\n            XCTAssertNotEqual(info, modified, line: line)\n        }\n\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_dev += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_mode += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_nlink += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_ino += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_uid += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_gid += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_rdev += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_size += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_blocks += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_blksize += 1 }\n\n        #if canImport(Darwin)\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_atimespec.tv_sec += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_mtimespec.tv_sec += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_ctimespec.tv_sec += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_birthtimespec.tv_sec += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_flags += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_gen += 1 }\n        #elseif canImport(Glibc) || canImport(Android)\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_atim.tv_sec += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_mtim.tv_sec += 1 }\n        assertNotEqualAfterMutation { $0.platformSpecificStatus!.st_ctim.tv_sec += 1 }\n        #endif\n    }\n\n    func testHashableConformance() {\n        let info = FileInfo(platformSpecificStatus: self.status)\n        let other = FileInfo(platformSpecificStatus: self.status)\n        XCTAssertEqual(Set([info, other]), [info])\n\n        func assertDifferentHashValueAfterMutation(\n            line: UInt = #line,\n            _ mutate: (inout FileInfo) -> Void\n        ) {\n            // Hash values _should_ be unique but aren't guaranteed to be. Generate 100 different\n            // versions of the value and expect that at least 80 different hash values.\n            var modified = info\n            var hashValues: Set<Int> = [info.hashValue]\n            for _ in 1..<100 {\n                mutate(&modified)\n                hashValues.insert(modified.hashValue)\n            }\n            XCTAssertGreaterThanOrEqual(hashValues.count, 80, line: line)\n        }\n\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_dev += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_mode += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_nlink += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_ino += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_uid += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_gid += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_rdev += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_size += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_blocks += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_blksize += 1 }\n\n        #if canImport(Darwin)\n        assertDifferentHashValueAfterMutation {\n            $0.platformSpecificStatus!.st_atimespec.tv_sec += 1\n        }\n        assertDifferentHashValueAfterMutation {\n            $0.platformSpecificStatus!.st_mtimespec.tv_sec += 1\n        }\n        assertDifferentHashValueAfterMutation {\n            $0.platformSpecificStatus!.st_ctimespec.tv_sec += 1\n        }\n        assertDifferentHashValueAfterMutation {\n            $0.platformSpecificStatus!.st_birthtimespec.tv_sec += 1\n        }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_flags += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_gen += 1 }\n        #elseif canImport(Glibc) || canImport(Android)\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_atim.tv_sec += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_mtim.tv_sec += 1 }\n        assertDifferentHashValueAfterMutation { $0.platformSpecificStatus!.st_ctim.tv_sec += 1 }\n        #endif\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/FileOpenOptionsTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_spi(Testing) import NIOFS\nimport XCTest\n\nfinal class FileOpenOptionsTests: XCTestCase {\n    private let expectedDefaults: FilePermissions = [\n        .ownerReadWrite,\n        .groupRead,\n        .otherRead,\n    ]\n\n    func testReadOptions() {\n        var options = OpenOptions.Read()\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [])\n\n        options.followSymbolicLinks = false\n        options.closeOnExec = true\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.noFollow, .closeOnExec])\n    }\n\n    func testDirectoryOptions() {\n        var options = OpenOptions.Directory()\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.directory])\n\n        options.followSymbolicLinks = false\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.noFollow, .directory])\n\n        options.followSymbolicLinks = true\n        options.closeOnExec = true\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.directory, .closeOnExec])\n    }\n\n    func testWriteOpenOrCreate() {\n        var options = OpenOptions.Write.modifyFile(createIfNecessary: true)\n        XCTAssertEqual(options.existingFile, .open)\n        XCTAssertEqual(options.permissionsForRegularFile, self.expectedDefaults)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create])\n\n        options = OpenOptions.Write.modifyFile(createIfNecessary: true, permissions: .groupExecute)\n        XCTAssertEqual(options.existingFile, .open)\n        XCTAssertEqual(options.permissionsForRegularFile, .groupExecute)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create])\n\n        options.followSymbolicLinks = false\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .noFollow])\n    }\n\n    func testWriteTruncateOrCreate() {\n        var options = OpenOptions.Write.newFile(replaceExisting: true)\n        XCTAssertEqual(options.existingFile, .truncate)\n        XCTAssertEqual(options.permissionsForRegularFile, self.expectedDefaults)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .truncate])\n\n        options = OpenOptions.Write.newFile(replaceExisting: true, permissions: .groupExecute)\n        XCTAssertEqual(options.existingFile, .truncate)\n        XCTAssertEqual(options.permissionsForRegularFile, .groupExecute)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .truncate])\n\n        options.followSymbolicLinks = false\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .truncate, .noFollow])\n    }\n\n    func testWriteExclusiveOpen() {\n        var options = OpenOptions.Write(existingFile: .open, newFile: nil)\n        XCTAssertEqual(options.existingFile, .open)\n        XCTAssertNil(options.newFile)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [])\n\n        options.followSymbolicLinks = false\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.noFollow])\n    }\n\n    func testWriteExclusiveCreate() {\n        var options = OpenOptions.Write.newFile(replaceExisting: false)\n        XCTAssertEqual(options.existingFile, .none)\n        XCTAssertEqual(options.permissionsForRegularFile, self.expectedDefaults)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .exclusiveCreate])\n\n        options = OpenOptions.Write.newFile(replaceExisting: false, permissions: .groupExecute)\n        XCTAssertEqual(options.existingFile, .none)\n        XCTAssertEqual(options.permissionsForRegularFile, .groupExecute)\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .exclusiveCreate])\n\n        options.followSymbolicLinks = false\n        XCTAssertEqual(FileDescriptor.OpenOptions(options), [.create, .exclusiveCreate, .noFollow])\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/FilePathTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_spi(Testing) @testable import NIOFS\nimport SystemPackage\nimport XCTest\n\n#if canImport(System)\nimport System\n#endif\n\nfinal class FilePathTests: XCTestCase {\n    /// Tests that the conversion of a SystemPackage.FilePath instance to a NIOFilePath instance (and vice-versa) results in the same underlying object.\n    func testConversion() {\n        // Create a NIOFilePath and SystemPackage.FilePath instance, both pointing to \"/foo/bar/../baz\"\n        let filePathNIO = NIOFilePath(\"/foo/bar/../baz\")\n        let filePathSystemPackage = SystemPackage.FilePath(\"/foo/bar/../baz\")\n\n        // Convert the NIOFilePath instance to a SystemPackage.FilePath one, and check if the result matches the\n        // directly initialized SystemPackage.FilePath instance\n        XCTAssertEqual(SystemPackage.FilePath(filePathNIO), filePathSystemPackage)\n\n        // Now do the opposite: convert the SystemPackage.FilePath instance to a NIOFilePath, and check if the result\n        // matches the directly initialized NIOFilePath instance\n        let systemPackageFilePathConvertedToNIO = NIOFilePath(filePathSystemPackage)\n        XCTAssertEqual(systemPackageFilePathConvertedToNIO, filePathNIO)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/FileSystemErrorTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_spi(Testing) import NIOFS\nimport XCTest\n\nfinal class FileSystemErrorTests: XCTestCase {\n    func testFileSystemErrorCustomStringConvertible() throws {\n        var error = FileSystemError(\n            code: .unsupported,\n            message: \"An error message.\",\n            cause: nil,\n            location: .init(function: \"fn(_:)\", file: \"file.swift\", line: 42)\n        )\n\n        XCTAssertEqual(String(describing: error), \"Unsupported: An error message.\")\n\n        struct SomeCausalInfo: Error {}\n        error.cause = SomeCausalInfo()\n\n        XCTAssertEqual(\n            String(describing: error),\n            \"Unsupported: An error message. (SomeCausalInfo())\"\n        )\n    }\n\n    func testFileSystemErrorCustomDebugStringConvertible() throws {\n        var error = FileSystemError(\n            code: .permissionDenied,\n            message: \"An error message.\",\n            cause: nil,\n            location: .init(function: \"fn(_:)\", file: \"file.swift\", line: 42)\n        )\n\n        XCTAssertEqual(\n            String(reflecting: error),\n            \"\"\"\n            Permission denied: \"An error message.\"\n            \"\"\"\n        )\n\n        struct SomeCausalInfo: Error, CustomStringConvertible, CustomDebugStringConvertible {\n            var description: String { \"SomeCausalInfo()\" }\n            var debugDescription: String {\n                String(reflecting: self.description)\n            }\n        }\n        error.cause = SomeCausalInfo()\n\n        XCTAssertEqual(\n            String(reflecting: error),\n            \"\"\"\n            Permission denied: \"An error message.\" (\"SomeCausalInfo()\")\n            \"\"\"\n        )\n    }\n\n    func testFileSystemErrorDetailedDescription() throws {\n        var error = FileSystemError(\n            code: .permissionDenied,\n            message: \"An error message.\",\n            cause: nil,\n            location: .init(function: \"fn(_:)\", file: \"file.swift\", line: 42)\n        )\n\n        XCTAssertEqual(\n            error.detailedDescription(),\n            \"\"\"\n            FileSystemError: Permission denied\n            ├─ Reason: An error message.\n            └─ Source location: fn(_:) (file.swift:42)\n            \"\"\"\n        )\n\n        struct SomeCausalInfo: Error, CustomStringConvertible {\n            var description: String { \"SomeCausalInfo()\" }\n        }\n        error.cause = SomeCausalInfo()\n\n        XCTAssertEqual(\n            error.detailedDescription(),\n            \"\"\"\n            FileSystemError: Permission denied\n            ├─ Reason: An error message.\n            ├─ Cause: SomeCausalInfo()\n            └─ Source location: fn(_:) (file.swift:42)\n            \"\"\"\n        )\n    }\n\n    func testFileSystemErrorCustomDebugStringConvertibleWithNestedCause() throws {\n        let location = FileSystemError.SourceLocation(\n            function: \"fn(_:)\",\n            file: \"file.swift\",\n            line: 42\n        )\n\n        let subCause = FileSystemError(\n            code: .notFound,\n            message: \"Where did I put that?\",\n            cause: FileSystemError.SystemCallError(systemCall: \"close\", errno: .badFileDescriptor),\n            location: location\n        )\n\n        let cause = FileSystemError(\n            code: .invalidArgument,\n            message: \"Can't close a file which is already closed.\",\n            cause: subCause,\n            location: location\n        )\n\n        let error = FileSystemError(\n            code: .permissionDenied,\n            message: \"I'm afraid I can't let you do that Dave.\",\n            cause: cause,\n            location: location\n        )\n\n        XCTAssertEqual(\n            error.detailedDescription(),\n            \"\"\"\n            FileSystemError: Permission denied\n            ├─ Reason: I'm afraid I can't let you do that Dave.\n            ├─ Cause:\n            │  └─ FileSystemError: Invalid argument\n            │     ├─ Reason: Can't close a file which is already closed.\n            │     ├─ Cause:\n            │     │  └─ FileSystemError: Not found\n            │     │     ├─ Reason: Where did I put that?\n            │     │     ├─ Cause: 'close' system call failed with '(9) Bad file descriptor'.\n            │     │     └─ Source location: fn(_:) (file.swift:42)\n            │     └─ Source location: fn(_:) (file.swift:42)\n            └─ Source location: fn(_:) (file.swift:42)\n            \"\"\"\n        )\n    }\n\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    func testErrorsMapToCorrectSyscallCause() throws {\n        let here = FileSystemError.SourceLocation(function: \"fn\", file: \"file\", line: 42)\n        let path = FilePath(\"/foo\")\n\n        for statName in [\"stat\", \"lstat\", \"fstat\"] {\n            assertCauseIsSyscall(statName, here) {\n                .stat(statName, errno: .badFileDescriptor, path: path, location: here)\n            }\n        }\n\n        assertCauseIsSyscall(\"fchmod\", here) {\n            .fchmod(\n                operation: .add,\n                operand: [],\n                permissions: [],\n                errno: .badFileDescriptor,\n                path: path,\n                location: here\n            )\n        }\n\n        assertCauseIsSyscall(\"flistxattr\", here) {\n            .flistxattr(errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"fgetxattr\", here) {\n            .fgetxattr(attribute: \"attr\", errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"fsetxattr\", here) {\n            .fsetxattr(attribute: \"attr\", errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"fremovexattr\", here) {\n            .fremovexattr(attribute: \"attr\", errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"fsync\", here) {\n            .fsync(errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"dup\", here) {\n            .dup(error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"close\", here) {\n            .close(error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"read\", here) {\n            .read(usingSyscall: .read, error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"pread\", here) {\n            .read(usingSyscall: .pread, error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"write\", here) {\n            .write(usingSyscall: .write, error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"pwrite\", here) {\n            .write(usingSyscall: .pwrite, error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"fdopendir\", here) {\n            .fdopendir(errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"readdir\", here) {\n            .readdir(errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"openat\", here) {\n            .open(\"openat\", error: Errno.badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"mkdir\", here) {\n            .mkdir(errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"rename\", here) {\n            .rename(\"rename\", errno: .badFileDescriptor, oldName: \"old\", newName: \"new\", location: here)\n        }\n\n        assertCauseIsSyscall(\"remove\", here) {\n            .remove(errno: .badFileDescriptor, path: path, location: here)\n        }\n\n        assertCauseIsSyscall(\"symlink\", here) {\n            .symlink(\"symlink\", errno: .badFileDescriptor, link: \"link\", target: \"target\", location: here)\n        }\n\n        assertCauseIsSyscall(\"unlink\", here) {\n            .unlink(\"unlink\", errno: .badFileDescriptor, path: \"unlink\", location: here)\n        }\n\n        assertCauseIsSyscall(\"readlink\", here) {\n            .readlink(errno: .badFileDescriptor, path: \"link\", location: here)\n        }\n\n        assertCauseIsSyscall(\"getcwd\", here) {\n            .getcwd(errno: .badFileDescriptor, location: here)\n        }\n\n        assertCauseIsSyscall(\"confstr\", here) {\n            .confstr(name: \"foo\", errno: .badFileDescriptor, location: here)\n        }\n\n        assertCauseIsSyscall(\"fcopyfile\", here) {\n            .fcopyfile(errno: .badFileDescriptor, from: \"src\", to: \"dst\", location: here)\n        }\n\n        assertCauseIsSyscall(\"copyfile\", here) {\n            .copyfile(errno: .badFileDescriptor, from: \"src\", to: \"dst\", location: here)\n        }\n\n        assertCauseIsSyscall(\"sendfile\", here) {\n            .sendfile(errno: .badFileDescriptor, from: \"src\", to: \"dst\", location: here)\n        }\n\n        assertCauseIsSyscall(\"ftruncate\", here) {\n            .ftruncate(error: Errno.badFileDescriptor, path: path, location: here)\n        }\n    }\n\n    func testErrnoMapping_stat() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed\n            ]\n        ) { errno in\n            .stat(\"stat\", errno: errno, path: \"path\", location: .fixed)\n        }\n    }\n\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    func testErrnoMapping_fchmod() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .invalidArgument: .invalidArgument,\n                .notPermitted: .permissionDenied,\n            ]\n        ) { errno in\n            .fchmod(\n                operation: .add,\n                operand: [],\n                permissions: [],\n                errno: errno,\n                path: \"\",\n                location: .fixed\n            )\n        }\n    }\n\n    func testErrnoMapping_flistxattr() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .notSupported: .unsupported,\n                .notPermitted: .unsupported,\n                .permissionDenied: .permissionDenied,\n            ]\n        ) { errno in\n            .flistxattr(errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_fgetxattr() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .notSupported: .unsupported,\n            ]\n        ) { errno in\n            .fgetxattr(attribute: \"attr\", errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_fsetxattr() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .notSupported: .unsupported,\n                .invalidArgument: .invalidArgument,\n            ]\n        ) { errno in\n            .fsetxattr(attribute: \"attr\", errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_fremovexattr() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .notSupported: .unsupported,\n            ]\n        ) { errno in\n            .fremovexattr(attribute: \"attr\", errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_fsync() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .fsync(errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_dup() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed\n            ]\n        ) { errno in\n            .dup(error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_close() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .close(error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_read() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .read(usingSyscall: .read, error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_pread() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .ioError: .io,\n                .illegalSeek: .unsupported,\n            ]\n        ) { errno in\n            .read(usingSyscall: .pread, error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_write() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .write(usingSyscall: .write, error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_pwrite() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .ioError: .io,\n                .illegalSeek: .unsupported,\n            ]\n        ) { errno in\n            .write(usingSyscall: .pwrite, error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_open() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .permissionDenied: .permissionDenied,\n                .fileExists: .fileAlreadyExists,\n                .ioError: .io,\n                .tooManyOpenFiles: .unavailable,\n                .noSuchFileOrDirectory: .notFound,\n                .notDirectory: .notFound,\n            ]\n        ) { errno in\n            .open(\"open\", error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_mkdir() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .isDirectory: .invalidArgument,\n                .notDirectory: .invalidArgument,\n                .noSuchFileOrDirectory: .invalidArgument,\n                .ioError: .io,\n                .fileExists: .fileAlreadyExists,\n            ]\n        ) { errno in\n            .mkdir(errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_rename() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .invalidArgument: .invalidArgument,\n                .noSuchFileOrDirectory: .notFound,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .rename(\"rename\", errno: errno, oldName: \"old\", newName: \"new\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_remove() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .notPermitted: .permissionDenied,\n                .resourceBusy: .unavailable,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .remove(errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_symlink() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .notPermitted: .permissionDenied,\n                .fileExists: .fileAlreadyExists,\n                .noSuchFileOrDirectory: .invalidArgument,\n                .notDirectory: .invalidArgument,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .symlink(\"symlink\", errno: errno, link: \"link\", target: \"target\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_unlink() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .notPermitted: .permissionDenied,\n                .noSuchFileOrDirectory: .notFound,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .unlink(\"unlink\", errno: errno, path: \"path\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_readlink() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .invalidArgument: .invalidArgument,\n                .noSuchFileOrDirectory: .notFound,\n                .ioError: .io,\n            ]\n        ) { errno in\n            .readlink(errno: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_copyfile() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .notSupported: .invalidArgument,\n                .permissionDenied: .permissionDenied,\n                .invalidArgument: .invalidArgument,\n                .fileExists: .fileAlreadyExists,\n                .tooManyOpenFiles: .unavailable,\n                .noSuchFileOrDirectory: .notFound,\n            ]\n        ) { errno in\n            .copyfile(errno: errno, from: \"src\", to: \"dst\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_fcopyfile() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .notSupported: .invalidArgument,\n                .invalidArgument: .invalidArgument,\n                .permissionDenied: .permissionDenied,\n            ]\n        ) { errno in\n            .fcopyfile(errno: errno, from: \"src\", to: \"dst\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_sendfile() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .ioError: .io,\n                .noMemory: .io,\n            ]\n        ) { errno in\n            .sendfile(errno: errno, from: \"src\", to: \"dst\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_resize() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .badFileDescriptor: .closed,\n                .fileTooLarge: .invalidArgument,\n                .invalidArgument: .invalidArgument,\n            ]\n        ) { errno in\n            .ftruncate(error: errno, path: \"\", location: .fixed)\n        }\n    }\n\n    func testErrnoMapping_futimens() {\n        self.testErrnoToErrorCode(\n            expected: [\n                .permissionDenied: .permissionDenied,\n                .notPermitted: .permissionDenied,\n                .readOnlyFileSystem: .unsupported,\n                .badFileDescriptor: .closed,\n            ]\n        ) { errno in\n            .futimens(errno: errno, path: \"\", lastAccessTime: nil, lastDataModificationTime: nil, location: .fixed)\n        }\n    }\n\n    private func testErrnoToErrorCode(\n        expected mapping: [Errno: FileSystemError.Code],\n        _ makeError: (Errno) -> FileSystemError\n    ) {\n        for (errno, code) in mapping {\n            let error = makeError(errno)\n            XCTAssertEqual(error.code, code, \"\\(error)\")\n        }\n\n        let errno = Errno(rawValue: -1)\n        let error = makeError(errno)\n        XCTAssertEqual(error.code, .unknown, \"\\(error)\")\n    }\n}\n\nprivate func assertCauseIsSyscall(\n    _ name: String,\n    _ location: FileSystemError.SourceLocation,\n    _ buildError: () -> FileSystemError\n) {\n    let error = buildError()\n\n    XCTAssertEqual(error.location, location)\n    if let cause = error.cause as? FileSystemError.SystemCallError {\n        XCTAssertEqual(cause.systemCall, name)\n    } else {\n        XCTFail(\"Unexpected error: \\(String(describing: error.cause))\")\n    }\n}\n\nextension FileSystemError.SourceLocation {\n    fileprivate static let fixed = Self(function: \"fn\", file: \"file\", line: 1)\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/FileTypeTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n@_spi(Testing) import NIOFS\nimport XCTest\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\nimport Glibc\n#elseif canImport(Android)\nimport Android\n#endif\n\nfinal class FileTypeTests: XCTestCase {\n    func testFileTypeEquatable() {\n        let types = FileType.allCases\n        // Use indices to avoid using the `Equatable` conformance to write the tests.\n        for index in types.indices {\n            XCTAssertEqual(types[index], types[index])\n            for otherIndex in types.indices where otherIndex != index {\n                XCTAssertNotEqual(types[index], types[otherIndex])\n            }\n        }\n    }\n\n    func testFileTypeHashable() {\n        // Tests there is `Hashable` conformance is sufficient as we rely on the compiler\n        // synthesising the implementation.\n        let types = FileType.allCases\n        let unique = Set(types)\n        XCTAssertEqual(types.count, unique.count)\n    }\n\n    func testCustomStringConvertible() {\n        XCTAssertEqual(String(describing: FileType.block), \"block\")\n        XCTAssertEqual(String(describing: FileType.character), \"character\")\n        XCTAssertEqual(String(describing: FileType.directory), \"directory\")\n        XCTAssertEqual(String(describing: FileType.fifo), \"fifo\")\n        XCTAssertEqual(String(describing: FileType.regular), \"regular\")\n        XCTAssertEqual(String(describing: FileType.socket), \"socket\")\n        XCTAssertEqual(String(describing: FileType.symlink), \"symlink\")\n        XCTAssertEqual(String(describing: FileType.unknown), \"unknown\")\n        XCTAssertEqual(String(describing: FileType.whiteout), \"whiteout\")\n    }\n\n    func testConversionFromModeT() {\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFIFO), .fifo)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFCHR), .character)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFDIR), .directory)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFBLK), .block)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFREG), .regular)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFLNK), .symlink)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFSOCK), .socket)\n        #if canImport(Darwin)\n        XCTAssertEqual(FileType(platformSpecificMode: S_IFWHT), .whiteout)\n        #endif\n    }\n\n    func testConversionFromDirentType() {\n        XCTAssertEqual(FileType(direntType: numericCast(DT_FIFO)), .fifo)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_CHR)), .character)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_DIR)), .directory)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_BLK)), .block)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_REG)), .regular)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_LNK)), .symlink)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_SOCK)), .socket)\n        #if canImport(Darwin)\n        XCTAssertEqual(FileType(direntType: numericCast(DT_WHT)), .whiteout)\n        #endif\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/Internal/CancellationTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\n@_spi(Testing) import NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class CancellationTests: XCTestCase {\n    func testWithoutCancellation() async throws {\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.cancelAll()\n\n            group.addTask {\n                XCTAssertTrue(Task.isCancelled)\n                try await withoutCancellation {\n                    XCTAssertFalse(Task.isCancelled)\n                }\n            }\n\n            group.addTask {\n                try await withoutCancellation {\n                    try Task.checkCancellation()\n                }\n            }\n\n            try await group.waitForAll()\n        }\n    }\n\n    func testUncancellableTearDownWhenNotThrowing() async throws {\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.cancelAll()\n\n            group.addTask {\n                let ranTearDown = ManagedAtomic(false)\n\n                let isCancelled = try await withUncancellableTearDown {\n                    Task.isCancelled\n                } tearDown: { _ in\n                    ranTearDown.store(true, ordering: .releasing)\n                }\n\n                XCTAssertTrue(isCancelled)\n\n                let didRunTearDown = ranTearDown.load(ordering: .acquiring)\n                XCTAssertTrue(didRunTearDown)\n            }\n\n            try await group.waitForAll()\n        }\n    }\n\n    func testUncancellableTearDownWhenThrowing() async throws {\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.cancelAll()\n\n            group.addTask {\n                let ranTearDown = ManagedAtomic(false)\n\n                await XCTAssertThrowsErrorAsync {\n                    try await withUncancellableTearDown {\n                        try Task.checkCancellation()\n                    } tearDown: { _ in\n                        ranTearDown.store(true, ordering: .releasing)\n                    }\n                } onError: { error in\n                    XCTAssert(error is CancellationError)\n                }\n\n                let didRunTearDown = ranTearDown.load(ordering: .acquiring)\n                XCTAssertTrue(didRunTearDown)\n            }\n\n            try await group.waitForAll()\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/Internal/Concurrency Primitives/BufferedStreamTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOFS\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfinal class BufferedStreamTests: XCTestCase {\n    // MARK: - sequenceDeinitialized\n\n    func testSequenceDeinitialized_whenNoIterator() async throws {\n        var (stream, source): (BufferedStream?, BufferedStream.Source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            withExtendedLifetime(stream) {}\n            stream = nil\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            do {\n                _ = try { try source.write(2) }()\n                XCTFail(\"Expected an error to be thrown\")\n            } catch {\n                XCTAssertTrue(error is AlreadyFinishedError)\n            }\n\n            group.cancelAll()\n        }\n    }\n\n    func testSequenceDeinitialized_whenIterator() async throws {\n        var (stream, source): (BufferedStream?, BufferedStream.Source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        var iterator = stream?.makeAsyncIterator()\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            try withExtendedLifetime(stream) {\n                let writeResult = try source.write(1)\n                writeResult.assertIsProducerMore()\n            }\n\n            stream = nil\n\n            do {\n                let writeResult = try { try source.write(2) }()\n                writeResult.assertIsProducerMore()\n            } catch {\n                XCTFail(\"Expected no error to be thrown\")\n            }\n\n            let element1 = try await iterator?.next()\n            XCTAssertEqual(element1, 1)\n            let element2 = try await iterator?.next()\n            XCTAssertEqual(element2, 2)\n\n            group.cancelAll()\n        }\n    }\n\n    func testSequenceDeinitialized_whenFinished() async throws {\n        var (stream, source): (BufferedStream?, BufferedStream.Source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            withExtendedLifetime(stream) {\n                source.finish(throwing: nil)\n            }\n\n            stream = nil\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            do {\n                _ = try { try source.write(1) }()\n                XCTFail(\"Expected an error to be thrown\")\n            } catch {\n                XCTAssertTrue(error is AlreadyFinishedError)\n            }\n\n            group.cancelAll()\n        }\n    }\n\n    func testSequenceDeinitialized_whenStreaming_andSuspendedProducer() async throws {\n        var (stream, source): (BufferedStream?, BufferedStream.Source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 2)\n        )\n\n        _ = try { try source.write(1) }()\n\n        do {\n            try await withCheckedThrowingContinuation { continuation in\n                source.write(1) { result in\n                    continuation.resume(with: result)\n                }\n\n                stream = nil\n                _ = stream?.makeAsyncIterator()\n            }\n        } catch {\n            XCTAssertTrue(error is AlreadyFinishedError)\n        }\n    }\n\n    // MARK: - iteratorInitialized\n\n    func testIteratorInitialized_whenInitial() async throws {\n        let (stream, _) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        _ = stream.makeAsyncIterator()\n    }\n\n    func testIteratorInitialized_whenStreaming() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        try await source.write(1)\n\n        var iterator = stream.makeAsyncIterator()\n        let element = try await iterator.next()\n        XCTAssertEqual(element, 1)\n    }\n\n    func testIteratorInitialized_whenSourceFinished() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        try await source.write(1)\n        source.finish(throwing: nil)\n\n        var iterator = stream.makeAsyncIterator()\n        let element1 = try await iterator.next()\n        XCTAssertEqual(element1, 1)\n        let element2 = try await iterator.next()\n        XCTAssertNil(element2)\n    }\n\n    func testIteratorInitialized_whenFinished() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        source.finish(throwing: nil)\n\n        var iterator = stream.makeAsyncIterator()\n        let element = try await iterator.next()\n        XCTAssertNil(element)\n    }\n\n    // MARK: - iteratorDeinitialized\n\n    func testIteratorDeinitialized_whenInitial() async throws {\n        var (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            iterator = nil\n            _ = try await iterator?.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testIteratorDeinitialized_whenStreaming() async throws {\n        var (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await source.write(1)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            iterator = nil\n            _ = try await iterator?.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testIteratorDeinitialized_whenSourceFinished() async throws {\n        var (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await source.write(1)\n        source.finish(throwing: nil)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            iterator = nil\n            _ = try await iterator?.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testIteratorDeinitialized_whenFinished() async throws {\n        var (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        source.finish(throwing: nil)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            iterator = nil\n            _ = try await iterator?.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testIteratorDeinitialized_whenStreaming_andSuspendedProducer() async throws {\n        var (stream, source): (BufferedStream?, BufferedStream.Source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 2)\n        )\n\n        var iterator: BufferedStream<Int>.AsyncIterator? = stream?.makeAsyncIterator()\n        stream = nil\n\n        _ = try { try source.write(1) }()\n\n        do {\n            try await withCheckedThrowingContinuation { continuation in\n                source.write(1) { result in\n                    continuation.resume(with: result)\n                }\n\n                iterator = nil\n            }\n        } catch {\n            XCTAssertTrue(error is AlreadyFinishedError)\n        }\n\n        _ = try await iterator?.next()\n    }\n\n    // MARK: - sourceDeinitialized\n\n    func testSourceDeinitialized_whenInitial() async throws {\n        var (stream, source): (BufferedStream, BufferedStream.Source?) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source?.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            source = nil\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n\n        withExtendedLifetime(stream) {}\n    }\n\n    func testSourceDeinitialized_whenStreaming_andEmptyBuffer() async throws {\n        var (stream, source): (BufferedStream, BufferedStream.Source?) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source?.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await source?.write(1)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            _ = try await iterator?.next()\n\n            source = nil\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testSourceDeinitialized_whenStreaming_andNotEmptyBuffer() async throws {\n        var (stream, source): (BufferedStream, BufferedStream.Source?) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source?.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await source?.write(1)\n        try await source?.write(2)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            _ = try await iterator?.next()\n\n            source = nil\n\n            _ = await onTerminationIterator.next()\n\n            _ = try await iterator?.next()\n            _ = try await iterator?.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testSourceDeinitialized_whenSourceFinished() async throws {\n        var (stream, source): (BufferedStream, BufferedStream.Source?) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source?.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        try await source?.write(1)\n        try await source?.write(2)\n        source?.finish(throwing: nil)\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            var iterator: BufferedStream<Int>.AsyncIterator? = stream.makeAsyncIterator()\n            _ = try await iterator?.next()\n\n            source = nil\n\n            _ = await onTerminationIterator.next()\n\n            _ = try await iterator?.next()\n            _ = try await iterator?.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testSourceDeinitialized_whenFinished() async throws {\n        var (stream, source): (BufferedStream, BufferedStream.Source?) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 5, high: 10)\n        )\n\n        let (onTerminationStream, onTerminationContinuation) = AsyncStream<Void>.makeStream()\n        source?.onTermination = {\n            onTerminationContinuation.finish()\n        }\n\n        source?.finish(throwing: nil)\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while !Task.isCancelled {\n                    onTerminationContinuation.yield()\n                    try await Task.sleep(nanoseconds: 200_000_000)\n                }\n            }\n\n            var onTerminationIterator = onTerminationStream.makeAsyncIterator()\n            _ = await onTerminationIterator.next()\n\n            _ = stream.makeAsyncIterator()\n\n            source = nil\n\n            _ = await onTerminationIterator.next()\n\n            let terminationResult: Void? = await onTerminationIterator.next()\n            XCTAssertNil(terminationResult)\n\n            group.cancelAll()\n        }\n    }\n\n    func testSourceDeinitialized_whenStreaming_andSuspendedProducer() async throws {\n        var (stream, source): (BufferedStream, BufferedStream.Source?) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 0, high: 0)\n        )\n        let (producerStream, producerContinuation) = AsyncThrowingStream<Void, Error>.makeStream()\n        var iterator = stream.makeAsyncIterator()\n\n        source?.write(1) {\n            producerContinuation.yield(with: $0)\n        }\n\n        _ = try await iterator.next()\n        source = nil\n\n        do {\n            try await producerStream.first { _ in true }\n            XCTFail(\"We expected to throw here\")\n        } catch {\n            XCTAssertTrue(error is AlreadyFinishedError)\n        }\n    }\n\n    // MARK: - write\n\n    func testWrite_whenInitial() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 5)\n        )\n\n        try await source.write(1)\n\n        var iterator = stream.makeAsyncIterator()\n        let element = try await iterator.next()\n        XCTAssertEqual(element, 1)\n    }\n\n    func testWrite_whenStreaming_andNoConsumer() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 5)\n        )\n\n        try await source.write(1)\n        try await source.write(2)\n\n        var iterator = stream.makeAsyncIterator()\n        let element1 = try await iterator.next()\n        XCTAssertEqual(element1, 1)\n        let element2 = try await iterator.next()\n        XCTAssertEqual(element2, 2)\n    }\n\n    func testWrite_whenStreaming_andSuspendedConsumer() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 5)\n        )\n\n        try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await stream.first { _ in true }\n            }\n\n            // This is always going to be a bit racy since we need the call to next() suspend\n            try await Task.sleep(nanoseconds: 500_000_000)\n\n            try await source.write(1)\n            let element = try await group.next()\n            XCTAssertEqual(element, 1)\n        }\n    }\n\n    func testWrite_whenStreaming_andSuspendedConsumer_andEmptySequence() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 5)\n        )\n\n        try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await stream.first { _ in true }\n            }\n\n            // This is always going to be a bit racy since we need the call to next() suspend\n            try await Task.sleep(nanoseconds: 500_000_000)\n\n            try await source.write(contentsOf: [])\n            try await source.write(contentsOf: [1])\n            let element = try await group.next()\n            XCTAssertEqual(element, 1)\n        }\n    }\n\n    // MARK: - enqueueProducer\n\n    func testEnqueueProducer_whenStreaming_andAndCancelled() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 2)\n        )\n\n        let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()\n\n        try await source.write(1)\n\n        let writeResult = try { try source.write(2) }()\n\n        switch writeResult {\n        case .produceMore:\n            preconditionFailure()\n        case .enqueueCallback(let callbackToken):\n            source.cancelCallback(callbackToken: callbackToken)\n\n            source.enqueueCallback(callbackToken: callbackToken) { result in\n                producerSource.yield(with: result)\n            }\n        }\n\n        do {\n            _ = try await producerStream.first { _ in true }\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertTrue(error is CancellationError)\n        }\n\n        let element = try await stream.first { _ in true }\n        XCTAssertEqual(element, 1)\n    }\n\n    func testEnqueueProducer_whenStreaming_andAndCancelled_andAsync() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 2)\n        )\n\n        try await source.write(1)\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                try await source.write(2)\n            }\n\n            group.cancelAll()\n            do {\n                try await group.next()\n                XCTFail(\"Expected an error to be thrown\")\n            } catch {\n                XCTAssertTrue(error is CancellationError)\n            }\n        }\n\n        let element = try await stream.first { _ in true }\n        XCTAssertEqual(element, 1)\n    }\n\n    func testEnqueueProducer_whenStreaming_andInterleaving() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 1)\n        )\n        var iterator = stream.makeAsyncIterator()\n\n        let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()\n\n        let writeResult = try { try source.write(1) }()\n\n        switch writeResult {\n        case .produceMore:\n            preconditionFailure()\n        case .enqueueCallback(let callbackToken):\n            let element = try await iterator.next()\n            XCTAssertEqual(element, 1)\n\n            source.enqueueCallback(callbackToken: callbackToken) { result in\n                producerSource.yield(with: result)\n            }\n        }\n\n        do {\n            _ = try await producerStream.first { _ in true }\n        } catch {\n            XCTFail(\"Expected no error to be thrown\")\n        }\n    }\n\n    func testEnqueueProducer_whenStreaming_andSuspending() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 1)\n        )\n        var iterator = stream.makeAsyncIterator()\n\n        let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()\n\n        let writeResult = try { try source.write(1) }()\n\n        switch writeResult {\n        case .produceMore:\n            preconditionFailure()\n        case .enqueueCallback(let callbackToken):\n            source.enqueueCallback(callbackToken: callbackToken) { result in\n                producerSource.yield(with: result)\n            }\n        }\n\n        let element = try await iterator.next()\n        XCTAssertEqual(element, 1)\n\n        do {\n            _ = try await producerStream.first { _ in true }\n        } catch {\n            XCTFail(\"Expected no error to be thrown\")\n        }\n    }\n\n    func testEnqueueProducer_whenFinished() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 1)\n        )\n        var iterator = stream.makeAsyncIterator()\n\n        let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()\n\n        let writeResult = try { try source.write(1) }()\n\n        switch writeResult {\n        case .produceMore:\n            preconditionFailure()\n        case .enqueueCallback(let callbackToken):\n            source.finish(throwing: nil)\n\n            source.enqueueCallback(callbackToken: callbackToken) { result in\n                producerSource.yield(with: result)\n            }\n        }\n\n        let element = try await iterator.next()\n        XCTAssertEqual(element, 1)\n\n        do {\n            _ = try await producerStream.first { _ in true }\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertTrue(error is AlreadyFinishedError)\n        }\n    }\n\n    // MARK: - cancelProducer\n\n    func testCancelProducer_whenStreaming() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 2)\n        )\n\n        let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()\n\n        try await source.write(1)\n\n        let writeResult = try { try source.write(2) }()\n\n        switch writeResult {\n        case .produceMore:\n            preconditionFailure()\n        case .enqueueCallback(let callbackToken):\n            source.enqueueCallback(callbackToken: callbackToken) { result in\n                producerSource.yield(with: result)\n            }\n\n            source.cancelCallback(callbackToken: callbackToken)\n        }\n\n        do {\n            _ = try await producerStream.first { _ in true }\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertTrue(error is CancellationError)\n        }\n\n        let element = try await stream.first { _ in true }\n        XCTAssertEqual(element, 1)\n    }\n\n    func testCancelProducer_whenSourceFinished() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 2)\n        )\n\n        let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()\n\n        try await source.write(1)\n\n        let writeResult = try { try source.write(2) }()\n\n        switch writeResult {\n        case .produceMore:\n            preconditionFailure()\n        case .enqueueCallback(let callbackToken):\n            source.enqueueCallback(callbackToken: callbackToken) { result in\n                producerSource.yield(with: result)\n            }\n\n            source.finish(throwing: nil)\n\n            source.cancelCallback(callbackToken: callbackToken)\n        }\n\n        do {\n            _ = try await producerStream.first { _ in true }\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertTrue(error is AlreadyFinishedError)\n        }\n\n        let element = try await stream.first { _ in true }\n        XCTAssertEqual(element, 1)\n    }\n\n    // MARK: - finish\n\n    func testFinish_whenStreaming_andConsumerSuspended() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 1)\n        )\n\n        try await withThrowingTaskGroup(of: Int?.self) { group in\n            group.addTask {\n                try await stream.first { $0 == 2 }\n            }\n\n            // This is always going to be a bit racy since we need the call to next() suspend\n            try await Task.sleep(nanoseconds: 500_000_000)\n\n            source.finish(throwing: nil)\n            let element = try await group.next()\n            XCTAssertEqual(element, .some(nil))\n        }\n    }\n\n    func testFinish_whenInitial() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 1, high: 1)\n        )\n\n        source.finish(throwing: CancellationError())\n\n        do {\n            for try await _ in stream {}\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertTrue(error is CancellationError)\n        }\n\n    }\n\n    // MARK: - Backpressure\n\n    func testBackPressure() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 4)\n        )\n\n        let (backPressureEventStream, backPressureEventContinuation) = AsyncStream.makeStream(\n            of: Void.self\n        )\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                while true {\n                    backPressureEventContinuation.yield(())\n                    try await source.write(contentsOf: [1])\n                }\n            }\n\n            var backPressureEventIterator = backPressureEventStream.makeAsyncIterator()\n            var iterator = stream.makeAsyncIterator()\n\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n\n            _ = try await iterator.next()\n            _ = try await iterator.next()\n            _ = try await iterator.next()\n\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n\n            group.cancelAll()\n        }\n    }\n\n    func testBackPressureSync() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 4)\n        )\n\n        let (backPressureEventStream, backPressureEventContinuation) = AsyncStream.makeStream(\n            of: Void.self\n        )\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            group.addTask {\n                @Sendable func yield() {\n                    backPressureEventContinuation.yield(())\n                    source.write(contentsOf: [1]) { result in\n                        switch result {\n                        case .success:\n                            yield()\n\n                        case .failure:\n                            break\n                        }\n                    }\n                }\n\n                yield()\n            }\n\n            var backPressureEventIterator = backPressureEventStream.makeAsyncIterator()\n            var iterator = stream.makeAsyncIterator()\n\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n\n            _ = try await iterator.next()\n            _ = try await iterator.next()\n            _ = try await iterator.next()\n\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n            await backPressureEventIterator.next()\n\n            group.cancelAll()\n        }\n    }\n\n    func testThrowsError() async throws {\n        let (stream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 4)\n        )\n\n        try await source.write(1)\n        try await source.write(2)\n        source.finish(throwing: CancellationError())\n\n        var elements = [Int]()\n        var iterator = stream.makeAsyncIterator()\n\n        do {\n            while let element = try await iterator.next() {\n                elements.append(element)\n            }\n            XCTFail(\"Expected an error to be thrown\")\n        } catch {\n            XCTAssertTrue(error is CancellationError)\n            XCTAssertEqual(elements, [1, 2])\n        }\n\n        let element = try await iterator.next()\n        XCTAssertNil(element)\n    }\n\n    func testAsyncSequenceWrite() async throws {\n        let (stream, continuation) = AsyncStream<Int>.makeStream()\n        let (backpressuredStream, source) = BufferedStream.makeStream(\n            of: Int.self,\n            backPressureStrategy: .watermark(low: 2, high: 4)\n        )\n\n        continuation.yield(1)\n        continuation.yield(2)\n        continuation.finish()\n\n        try await source.write(contentsOf: stream)\n        source.finish(throwing: nil)\n\n        let elements = try await backpressuredStream.collect()\n        XCTAssertEqual(elements, [1, 2])\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncSequence {\n    /// Collect all elements in the sequence into an array.\n    fileprivate func collect() async rethrows -> [Element] {\n        try await self.reduce(into: []) { accumulated, next in\n            accumulated.append(next)\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension BufferedStream.Source.WriteResult {\n    func assertIsProducerMore() {\n        switch self {\n        case .produceMore:\n            return\n\n        case .enqueueCallback:\n            XCTFail(\"Expected produceMore\")\n        }\n    }\n\n    func assertIsEnqueueCallback() {\n        switch self {\n        case .produceMore:\n            XCTFail(\"Expected enqueueCallback\")\n\n        case .enqueueCallback:\n            return\n        }\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncStream {\n    static func makeStream(\n        of elementType: Element.Type = Element.self,\n        bufferingPolicy limit: AsyncStream<Element>.Continuation.BufferingPolicy = .unbounded\n    ) -> (stream: AsyncStream<Element>, continuation: AsyncStream<Element>.Continuation) {\n        var continuation: AsyncStream<Element>.Continuation!\n        let stream = AsyncStream(bufferingPolicy: limit) { continuation = $0 }\n        return (stream, continuation!)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncThrowingStream {\n    static func makeStream(\n        of elementType: Element.Type = Element.self,\n        throwing failureType: Failure.Type = Failure.self,\n        bufferingPolicy limit: AsyncThrowingStream<Element, Failure>.Continuation.BufferingPolicy =\n            .unbounded\n    ) -> (\n        stream: AsyncThrowingStream<Element, Failure>,\n        continuation: AsyncThrowingStream<Element, Failure>.Continuation\n    ) where Failure == Error {\n        var continuation: AsyncThrowingStream<Element, Failure>.Continuation!\n        let stream = AsyncThrowingStream(bufferingPolicy: limit) { continuation = $0 }\n        return (stream, continuation!)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFSTests/Internal/MockingInfrastructure.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n//This source file is part of the Swift System open source project\n//\n//Copyright (c) 2020 Apple Inc. and the Swift System project authors\n//Licensed under Apache License v2.0 with Runtime Library Exception\n//\n//See https://swift.org/LICENSE.txt for license information\n\n@_spi(Testing) import NIOFS\nimport SystemPackage\nimport XCTest\n\n#if ENABLE_MOCKING\ninternal struct Wildcard: Hashable {}\n\nextension Trace.Entry {\n    /// This implements `==` with wildcard matching.\n    /// (`Entry` cannot conform to `Equatable`/`Hashable` this way because\n    /// the wildcard matching `==` relation isn't transitive.)\n    internal func matches(_ other: Self) -> Bool {\n        guard self.name == other.name else { return false }\n        guard self.arguments.count == other.arguments.count else { return false }\n        for i in self.arguments.indices {\n            if self.arguments[i] is Wildcard || other.arguments[i] is Wildcard {\n                continue\n            }\n            guard self.arguments[i] == other.arguments[i] else { return false }\n        }\n        return true\n    }\n}\n\ninternal protocol TestCase {\n    // TODO: want a source location stack, more fidelity, kinds of stack entries, etc\n    var file: StaticString { get }\n    var line: UInt { get }\n\n    // TODO: Instead have an attribute to register a test in a allTests var, similar to the argument parser.\n    func runAllTests()\n\n    // Customization hook: add adornment to reported failure reason\n    // Defaut: reason or empty\n    func failureMessage(_ reason: String?) -> String\n}\n\nextension TestCase {\n    // Default implementation\n    func failureMessage(_ reason: String?) -> String { reason ?? \"\" }\n\n    func expectEqualSequence<S1: Sequence, S2: Sequence>(\n        _ expected: S1,\n        _ actual: S2,\n        _ message: String? = nil\n    ) where S1.Element: Equatable, S1.Element == S2.Element {\n        if !expected.elementsEqual(actual) {\n            defer { print(\"expected: \\(expected)\\n  actual: \\(actual)\") }\n            fail(message)\n        }\n    }\n    func expectEqual<E: Equatable>(\n        _ expected: E,\n        _ actual: E,\n        _ message: String? = nil\n    ) {\n        if actual != expected {\n            defer { print(\"expected: \\(expected)\\n  actual: \\(actual)\") }\n            fail(message)\n        }\n    }\n    func expectNotEqual<E: Equatable>(\n        _ expected: E,\n        _ actual: E,\n        _ message: String? = nil\n    ) {\n        if actual == expected {\n            defer { print(\"expected not equal: \\(expected) and \\(actual)\") }\n            fail(message)\n        }\n    }\n    func expectMatch(\n        _ expected: Trace.Entry?,\n        _ actual: Trace.Entry?,\n        _ message: String? = nil\n    ) {\n        func check() -> Bool {\n            switch (expected, actual) {\n            case let (expected?, actual?):\n                return expected.matches(actual)\n            case (nil, nil):\n                return true\n            default:\n                return false\n            }\n        }\n        if !check() {\n            let e = expected.map { \"\\($0)\" } ?? \"nil\"\n            let a = actual.map { \"\\($0)\" } ?? \"nil\"\n            defer { print(\"expected: \\(e)\\n  actual: \\(a)\") }\n            fail(message)\n        }\n    }\n    func expectNil<T>(\n        _ actual: T?,\n        _ message: String? = nil\n    ) {\n        if actual != nil {\n            defer { print(\"expected nil: \\(actual!)\") }\n            fail(message)\n        }\n    }\n    func expectNotNil<T>(\n        _ actual: T?,\n        _ message: String? = nil\n    ) {\n        if actual == nil {\n            defer { print(\"expected non-nil\") }\n            fail(message)\n        }\n    }\n    func expectTrue(\n        _ actual: Bool,\n        _ message: String? = nil\n    ) {\n        if !actual { fail(message) }\n    }\n    func expectFalse(\n        _ actual: Bool,\n        _ message: String? = nil\n    ) {\n        if actual { fail(message) }\n    }\n\n    func fail(_ reason: String? = nil) {\n        XCTAssert(false, failureMessage(reason), file: file, line: line)\n    }\n}\n\ninternal struct MockTestCase: TestCase {\n    var file: StaticString\n    var line: UInt\n\n    var expected: Trace.Entry\n    var interruptBehavior: InterruptBehavior\n\n    var interruptable: Bool { interruptBehavior == .interruptable }\n\n    internal enum InterruptBehavior {\n        // Retry the syscall on EINTR\n        case interruptable\n\n        // Cannot return EINTR\n        case noInterrupt\n\n        // Cannot error at all\n        case noError\n    }\n\n    var body: (_ retryOnInterrupt: Bool) throws -> Void\n\n    init(\n        _ file: StaticString = #file,\n        _ line: UInt = #line,\n        name: String,\n        _ interruptable: InterruptBehavior,\n        _ args: AnyHashable...,\n        body: @escaping (_ retryOnInterrupt: Bool) throws -> Void\n    ) {\n        self.file = file\n        self.line = line\n        self.expected = Trace.Entry(name: name, args)\n        self.interruptBehavior = interruptable\n        self.body = body\n    }\n\n    func runAllTests() {\n        XCTAssertFalse(MockingDriver.enabled)\n        MockingDriver.withMockingEnabled { mocking in\n            // Make sure we completely match the trace queue\n            self.expectTrue(mocking.trace.isEmpty)\n            defer { self.expectTrue(mocking.trace.isEmpty) }\n\n            // Test our API mappings to the lower-level syscall invocation\n            do {\n                try body(true)\n                self.expectMatch(self.expected, mocking.trace.dequeue())\n            } catch {\n                self.fail()\n            }\n\n            // Non-error-ing syscalls shouldn't ever throw\n            guard interruptBehavior != .noError else {\n                do {\n                    try body(interruptable)\n                    self.expectMatch(self.expected, mocking.trace.dequeue())\n                    try body(!interruptable)\n                    self.expectMatch(self.expected, mocking.trace.dequeue())\n                } catch {\n                    self.fail()\n                }\n                return\n            }\n\n            // Test interupt behavior. Interruptable calls will be told not to\n            // retry to catch the EINTR. Non-interruptable calls will be told to\n            // retry, to make sure they don't spin (e.g. if API changes to include\n            // interruptable)\n            do {\n                mocking.forceErrno = .always(errno: EINTR)\n                try body(!interruptable)\n                self.fail()\n            } catch Errno.interrupted {\n                // Success!\n                self.expectMatch(self.expected, mocking.trace.dequeue())\n            } catch {\n                self.fail()\n            }\n\n            // Force a limited number of EINTRs, and make sure interruptable functions\n            // retry that number of times. Non-interruptable functions should throw it.\n            do {\n                mocking.forceErrno = .counted(errno: EINTR, count: 3)\n\n                try body(interruptable)\n                self.expectMatch(self.expected, mocking.trace.dequeue())  // EINTR\n                self.expectMatch(self.expected, mocking.trace.dequeue())  // EINTR\n                self.expectMatch(self.expected, mocking.trace.dequeue())  // EINTR\n                self.expectMatch(self.expected, mocking.trace.dequeue())  // Success\n            } catch Errno.interrupted {\n                self.expectFalse(interruptable)\n                self.expectMatch(self.expected, mocking.trace.dequeue())  // EINTR\n            } catch {\n                self.fail()\n            }\n        }\n    }\n}\n\ninternal func withWindowsPaths(enabled: Bool, _ body: () -> Void) {\n    _withWindowsPaths(enabled: enabled, body)\n}\n#endif\n"
  },
  {
    "path": "Tests/NIOFSTests/Internal/SyscallTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\n@_spi(Testing) import NIOFS\nimport SystemPackage\nimport XCTest\n\n#if ENABLE_MOCKING\nfinal class SyscallTests: XCTestCase {\n    func test_openat() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let testCases = [\n            MockTestCase(\n                name: \"fdopenat\",\n                .interruptable,\n                fd.rawValue,\n                \"a path\",\n                O_RDONLY | O_NONBLOCK\n            ) { retryOnInterrupt in\n                _ = try fd.open(\n                    atPath: \"a path\",\n                    mode: .readOnly,\n                    options: [.nonBlocking],\n                    permissions: nil,\n                    retryOnInterrupt: retryOnInterrupt\n                ).get()\n            },\n\n            MockTestCase(\n                name: \"fdopenat\",\n                .interruptable,\n                fd.rawValue,\n                \"a path\",\n                O_WRONLY | O_CREAT,\n                0o777\n            ) { retryOnInterrupt in\n                _ = try fd.open(\n                    atPath: \"a path\",\n                    mode: .writeOnly,\n                    options: [.create],\n                    permissions: [\n                        .groupReadWriteExecute, .ownerReadWriteExecute, .otherReadWriteExecute,\n                    ],\n                    retryOnInterrupt: retryOnInterrupt\n                ).get()\n            },\n\n        ]\n\n        testCases.run()\n    }\n\n    func test_stat() throws {\n        let testCases = [\n            MockTestCase(name: \"stat\", .noInterrupt, \"a path\") { _ in\n                _ = try Syscall.stat(path: \"a path\").get()\n            },\n\n            MockTestCase(name: \"lstat\", .noInterrupt, \"a path\") { _ in\n                _ = try Syscall.lstat(path: \"a path\").get()\n            },\n\n            MockTestCase(name: \"fstat\", .noInterrupt, 42) { _ in\n                _ = try FileDescriptor(rawValue: 42).status().get()\n            },\n        ]\n\n        testCases.run()\n    }\n\n    func test_fchmod() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let permissions: FilePermissions = [\n            .groupReadWriteExecute,\n            .otherReadWriteExecute,\n            .ownerReadWriteExecute,\n        ]\n\n        let testCases = [\n            MockTestCase(name: \"fchmod\", .interruptable, 42, 0) { retryOnInterrupt in\n                try fd.changeMode([], retryOnInterrupt: retryOnInterrupt).get()\n            },\n\n            MockTestCase(name: \"fchmod\", .interruptable, 42, 0o777) { retryOnInterrupt in\n                try fd.changeMode(permissions, retryOnInterrupt: retryOnInterrupt).get()\n            },\n        ]\n\n        testCases.run()\n    }\n\n    func test_fsync() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let testCases = [\n            MockTestCase(name: \"fsync\", .interruptable, 42) { retryOnInterrupt in\n                try fd.synchronize(retryOnInterrupt: retryOnInterrupt).get()\n            }\n        ]\n\n        testCases.run()\n    }\n\n    func test_mkdir() throws {\n        let testCases = [\n            MockTestCase(name: \"mkdir\", .noInterrupt, \"a path\", 0) { _ in\n                try Syscall.mkdir(at: \"a path\", permissions: []).get()\n            },\n\n            MockTestCase(name: \"mkdir\", .noInterrupt, \"a path\", 0o777) { _ in\n                try Syscall.mkdir(\n                    at: \"a path\",\n                    permissions: [\n                        .groupReadWriteExecute, .otherReadWriteExecute, .ownerReadWriteExecute,\n                    ]\n                ).get()\n            },\n        ]\n\n        testCases.run()\n    }\n\n    func test_linkat() throws {\n        #if canImport(Glibc) || canImport(Bionic)\n        let fd1 = FileDescriptor(rawValue: 13)\n        let fd2 = FileDescriptor(rawValue: 42)\n\n        let testCases = [\n            MockTestCase(name: \"linkat\", .noInterrupt, 13, \"src\", 42, \"dst\", 0) { _ in\n                try Syscall.linkAt(\n                    from: \"src\",\n                    relativeTo: fd1,\n                    to: \"dst\",\n                    relativeTo: fd2,\n                    flags: []\n                ).get()\n            },\n            MockTestCase(name: \"linkat\", .noInterrupt, 13, \"src\", 42, \"dst\", 4096) { _ in\n                try Syscall.linkAt(\n                    from: \"src\",\n                    relativeTo: fd1,\n                    to: \"dst\",\n                    relativeTo: fd2,\n                    flags: [.emptyPath]\n                ).get()\n            },\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'linkat' is only supported on Linux\")\n        #endif\n    }\n\n    func test_link() throws {\n        let testCases = [\n            MockTestCase(name: \"link\", .noInterrupt, \"src\", \"dst\") { _ in\n                try Syscall.link(from: \"src\", to: \"dst\").get()\n            }\n        ]\n        testCases.run()\n    }\n\n    func test_unlink() throws {\n        let testCases = [\n            MockTestCase(name: \"unlink\", .noInterrupt, \"path\") { _ in\n                try Syscall.unlink(path: \"path\").get()\n            }\n        ]\n        testCases.run()\n    }\n\n    func test_unlinkat() throws {\n        let directoryFileDescriptor = FileDescriptor(rawValue: 42)\n\n        let testCases = [\n            MockTestCase(name: \"unlinkat\", .noInterrupt, 42, \"filename.txt\", 0) { _ in\n                try Syscall.unlinkat(\n                    path: \"filename.txt\",\n                    relativeTo: directoryFileDescriptor\n                ).get()\n            }\n        ]\n\n        testCases.run()\n    }\n\n    func test_symlink() throws {\n        let testCases = [\n            MockTestCase(name: \"symlink\", .noInterrupt, \"one\", \"two\") { _ in\n                try Syscall.symlink(to: \"one\", from: \"two\").get()\n            }\n        ]\n\n        testCases.run()\n    }\n\n    func test_symlinkat() throws {\n        let directoryFileDescriptor = FileDescriptor(rawValue: 42)\n\n        let testCases = [\n            MockTestCase(name: \"symlinkat\", .noInterrupt, \"target.txt\", 42, \"linkpath.txt\") { _ in\n                try Syscall.symlinkat(\n                    to: \"target.txt\",\n                    in: directoryFileDescriptor,\n                    from: \"linkpath.txt\"\n                ).get()\n            }\n        ]\n\n        testCases.run()\n    }\n\n    func test_readlink() throws {\n        let testCases = [\n            MockTestCase(\n                name: \"readlink\",\n                .noInterrupt,\n                \"a path\",\n                \"<buffer>\",\n                CInterop.maxPathLength\n            ) { _ in\n                _ = try Syscall.readlink(at: \"a path\").get()\n            }\n        ]\n\n        testCases.run()\n    }\n\n    func test_flistxattr() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let buffer = UnsafeMutableBufferPointer<CInterop.PlatformChar>.allocate(capacity: 1024)\n        defer { buffer.deallocate() }\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"flistxattr\", .noInterrupt, 42, \"nil\", 0) { _ in\n                _ = try fd.listExtendedAttributes(nil).get()\n            },\n\n            MockTestCase(name: \"flistxattr\", .noInterrupt, 42, \"<buffer>\", 1024) { _ in\n                _ = try fd.listExtendedAttributes(buffer).get()\n            },\n        ]\n\n        testCases.run()\n    }\n\n    func test_fgetxattr() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 1024, alignment: 1)\n        defer { buffer.deallocate() }\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"fgetxattr\", .noInterrupt, 42, \"an attribute\", \"nil\", 0) { _ in\n                _ = try fd.getExtendedAttribute(named: \"an attribute\", buffer: nil).get()\n            },\n\n            MockTestCase(name: \"fgetxattr\", .noInterrupt, 42, \"an attribute\", \"<buffer>\", 1024) {\n                _ in\n                _ = try fd.getExtendedAttribute(named: \"an attribute\", buffer: buffer).get()\n            },\n        ]\n\n        testCases.run()\n    }\n\n    func test_fsetxattr() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 1024, alignment: 1)\n        defer { buffer.deallocate() }\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"fsetxattr\", .noInterrupt, 42, \"attr name\", \"nil\", 0) { _ in\n                _ = try fd.setExtendedAttribute(named: \"attr name\", to: nil).get()\n            },\n\n            MockTestCase(name: \"fsetxattr\", .noInterrupt, 42, \"attr name\", \"<buffer>\", 1024) { _ in\n                _ = try fd.setExtendedAttribute(named: \"attr name\", to: .init(buffer)).get()\n            },\n        ]\n\n        testCases.run()\n    }\n\n    func test_fremovexattr() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"fremovexattr\", .noInterrupt, 42, \"attr name\") { _ in\n                _ = try fd.removeExtendedAttribute(\"attr name\").get()\n            }\n        ]\n        testCases.run()\n    }\n\n    func test_rename() throws {\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"rename\", .noInterrupt, \"old\", \"new\") { _ in\n                try Syscall.rename(from: \"old\", to: \"new\").get()\n            }\n        ]\n        testCases.run()\n    }\n\n    func test_renamex_np() throws {\n        #if canImport(Darwin)\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"renamex_np\", .noInterrupt, \"foo\", \"bar\", 0) { _ in\n                _ = try Syscall.rename(from: \"foo\", to: \"bar\", options: []).get()\n            },\n            MockTestCase(name: \"renamex_np\", .noInterrupt, \"bar\", \"baz\", 2) { _ in\n                _ = try Syscall.rename(from: \"bar\", to: \"baz\", options: [.swap]).get()\n            },\n            MockTestCase(name: \"renamex_np\", .noInterrupt, \"bar\", \"baz\", 4) { _ in\n                _ = try Syscall.rename(from: \"bar\", to: \"baz\", options: [.exclusive]).get()\n            },\n            MockTestCase(name: \"renamex_np\", .noInterrupt, \"bar\", \"baz\", 2) { _ in\n                _ = try Syscall.rename(from: \"bar\", to: \"baz\", options: [.swap]).get()\n            },\n            MockTestCase(name: \"renamex_np\", .noInterrupt, \"bar\", \"baz\", 6) { _ in\n                _ = try Syscall.rename(from: \"bar\", to: \"baz\", options: [.exclusive, .swap]).get()\n            },\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'renamex_np' is only supported on Darwin\")\n        #endif\n    }\n\n    func test_renameatx_np() throws {\n        #if canImport(Darwin)\n        let sourceDirectoryFileDescriptor = FileDescriptor(rawValue: 13)\n        let destinationDirectoryFileDescriptor = FileDescriptor(rawValue: 42)\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"renameatx_np\", .noInterrupt, 13, \"source.txt\", 42, \"destination.txt\", 0) { _ in\n                _ = try Syscall.rename(\n                    from: \"source.txt\",\n                    relativeTo: sourceDirectoryFileDescriptor,\n                    to: \"destination.txt\",\n                    relativeTo: destinationDirectoryFileDescriptor,\n                    options: []\n                ).get()\n            },\n            MockTestCase(name: \"renameatx_np\", .noInterrupt, 13, \"source.txt\", 42, \"destination.txt\", 4) { _ in\n                _ = try Syscall.rename(\n                    from: \"source.txt\",\n                    relativeTo: sourceDirectoryFileDescriptor,\n                    to: \"destination.txt\",\n                    relativeTo: destinationDirectoryFileDescriptor,\n                    options: [.exclusive]\n                ).get()\n            },\n            MockTestCase(name: \"renameatx_np\", .noInterrupt, 13, \"source.txt\", 42, \"destination.txt\", 2) { _ in\n                _ = try Syscall.rename(\n                    from: \"source.txt\",\n                    relativeTo: sourceDirectoryFileDescriptor,\n                    to: \"destination.txt\",\n                    relativeTo: destinationDirectoryFileDescriptor,\n                    options: [.swap]\n                ).get()\n            },\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'renameatx_np' is only supported on Darwin\")\n        #endif\n    }\n\n    func test_renameat2() throws {\n        #if canImport(Glibc) || canImport(Bionic)\n        let fd1 = FileDescriptor(rawValue: 13)\n        let fd2 = FileDescriptor(rawValue: 42)\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"renameat2\", .noInterrupt, 13, \"foo\", 42, \"bar\", 0) { _ in\n                _ = try Syscall.rename(\n                    from: \"foo\",\n                    relativeTo: fd1,\n                    to: \"bar\",\n                    relativeTo: fd2,\n                    flags: []\n                ).get()\n            },\n            MockTestCase(name: \"renameat2\", .noInterrupt, 13, \"foo\", 42, \"bar\", 1) { _ in\n                _ = try Syscall.rename(\n                    from: \"foo\",\n                    relativeTo: fd1,\n                    to: \"bar\",\n                    relativeTo: fd2,\n                    flags: [.exclusive]\n                ).get()\n            },\n            MockTestCase(name: \"renameat2\", .noInterrupt, 13, \"foo\", 42, \"bar\", 2) { _ in\n                _ = try Syscall.rename(\n                    from: \"foo\",\n                    relativeTo: fd1,\n                    to: \"bar\",\n                    relativeTo: fd2,\n                    flags: [.swap]\n                ).get()\n            },\n            MockTestCase(name: \"renameat2\", .noInterrupt, 13, \"foo\", 42, \"bar\", 3) { _ in\n                _ = try Syscall.rename(\n                    from: \"foo\",\n                    relativeTo: fd1,\n                    to: \"bar\",\n                    relativeTo: fd2,\n                    flags: [.swap, .exclusive]\n                ).get()\n            },\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'renameat2' is only supported on Linux\")\n        #endif\n    }\n\n    func test_sendfile() throws {\n        #if canImport(Glibc) || canImport(Bionic)\n        let input = FileDescriptor(rawValue: 42)\n        let output = FileDescriptor(rawValue: 1)\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"sendfile\", .noInterrupt, 1, 42, 0, 1024) { _ in\n                _ = try Syscall.sendfile(to: output, from: input, offset: 0, size: 1024).get()\n            },\n            MockTestCase(name: \"sendfile\", .noInterrupt, 1, 42, 100, 512) { _ in\n                _ = try Syscall.sendfile(to: output, from: input, offset: 100, size: 512).get()\n            },\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'sendfile' is only supported on Linux\")\n        #endif\n    }\n\n    func test_fcopyfile() throws {\n        #if canImport(Darwin)\n        let input = FileDescriptor(rawValue: 42)\n        let output = FileDescriptor(rawValue: 1)\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"fcopyfile\", .noInterrupt, 42, 1, \"nil\", 0) { _ in\n                try Libc.fcopyfile(from: input, to: output, state: nil, flags: 0).get()\n            }\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'fcopyfile' is only supported on Darwin\")\n        #endif\n    }\n\n    func test_copyfile() throws {\n        #if canImport(Darwin)\n\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"copyfile\", .noInterrupt, \"foo\", \"bar\", \"nil\", 0) { _ in\n                try Libc.copyfile(from: \"foo\", to: \"bar\", state: nil, flags: 0).get()\n            }\n        ]\n        testCases.run()\n        #else\n        throw XCTSkip(\"'copyfile' is only supported on Darwin\")\n        #endif\n    }\n\n    func test_remove() throws {\n        let testCases: [MockTestCase] = [\n            MockTestCase(name: \"remove\", .noInterrupt, \"somepath\") { _ in\n                try Libc.remove(\"somepath\").get()\n            }\n        ]\n        testCases.run()\n    }\n\n    func test_futimens() throws {\n        let fd = FileDescriptor(rawValue: 42)\n        let times = timespec(tv_sec: 1, tv_nsec: 1)\n        withUnsafePointer(to: times) { unsafeTimesPointer in\n            let testCases = [\n                MockTestCase(name: \"futimens\", .noInterrupt, 42, unsafeTimesPointer) { _ in\n                    try Syscall.futimens(\n                        fileDescriptor: fd,\n                        times: unsafeTimesPointer\n                    ).get()\n                }\n            ]\n            testCases.run()\n        }\n    }\n\n    func testValueOrErrno() throws {\n        let r1: Result<Int, Errno> = valueOrErrno(retryOnInterrupt: false) {\n            Errno._current = .addressInUse\n            return -1\n        }\n        XCTAssertEqual(r1, .failure(.addressInUse))\n\n        var shouldInterrupt = true\n        let r2: Result<Int, Errno> = valueOrErrno(retryOnInterrupt: true) {\n            if shouldInterrupt {\n                shouldInterrupt = false\n                Errno._current = .interrupted\n                return -1\n            } else {\n                Errno._current = .permissionDenied\n                return -1\n            }\n        }\n        XCTAssertFalse(shouldInterrupt)\n        XCTAssertEqual(r2, .failure(.permissionDenied))\n\n        let r3: Result<Int, Errno> = valueOrErrno(retryOnInterrupt: false) { 0 }\n        XCTAssertEqual(r3, .success(0))\n    }\n\n    func testNothingOrErrno() throws {\n        let r1: Result<Void, Errno> = nothingOrErrno(retryOnInterrupt: false) {\n            Errno._current = .addressInUse\n            return -1\n        }\n\n        XCTAssertThrowsError(try r1.get()) { error in\n            XCTAssertEqual(error as? Errno, .addressInUse)\n        }\n\n        var shouldInterrupt = true\n        let r2: Result<Void, Errno> = nothingOrErrno(retryOnInterrupt: true) {\n            if shouldInterrupt {\n                shouldInterrupt = false\n                Errno._current = .interrupted\n                return -1\n            } else {\n                Errno._current = .permissionDenied\n                return -1\n            }\n        }\n        XCTAssertFalse(shouldInterrupt)\n        XCTAssertThrowsError(try r2.get()) { error in\n            XCTAssertEqual(error as? Errno, .permissionDenied)\n        }\n\n        let r3: Result<Void, Errno> = nothingOrErrno(retryOnInterrupt: false) { 0 }\n        XCTAssertNoThrow(try r3.get())\n    }\n\n    func testOptionalValueOrErrno() throws {\n        let r1: Result<String?, Errno> = optionalValueOrErrno(retryOnInterrupt: false) {\n            Errno._current = .addressInUse\n            return nil\n        }\n        XCTAssertEqual(r1, .failure(.addressInUse))\n\n        var shouldInterrupt = true\n        let r2: Result<String?, Errno> = optionalValueOrErrno(retryOnInterrupt: true) {\n            if shouldInterrupt {\n                shouldInterrupt = false\n                Errno._current = .interrupted\n                return nil\n            } else {\n                return \"foo\"\n            }\n        }\n        XCTAssertFalse(shouldInterrupt)\n        XCTAssertEqual(r2, .success(\"foo\"))\n\n        let r3: Result<String?, Errno> = optionalValueOrErrno(retryOnInterrupt: false) { \"bar\" }\n        XCTAssertEqual(r3, .success(\"bar\"))\n\n        let r4: Result<String?, Errno> = optionalValueOrErrno(retryOnInterrupt: false) { nil }\n        XCTAssertEqual(r4, .success(nil))\n    }\n}\n\nextension Array where Element == MockTestCase {\n    fileprivate func run() {\n        for testCase in self {\n            testCase.runAllTests()\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Tests/NIOFSTests/XCTestExtensions.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOFS\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nfunc XCTAssertThrowsErrorAsync<R>(\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    expression: () async throws -> R,\n    onError: (Error) -> Void = { _ in }\n) async {\n    do {\n        _ = try await expression()\n        XCTFail(\"expression did not throw\", file: file, line: line)\n    } catch {\n        onError(error)\n    }\n}\n\nfunc XCTAssertThrowsFileSystemError<R>(\n    _ expression: @autoclosure () throws -> R,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ onError: (FileSystemError) -> Void = { _ in }\n) {\n    XCTAssertThrowsError(try expression(), file: file, line: line) { error in\n        if let fsError = error as? FileSystemError {\n            onError(fsError)\n        } else {\n            XCTFail(\n                \"Expected 'FileSystemError' but found '\\(type(of: error))'\",\n                file: file,\n                line: line\n            )\n        }\n    }\n}\n\nfunc XCTAssertSystemCallError(\n    _ error: (any Error)?,\n    name: String,\n    errno: Errno,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    guard let systemCallError = error as? FileSystemError.SystemCallError else {\n        return XCTFail(\n            \"Expected FileSystemError.SystemCallError but found '\\(type(of: error))'\",\n            file: file,\n            line: line\n        )\n    }\n\n    XCTAssertEqual(systemCallError.systemCall, name, file: file, line: line)\n    XCTAssertEqual(systemCallError.errno, errno, file: file, line: line)\n}\n"
  },
  {
    "path": "Tests/NIOFoundationCompatTests/ByteBuffer+UUIDTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOFoundationCompat\nimport XCTest\n\nfinal class ByteBufferUUIDTests: XCTestCase {\n    func testSetUUIDBytes() {\n        let uuid = UUID(\n            uuid: (\n                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,\n                0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf\n            )\n        )\n        var buffer = ByteBuffer()\n\n        XCTAssertEqual(buffer.storageCapacity, 0)\n        XCTAssertEqual(buffer.setUUIDBytes(uuid, at: 0), 16)\n        XCTAssertEqual(buffer.writerIndex, 0)\n        XCTAssertEqual(buffer.readableBytes, 0)\n        XCTAssertGreaterThanOrEqual(buffer.storageCapacity, 16)\n\n        buffer.moveWriterIndex(forwardBy: 16)\n        let bytes = buffer.getBytes(at: buffer.readerIndex, length: 16)\n        XCTAssertEqual(bytes, Array(0..<16))\n    }\n\n    func testSetUUIDBytesBlatsExistingBytes() {\n        var buffer = ByteBuffer()\n        buffer.writeRepeatingByte(.max, count: 32)\n\n        let uuid = UUID(\n            uuid: (\n                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,\n                0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf\n            )\n        )\n        buffer.setUUIDBytes(uuid, at: buffer.readerIndex + 4)\n\n        XCTAssertEqual(buffer.readBytes(length: 4), Array(repeating: .max, count: 4))\n        XCTAssertEqual(buffer.readBytes(length: 16), Array(0..<16))\n        XCTAssertEqual(buffer.readBytes(length: 12), Array(repeating: .max, count: 12))\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testGetUUIDEmptyBuffer() {\n        let buffer = ByteBuffer()\n        XCTAssertNil(buffer.getUUIDBytes(at: 0))\n    }\n\n    func testGetUUIDAfterSet() {\n        let uuid = UUID()\n        var buffer = ByteBuffer()\n        XCTAssertEqual(buffer.setUUIDBytes(uuid, at: 0), 16)\n        // nil because there are no bytes to read\n        XCTAssertNil(buffer.getUUIDBytes(at: 0))\n    }\n\n    func testWriteUUIDBytesIntoEmptyBuffer() {\n        let uuid = UUID(\n            uuid: (\n                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,\n                0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf\n            )\n        )\n        var buffer = ByteBuffer()\n\n        XCTAssertEqual(buffer.writeUUIDBytes(uuid), 16)\n        XCTAssertEqual(\n            buffer.readableBytesView,\n            [\n                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,\n                0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,\n            ]\n        )\n        XCTAssertEqual(buffer.readableBytes, 16)\n        XCTAssertEqual(buffer.writerIndex, 16)\n    }\n\n    func testWriteUUIDBytesIntoNonEmptyBuffer() {\n        let uuid = UUID(\n            uuid: (\n                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,\n                0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf\n            )\n        )\n\n        var buffer = ByteBuffer()\n        buffer.writeRepeatingByte(42, count: 10)\n        XCTAssertEqual(buffer.writeUUIDBytes(uuid), 16)\n        XCTAssertEqual(buffer.readableBytes, 26)\n        XCTAssertEqual(buffer.writerIndex, 26)\n\n        XCTAssertEqual(\n            buffer.readableBytesView.dropFirst(10),\n            [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf]\n        )\n    }\n\n    func testReadUUID() {\n        let uuid = UUID(\n            uuid: (\n                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,\n                0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf\n            )\n        )\n        var buffer = ByteBuffer()\n        XCTAssertEqual(buffer.writeUUIDBytes(uuid), 16)\n        XCTAssertEqual(buffer.readUUIDBytes(), uuid)\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n\n    func testReadUUIDNotEnoughBytes() {\n        var buffer = ByteBuffer()\n        XCTAssertNil(buffer.readUUIDBytes())\n        XCTAssertEqual(buffer.readerIndex, 0)\n\n        buffer.writeRepeatingByte(0, count: 8)\n        XCTAssertNil(buffer.readUUIDBytes())\n        XCTAssertEqual(buffer.readerIndex, 0)\n\n        buffer.writeRepeatingByte(0, count: 8)\n        XCTAssertEqual(\n            buffer.readUUIDBytes(),\n            UUID(uuid: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))\n        )\n        XCTAssertEqual(buffer.readerIndex, 16)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFoundationCompatTests/ByteBufferDataProtocolTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOFoundationCompat\nimport XCTest\n\nstruct FakeContiguousBytes: ContiguousBytes {\n    func withUnsafeBytes<T>(_ block: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {\n        let ptr = UnsafeMutableRawBufferPointer.allocate(byteCount: 8, alignment: 1)\n        ptr.initializeMemory(as: UInt8.self, repeating: 0xff)\n        defer {\n            ptr.deallocate()\n        }\n\n        return try block(UnsafeRawBufferPointer(ptr))\n    }\n}\n\nclass ByteBufferDataProtocolTests: XCTestCase {\n    func testWritingData() {\n        let d = Data([1, 2, 3, 4])\n        var b = ByteBufferAllocator().buffer(capacity: 1024)\n        b.writeData(d)\n        XCTAssertEqual(b.readBytes(length: b.readableBytes), [1, 2, 3, 4])\n    }\n\n    func testWritingDispatchDataThoughDataProtocol() {\n        var dd = DispatchData.empty\n        var buffer = ByteBufferAllocator().buffer(capacity: 12)\n        buffer.writeBytes([1, 2, 3, 4])\n        dd.append(DispatchData(buffer: buffer))\n        dd.append(DispatchData(buffer: buffer))\n\n        buffer.clear()\n        buffer.writeData(dd)\n        XCTAssertEqual(buffer.readBytes(length: buffer.readableBytes), [1, 2, 3, 4, 1, 2, 3, 4])\n    }\n\n    func testSettingData() {\n        let d = Data([1, 2, 3, 4])\n        var b = ByteBufferAllocator().buffer(capacity: 1024)\n        b.writeInteger(UInt64.max)\n        b.setData(d, at: 2)\n        XCTAssertEqual(b.readBytes(length: b.readableBytes), [0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0xFF, 0xFF])\n    }\n\n    func testSettingDispatchDataThoughDataProtocol() {\n        var dd = DispatchData.empty\n        var buffer = ByteBufferAllocator().buffer(capacity: 12)\n        buffer.writeBytes([1, 2, 3, 4])\n        dd.append(DispatchData(buffer: buffer))\n        dd.append(DispatchData(buffer: buffer))\n\n        buffer.clear()\n        buffer.writeInteger(UInt64.max)\n        buffer.writeInteger(UInt64.max)\n        buffer.setData(dd, at: 4)\n        XCTAssertEqual(\n            buffer.readBytes(length: buffer.readableBytes),\n            [0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0xFF, 0xFF, 0xFF, 0xFF]\n        )\n    }\n\n    func testWriteContiguousBytes() {\n        let fake = FakeContiguousBytes()\n        var b = ByteBufferAllocator().buffer(capacity: 1024)\n        b.writeContiguousBytes(fake)\n\n        XCTAssertEqual(b.readBytes(length: b.readableBytes), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])\n    }\n\n    func testSetContiguousBytes() {\n        let fake = FakeContiguousBytes()\n        var b = ByteBufferAllocator().buffer(capacity: 1024)\n        b.writeInteger(UInt64.min)\n        b.writeInteger(UInt64.min)\n        b.setContiguousBytes(fake, at: 4)\n\n        XCTAssertEqual(\n            b.readBytes(length: b.readableBytes),\n            [0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFoundationCompatTests/ByteBufferView+MutableDataProtocolTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOFoundationCompat\nimport XCTest\n\nclass ByteBufferViewDataProtocolTests: XCTestCase {\n\n    func testResetBytes() {\n        var view = ByteBufferView()\n        view.resetBytes(in: view.indices)\n        XCTAssertTrue(view.elementsEqual([]))\n\n        view.replaceSubrange(view.indices, with: [1, 2, 3, 4, 5])\n\n        view.resetBytes(in: 0..<2)\n        XCTAssertTrue(view.elementsEqual([0, 0, 3, 4, 5]))\n\n        view.resetBytes(in: 2...4)\n        XCTAssertTrue(view.elementsEqual([0, 0, 0, 0, 0]))\n    }\n\n    func testCreateDataFromBuffer() {\n        let testString = \"some sample bytes\"\n        let buffer = ByteBuffer(ByteBufferView(testString.utf8))\n        let data = Data(buffer: buffer)\n        XCTAssertEqual(Array(data), Array(testString.utf8))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFoundationCompatTests/Codable+ByteBufferTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOFoundationCompat\nimport XCTest\n\nclass CodableByteBufferTest: XCTestCase {\n    var buffer: ByteBuffer!\n    var allocator: ByteBufferAllocator!\n    var decoder: JSONDecoder!\n    var encoder: JSONEncoder!\n\n    override func setUp() {\n        self.allocator = ByteBufferAllocator()\n        self.buffer = self.allocator.buffer(capacity: 1024)\n        self.buffer.writeString(String(repeating: \"A\", count: 1024))\n        self.buffer.moveReaderIndex(to: 129)\n        self.buffer.moveWriterIndex(to: 129)\n        self.decoder = JSONDecoder()\n        self.encoder = JSONEncoder()\n    }\n\n    override func tearDown() {\n        self.encoder = nil\n        self.decoder = nil\n        self.buffer = nil\n        self.allocator = nil\n    }\n\n    func testSimpleDecode() {\n        self.buffer.writeString(#\"{\"string\": \"hello\", \"int\": 42}\"#)\n        var sAndI: StringAndInt?\n        XCTAssertNoThrow(sAndI = try self.decoder.decode(StringAndInt.self, from: self.buffer))\n        XCTAssertEqual(StringAndInt(string: \"hello\", int: 42), sAndI)\n    }\n\n    func testSimpleEncodeIntoBuffer() {\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        XCTAssertNoThrow(try self.encoder.encode(expectedSandI, into: &self.buffer))\n        XCTAssertNoThrow(XCTAssertEqual(expectedSandI, try self.decoder.decode(StringAndInt.self, from: self.buffer)))\n    }\n\n    func testSimpleEncodeToFreshByteBuffer() {\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        var buffer = self.allocator.buffer(capacity: 0)\n        XCTAssertNoThrow(buffer = try self.encoder.encodeAsByteBuffer(expectedSandI, allocator: self.allocator))\n        XCTAssertNoThrow(XCTAssertEqual(expectedSandI, try self.decoder.decode(StringAndInt.self, from: buffer)))\n    }\n\n    func testGetJSONDecodableFromBufferWorks() {\n        self.buffer.writeString(\"GARBAGE {}!!? / GARBAGE\")\n        let beginIndex = self.buffer.writerIndex\n        self.buffer.writeString(#\"{\"string\": \"hello\", \"int\": 42}\"#)\n        let endIndex = self.buffer.writerIndex\n        self.buffer.writeString(\"GARBAGE {}!!? / GARBAGE\")\n\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                expectedSandI,\n                try self.buffer.getJSONDecodable(\n                    StringAndInt.self,\n                    at: beginIndex,\n                    length: endIndex - beginIndex\n                )\n            )\n        )\n    }\n\n    func testGetJSONDecodableFromBufferFailsBecauseShort() {\n        self.buffer.writeString(\"GARBAGE {}!!? / GARBAGE\")\n        let beginIndex = self.buffer.writerIndex\n        self.buffer.writeString(#\"{\"string\": \"hello\", \"int\": 42}\"#)\n        let endIndex = self.buffer.writerIndex\n\n        XCTAssertThrowsError(\n            try self.buffer.getJSONDecodable(\n                StringAndInt.self,\n                at: beginIndex,\n                length: endIndex - beginIndex - 1\n            )\n        ) { error in\n            XCTAssert(error is DecodingError)\n        }\n    }\n\n    func testReadJSONDecodableFromBufferWorks() {\n        let beginIndex = self.buffer.writerIndex\n        self.buffer.writeString(#\"{\"string\": \"hello\", \"int\": 42}\"#)\n        let endIndex = self.buffer.writerIndex\n        self.buffer.writeString(\"GARBAGE {}!!? / GARBAGE\")\n\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                expectedSandI,\n                try self.buffer.readJSONDecodable(\n                    StringAndInt.self,\n                    length: endIndex - beginIndex\n                )\n            )\n        )\n    }\n\n    func testReadJSONDecodableFromBufferFailsBecauseShort() {\n        let beginIndex = self.buffer.writerIndex\n        self.buffer.writeString(#\"{\"string\": \"hello\", \"int\": 42}\"#)\n        let endIndex = self.buffer.writerIndex\n\n        XCTAssertThrowsError(\n            try self.buffer.readJSONDecodable(\n                StringAndInt.self,\n                length: endIndex - beginIndex - 1\n            )\n        ) { error in\n            XCTAssert(error is DecodingError)\n        }\n    }\n\n    func testReadWriteJSONDecodableWorks() {\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        self.buffer.writeString(\"hello\")\n        self.buffer.moveReaderIndex(forwardBy: 5)\n        var writtenBytes: Int?\n        XCTAssertNoThrow(writtenBytes = try self.buffer.writeJSONEncodable(expectedSandI))\n        for _ in 0..<10 {\n            XCTAssertNoThrow(try self.buffer.writeJSONEncodable(expectedSandI, encoder: JSONEncoder()))\n        }\n        for _ in 0..<11 {\n            XCTAssertNoThrow(try self.buffer.readJSONDecodable(StringAndInt.self, length: writtenBytes ?? -1))\n        }\n        XCTAssertEqual(0, self.buffer.readableBytes)\n    }\n\n    func testGetSetJSONDecodableWorks() {\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        self.buffer.writeString(String(repeating: \"{\", count: 1000))\n        var writtenBytes: Int?\n        XCTAssertNoThrow(\n            writtenBytes = try self.buffer.setJSONEncodable(\n                expectedSandI,\n                at: self.buffer.readerIndex + 123\n            )\n        )\n        XCTAssertNoThrow(\n            try self.buffer.setJSONEncodable(\n                expectedSandI,\n                encoder: JSONEncoder(),\n                at: self.buffer.readerIndex + 501\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                expectedSandI,\n                try self.buffer.getJSONDecodable(\n                    StringAndInt.self,\n                    at: self.buffer.readerIndex + 123,\n                    length: writtenBytes ?? -1\n                )\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                expectedSandI,\n                try self.buffer.getJSONDecodable(\n                    StringAndInt.self,\n                    at: self.buffer.readerIndex + 501,\n                    length: writtenBytes ?? -1\n                )\n            )\n        )\n    }\n\n    func testFailingReadsDoNotChangeReaderIndex() {\n        let expectedSandI = StringAndInt(string: \"hello\", int: 42)\n        var writtenBytes: Int?\n        XCTAssertNoThrow(writtenBytes = try self.buffer.writeJSONEncodable(expectedSandI))\n        for length in 0..<(writtenBytes ?? 0) {\n            XCTAssertThrowsError(\n                try self.buffer.readJSONDecodable(\n                    StringAndInt.self,\n                    length: length\n                )\n            ) { error in\n                XCTAssert(error is DecodingError)\n            }\n        }\n        XCTAssertNoThrow(try self.buffer.readJSONDecodable(StringAndInt.self, length: writtenBytes ?? -1))\n    }\n\n    func testCustomEncoderIsRespected() {\n        let expectedDate = Date(timeIntervalSinceReferenceDate: 86400)\n        let strategyExpectation = XCTestExpectation(description: \"Custom encoding strategy invoked\")\n        let encoder = JSONEncoder()\n        encoder.dateEncodingStrategy = .custom({ date, encoder in\n            var container = encoder.singleValueContainer()\n            try container.encode(date.timeIntervalSinceReferenceDate)\n            strategyExpectation.fulfill()\n        })\n        XCTAssertNoThrow(try encoder.encode([\"date\": expectedDate], into: &self.buffer))\n        XCTAssertEqual(XCTWaiter().wait(for: [strategyExpectation], timeout: 0.0), .completed)\n    }\n\n    func testCustomDecoderIsRespected() {\n        let expectedDate = Date(timeIntervalSinceReferenceDate: 86400)\n        let strategyExpectation = XCTestExpectation(description: \"Custom decoding strategy invoked\")\n        let encoder = JSONEncoder()\n        let decoder = JSONDecoder()\n        encoder.dateEncodingStrategy = .custom({ date, encoder in\n            var container = encoder.singleValueContainer()\n            try container.encode(date.timeIntervalSinceReferenceDate)\n        })\n        decoder.dateDecodingStrategy = .custom({ decoder in\n            strategyExpectation.fulfill()\n            let container = try decoder.singleValueContainer()\n            return Date(timeIntervalSinceReferenceDate: try container.decode(Double.self))\n        })\n        XCTAssertNoThrow(try encoder.encode([\"date\": expectedDate], into: &self.buffer))\n        XCTAssertNoThrow(\n            XCTAssertEqual([\"date\": expectedDate], try decoder.decode(Dictionary<String, Date>.self, from: self.buffer))\n        )\n        XCTAssertEqual(XCTWaiter().wait(for: [strategyExpectation], timeout: 0.0), .completed)\n    }\n\n    func testCustomCodersAreRespectedWhenUsingReadWriteJSONDecodable() {\n        let expectedDate = Date(timeIntervalSinceReferenceDate: 86400)\n        let decoderStrategyExpectation = XCTestExpectation(description: \"Custom decoding strategy invoked\")\n        let encoderStrategyExpectation = XCTestExpectation(description: \"Custom encoding strategy invoked\")\n\n        let encoder = JSONEncoder()\n        let decoder = JSONDecoder()\n        encoder.dateEncodingStrategy = .custom({ date, encoder in\n            encoderStrategyExpectation.fulfill()\n            var container = encoder.singleValueContainer()\n            try container.encode(date.timeIntervalSinceReferenceDate)\n        })\n        decoder.dateDecodingStrategy = .custom({ decoder in\n            decoderStrategyExpectation.fulfill()\n            let container = try decoder.singleValueContainer()\n            return Date(timeIntervalSinceReferenceDate: try container.decode(Double.self))\n        })\n        XCTAssertNoThrow(try self.buffer.writeJSONEncodable([\"date\": expectedDate], encoder: encoder))\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                [\"date\": expectedDate],\n                try self.buffer.readJSONDecodable(\n                    Dictionary<String, Date>.self,\n                    decoder: decoder,\n                    length: self.buffer.readableBytes\n                )\n            )\n        )\n        XCTAssertEqual(XCTWaiter().wait(for: [decoderStrategyExpectation], timeout: 0.0), .completed)\n        XCTAssertEqual(XCTWaiter().wait(for: [encoderStrategyExpectation], timeout: 0.0), .completed)\n    }\n}\n\nstruct StringAndInt: Codable, Equatable {\n    var string: String\n    var int: Int\n}\n"
  },
  {
    "path": "Tests/NIOFoundationCompatTests/JSONSerialization+ByteBufferTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOFoundationCompat\nimport XCTest\n\nclass JSONSerializationByteBufferTest: XCTestCase {\n\n    func testSerializationRoundTrip() {\n\n        let array = [\"String1\", \"String2\", \"String3\"]\n        let dictionary = [\"key1\": \"val1\", \"key2\": \"val2\", \"key3\": \"val3\"]\n\n        var dataArray = Data()\n        var dataDictionary = Data()\n\n        XCTAssertTrue(JSONSerialization.isValidJSONObject(array), \"Array object cannot be converted to JSON\")\n        XCTAssertTrue(JSONSerialization.isValidJSONObject(dictionary), \"Dictionary object cannot be converted to JSON\")\n\n        XCTAssertNoThrow(dataArray = try JSONSerialization.data(withJSONObject: array, options: .prettyPrinted))\n        XCTAssertNoThrow(\n            dataDictionary = try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)\n        )\n\n        let arrayByteBuffer = ByteBuffer(data: dataArray)\n        let dictByteBuffer = ByteBuffer(data: dataDictionary)\n\n        var foundationArray: [String] = []\n        var foundationDict: [String: String] = [:]\n\n        // Mutable containers comparison.\n        XCTAssertNoThrow(\n            foundationArray =\n                try JSONSerialization.jsonObject(with: arrayByteBuffer, options: .mutableContainers) as! [String]\n        )\n        XCTAssertEqual(foundationArray, array)\n\n        XCTAssertNoThrow(\n            foundationDict =\n                try JSONSerialization.jsonObject(with: dictByteBuffer, options: .mutableContainers) as! [String: String]\n        )\n        XCTAssertEqual(foundationDict, dictionary)\n\n        // Mutable leaves comparison.\n        XCTAssertNoThrow(\n            foundationArray =\n                try JSONSerialization.jsonObject(with: arrayByteBuffer, options: .mutableLeaves) as! [String]\n        )\n        XCTAssertEqual(foundationArray, array)\n\n        XCTAssertNoThrow(\n            foundationDict =\n                try JSONSerialization.jsonObject(with: dictByteBuffer, options: .mutableLeaves) as! [String: String]\n        )\n        XCTAssertEqual(foundationDict, dictionary)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOFoundationCompatTests/WaitSpinningRunLoopTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIO\nimport NIOFoundationCompat\nimport XCTest\n\nfinal class WaitSpinningRunLoopTests: XCTestCase {\n    private let loop = MultiThreadedEventLoopGroup.singleton.any()\n\n    func testPreFailedWorks() {\n        struct Dummy: Error {}\n        let future: EventLoopFuture<Never> = self.loop.makeFailedFuture(Dummy())\n        XCTAssertThrowsError(try future.waitSpinningRunLoop()) { error in\n            XCTAssert(error is Dummy)\n        }\n    }\n\n    func testPreSucceededWorks() {\n        let future = self.loop.makeSucceededFuture(\"hello\")\n        XCTAssertEqual(\"hello\", try future.waitSpinningRunLoop())\n    }\n\n    func testFailingAfterALittleWhileWorks() {\n        struct Dummy: Error {}\n        let future: EventLoopFuture<Never> = self.loop.scheduleTask(in: .milliseconds(10)) {\n            throw Dummy()\n        }.futureResult\n        XCTAssertThrowsError(try future.waitSpinningRunLoop()) { error in\n            XCTAssert(error is Dummy)\n        }\n    }\n\n    func testSucceedingAfterALittleWhileWorks() {\n        let future = self.loop.scheduleTask(in: .milliseconds(10)) {\n            \"hello\"\n        }.futureResult\n        XCTAssertEqual(\"hello\", try future.waitSpinningRunLoop())\n    }\n\n    func testWeCanStillUseOurRunLoopWhilstBlocking() {\n        let promise = self.loop.makePromise(of: String.self)\n        let myRunLoop = RunLoop.current\n        let timer = Timer(timeInterval: 0.1, repeats: false) { [loop = self.loop] _ in\n            loop.scheduleTask(in: .microseconds(10)) {\n                promise.succeed(\"hello\")\n            }\n        }\n        myRunLoop.add(timer, forMode: .default)\n        XCTAssertEqual(\"hello\", try promise.futureResult.waitSpinningRunLoop())\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/ByteBufferUtilsTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@testable import NIOHTTP1\n\nprivate enum DummyError: Error {\n    case err\n}\n\nclass ByteBufferUtilsTest: XCTestCase {\n\n    func testComparators() {\n        let someByteBuffer: ByteBuffer = ByteBuffer(string: \"fiRSt\")\n        XCTAssert(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"first\".utf8\n            )\n        )\n        XCTAssert(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"fiRSt\".utf8\n            )\n        )\n        XCTAssert(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"fIrst\".utf8\n            )\n        )\n        XCTAssertFalse(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"fIrt\".utf8\n            )\n        )\n        XCTAssertFalse(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"firsta\".utf8\n            )\n        )\n        XCTAssertFalse(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"afirst\".utf8\n            )\n        )\n        XCTAssertFalse(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"eiRSt\".utf8\n            )\n        )\n        XCTAssertFalse(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"fIrso\".utf8\n            )\n        )\n        XCTAssertFalse(\n            someByteBuffer.readableBytesView.compareCaseInsensitiveASCIIBytes(\n                to: \"firot\".utf8\n            )\n        )\n    }\n\n    private func byteBufferView(string: String) -> ByteBufferView {\n        let byteBufferAllocator = ByteBufferAllocator()\n        var buffer = byteBufferAllocator.buffer(capacity: string.lengthOfBytes(using: .utf8))\n        buffer.writeString(string)\n        return buffer.readableBytesView\n    }\n\n    func testTrimming() {\n        XCTAssertEqual(\n            byteBufferView(string: \"   first\").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"first\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"   first  \").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"first\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"first  \").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"first\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"first\").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"first\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \" \\t\\t  fi  rst\").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"fi  rst\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"   firs  t \\t \").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"firs  t\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"f\\t  irst  \").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"f\\t  irst\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"f i  rs  t\").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"f i  rs  t\").map({ CChar($0) })\n        )\n        XCTAssertEqual(\n            byteBufferView(string: \"   \\t \\t \").trimSpaces().map({ CChar($0) }),\n            byteBufferView(string: \"\").map({ CChar($0) })\n        )\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/ContentLengthTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOHTTP1\nimport XCTest\n\nfinal class ContentLengthTests: XCTestCase {\n\n    /// Client receives a response longer than the content-length header\n    func testResponseContentTooLong() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n        defer {\n            _ = try? channel.finish()\n        }\n        // Receive a response with a content-length header of 2 but a body of more than 2 bytes\n        let badResponse = \"HTTP/1.1 200 OK\\r\\nServer: foo\\r\\nContent-Length: 2\\r\\n\\r\\ntoo many bytes\"\n\n        XCTAssertThrowsError(try channel.sendRequestAndReceiveResponse(response: badResponse)) { error in\n            XCTAssertEqual(error as? HTTPParserError, .invalidConstant)\n        }\n\n        channel.embeddedEventLoop.run()\n    }\n\n    /// Client receives a response shorter than the content-length header\n    func testResponseContentTooShort() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n        defer {\n            _ = try? channel.finish()\n        }\n        // Receive a response with a content-length header of 100 but a body of less than 100 bytes\n        let badResponse = \"HTTP/1.1 200 OK\\r\\nServer: foo\\r\\nContent-Length: 100\\r\\n\\r\\nnot many bytes\"\n\n        // First is successful, it just waits for more bytes\n        XCTAssertNoThrow(try channel.sendRequestAndReceiveResponse(response: badResponse))\n        // It is waiting for 100-14 = 86 more bytes\n        // We will send the same response again (75 bytes)\n        // The client will consider this as part of the body of the previous response. No error expected\n        XCTAssertNoThrow(try channel.sendRequestAndReceiveResponse(response: badResponse))\n        // Now the client is expected only 86-75 = 11 bytes. We wil send the same 75 byte request again\n        // An error is expected because everything from the 12th byte forward will be parsed as a new message, which isn't well formed\n        XCTAssertThrowsError(try channel.sendRequestAndReceiveResponse(response: badResponse)) { error in\n            XCTAssertEqual(error as? HTTPParserError, .invalidConstant)\n        }\n\n        channel.embeddedEventLoop.run()\n    }\n\n    /// Server receives a request longer than the content-length header\n    func testRequestContentTooLong() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline()\n        defer {\n            _ = try? channel.finish()\n        }\n        // Receive a request with a content-length header of 2 but a body of more than 2 bytes\n        let badRequest = \"POST / HTTP/1.1\\r\\nContent-Length: 2\\r\\n\\r\\nhello\"\n        // First one is fine, the extra bytes will be treated as the next request\n        XCTAssertNoThrow(try channel.receiveRequestAndSendResponse(request: badRequest, sendResponse: true))\n        // Which means the next request is now malformed\n        XCTAssertThrowsError(try channel.receiveRequestAndSendResponse(request: badRequest, sendResponse: true)) {\n            error in\n            XCTAssertEqual(error as? HTTPParserError, .invalidMethod)\n        }\n\n        channel.embeddedEventLoop.run()\n    }\n\n    /// Server receives a request shorter than the content-length header\n    func testRequestContentTooShort() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline()\n        defer {\n            _ = try? channel.finish()\n        }\n        // Receive a request with a content-length header of 100 but a body of less\n        let badRequest = \"POST / HTTP/1.1\\r\\nContent-Length: 100\\r\\n\\r\\nnot many bytes\"\n        // First one is fine, server will wait for 100-14 (86) further bytes to come\n        XCTAssertNoThrow(try channel.receiveRequestAndSendResponse(request: badRequest, sendResponse: false))\n        // The full request (60 bytes) will be treated as the body of the original request\n        XCTAssertNoThrow(try channel.receiveRequestAndSendResponse(request: badRequest, sendResponse: false))\n        // The original request is still 26 bytes short. Sending the request once more will complete it\n        XCTAssertNoThrow(try channel.receiveRequestAndSendResponse(request: badRequest, sendResponse: true))\n        // The leftover bytes from the previous write (we wrote 100 bytes where it wanted 26) will form a new malformed request\n        XCTAssertThrowsError(try channel.receiveRequestAndSendResponse(request: badRequest, sendResponse: true)) {\n            error in\n            XCTAssertEqual(error as? HTTPParserError, .invalidMethod)\n        }\n\n        channel.embeddedEventLoop.run()\n    }\n}\n\nextension EmbeddedChannel {\n    /// Do a request-response cycle\n    /// Asserts that sending the request won't fail\n    /// Throws if receiving the response fails\n    fileprivate func sendRequestAndReceiveResponse(response: String) throws {\n        // Send a request\n        XCTAssertNoThrow(\n            try self.writeOutbound(HTTPClientRequestPart.head(.init(version: .http1_1, method: .GET, uri: \"/\")))\n        )\n        XCTAssertNoThrow(try self.writeOutbound(HTTPClientRequestPart.end(nil)))\n        // Receive a response\n        try self.writeInbound(ByteBuffer(string: response))\n    }\n\n    /// Do a response-request cycle\n    /// Throws if receiving the request fails\n    /// Asserts that sending the response won't fail\n    fileprivate func receiveRequestAndSendResponse(request: String, sendResponse: Bool) throws {\n        // Receive a request\n        try self.writeInbound(ByteBuffer(string: request))\n        // Send a response\n        if sendResponse {\n            XCTAssertNoThrow(try self.writeOutbound(HTTPServerResponsePart.head(.init(version: .http1_1, status: .ok))))\n            XCTAssertNoThrow(try self.writeOutbound(HTTPServerResponsePart.end(nil)))\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPClientUpgradeTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOHTTP1\n\nextension EmbeddedChannel {\n\n    fileprivate func readByteBufferOutputAsString() throws -> String? {\n\n        if let requestData: IOData = try self.readOutbound(),\n            case .byteBuffer(var requestBuffer) = requestData\n        {\n\n            return requestBuffer.readString(length: requestBuffer.readableBytes)\n        }\n\n        return nil\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nprotocol TypedAndUntypedHTTPClientProtocolUpgrader: NIOHTTPClientProtocolUpgrader, NIOTypedHTTPClientProtocolUpgrader\nwhere UpgradeResult == Bool {}\n\nprivate final class SuccessfulClientUpgrader: TypedAndUntypedHTTPClientProtocolUpgrader {\n    fileprivate let supportedProtocol: String\n    fileprivate let requiredUpgradeHeaders: [String]\n    fileprivate let upgradeHeaders: [(String, String)]\n\n    private struct Counts {\n        var addCustomUpgradeRequestHeadersCallCount = 0\n        var shouldAllowUpgradeCallCount = 0\n        var upgradeContextResponseCallCount = 0\n    }\n\n    private let counts = NIOLockedValueBox(Counts())\n\n    var addCustomUpgradeRequestHeadersCallCount: Int {\n        self.counts.withLockedValue { $0.addCustomUpgradeRequestHeadersCallCount }\n    }\n\n    var shouldAllowUpgradeCallCount: Int {\n        self.counts.withLockedValue { $0.shouldAllowUpgradeCallCount }\n    }\n\n    var upgradeContextResponseCallCount: Int {\n        self.counts.withLockedValue { $0.upgradeContextResponseCallCount }\n    }\n\n    fileprivate init(\n        forProtocol `protocol`: String,\n        requiredUpgradeHeaders: [String] = [],\n        upgradeHeaders: [(String, String)] = []\n    ) {\n        self.supportedProtocol = `protocol`\n        self.requiredUpgradeHeaders = requiredUpgradeHeaders\n        self.upgradeHeaders = upgradeHeaders\n    }\n\n    fileprivate func addCustom(upgradeRequestHeaders: inout HTTPHeaders) {\n        self.counts.withLockedValue {\n            $0.addCustomUpgradeRequestHeadersCallCount += 1\n        }\n        for (name, value) in self.upgradeHeaders {\n            upgradeRequestHeaders.replaceOrAdd(name: name, value: value)\n        }\n    }\n\n    fileprivate func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n        self.counts.withLockedValue {\n            $0.shouldAllowUpgradeCallCount += 1\n        }\n        return true\n    }\n\n    fileprivate func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void>\n    {\n        self.counts.withLockedValue {\n            $0.upgradeContextResponseCallCount += 1\n        }\n        return context.channel.eventLoop.makeSucceededFuture(())\n    }\n\n    func upgrade(channel: any Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Bool> {\n        self.counts.withLockedValue {\n            $0.upgradeContextResponseCallCount += 1\n        }\n        return channel.eventLoop.makeSucceededFuture(true)\n    }\n}\n\nprivate final class ExplodingClientUpgrader: TypedAndUntypedHTTPClientProtocolUpgrader {\n\n    fileprivate let supportedProtocol: String\n    fileprivate let requiredUpgradeHeaders: [String]\n    fileprivate let upgradeHeaders: [(String, String)]\n\n    fileprivate init(\n        forProtocol `protocol`: String,\n        requiredUpgradeHeaders: [String] = [],\n        upgradeHeaders: [(String, String)] = []\n    ) {\n        self.supportedProtocol = `protocol`\n        self.requiredUpgradeHeaders = requiredUpgradeHeaders\n        self.upgradeHeaders = upgradeHeaders\n    }\n\n    fileprivate func addCustom(upgradeRequestHeaders: inout HTTPHeaders) {\n        for (name, value) in self.upgradeHeaders {\n            upgradeRequestHeaders.replaceOrAdd(name: name, value: value)\n        }\n    }\n\n    fileprivate func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n        XCTFail(\"This method should not be called.\")\n        return false\n    }\n\n    fileprivate func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void>\n    {\n        XCTFail(\"Upgrade should not be called.\")\n        return context.channel.eventLoop.makeSucceededFuture(())\n    }\n\n    func upgrade(channel: any Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Bool> {\n        XCTFail(\"Upgrade should not be called.\")\n        return channel.eventLoop.makeSucceededFuture(false)\n    }\n}\n\nprivate final class DenyingClientUpgrader: TypedAndUntypedHTTPClientProtocolUpgrader {\n\n    fileprivate let supportedProtocol: String\n    fileprivate let requiredUpgradeHeaders: [String]\n    fileprivate let upgradeHeaders: [(String, String)]\n\n    private let _addCustomUpgradeRequestHeadersCallCount = NIOLockedValueBox(0)\n\n    var addCustomUpgradeRequestHeadersCallCount: Int {\n        self._addCustomUpgradeRequestHeadersCallCount.withLockedValue { $0 }\n    }\n\n    fileprivate init(\n        forProtocol `protocol`: String,\n        requiredUpgradeHeaders: [String] = [],\n        upgradeHeaders: [(String, String)] = []\n    ) {\n\n        self.supportedProtocol = `protocol`\n        self.requiredUpgradeHeaders = requiredUpgradeHeaders\n        self.upgradeHeaders = upgradeHeaders\n    }\n\n    fileprivate func addCustom(upgradeRequestHeaders: inout HTTPHeaders) {\n        self._addCustomUpgradeRequestHeadersCallCount.withLockedValue { $0 += 1 }\n        for (name, value) in self.upgradeHeaders {\n            upgradeRequestHeaders.replaceOrAdd(name: name, value: value)\n        }\n    }\n\n    fileprivate func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n        false\n    }\n\n    fileprivate func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void>\n    {\n        XCTFail(\"Upgrade should not be called.\")\n        return context.channel.eventLoop.makeSucceededFuture(())\n    }\n\n    func upgrade(channel: any Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Bool> {\n        XCTFail(\"Upgrade should not be called.\")\n        return channel.eventLoop.makeSucceededFuture(false)\n    }\n}\n\nprivate final class UpgradeDelayClientUpgrader: TypedAndUntypedHTTPClientProtocolUpgrader {\n\n    fileprivate let supportedProtocol: String\n    fileprivate let requiredUpgradeHeaders: [String]\n    fileprivate let upgradeHeaders: [(String, String)]\n\n    fileprivate let upgradedHandler = SimpleUpgradedHandler()\n\n    private let upgradePromise: NIOLockedValueBox<EventLoopPromise<Void>?>\n\n    fileprivate init(\n        forProtocol `protocol`: String,\n        requiredUpgradeHeaders: [String] = [],\n        upgradeHeaders: [(String, String)] = []\n    ) {\n        self.supportedProtocol = `protocol`\n        self.requiredUpgradeHeaders = requiredUpgradeHeaders\n        self.upgradeHeaders = upgradeHeaders\n        self.upgradePromise = NIOLockedValueBox(nil)\n    }\n\n    fileprivate func addCustom(upgradeRequestHeaders: inout HTTPHeaders) {\n        for (name, value) in self.upgradeHeaders {\n            upgradeRequestHeaders.replaceOrAdd(name: name, value: value)\n        }\n    }\n\n    fileprivate func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n        true\n    }\n\n    fileprivate func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void>\n    {\n        let promise = context.eventLoop.makePromise(of: Void.self)\n        self.upgradePromise.withLockedValue {\n            assert($0 == nil)\n            $0 = promise\n        }\n        return promise.futureResult.flatMap { [pipeline = context.pipeline] in\n            pipeline.addHandler(self.upgradedHandler)\n        }\n    }\n\n    func upgrade(channel: any Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Bool> {\n        let promise = channel.eventLoop.makePromise(of: Void.self)\n        self.upgradePromise.withLockedValue {\n            assert($0 == nil)\n            $0 = promise\n        }\n        return promise.futureResult.flatMap {\n            channel.pipeline.addHandler(self.upgradedHandler)\n        }.map { _ in true }\n    }\n\n    fileprivate func unblockUpgrade() {\n        let promise = self.upgradePromise.withLockedValue { $0 }\n        promise!.succeed()\n    }\n}\n\nprivate final class SimpleUpgradedHandler: ChannelInboundHandler, Sendable {\n    fileprivate typealias InboundIn = ByteBuffer\n    fileprivate typealias OutboundOut = ByteBuffer\n\n    private struct Counts {\n        var handlerAddedContextCallCount = 0\n        var channelReadContextDataCallCount = 0\n    }\n\n    private let counts = NIOLockedValueBox(Counts())\n\n    fileprivate var handlerAddedContextCallCount: Int {\n        self.counts.withLockedValue { $0.handlerAddedContextCallCount }\n    }\n    fileprivate var channelReadContextDataCallCount: Int {\n        self.counts.withLockedValue { $0.channelReadContextDataCallCount }\n    }\n\n    fileprivate func handlerAdded(context: ChannelHandlerContext) {\n        self.counts.withLockedValue {\n            $0.handlerAddedContextCallCount += 1\n        }\n    }\n\n    fileprivate func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.counts.withLockedValue {\n            $0.channelReadContextDataCallCount += 1\n        }\n    }\n}\n\nextension ChannelInboundHandler where OutboundOut == HTTPClientRequestPart {\n\n    fileprivate func fireSendRequest(context: ChannelHandlerContext) {\n\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        headers.add(name: \"Content-Length\", value: \"\\(0)\")\n\n        let requestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/\",\n            headers: headers\n        )\n\n        context.write(Self.wrapOutboundOut(.head(requestHead)), promise: nil)\n\n        let emptyBuffer = context.channel.allocator.buffer(capacity: 0)\n        let body = HTTPClientRequestPart.body(.byteBuffer(emptyBuffer))\n        context.write(self.wrapOutboundOut(body), promise: nil)\n\n        context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n    }\n}\n\n// A HTTP handler that will send a request and then fail if it receives a response or an error.\n// It can be used when there is a successful upgrade as the handler should be removed by the upgrader.\nprivate final class ExplodingHTTPHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n    fileprivate typealias InboundIn = HTTPClientResponsePart\n    fileprivate typealias OutboundOut = HTTPClientRequestPart\n\n    fileprivate func channelActive(context: ChannelHandlerContext) {\n        // We are connected. It's time to send the message to the server to initialise the upgrade dance.\n        self.fireSendRequest(context: context)\n    }\n\n    fileprivate func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        XCTFail(\"Received unexpected read\")\n    }\n\n    fileprivate func errorCaught(context: ChannelHandlerContext, error: Error) {\n        XCTFail(\"Received unexpected erro\")\n    }\n}\n\n// A HTTP handler that will send an initial request which can be augmented by the upgrade handler.\n// It will record which error or response calls it receives so that they can be measured at a later time.\nprivate final class RecordingHTTPHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n    fileprivate typealias InboundIn = HTTPClientResponsePart\n    fileprivate typealias OutboundOut = HTTPClientRequestPart\n\n    private struct State {\n        fileprivate var channelReadChannelHandlerContextDataCallCount = 0\n        fileprivate var errorCaughtChannelHandlerContextCallCount = 0\n        fileprivate var errorCaughtChannelHandlerLatestError: Error?\n    }\n\n    private let state = NIOLockedValueBox(State())\n\n    fileprivate var channelReadChannelHandlerContextDataCallCount: Int {\n        self.state.withLockedValue { $0.channelReadChannelHandlerContextDataCallCount }\n    }\n    fileprivate var errorCaughtChannelHandlerContextCallCount: Int {\n        self.state.withLockedValue { $0.errorCaughtChannelHandlerContextCallCount }\n    }\n    fileprivate var errorCaughtChannelHandlerLatestError: Error? {\n        self.state.withLockedValue { $0.errorCaughtChannelHandlerLatestError }\n    }\n\n    fileprivate func channelActive(context: ChannelHandlerContext) {\n        // We are connected. It's time to send the message to the server to initialise the upgrade dance.\n        self.fireSendRequest(context: context)\n    }\n\n    fileprivate func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.state.withLockedValue {\n            $0.channelReadChannelHandlerContextDataCallCount += 1\n        }\n    }\n\n    fileprivate func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.state.withLockedValue {\n            $0.errorCaughtChannelHandlerContextCallCount += 1\n            $0.errorCaughtChannelHandlerLatestError = error\n        }\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nprivate func assertPipelineContainsUpgradeHandler(channel: Channel) {\n    let handler = try? channel.pipeline.syncOperations.handler(type: NIOHTTPClientUpgradeHandler.self)\n\n    let typedHandler = try? channel.pipeline.syncOperations.handler(type: NIOTypedHTTPClientUpgradeHandler<Bool>.self)\n    XCTAssertTrue(handler != nil || typedHandler != nil)\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nclass HTTPClientUpgradeTestCase: XCTestCase {\n    func setUpClientChannel(\n        previousHTTPHandler: (RemovableChannelHandler & Sendable)? = nil,\n        clientHTTPHandler: RemovableChannelHandler & Sendable,\n        clientUpgraders: [any TypedAndUntypedHTTPClientProtocolUpgrader],\n        _ upgradeCompletionHandler: @escaping @Sendable (ChannelHandlerContext) -> Void\n    ) throws -> EmbeddedChannel {\n\n        let channel = EmbeddedChannel()\n\n        let config: NIOHTTPClientUpgradeSendableConfiguration = (\n            upgraders: clientUpgraders,\n            completionHandler: { context in\n                channel.pipeline.removeHandler(clientHTTPHandler, promise: nil)\n                upgradeCompletionHandler(context)\n            }\n        )\n\n        try channel.pipeline.addHTTPClientHandlers(leftOverBytesStrategy: .forwardBytes, withClientUpgrade: config)\n            .flatMap({\n                channel.pipeline.addHandler(clientHTTPHandler)\n            }).wait()\n\n        try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n            .wait()\n\n        return channel\n    }\n\n    // MARK: Test basic happy path requests and responses.\n\n    func testSimpleUpgradeSucceeds() throws {\n\n        let upgradeProtocol = \"myProto\"\n        let addedUpgradeHeader = \"myUpgradeHeader\"\n        let addedUpgradeValue = \"upgradeHeader\"\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        // This header is not required by the server but we will validate its receipt.\n        let clientHeaders = [(addedUpgradeHeader, addedUpgradeValue)]\n\n        let clientUpgrader = SuccessfulClientUpgrader(\n            forProtocol: upgradeProtocol,\n            upgradeHeaders: clientHeaders\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                \"GET / HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol.lowercased())\\r\\n\\(addedUpgradeHeader): \\(addedUpgradeValue)\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Validate the pipeline still has http handlers.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        assertPipelineContainsUpgradeHandler(channel: clientChannel)\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Once upgraded, validate the pipeline has been removed.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n\n        // Check the client upgrader was used correctly.\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n        XCTAssertEqual(1, clientUpgrader.shouldAllowUpgradeCallCount)\n        XCTAssertEqual(1, clientUpgrader.upgradeContextResponseCallCount)\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n    }\n\n    func testUpgradeWithRequiredHeadersShowsInRequest() throws {\n\n        let upgradeProtocol = \"myProto\"\n        let addedUpgradeHeader = \"myUpgradeHeader\"\n        let addedUpgradeValue = \"upgradeValue\"\n\n        let clientHeaders = [(addedUpgradeHeader, addedUpgradeValue)]\n\n        let clientUpgrader = SuccessfulClientUpgrader(\n            forProtocol: upgradeProtocol,\n            requiredUpgradeHeaders: [addedUpgradeHeader],\n            upgradeHeaders: clientHeaders\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Read the server request and check that it has the required header also added to the connection header.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                \"GET / HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\\r\\nConnection: upgrade,\\(addedUpgradeHeader)\\r\\nUpgrade: \\(upgradeProtocol.lowercased())\\r\\n\\(addedUpgradeHeader): \\(addedUpgradeValue)\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Check the client upgrader was used correctly, no response received.\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n        XCTAssertEqual(0, clientUpgrader.shouldAllowUpgradeCallCount)\n        XCTAssertEqual(0, clientUpgrader.upgradeContextResponseCallCount)\n    }\n\n    func testSimpleUpgradeSucceedsWhenMultipleAvailableProtocols() throws {\n\n        let unusedUpgradeProtocol = \"unusedMyProto\"\n        let unusedUpgradeHeader = \"unusedMyUpgradeHeader\"\n        let unusedUpgradeValue = \"unusedUpgradeHeaderValue\"\n\n        let upgradeProtocol = \"myProto\"\n        let addedUpgradeHeader = \"myUpgradeHeader\"\n        let addedUpgradeValue = \"upgradeHeaderValue\"\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        // These headers are not required by the server but we will validate their receipt.\n        let unusedClientHeaders = [(unusedUpgradeHeader, unusedUpgradeValue)]\n        let clientHeaders = [(addedUpgradeHeader, addedUpgradeValue)]\n\n        let unusedClientUpgrader = ExplodingClientUpgrader(\n            forProtocol: unusedUpgradeProtocol,\n            upgradeHeaders: unusedClientHeaders\n        )\n\n        let clientUpgrader = SuccessfulClientUpgrader(\n            forProtocol: upgradeProtocol,\n            upgradeHeaders: clientHeaders\n        )\n\n        let clientUpgraders: [any TypedAndUntypedHTTPClientProtocolUpgrader] = [unusedClientUpgrader, clientUpgrader]\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: clientUpgraders\n        ) { (context) in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n\n            // Check that the details for both protocols are sent to the server, in preference order.\n            let expectedUpgrade = \"\\(unusedUpgradeProtocol),\\(upgradeProtocol)\".lowercased()\n\n            XCTAssertEqual(\n                requestString,\n                \"GET / HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\\r\\nConnection: upgrade\\r\\nUpgrade: \\(expectedUpgrade)\\r\\n\\(unusedUpgradeHeader): \\(unusedUpgradeValue)\\r\\n\\(addedUpgradeHeader): \\(addedUpgradeValue)\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should just upgrade to the accepted protocol, the other protocol uses an exploding upgrader.\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n        XCTAssertEqual(1, clientUpgrader.shouldAllowUpgradeCallCount)\n        XCTAssertEqual(1, clientUpgrader.upgradeContextResponseCallCount)\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testUpgradeCompleteFlush() throws {\n        final class ChannelReadWriteHandler: ChannelDuplexHandler, Sendable {\n            typealias OutboundIn = Any\n            typealias InboundIn = Any\n            typealias OutboundOut = Any\n\n            private let _messagesReceived = NIOLockedValueBox(0)\n\n            var messagesReceived: Int {\n                self._messagesReceived.withLockedValue { $0 }\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                self._messagesReceived.withLockedValue { $0 += 1 }\n                context.writeAndFlush(data, promise: nil)\n            }\n        }\n\n        final class AddHandlerClientUpgrader<T: ChannelInboundHandler & Sendable>:\n            TypedAndUntypedHTTPClientProtocolUpgrader, Sendable\n        {\n            fileprivate let requiredUpgradeHeaders: [String] = []\n            fileprivate let supportedProtocol: String\n            fileprivate let handler: T\n\n            fileprivate init(forProtocol `protocol`: String, addingHandler handler: T) {\n                self.supportedProtocol = `protocol`\n                self.handler = handler\n            }\n\n            func addCustom(upgradeRequestHeaders: inout HTTPHeaders) {}\n\n            func shouldAllowUpgrade(upgradeResponse: HTTPResponseHead) -> Bool {\n                true\n            }\n\n            func upgrade(context: ChannelHandlerContext, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Void> {\n                context.pipeline.addHandler(handler)\n            }\n\n            func upgrade(channel: any Channel, upgradeResponse: HTTPResponseHead) -> EventLoopFuture<Bool> {\n                channel.pipeline.addHandler(handler).map { _ in true }\n            }\n        }\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n        let handler = ChannelReadWriteHandler()\n        let upgrader = AddHandlerClientUpgrader(forProtocol: \"myproto\", addingHandler: handler)\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [upgrader]\n        ) { (context) in\n\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                \"GET / HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\\r\\nConnection: upgrade\\r\\nUpgrade: myproto\\r\\n\\r\\n\"\n            )\n            XCTAssertNoThrow(XCTAssertEqual(try clientChannel.readByteBufferOutputAsString(), \"\"))  // Empty body\n            XCTAssertNoThrow(XCTAssertNil(try clientChannel.readByteBufferOutputAsString()))\n        } else {\n            XCTFail()\n        }\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: myproto\\r\\n\\r\\nTest\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertEqual(handler.messagesReceived, 1)\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n        XCTAssertNoThrow(XCTAssertEqual(try clientChannel.readByteBufferOutputAsString(), \"Test\"))\n    }\n\n    // MARK: Test requests and responses with other specific actions.\n\n    func testNoUpgradeAsNoServerUpgrade() throws {\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 200 OK\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertEqual(1, clientHandler.channelReadChannelHandlerContextDataCallCount)\n        // Is not an error, just silently remove as there is no upgrade.\n        XCTAssertEqual(0, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testFirstResponseReturnsServerError() throws {\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 404 Not Found\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is malformed) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertEqual(1, clientHandler.channelReadChannelHandlerContextDataCallCount)\n\n        // Check a separate error is not reported, the error response will be forwarded on.\n        XCTAssertEqual(0, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testUpgradeResponseMissingAllProtocols() throws {\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is malformed) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertLessThanOrEqual(1, clientHandler.channelReadChannelHandlerContextDataCallCount)\n        // Check an error is reported\n        XCTAssertEqual(1, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        let reportedError = clientHandler.errorCaughtChannelHandlerLatestError! as! NIOHTTPClientUpgradeError\n        XCTAssertEqual(NIOHTTPClientUpgradeError.responseProtocolNotFound, reportedError)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testUpgradeOnlyHandlesKnownProtocols() throws {\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: unknownProtocol\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is malformed) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertLessThanOrEqual(1, clientHandler.channelReadChannelHandlerContextDataCallCount)\n        // Check an error is reported\n        XCTAssertEqual(1, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        let reportedError = clientHandler.errorCaughtChannelHandlerLatestError! as! NIOHTTPClientUpgradeError\n        XCTAssertEqual(NIOHTTPClientUpgradeError.responseProtocolNotFound, reportedError)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testUpgradeResponseCanBeRejectedByClientUpgrader() throws {\n\n        let upgradeProtocol = \"myProto\"\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = DenyingClientUpgrader(forProtocol: upgradeProtocol)\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is denied) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertLessThanOrEqual(1, clientHandler.channelReadChannelHandlerContextDataCallCount)\n\n        // Check an error is reported\n        XCTAssertEqual(1, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        let reportedError = clientHandler.errorCaughtChannelHandlerLatestError! as! NIOHTTPClientUpgradeError\n        XCTAssertEqual(NIOHTTPClientUpgradeError.upgraderDeniedUpgrade, reportedError)\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testUpgradeIsCaseInsensitive() throws {\n\n        let upgradeProtocol = \"mYPrOtO123\"\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = SuccessfulClientUpgrader(forProtocol: upgradeProtocol)\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nCoNnEcTiOn: uPgRaDe\\r\\nuPgRaDe: \\(upgradeProtocol)\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is denied) and remove upgrader from pipeline.\n\n        // Check that the http elements are removed from the pipeline.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n\n        // Check the client upgrader was used.\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n        XCTAssertEqual(1, clientUpgrader.shouldAllowUpgradeCallCount)\n        XCTAssertEqual(1, clientUpgrader.upgradeContextResponseCallCount)\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    // MARK: Test when client pipeline experiences delay.\n\n    func testBuffersInboundDataDuringAddingHandlers() throws {\n\n        let upgradeProtocol = \"myProto\"\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = UpgradeDelayClientUpgrader(forProtocol: upgradeProtocol)\n\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [clientUpgrader]\n        ) { (context) in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        // Run the processing of the response, but with the upgrade delayed by the client upgrader.\n        clientChannel.embeddedEventLoop.run()\n\n        // Soundness check that the upgrade was delayed.\n        XCTAssertEqual(0, clientUpgrader.upgradedHandler.handlerAddedContextCallCount)\n\n        // Add some non-http data.\n        let appData = \"supersecretawesome data definitely not http\\r\\nawesome\\r\\ndata\\ryeah\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: appData)))\n\n        // Upgrade now.\n        clientUpgrader.unblockUpgrade()\n        clientChannel.embeddedEventLoop.run()\n\n        // Check that the http elements are removed from the pipeline.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        // Check that the data gets fired to the new handler once it is added.\n        XCTAssertEqual(1, clientUpgrader.upgradedHandler.handlerAddedContextCallCount)\n        XCTAssertEqual(1, clientUpgrader.upgradedHandler.channelReadContextDataCallCount)\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    func testFiresOutboundErrorDuringAddingHandlers() throws {\n\n        let upgradeProtocol = \"myProto\"\n        var errorOnAdditionalChannelWrite: Error?\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = UpgradeDelayClientUpgrader(forProtocol: upgradeProtocol)\n        let clientHandler = RecordingHTTPHandler()\n\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { (context) in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n\n        // Okay: uses embedded EL.\n        promise.futureResult.assumeIsolated().whenFailure { error in\n            errorOnAdditionalChannelWrite = error\n        }\n\n        // Send another outbound request during the upgrade.\n        let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n        let secondRequest: HTTPClientRequestPart = .head(requestHead)\n        clientChannel.writeAndFlush(secondRequest, promise: promise)\n\n        clientChannel.embeddedEventLoop.run()\n\n        let reportedError = clientHandler.errorCaughtChannelHandlerLatestError! as! NIOHTTPClientUpgradeError\n        XCTAssertEqual(NIOHTTPClientUpgradeError.writingToHandlerDuringUpgrade, reportedError)\n\n        let promiseError = errorOnAdditionalChannelWrite as! NIOHTTPClientUpgradeError\n        XCTAssertEqual(NIOHTTPClientUpgradeError.writingToHandlerDuringUpgrade, promiseError)\n\n        // Soundness check that the upgrade was delayed.\n        XCTAssertEqual(0, clientUpgrader.upgradedHandler.handlerAddedContextCallCount)\n\n        // Upgrade now.\n        clientUpgrader.unblockUpgrade()\n        clientChannel.embeddedEventLoop.run()\n\n        // Check that the upgrade was still successful, despite the interruption.\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n        XCTAssertEqual(1, clientUpgrader.upgradedHandler.handlerAddedContextCallCount)\n    }\n\n    func testFiresInboundErrorBeforeSendsRequestUpgrade() throws {\n\n        let upgradeProtocol = \"myProto\"\n\n        let clientUpgrader = SuccessfulClientUpgrader(forProtocol: upgradeProtocol)\n        let clientHandler = RecordingHTTPHandler()\n\n        let clientChannel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let upgrader = NIOHTTPClientUpgradeHandler(\n            upgraders: [clientUpgrader],\n            httpHandlers: [clientHandler],\n            upgradeCompletionHandler: { context in\n            }\n        )\n\n        try clientChannel.pipeline.addHandler(upgrader).wait()\n\n        try clientChannel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0)).wait()\n\n        let headers = HTTPHeaders([\n            (\"Connection\", \"upgrade\"),\n            (\"Upgrade\", \"\\(upgradeProtocol)\"),\n        ])\n        let head = HTTPResponseHead(\n            version: .http1_1,\n            status: .switchingProtocols,\n            headers: headers\n        )\n        let response = HTTPClientResponsePart.head(head)\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(response)) { error in\n            let reportedError = error as! NIOHTTPClientUpgradeError\n            XCTAssertEqual(NIOHTTPClientUpgradeError.receivedResponseBeforeRequestSent, reportedError)\n        }\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal class TypedHTTPClientUpgradeTestCase: HTTPClientUpgradeTestCase {\n\n    func setUpClientChannel(\n        previousHTTPHandler: (RemovableChannelHandler & Sendable)? = nil,\n        clientHTTPHandler: RemovableChannelHandler & Sendable,\n        clientUpgraders: [any TypedAndUntypedHTTPClientProtocolUpgrader],\n        _ upgradeCompletionHandler: @escaping (ChannelHandlerContext, Result<Bool, Error>) -> Void\n    ) throws -> EmbeddedChannel {\n        let channel = EmbeddedChannel()\n        try setUpClientChannel(\n            channel: channel,\n            previousHTTPHandler: previousHTTPHandler,\n            clientHTTPHandler: clientHTTPHandler,\n            clientUpgraders: clientUpgraders,\n            upgradeCompletionHandler\n        )\n        try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n            .wait()\n        return channel\n    }\n\n    func setUpClientChannel(\n        channel: Channel,\n        previousHTTPHandler: (RemovableChannelHandler & Sendable)? = nil,\n        clientHTTPHandler: RemovableChannelHandler & Sendable,\n        clientUpgraders: [any TypedAndUntypedHTTPClientProtocolUpgrader],\n        _ upgradeCompletionHandler: @escaping (ChannelHandlerContext, Result<Bool, Error>) -> Void\n    ) throws {\n        if let previousHTTPHandler {\n            try channel.pipeline.syncOperations.addHandler(previousHTTPHandler)\n        }\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        headers.add(name: \"Content-Length\", value: \"\\(0)\")\n\n        let requestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/\",\n            headers: headers\n        )\n\n        let upgraders: [any NIOTypedHTTPClientProtocolUpgrader<Bool>] = Array(\n            clientUpgraders.map { $0 as! any NIOTypedHTTPClientProtocolUpgrader<Bool> }\n        )\n\n        let config = NIOTypedHTTPClientUpgradeConfiguration<Bool>(\n            upgradeRequestHead: requestHead,\n            upgraders: upgraders\n        ) { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHandler(clientHTTPHandler)\n            }.map { _ in\n                false\n            }\n        }\n        var configuration = NIOUpgradableHTTPClientPipelineConfiguration(upgradeConfiguration: config)\n        configuration.leftOverBytesStrategy = .forwardBytes\n        let upgradeResult = try channel.pipeline.syncOperations.configureUpgradableHTTPClientPipeline(\n            configuration: configuration\n        )\n        let context = try channel.pipeline.syncOperations.context(\n            handlerType: NIOTypedHTTPClientUpgradeHandler<Bool>.self\n        )\n\n        let loopBoundContext = context.loopBound\n        upgradeResult.assumeIsolated().whenComplete { result in\n            upgradeCompletionHandler(loopBoundContext.value, result)\n        }\n    }\n\n    override func setUpClientChannel(\n        previousHTTPHandler: (RemovableChannelHandler & Sendable)? = nil,\n        clientHTTPHandler: RemovableChannelHandler & Sendable,\n        clientUpgraders: [any TypedAndUntypedHTTPClientProtocolUpgrader],\n        _ upgradeCompletionHandler: @escaping (ChannelHandlerContext) -> Void\n    ) throws -> EmbeddedChannel {\n        try setUpClientChannel(\n            previousHTTPHandler: previousHTTPHandler,\n            clientHTTPHandler: clientHTTPHandler,\n            clientUpgraders: clientUpgraders\n        ) { context, result in\n            switch result {\n            case .success(true):\n                upgradeCompletionHandler(context)\n            default:\n                break\n            }\n        }\n    }\n\n    // - MARK: The following tests are all overridden from the base class since they slightly differ in behaviour\n\n    override func testUpgradeOnlyHandlesKnownProtocols() throws {\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: unknownProtocol\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, .responseProtocolNotFound)\n        }\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is malformed) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertLessThanOrEqual(0, clientHandler.channelReadChannelHandlerContextDataCallCount)\n        // Check an error is reported\n        XCTAssertEqual(0, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    override func testUpgradeResponseCanBeRejectedByClientUpgrader() throws {\n        let upgradeProtocol = \"myProto\"\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = DenyingClientUpgrader(forProtocol: upgradeProtocol)\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, .upgraderDeniedUpgrade)\n        }\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is denied) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n\n        // Check that the HTTP handler received its response.\n        XCTAssertLessThanOrEqual(0, clientHandler.channelReadChannelHandlerContextDataCallCount)\n\n        // Check an error is reported\n        XCTAssertEqual(0, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    override func testFiresOutboundErrorDuringAddingHandlers() throws {\n        let upgradeProtocol = \"myProto\"\n        var errorOnAdditionalChannelWrite: Error?\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = UpgradeDelayClientUpgrader(forProtocol: upgradeProtocol)\n        let clientHandler = RecordingHTTPHandler()\n\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { (context) in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n\n        promise.futureResult.assumeIsolated().whenFailure { error in\n            errorOnAdditionalChannelWrite = error\n        }\n\n        // Send another outbound request during the upgrade.\n        let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n        let secondRequest: HTTPClientRequestPart = .head(requestHead)\n        clientChannel.writeAndFlush(secondRequest, promise: promise)\n\n        clientChannel.embeddedEventLoop.run()\n\n        let promiseError = errorOnAdditionalChannelWrite as! NIOHTTPClientUpgradeError\n        XCTAssertEqual(NIOHTTPClientUpgradeError.writingToHandlerDuringUpgrade, promiseError)\n\n        // Soundness check that the upgrade was delayed.\n        XCTAssertEqual(0, clientUpgrader.upgradedHandler.handlerAddedContextCallCount)\n\n        // Upgrade now.\n        clientUpgrader.unblockUpgrade()\n        clientChannel.embeddedEventLoop.run()\n\n        // Check that the upgrade was still successful, despite the interruption.\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n        XCTAssertEqual(1, clientUpgrader.upgradedHandler.handlerAddedContextCallCount)\n    }\n\n    func testReturnsErrorsFromPriorChannelHandlers() throws {\n        struct FailedError: Error {}\n        final class FailingChannelHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.fireErrorCaught(FailedError())\n                context.close(promise: nil)\n            }\n        }\n        var upgradeResult: Result<Bool, Error>?\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        let clientChannel = try setUpClientChannel(\n            previousHTTPHandler: FailingChannelHandler(),\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _, result in\n            upgradeResult = result\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: myProto\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssert(error is FailedError)\n        }\n\n        clientChannel.flush()\n        clientChannel.embeddedEventLoop.run()\n\n        let result = try XCTUnwrap(upgradeResult)\n        switch result {\n        case .failure(is FailedError):\n            break\n        default:\n            XCTFail(\"Wrong result \\(result)\")\n        }\n    }\n\n    override func testUpgradeResponseMissingAllProtocols() throws {\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        let clientUpgrader = ExplodingClientUpgrader(forProtocol: \"myProto\")\n        let clientHandler = RecordingHTTPHandler()\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: clientHandler,\n            clientUpgraders: [clientUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, .responseProtocolNotFound)\n        }\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Should fail with error (response is malformed) and remove upgrader from pipeline.\n\n        // Check that the http elements are not removed from the pipeline.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n\n        // Now feed inbound EOF, which will trigger an error.\n        clientChannel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        XCTAssertThrowsError(\n            try clientChannel.throwIfErrorCaught()\n        ) { error in\n            XCTAssertEqual(.invalidEOFState, error as? HTTPParserError)\n        }\n\n        // Check that the HTTP handler received its response.\n        XCTAssertLessThanOrEqual(0, clientHandler.channelReadChannelHandlerContextDataCallCount)\n        // Check an error is reported\n        XCTAssertEqual(0, clientHandler.errorCaughtChannelHandlerContextCallCount)\n\n        XCTAssertFalse(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n    }\n\n    // MARK: Tests specific to typed handler\n\n    func testUpgradeHappensAfterHandlerAdded() throws {\n        let upgradeProtocol = \"myProto\"\n        let addedUpgradeHeader = \"myUpgradeHeader\"\n        let addedUpgradeValue = \"upgradeHeader\"\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        // This header is not required by the server but we will validate its receipt.\n        let clientHeaders = [(addedUpgradeHeader, addedUpgradeValue)]\n\n        let clientUpgrader = SuccessfulClientUpgrader(\n            forProtocol: upgradeProtocol,\n            upgradeHeaders: clientHeaders\n        )\n\n        let clientChannel = EmbeddedChannel()\n        try clientChannel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n            .wait()\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n        try setUpClientChannel(\n            channel: clientChannel,\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [clientUpgrader]\n        ) { _, result in\n            switch result {\n            case .success(true):\n                upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n            default:\n                break\n            }\n        }\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                \"GET / HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol.lowercased())\\r\\n\\(addedUpgradeHeader): \\(addedUpgradeValue)\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Validate the pipeline still has http handlers.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        assertPipelineContainsUpgradeHandler(channel: clientChannel)\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Once upgraded, validate the pipeline has been removed.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n\n        // Check the client upgrader was used correctly.\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n        XCTAssertEqual(1, clientUpgrader.shouldAllowUpgradeCallCount)\n        XCTAssertEqual(1, clientUpgrader.upgradeContextResponseCallCount)\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n    }\n\n    func testUpgradeHappensWhenAddedDuringChannelActive() throws {\n        final class OnActiveChannelHandler: ChannelInboundHandler {\n            fileprivate typealias InboundIn = ByteBuffer\n            fileprivate typealias OutboundOut = ByteBuffer\n\n            let onActive: (Channel) throws -> Void\n\n            init(_ onActive: @escaping (Channel) throws -> Void) {\n                self.onActive = onActive\n            }\n            func channelActive(context: ChannelHandlerContext) {\n                do {\n                    try onActive(context.channel)\n                } catch {\n                    context.fireErrorCaught(error)\n                }\n                context.fireChannelActive()\n            }\n        }\n        let upgradeProtocol = \"myProto\"\n        let addedUpgradeHeader = \"myUpgradeHeader\"\n        let addedUpgradeValue = \"upgradeHeader\"\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n\n        // This header is not required by the server but we will validate its receipt.\n        let clientHeaders = [(addedUpgradeHeader, addedUpgradeValue)]\n\n        let clientUpgrader = SuccessfulClientUpgrader(\n            forProtocol: upgradeProtocol,\n            upgradeHeaders: clientHeaders\n        )\n\n        let clientChannel = EmbeddedChannel()\n        let setupUpgraderOnActiveChannelHandler = OnActiveChannelHandler { [self] channel in\n            try setUpClientChannel(\n                channel: channel,\n                clientHTTPHandler: ExplodingHTTPHandler(),\n                clientUpgraders: [clientUpgrader]\n            ) { _, result in\n                switch result {\n                case .success(true):\n                    upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n                default:\n                    break\n                }\n            }\n        }\n        try clientChannel.pipeline.syncOperations.addHandler(setupUpgraderOnActiveChannelHandler)\n        try clientChannel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n            .wait()\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish())\n        }\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                \"GET / HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol.lowercased())\\r\\n\\(addedUpgradeHeader): \\(addedUpgradeValue)\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Validate the pipeline still has http handlers.\n        clientChannel.pipeline.assertContains(handlerType: HTTPRequestEncoder.self)\n        clientChannel.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        assertPipelineContainsUpgradeHandler(channel: clientChannel)\n\n        // Push the successful server response.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: \\(upgradeProtocol)\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Once upgraded, validate the pipeline has been removed.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n\n        // Check the client upgrader was used correctly.\n        XCTAssertEqual(1, clientUpgrader.addCustomUpgradeRequestHeadersCallCount)\n        XCTAssertEqual(1, clientUpgrader.shouldAllowUpgradeCallCount)\n        XCTAssertEqual(1, clientUpgrader.upgradeContextResponseCallCount)\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPDecoderLengthTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOHTTP1\nimport XCTest\n\nprivate class MessageEndHandler<Head: Equatable, Body: Equatable>: ChannelInboundHandler {\n    typealias InboundIn = HTTPPart<Head, Body>\n\n    var seenEnd = false\n    var seenBody = false\n    var seenHead = false\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch Self.unwrapInboundIn(data) {\n        case .head:\n            XCTAssertFalse(self.seenHead)\n            self.seenHead = true\n        case .body:\n            XCTAssertFalse(self.seenBody)\n            self.seenBody = true\n        case .end:\n            XCTAssertFalse(self.seenEnd)\n            self.seenEnd = true\n        }\n    }\n}\n\n/// Tests for the HTTP decoder's handling of message body framing.\n///\n/// Mostly tests assertions in [RFC 7230 § 3.3.3](https://tools.ietf.org/html/rfc7230#section-3.3.3).\nclass HTTPDecoderLengthTest: XCTestCase {\n    private var channel: EmbeddedChannel!\n    private var loop: EmbeddedEventLoop {\n        self.channel.embeddedEventLoop\n    }\n\n    override func setUp() {\n        self.channel = EmbeddedChannel()\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.channel?.finish(acceptAlreadyClosed: true))\n        self.channel = nil\n    }\n\n    /// The mechanism by which EOF is being sent.\n    enum EOFMechanism {\n        case channelInactive\n        case halfClosure\n    }\n\n    /// The various header fields that can be used to frame a response.\n    enum FramingField {\n        case contentLength\n        case transferEncoding\n        case neither\n    }\n\n    private func assertSemanticEOFOnChannelInactiveResponse(version: HTTPVersion, how eofMechanism: EOFMechanism) throws\n    {\n        class ChannelInactiveHandler: ChannelInboundHandler {\n            typealias InboundIn = HTTPClientResponsePart\n            var response: HTTPResponseHead?\n            var receivedEnd = false\n            var eof = false\n            var body: [UInt8]?\n            private let eofMechanism: EOFMechanism\n\n            init(_ eofMechanism: EOFMechanism) {\n                self.eofMechanism = eofMechanism\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                switch Self.unwrapInboundIn(data) {\n                case .head(let h):\n                    self.response = h\n                case .end:\n                    self.receivedEnd = true\n                case .body(var b):\n                    XCTAssertNil(self.body)\n                    self.body = b.readBytes(length: b.readableBytes)!\n                }\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                if case .channelInactive = self.eofMechanism {\n                    XCTAssert(self.receivedEnd, \"Received channelInactive before response end!\")\n                    self.eof = true\n                } else {\n                    XCTAssert(self.eof, \"Did not receive .inputClosed\")\n                }\n            }\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                guard case .halfClosure = self.eofMechanism else {\n                    XCTFail(\"Got half closure when not expecting it\")\n                    return\n                }\n\n                guard let evt = event as? ChannelEvent, case .inputClosed = evt else {\n                    context.fireUserInboundEventTriggered(event)\n                    return\n                }\n\n                XCTAssert(self.receivedEnd, \"Received inputClosed before response end!\")\n                self.eof = true\n            }\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        let handler = ChannelInactiveHandler(eofMechanism)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Prime the decoder with a GET and consume it.\n        XCTAssertTrue(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(HTTPRequestHead(version: version, method: .GET, uri: \"/\"))\n            ).isFull\n        )\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        // We now want to send a HTTP/1.1 response. This response has no content-length, no transfer-encoding,\n        // is not a response to a HEAD request, is not a 2XX response to CONNECT, and is not 1XX, 204, or 304.\n        // That means, per RFC 7230 § 3.3.3, the body is framed by EOF. Because this is a response, that EOF\n        // may be transmitted by channelInactive.\n        let response = \"HTTP/\\(version.major).\\(version.minor) 200 OK\\r\\nServer: example\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(IOData.byteBuffer(channel.allocator.buffer(string: response))))\n\n        // We should have a response but no body.\n        XCTAssertNotNil(handler.response)\n        XCTAssertNil(handler.body)\n        XCTAssertFalse(handler.receivedEnd)\n        XCTAssertFalse(handler.eof)\n\n        // Send a body chunk. This should be immediately passed on. Still no end or EOF.\n        XCTAssertNoThrow(\n            try channel.writeInbound(IOData.byteBuffer(channel.allocator.buffer(string: \"some body data\")))\n        )\n        XCTAssertNotNil(handler.response)\n        XCTAssertEqual(handler.body!, Array(\"some body data\".utf8))\n        XCTAssertFalse(handler.receivedEnd)\n        XCTAssertFalse(handler.eof)\n\n        // Now we send EOF. This should cause a response end. The handler will enforce ordering.\n        if case .halfClosure = eofMechanism {\n            channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        } else {\n            channel.pipeline.fireChannelInactive()\n        }\n        XCTAssertNotNil(handler.response)\n        XCTAssertEqual(handler.body!, Array(\"some body data\".utf8))\n        XCTAssertTrue(handler.receivedEnd)\n        XCTAssertTrue(handler.eof)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testHTTP11SemanticEOFOnChannelInactive() throws {\n        try assertSemanticEOFOnChannelInactiveResponse(version: .http1_1, how: .channelInactive)\n    }\n\n    func testHTTP10SemanticEOFOnChannelInactive() throws {\n        try assertSemanticEOFOnChannelInactiveResponse(version: .http1_0, how: .channelInactive)\n    }\n\n    func testHTTP11SemanticEOFOnHalfClosure() throws {\n        try assertSemanticEOFOnChannelInactiveResponse(version: .http1_1, how: .halfClosure)\n    }\n\n    func testHTTP10SemanticEOFOnHalfClosure() throws {\n        try assertSemanticEOFOnChannelInactiveResponse(version: .http1_0, how: .halfClosure)\n    }\n\n    private func assertIgnoresLengthFields(\n        requestMethod: HTTPMethod,\n        responseStatus: HTTPResponseStatus,\n        responseFramingField: FramingField\n    ) throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        let decoder = HTTPResponseDecoder(leftOverBytesStrategy: .dropBytes, informationalResponseStrategy: .forward)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(decoder)))\n\n        let handler = MessageEndHandler<HTTPResponseHead, ByteBuffer>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Prime the decoder with a request and consume it.\n        XCTAssertTrue(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    HTTPRequestHead(\n                        version: .http1_1,\n                        method: requestMethod,\n                        uri: \"/\"\n                    )\n                )\n            ).isFull\n        )\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        // We now want to send a HTTP/1.1 response. This response may contain some length framing fields that RFC 7230 says MUST\n        // be ignored.\n        var response = channel.allocator.buffer(capacity: 256)\n        response.writeString(\"HTTP/1.1 \\(responseStatus.code) \\(responseStatus.reasonPhrase)\\r\\nServer: example\\r\\n\")\n\n        switch responseFramingField {\n        case .contentLength:\n            response.writeStaticString(\"Content-Length: 16\\r\\n\")\n        case .transferEncoding:\n            response.writeStaticString(\"Transfer-Encoding: chunked\\r\\n\")\n        case .neither:\n            break\n        }\n        response.writeStaticString(\"\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeInbound(IOData.byteBuffer(response)))\n\n        // We should have a response, no body, and immediately see EOF.\n        XCTAssert(handler.seenHead)\n        switch responseStatus.code {\n        case 100, 102..<200:\n            // If an informational response header is tested, we expect another \"real\" header to\n            // follow. For this reason, we don't expect an `.end` here.\n            XCTAssertFalse(handler.seenBody)\n            XCTAssertFalse(handler.seenEnd)\n\n        default:\n            XCTAssertFalse(handler.seenBody)\n            XCTAssert(handler.seenEnd)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testIgnoresTransferEncodingFieldOnCONNECTResponses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .CONNECT,\n            responseStatus: .ok,\n            responseFramingField: .transferEncoding\n        )\n    }\n\n    func testIgnoresContentLengthFieldOnCONNECTResponses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .CONNECT,\n            responseStatus: .ok,\n            responseFramingField: .contentLength\n        )\n    }\n\n    func testEarlyFinishWithoutLengthAtAllOnCONNECTResponses() throws {\n        try assertIgnoresLengthFields(requestMethod: .CONNECT, responseStatus: .ok, responseFramingField: .neither)\n    }\n\n    func testIgnoresTransferEncodingFieldOnHEADResponses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .HEAD,\n            responseStatus: .ok,\n            responseFramingField: .transferEncoding\n        )\n    }\n\n    func testIgnoresContentLengthFieldOnHEADResponses() throws {\n        try assertIgnoresLengthFields(requestMethod: .HEAD, responseStatus: .ok, responseFramingField: .contentLength)\n    }\n\n    func testEarlyFinishWithoutLengthAtAllOnHEADResponses() throws {\n        try assertIgnoresLengthFields(requestMethod: .HEAD, responseStatus: .ok, responseFramingField: .neither)\n    }\n\n    func testIgnoresTransferEncodingFieldOn1XXResponses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"),\n            responseFramingField: .transferEncoding\n        )\n    }\n\n    func testIgnoresContentLengthFieldOn1XXResponses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"),\n            responseFramingField: .contentLength\n        )\n    }\n\n    func testEarlyFinishWithoutLengthAtAllOn1XXResponses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"),\n            responseFramingField: .neither\n        )\n    }\n\n    func testIgnoresTransferEncodingFieldOn204Responses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .noContent,\n            responseFramingField: .transferEncoding\n        )\n    }\n\n    func testIgnoresContentLengthFieldOn204Responses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .noContent,\n            responseFramingField: .contentLength\n        )\n    }\n\n    func testEarlyFinishWithoutLengthAtAllOn204Responses() throws {\n        try assertIgnoresLengthFields(requestMethod: .GET, responseStatus: .noContent, responseFramingField: .neither)\n    }\n\n    func testIgnoresTransferEncodingFieldOn304Responses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .notModified,\n            responseFramingField: .transferEncoding\n        )\n    }\n\n    func testIgnoresContentLengthFieldOn304Responses() throws {\n        try assertIgnoresLengthFields(\n            requestMethod: .GET,\n            responseStatus: .notModified,\n            responseFramingField: .contentLength\n        )\n    }\n\n    func testEarlyFinishWithoutLengthAtAllOn304Responses() throws {\n        try assertIgnoresLengthFields(requestMethod: .GET, responseStatus: .notModified, responseFramingField: .neither)\n    }\n\n    private func assertRequestTransferEncodingInError(transferEncodingHeader: String) throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        let handler = MessageEndHandler<HTTPRequestHead, ByteBuffer>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Send a GET with the appropriate Transfer Encoding header.\n        XCTAssertThrowsError(\n            try channel.writeInbound(\n                channel.allocator.buffer(\n                    string: \"POST / HTTP/1.1\\r\\nTransfer-Encoding: \\(transferEncodingHeader)\\r\\n\\r\\n\"\n                )\n            )\n        ) { error in\n            XCTAssertEqual(error as? HTTPParserError, .unknown)\n        }\n    }\n\n    func testMultipleTEWithChunkedLastWorksFine() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        let handler = MessageEndHandler<HTTPRequestHead, ByteBuffer>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Send a GET with the appropriate Transfer Encoding header.\n        XCTAssertNoThrow(\n            try channel.writeInbound(\n                channel.allocator.buffer(string: \"POST / HTTP/1.1\\r\\nTransfer-Encoding: gzip, chunked\\r\\n\\r\\n0\\r\\n\\r\\n\")\n            )\n        )\n\n        // We should have a request, no body, and immediately see end of request.\n        XCTAssert(handler.seenHead)\n        XCTAssertFalse(handler.seenBody)\n        XCTAssert(handler.seenEnd)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testMultipleTEWithChunkedFirstHasNoBodyOnRequest() throws {\n        try assertRequestTransferEncodingInError(transferEncodingHeader: \"chunked, gzip\")\n    }\n\n    func testMultipleTEWithChunkedInTheMiddleHasNoBodyOnRequest() throws {\n        try assertRequestTransferEncodingInError(transferEncodingHeader: \"gzip, chunked, deflate\")\n    }\n\n    private func assertResponseTransferEncodingHasBodyTerminatedByEOF(\n        transferEncodingHeader: String,\n        eofMechanism: EOFMechanism\n    ) throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        let handler = MessageEndHandler<HTTPResponseHead, ByteBuffer>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Prime the decoder with a request and consume it.\n        XCTAssertTrue(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    HTTPRequestHead(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/\"\n                    )\n                )\n            ).isFull\n        )\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        // Send a 200 with the appropriate Transfer Encoding header. We should see the request,\n        // but no body or end.\n        XCTAssertNoThrow(\n            try channel.writeInbound(\n                channel.allocator.buffer(\n                    string: \"HTTP/1.1 200 OK\\r\\nTransfer-Encoding: \\(transferEncodingHeader)\\r\\n\\r\\n\"\n                )\n            )\n        )\n        XCTAssert(handler.seenHead)\n        XCTAssertFalse(handler.seenBody)\n        XCTAssertFalse(handler.seenEnd)\n\n        // Now send body. Note that this is *not* chunk encoded. We should also see a body.\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: \"caribbean\")))\n        XCTAssert(handler.seenHead)\n        XCTAssert(handler.seenBody)\n        XCTAssertFalse(handler.seenEnd)\n\n        // Now send EOF. This should send the end as well.\n        if case .halfClosure = eofMechanism {\n            channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        } else {\n            channel.pipeline.fireChannelInactive()\n        }\n        XCTAssert(handler.seenHead)\n        XCTAssert(handler.seenBody)\n        XCTAssert(handler.seenEnd)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    private func assertResponseTransferEncodingHasBodyTerminatedByEndOfChunk(\n        transferEncodingHeader: String,\n        eofMechanism: EOFMechanism\n    ) throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        let handler = MessageEndHandler<HTTPResponseHead, ByteBuffer>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Prime the decoder with a request and consume it.\n        XCTAssertTrue(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    HTTPRequestHead(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/\"\n                    )\n                )\n            ).isFull\n        )\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        // Send a 200 with the appropriate Transfer Encoding header. We should see the request.\n        XCTAssertNoThrow(\n            try channel.writeInbound(\n                channel.allocator.buffer(\n                    string: \"HTTP/1.1 200 OK\\r\\nTransfer-Encoding: \\(transferEncodingHeader)\\r\\n\\r\\n\"\n                )\n            )\n        )\n        XCTAssert(handler.seenHead)\n        XCTAssertFalse(handler.seenBody)\n        XCTAssertFalse(handler.seenEnd)\n\n        // Now send body. Note that this *is* chunk encoded. We should also see a body.\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: \"9\\r\\ncaribbean\\r\\n\")))\n        XCTAssert(handler.seenHead)\n        XCTAssert(handler.seenBody)\n        XCTAssertFalse(handler.seenEnd)\n\n        // Now send EOF. This should error, as we're expecting the end chunk.\n        if case .halfClosure = eofMechanism {\n            channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        } else {\n            channel.pipeline.fireChannelInactive()\n        }\n\n        XCTAssert(handler.seenHead)\n        XCTAssert(handler.seenBody)\n        XCTAssertFalse(handler.seenEnd)\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertEqual(error as? HTTPParserError, .invalidEOFState)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testMultipleTEWithChunkedLastHasEOFBodyOnResponseWithChannelInactive() throws {\n        try assertResponseTransferEncodingHasBodyTerminatedByEndOfChunk(\n            transferEncodingHeader: \"gzip, chunked\",\n            eofMechanism: .channelInactive\n        )\n    }\n\n    func testMultipleTEWithChunkedFirstHasEOFBodyOnResponseWithChannelInactive() throws {\n        // Here http_parser is right, and this is EOF terminated.\n        try assertResponseTransferEncodingHasBodyTerminatedByEOF(\n            transferEncodingHeader: \"chunked, gzip\",\n            eofMechanism: .channelInactive\n        )\n    }\n\n    func testMultipleTEWithChunkedInTheMiddleHasEOFBodyOnResponseWithChannelInactive() throws {\n        // Here http_parser is right, and this is EOF terminated.\n        try assertResponseTransferEncodingHasBodyTerminatedByEOF(\n            transferEncodingHeader: \"gzip, chunked, deflate\",\n            eofMechanism: .channelInactive\n        )\n    }\n\n    func testMultipleTEWithChunkedLastHasEOFBodyOnResponseWithHalfClosure() throws {\n        try assertResponseTransferEncodingHasBodyTerminatedByEndOfChunk(\n            transferEncodingHeader: \"gzip, chunked\",\n            eofMechanism: .halfClosure\n        )\n    }\n\n    func testMultipleTEWithChunkedFirstHasEOFBodyOnResponseWithHalfClosure() throws {\n        // Here http_parser is right, and this is EOF terminated.\n        try assertResponseTransferEncodingHasBodyTerminatedByEOF(\n            transferEncodingHeader: \"chunked, gzip\",\n            eofMechanism: .halfClosure\n        )\n    }\n\n    func testMultipleTEWithChunkedInTheMiddleHasEOFBodyOnResponseWithHalfClosure() throws {\n        // Here http_parser is right, and this is EOF terminated.\n        try assertResponseTransferEncodingHasBodyTerminatedByEOF(\n            transferEncodingHeader: \"gzip, chunked, deflate\",\n            eofMechanism: .halfClosure\n        )\n    }\n\n    func testRequestWithTEAndContentLengthErrors() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // Send a GET with the invalid headers.\n        let request = channel.allocator.buffer(\n            string: \"POST / HTTP/1.1\\r\\nTransfer-Encoding: chunked\\r\\nContent-Length: 4\\r\\n\\r\\n\"\n        )\n        XCTAssertThrowsError(try channel.writeInbound(request)) { error in\n            XCTAssertEqual(HTTPParserError.invalidContentLength, error as? HTTPParserError)\n        }\n\n        // Must spin the loop.\n        XCTAssertFalse(channel.isActive)\n        channel.embeddedEventLoop.run()\n    }\n\n    func testResponseWithTEAndContentLengthErrors() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        // Prime the decoder with a request.\n        XCTAssertTrue(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    HTTPRequestHead(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/\"\n                    )\n                )\n            ).isFull\n        )\n\n        // Send a 200 OK with the invalid headers.\n        let response = \"HTTP/1.1 200 OK\\r\\nTransfer-Encoding: chunked\\r\\nContent-Length: 4\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try channel.writeInbound(channel.allocator.buffer(string: response))) { error in\n            XCTAssertEqual(HTTPParserError.invalidContentLength, error as? HTTPParserError)\n        }\n\n        // Must spin the loop.\n        XCTAssertFalse(channel.isActive)\n        channel.embeddedEventLoop.run()\n    }\n\n    private func assertRequestWithInvalidCLErrors(contentLengthField: String) throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // Send a GET with the invalid headers.\n        let request = \"POST / HTTP/1.1\\r\\nContent-Length: \\(contentLengthField)\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try channel.writeInbound(channel.allocator.buffer(string: request))) { error in\n            XCTAssert(\n                HTTPParserError.unexpectedContentLength == error as? HTTPParserError\n                    || HTTPParserError.invalidContentLength == error as? HTTPParserError\n            )\n        }\n\n        // Must spin the loop.\n        XCTAssertFalse(channel.isActive)\n        channel.embeddedEventLoop.run()\n    }\n\n    func testRequestWithMultipleDifferentContentLengthsFails() throws {\n        try assertRequestWithInvalidCLErrors(contentLengthField: \"4, 5\")\n    }\n\n    func testRequestWithMultipleDifferentContentLengthsOnDifferentLinesFails() throws {\n        try assertRequestWithInvalidCLErrors(contentLengthField: \"4\\r\\nContent-Length: 5\")\n    }\n\n    func testRequestWithInvalidContentLengthFails() throws {\n        try assertRequestWithInvalidCLErrors(contentLengthField: \"pie\")\n    }\n\n    func testRequestWithIdenticalContentLengthRepeatedErrors() throws {\n        // This is another case where http_parser is, if not wrong, then aggressively interpreting\n        // the spec. Regardless, we match it.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // Send two POSTs with repeated content length, one with one field and one with two.\n        // Both should error.\n        let request = \"POST / HTTP/1.1\\r\\nContent-Length: 4, 4\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try channel.writeInbound(channel.allocator.buffer(string: request))) { error in\n            XCTAssertEqual(HTTPParserError.invalidContentLength, error as? HTTPParserError)\n        }\n\n        // Must spin the loop.\n        XCTAssertFalse(channel.isActive)\n        channel.embeddedEventLoop.run()\n    }\n\n    func testRequestWithMultipleIdenticalContentLengthFieldsErrors() throws {\n        // This is another case where http_parser is, if not wrong, then aggressively interpreting\n        // the spec. Regardless, we match it.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        let request = \"POST / HTTP/1.1\\r\\nContent-Length: 4\\r\\nContent-Length: 4\\r\\n\\r\\n\"\n        XCTAssertThrowsError(try channel.writeInbound(channel.allocator.buffer(string: request))) { error in\n            XCTAssertEqual(HTTPParserError.unexpectedContentLength, error as? HTTPParserError)\n        }\n\n        // Must spin the loop.\n        XCTAssertFalse(channel.isActive)\n        channel.embeddedEventLoop.run()\n    }\n\n    func testRequestWithoutExplicitLengthIsZeroLength() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        let handler = MessageEndHandler<HTTPRequestHead, ByteBuffer>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        // Send a POST without a length field of any kind. This should be a zero-length request,\n        // so .end should come immediately.\n        XCTAssertNoThrow(\n            try channel.writeInbound(channel.allocator.buffer(string: \"POST / HTTP/1.1\\r\\nHost: example.org\\r\\n\\r\\n\"))\n        )\n        XCTAssert(handler.seenHead)\n        XCTAssertFalse(handler.seenBody)\n        XCTAssert(handler.seenEnd)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPDecoderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOHTTP1\nimport NIOTestUtils\nimport XCTest\n\nclass HTTPDecoderTest: XCTestCase {\n    private var channel: EmbeddedChannel!\n    private var loop: EmbeddedEventLoop {\n        self.channel.embeddedEventLoop\n    }\n\n    override func setUp() {\n        self.channel = EmbeddedChannel()\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.channel?.finish(acceptAlreadyClosed: true))\n        self.channel = nil\n    }\n\n    func testDoesNotDecodeRealHTTP09Request() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is an invalid HTTP/0.9 simple request (too many CRLFs), but we need to\n        // trigger https://github.com/nodejs/http-parser/issues/386 or http_parser won't\n        // actually parse this at all.\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"GET /a-file\\r\\n\\r\\n\")\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidVersion, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testDoesNotDecodeFakeHTTP09Request() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is a HTTP/1.1-formatted request that claims to be HTTP/0.9.\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"GET / HTTP/0.9\\r\\nHost: whatever\\r\\n\\r\\n\")\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidVersion, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testDoesNotDecodeHTTP2XRequest() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is a hypothetical HTTP/2.0 protocol request, assuming it is\n        // byte for byte identical (which such a protocol would never be).\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"GET / HTTP/2.0\\r\\nHost: whatever\\r\\n\\r\\n\")\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidVersion, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testDoesNotDecodeRealHTTP09Response() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        // We need to prime the decoder by seeing a GET request.\n        try channel.writeOutbound(\n            HTTPClientRequestPart.head(HTTPRequestHead(version: .http0_9, method: .GET, uri: \"/\"))\n        )\n\n        // The HTTP parser has no special logic for HTTP/0.9 simple responses, but we'll send\n        // one anyway just to prove it explodes.\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"This is file data\\n\")\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidConstant, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testDoesNotDecodeFakeHTTP09Response() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        // We need to prime the decoder by seeing a GET request.\n        try channel.writeOutbound(\n            HTTPClientRequestPart.head(HTTPRequestHead(version: .http0_9, method: .GET, uri: \"/\"))\n        )\n\n        // The HTTP parser rejects HTTP/1.1-formatted responses claiming 0.9 as a version.\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"HTTP/0.9 200 OK\\r\\nServer: whatever\\r\\n\\r\\n\")\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidVersion, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testDoesNotDecodeHTTP2XResponse() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPResponseDecoder())))\n\n        // We need to prime the decoder by seeing a GET request.\n        try channel.writeOutbound(HTTPClientRequestPart.head(HTTPRequestHead(version: .http2, method: .GET, uri: \"/\")))\n\n        // This is a hypothetical HTTP/2.0 protocol response, assuming it is\n        // byte for byte identical (which such a protocol would never be).\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"HTTP/2.0 200 OK\\r\\nServer: whatever\\r\\n\\r\\n\")\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidVersion, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testCorrectlyMaintainIndicesWhenDiscardReadBytes() throws {\n        class Receiver: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .head(let h):\n                    XCTAssertEqual(\"/SomeURL\", h.uri)\n                    for h in h.headers {\n                        XCTAssertEqual(\"X-Header\", h.name)\n                        XCTAssertEqual(\"value\", h.value)\n                    }\n                default:\n                    break\n                }\n            }\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(Receiver()))\n\n        // This is a hypothetical HTTP/2.0 protocol response, assuming it is\n        // byte for byte identical (which such a protocol would never be).\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"GET /SomeURL HTTP/1.1\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        var written = 0\n        repeat {\n            var buffer2 = channel.allocator.buffer(capacity: 16)\n\n            written += buffer2.writeStaticString(\"X-Header: value\\r\\n\")\n            try channel.writeInbound(buffer2)\n        } while written < 8192  // Use a value that w\n\n        var buffer3 = channel.allocator.buffer(capacity: 2)\n        buffer3.writeStaticString(\"\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeInbound(buffer3))\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testDropExtraBytes() throws {\n        class Receiver: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .end:\n                    // ignore\n                    _ = context.pipeline.removeHandler(name: \"decoder\")\n                default:\n                    break\n                }\n            }\n        }\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                ByteToMessageHandler(HTTPRequestDecoder()),\n                name: \"decoder\"\n            )\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(Receiver()))\n\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\"\n        )\n\n        // allow the event loop to run (removal is not synchronous here)\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        (channel.eventLoop as! EmbeddedEventLoop).run()\n        XCTAssertNoThrow(\n            try channel.pipeline.assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPRequestDecoder>.self)\n        )\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testDontDropExtraBytesRequest() throws {\n        class ByteCollector: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            var called: Bool = false\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buffer = Self.unwrapInboundIn(data)\n                XCTAssertEqual(\"XXXX\", buffer.readString(length: buffer.readableBytes)!)\n                self.called = true\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                context.pipeline.removeHandler(name: \"decoder\").whenComplete { result in\n                    _ = result.mapError { (error: Error) -> Error in\n                        XCTFail(\"unexpected error \\(error)\")\n                        return error\n                    }\n                }\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertTrue(self.called)\n            }\n        }\n\n        class Receiver: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = HTTPServerRequestPart\n            let collector = ByteCollector()\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .end:\n                    _ = context.pipeline.syncOperations.removeHandler(self).assumeIsolated().flatMapThrowing {\n                        [pipeline = context.pipeline] _ in\n                        try pipeline.syncOperations.addHandler(self.collector)\n                    }\n                default:\n                    // ignore\n                    break\n                }\n            }\n        }\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .forwardBytes)),\n                name: \"decoder\"\n            )\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(Receiver()))\n\n        // This connect call is semantically wrong, but it's how you\n        // active embedded channels properly right now.\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 8888)).wait())\n\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\"\n        )\n\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        // allow the event loop to run (removal is not synchrnous here)\n        (channel.eventLoop as! EmbeddedEventLoop).run()\n        XCTAssertNoThrow(\n            try channel.pipeline.assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPRequestDecoder>.self)\n        )\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testDontDropExtraBytesResponse() throws {\n        class ByteCollector: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            var called: Bool = false\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buffer = Self.unwrapInboundIn(data)\n                XCTAssertEqual(\"XXXX\", buffer.readString(length: buffer.readableBytes)!)\n                self.called = true\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                _ = context.pipeline.removeHandler(name: \"decoder\")\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssert(self.called)\n            }\n        }\n\n        class Receiver: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = HTTPClientResponsePart\n            typealias InboundOut = HTTPClientResponsePart\n            typealias OutboundOut = HTTPClientRequestPart\n\n            func channelActive(context: ChannelHandlerContext) {\n                var upgradeReq = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n                upgradeReq.headers.add(name: \"Connection\", value: \"Upgrade\")\n                upgradeReq.headers.add(name: \"Upgrade\", value: \"myprot\")\n                upgradeReq.headers.add(name: \"Host\", value: \"localhost\")\n                context.write(wrapOutboundOut(.head(upgradeReq)), promise: nil)\n                context.writeAndFlush(wrapOutboundOut(.end(nil)), promise: nil)\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .end:\n                    _ = context.pipeline.syncOperations.removeHandler(self).assumeIsolated().flatMapThrowing {\n                        [pipeline = context.pipeline] _ in\n                        try pipeline.syncOperations.addHandler(ByteCollector())\n                    }\n                    break\n                default:\n                    // ignore\n                    break\n                }\n            }\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                ByteToMessageHandler(HTTPResponseDecoder(leftOverBytesStrategy: .forwardBytes)),\n                name: \"decoder\"\n            )\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(Receiver()))\n\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 8888)).wait())\n\n        var buffer = channel.allocator.buffer(capacity: 32)\n        buffer.writeStaticString(\n            \"HTTP/1.1 101 Switching Protocols\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\"\n        )\n\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        // allow the event loop to run (removal is not synchronous here)\n        (channel.eventLoop as! EmbeddedEventLoop).run()\n        XCTAssertNoThrow(\n            try channel.pipeline.assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPRequestDecoder>.self)\n        )\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testExtraCRLF() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is a simple HTTP/1.1 request with a few too many CRLFs before it, to trigger\n        // https://github.com/nodejs/http-parser/pull/432.\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"\\r\\nGET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n\")\n        try channel.writeInbound(buffer)\n\n        let message: HTTPServerRequestPart? = try self.channel.readInbound()\n        guard case .some(.head(let head)) = message else {\n            XCTFail(\"Invalid message: \\(String(describing: message))\")\n            return\n        }\n\n        XCTAssertEqual(head.method, .GET)\n        XCTAssertEqual(head.uri, \"/\")\n        XCTAssertEqual(head.version, .http1_1)\n        XCTAssertEqual(head.headers, HTTPHeaders([(\"Host\", \"example.com\")]))\n\n        let secondMessage: HTTPServerRequestPart? = try self.channel.readInbound()\n        guard case .some(.end(.none)) = secondMessage else {\n            XCTFail(\"Invalid second message: \\(String(describing: secondMessage))\")\n            return\n        }\n\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testSOURCEDoesntExplodeUs() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is a simple HTTP/1.1 request with the SOURCE verb which is newly added to\n        // http_parser.\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"SOURCE / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n\")\n        try channel.writeInbound(buffer)\n\n        let message: HTTPServerRequestPart? = try self.channel.readInbound()\n        guard case .some(.head(let head)) = message else {\n            XCTFail(\"Invalid message: \\(String(describing: message))\")\n            return\n        }\n\n        XCTAssertEqual(head.method, .RAW(value: \"SOURCE\"))\n        XCTAssertEqual(head.uri, \"/\")\n        XCTAssertEqual(head.version, .http1_1)\n        XCTAssertEqual(head.headers, HTTPHeaders([(\"Host\", \"example.com\")]))\n\n        let secondMessage: HTTPServerRequestPart? = try self.channel.readInbound()\n        guard case .some(.end(.none)) = secondMessage else {\n            XCTFail(\"Invalid second message: \\(String(describing: secondMessage))\")\n            return\n        }\n\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testExtraCarriageReturnBetweenSubsequentRequests() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is a simple HTTP/1.1 request with an extra \\r between first and second message, designed to hit the code\n        // changed in https://github.com/nodejs/http-parser/pull/432 .\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n\")\n        buffer.writeStaticString(\"\\r\")  // this is extra\n        buffer.writeStaticString(\"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n\")\n        try channel.writeInbound(buffer)\n\n        let message: HTTPServerRequestPart? = try self.channel.readInbound()\n        guard case .some(.head(let head)) = message else {\n            XCTFail(\"Invalid message: \\(String(describing: message))\")\n            return\n        }\n\n        XCTAssertEqual(head.method, .GET)\n        XCTAssertEqual(head.uri, \"/\")\n        XCTAssertEqual(head.version, .http1_1)\n        XCTAssertEqual(head.headers, HTTPHeaders([(\"Host\", \"example.com\")]))\n\n        let secondMessage: HTTPServerRequestPart? = try self.channel.readInbound()\n        guard case .some(.end(.none)) = secondMessage else {\n            XCTFail(\"Invalid second message: \\(String(describing: secondMessage))\")\n            return\n        }\n\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testIllegalHeaderNamesCauseError() {\n        func writeToFreshRequestDecoderChannel(_ string: String) throws {\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            defer {\n                XCTAssertNoThrow(try channel.finish())\n            }\n            var buffer = channel.allocator.buffer(capacity: 256)\n            buffer.writeString(string)\n            try channel.writeInbound(buffer)\n        }\n\n        // non-ASCII character in header name\n        XCTAssertThrowsError(try writeToFreshRequestDecoderChannel(\"GET / HTTP/1.1\\r\\nföo: bar\\r\\n\\r\\n\")) { error in\n            XCTAssertEqual(HTTPParserError.invalidHeaderToken, error as? HTTPParserError)\n        }\n\n        // empty header name\n        XCTAssertThrowsError(try writeToFreshRequestDecoderChannel(\"GET / HTTP/1.1\\r\\n: bar\\r\\n\\r\\n\")) { error in\n            XCTAssertEqual(HTTPParserError.invalidHeaderToken, error as? HTTPParserError)\n        }\n\n        // just a space as header name\n        XCTAssertThrowsError(try writeToFreshRequestDecoderChannel(\"GET / HTTP/1.1\\r\\n : bar\\r\\n\\r\\n\")) { error in\n            XCTAssertEqual(HTTPParserError.invalidHeaderToken, error as? HTTPParserError)\n        }\n    }\n\n    func testNonASCIIWorksAsHeaderValue() {\n        func writeToFreshRequestDecoderChannel(_ string: String) throws -> HTTPServerRequestPart? {\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            defer {\n                XCTAssertNoThrow(try channel.finish())\n            }\n            var buffer = channel.allocator.buffer(capacity: 256)\n            buffer.writeString(string)\n            try channel.writeInbound(buffer)\n            return try channel.readInbound(as: HTTPServerRequestPart.self)\n        }\n\n        var expectedHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n        expectedHead.headers.add(name: \"foo\", value: \"bär\")\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                .head(expectedHead),\n                try writeToFreshRequestDecoderChannel(\"GET / HTTP/1.1\\r\\nfoo: bär\\r\\n\\r\\n\")\n            )\n        )\n    }\n\n    func testDoesNotDeliverLeftoversUnnecessarily() {\n        // This test isolates a nasty problem where the http parser offset would never be reset to zero. This would cause us to gradually leak\n        // very small amounts of memory on each connection, or sometimes crash.\n        let data: StaticString = \"GET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n\"\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        var dataBuffer = channel.allocator.buffer(capacity: 128)\n        dataBuffer.writeStaticString(data)\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .fireError))\n            )\n        )\n        XCTAssertNoThrow(try channel.writeInbound(dataBuffer.getSlice(at: 0, length: dataBuffer.readableBytes - 6)!))\n        XCTAssertNoThrow(try channel.writeInbound(dataBuffer.getSlice(at: dataBuffer.readableBytes - 6, length: 6)!))\n\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        channel.pipeline.fireChannelInactive()\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n    }\n\n    func testHTTPResponseWithoutHeaders() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        var buffer = channel.allocator.buffer(capacity: 128)\n        buffer.writeStaticString(\"HTTP/1.0 200 ok\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                ByteToMessageHandler(HTTPResponseDecoder(leftOverBytesStrategy: .fireError))\n            )\n        )\n        XCTAssertNoThrow(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    .init(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/\"\n                    )\n                )\n            )\n        )\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                HTTPClientResponsePart.head(\n                    .init(\n                        version: .http1_0,\n                        status: .ok\n                    )\n                ),\n                try channel.readInbound()\n            )\n        )\n    }\n\n    func testBasicVerifications() {\n        let byteBufferContainingJustAnX = ByteBuffer(string: \"X\")\n        let expectedInOuts: [(String, [HTTPServerRequestPart])] = [\n            (\n                \"GET / HTTP/1.1\\r\\n\\r\\n\",\n                [\n                    .head(.init(version: .http1_1, method: .GET, uri: \"/\")),\n                    .end(nil),\n                ]\n            ),\n            (\n                \"POST /foo HTTP/1.1\\r\\n\\r\\n\",\n                [\n                    .head(.init(version: .http1_1, method: .POST, uri: \"/foo\")),\n                    .end(nil),\n                ]\n            ),\n            (\n                \"POST / HTTP/1.1\\r\\ncontent-length: 1\\r\\n\\r\\nX\",\n                [\n                    .head(\n                        .init(\n                            version: .http1_1,\n                            method: .POST,\n                            uri: \"/\",\n                            headers: .init([(\"content-length\", \"1\")])\n                        )\n                    ),\n                    .body(byteBufferContainingJustAnX),\n                    .end(nil),\n                ]\n            ),\n            (\n                \"POST / HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n1\\r\\nX\\r\\n0\\r\\n\\r\\n\",\n                [\n                    .head(\n                        .init(\n                            version: .http1_1,\n                            method: .POST,\n                            uri: \"/\",\n                            headers: .init([(\"transfer-encoding\", \"chunked\")])\n                        )\n                    ),\n                    .body(byteBufferContainingJustAnX),\n                    .end(nil),\n                ]\n            ),\n            (\n                \"POST / HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\none: two\\r\\n\\r\\n1\\r\\nX\\r\\n0\\r\\nfoo: bar\\r\\n\\r\\n\",\n                [\n                    .head(\n                        .init(\n                            version: .http1_1,\n                            method: .POST,\n                            uri: \"/\",\n                            headers: .init([(\"transfer-encoding\", \"chunked\"), (\"one\", \"two\")])\n                        )\n                    ),\n                    .body(byteBufferContainingJustAnX),\n                    .end(.init([(\"foo\", \"bar\")])),\n                ]\n            ),\n        ]\n\n        let expectedInOutsBB: [(ByteBuffer, [HTTPServerRequestPart])] = expectedInOuts.map { io in\n            (ByteBuffer(string: io.0), io.1)\n        }\n        XCTAssertNoThrow(\n            try ByteToMessageDecoderVerifier.verifyDecoder(\n                inputOutputPairs: expectedInOutsBB,\n                decoderFactory: { HTTPRequestDecoder() }\n            )\n        )\n    }\n\n    func testNothingHappensOnEOFForLeftOversInAllLeftOversModes() throws {\n        class Receiver: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n\n            private var numberOfErrors = 0\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .head(let head):\n                    XCTAssertEqual(.OPTIONS, head.method)\n                case .body:\n                    XCTFail(\"unexpected .body part\")\n                case .end:\n                    ()\n                }\n            }\n        }\n\n        for leftOverBytesStrategy in [RemoveAfterUpgradeStrategy.dropBytes, .fireError, .forwardBytes] {\n            let channel = EmbeddedChannel()\n            var buffer = channel.allocator.buffer(capacity: 64)\n            buffer.writeStaticString(\"OPTIONS * HTTP/1.1\\r\\nHost: L\\r\\nUpgrade: P\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\")\n\n            let decoder = HTTPRequestDecoder(leftOverBytesStrategy: leftOverBytesStrategy)\n            XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(decoder)))\n            XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(Receiver()))\n            XCTAssertNoThrow(try channel.writeInbound(buffer))\n            XCTAssertNoThrow(XCTAssert(try channel.finish().isClean))\n        }\n    }\n\n    func testBytesCanBeForwardedWhenHandlerRemoved() throws {\n        class Receiver: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = HTTPServerRequestPart\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .head(let head):\n                    XCTAssertEqual(.OPTIONS, head.method)\n                case .body:\n                    XCTFail(\"unexpected .body part\")\n                case .end:\n                    ()\n                }\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"OPTIONS * HTTP/1.1\\r\\nHost: L\\r\\nUpgrade: P\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\")\n\n        let receiver = Receiver()\n        let decoder = ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .forwardBytes))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(receiver))\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        let removalFutures = [\n            channel.pipeline.syncOperations.removeHandler(receiver),\n            channel.pipeline.syncOperations.removeHandler(decoder),\n        ]\n        channel.embeddedEventLoop.run()\n        for future in removalFutures {\n            XCTAssertNoThrow(try future.wait())\n        }\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"XXXX\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(XCTAssert(try channel.finish().isClean))\n    }\n\n    func testBytesCanBeFiredAsErrorWhenHandlerRemoved() throws {\n        class Receiver: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = HTTPServerRequestPart\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .head(let head):\n                    XCTAssertEqual(.OPTIONS, head.method)\n                case .body:\n                    XCTFail(\"unexpected .body part\")\n                case .end:\n                    ()\n                }\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"OPTIONS * HTTP/1.1\\r\\nHost: L\\r\\nUpgrade: P\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\")\n\n        let receiver = Receiver()\n        let decoder = ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .fireError))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(receiver))\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        let removalFutures = [\n            channel.pipeline.syncOperations.removeHandler(receiver),\n            channel.pipeline.syncOperations.removeHandler(decoder),\n        ]\n        channel.embeddedEventLoop.run()\n        for future in removalFutures {\n            XCTAssertNoThrow(try future.wait())\n        }\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            switch error as? ByteToMessageDecoderError {\n            case .some(ByteToMessageDecoderError.leftoverDataWhenDone(let buffer)):\n                XCTAssertEqual(\"XXXX\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n            case .some(let error):\n                XCTFail(\"unexpected error: \\(error)\")\n            case .none:\n                XCTFail(\"unexpected error\")\n            }\n        }\n        XCTAssertNoThrow(XCTAssert(try channel.finish().isClean))\n    }\n\n    func testBytesCanBeDroppedWhenHandlerRemoved() throws {\n        class Receiver: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = HTTPServerRequestPart\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let part = Self.unwrapInboundIn(data)\n                switch part {\n                case .head(let head):\n                    XCTAssertEqual(.OPTIONS, head.method)\n                case .body:\n                    XCTFail(\"unexpected .body part\")\n                case .end:\n                    ()\n                }\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"OPTIONS * HTTP/1.1\\r\\nHost: L\\r\\nUpgrade: P\\r\\nConnection: upgrade\\r\\n\\r\\nXXXX\")\n\n        let receiver = Receiver()\n        let decoder = ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .dropBytes))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(receiver))\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        let removalFutures = [\n            channel.pipeline.syncOperations.removeHandler(receiver),\n            channel.pipeline.syncOperations.removeHandler(decoder),\n        ]\n        channel.embeddedEventLoop.run()\n        for future in removalFutures {\n            XCTAssertNoThrow(try future.wait())\n        }\n        XCTAssertNoThrow(XCTAssert(try channel.finish().isClean))\n    }\n\n    func testAppropriateErrorWhenReceivingUnsolicitedResponse() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"HTTP/1.1 200 OK\\r\\nServer: a-bad-server/1.0.0\\r\\n\\r\\n\")\n\n        let decoder = ByteToMessageHandler(HTTPResponseDecoder(leftOverBytesStrategy: .dropBytes))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(error as? NIOHTTPDecoderError, .unsolicitedResponse)\n        }\n    }\n\n    func testAppropriateErrorWhenReceivingUnsolicitedResponseDoesNotRecover() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"HTTP/1.1 200 OK\\r\\nServer: a-bad-server/1.0.0\\r\\n\\r\\n\")\n\n        let decoder = ByteToMessageHandler(HTTPResponseDecoder(leftOverBytesStrategy: .dropBytes))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(error as? NIOHTTPDecoderError, .unsolicitedResponse)\n        }\n\n        // Write a request.\n        let request = HTTPClientRequestPart.head(.init(version: .http1_1, method: .GET, uri: \"/\"))\n        XCTAssertNoThrow(try channel.writeOutbound(request))\n\n        // The server sending another response should lead to another error.\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            guard case .some(.dataReceivedInErrorState(let baseError, _)) = error as? ByteToMessageDecoderError else {\n                XCTFail(\"Unexpected error type: \\(error)\")\n                return\n            }\n\n            XCTAssertEqual(baseError as? NIOHTTPDecoderError, .unsolicitedResponse)\n        }\n    }\n\n    func testOneRequestTwoResponses() {\n        let eventCounter = EventCounterHandler()\n        let responseDecoder = ByteToMessageHandler(HTTPResponseDecoder())\n        let channel = EmbeddedChannel(handler: responseDecoder)\n        XCTAssertNoThrow(try channel.pipeline.addHandler(eventCounter).wait())\n\n        XCTAssertNoThrow(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    .init(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/\"\n                    )\n                )\n            )\n        )\n        var buffer = channel.allocator.buffer(capacity: 128)\n        buffer.writeString(\"HTTP/1.1 200 ok\\r\\ncontent-length: 0\\r\\n\\r\\nHTTP/1.1 200 ok\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.unsolicitedResponse, error as? NIOHTTPDecoderError)\n        }\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                .head(\n                    .init(\n                        version: .http1_1,\n                        status: .ok,\n                        headers: [\"content-length\": \"0\"]\n                    )\n                ),\n                try channel.readInbound(as: HTTPClientResponsePart.self)\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                .end(nil),\n                try channel.readInbound(as: HTTPClientResponsePart.self)\n            )\n        )\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound(as: HTTPClientResponsePart.self)))\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readOutbound()))\n        XCTAssertEqual(1, eventCounter.writeCalls)\n        XCTAssertEqual(1, eventCounter.flushCalls)\n        XCTAssertEqual(2, eventCounter.channelReadCalls)  // .head & .end\n        XCTAssertEqual(1, eventCounter.channelReadCompleteCalls)\n        XCTAssertEqual(\n            [\"channelReadComplete\", \"write\", \"flush\", \"channelRead\", \"errorCaught\"],\n            eventCounter.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testForwardContinueThenResponse() {\n        let eventCounter = EventCounterHandler()\n        let decoder = HTTPResponseDecoder(leftOverBytesStrategy: .dropBytes, informationalResponseStrategy: .forward)\n        let responseDecoder = ByteToMessageHandler(decoder)\n        let channel = EmbeddedChannel(handler: responseDecoder)\n        XCTAssertNoThrow(try channel.pipeline.addHandler(eventCounter).wait())\n\n        let requestHead: HTTPClientRequestPart = .head(.init(version: .http1_1, method: .POST, uri: \"/\"))\n        XCTAssertNoThrow(try channel.writeOutbound(requestHead))\n        var buffer = channel.allocator.buffer(capacity: 128)\n        buffer.writeString(\"HTTP/1.1 100 continue\\r\\n\\r\\nHTTP/1.1 200 ok\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertEqual(\n            try channel.readInbound(as: HTTPClientResponsePart.self),\n            .head(.init(version: .http1_1, status: .continue))\n        )\n        XCTAssertEqual(\n            try channel.readInbound(as: HTTPClientResponsePart.self),\n            .head(.init(version: .http1_1, status: .ok, headers: [\"content-length\": \"0\"]))\n        )\n        XCTAssertEqual(.end(nil), try channel.readInbound(as: HTTPClientResponsePart.self))\n        XCTAssertNil(try channel.readInbound(as: HTTPClientResponsePart.self))\n        XCTAssertNotNil(try channel.readOutbound())\n\n        XCTAssertEqual(1, eventCounter.writeCalls)\n        XCTAssertEqual(1, eventCounter.flushCalls)\n        XCTAssertEqual(3, eventCounter.channelReadCalls)  // .head, .head & .end\n        XCTAssertEqual(1, eventCounter.channelReadCompleteCalls)\n        XCTAssertEqual([\"channelReadComplete\", \"channelRead\", \"write\", \"flush\"], eventCounter.allTriggeredEvents())\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testForwardMultipleContinuesThenResponse() {\n        let eventCounter = EventCounterHandler()\n        let decoder = HTTPResponseDecoder(leftOverBytesStrategy: .dropBytes, informationalResponseStrategy: .forward)\n        let responseDecoder = ByteToMessageHandler(decoder)\n        let channel = EmbeddedChannel(handler: responseDecoder)\n        XCTAssertNoThrow(try channel.pipeline.addHandler(eventCounter).wait())\n\n        let requestHead: HTTPClientRequestPart = .head(.init(version: .http1_1, method: .POST, uri: \"/\"))\n        XCTAssertNoThrow(try channel.writeOutbound(requestHead))\n        var buffer = channel.allocator.buffer(capacity: 128)\n        let continueCount = (3...10).randomElement()!\n        for _ in 0..<continueCount {\n            buffer.writeString(\"HTTP/1.1 100 continue\\r\\n\\r\\n\")\n            XCTAssertNoThrow(try channel.writeInbound(buffer))\n            XCTAssertEqual(\n                try channel.readInbound(as: HTTPClientResponsePart.self),\n                .head(.init(version: .http1_1, status: .continue))\n            )\n            buffer.clear()\n        }\n\n        buffer.writeString(\"HTTP/1.1 200 ok\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertEqual(\n            try channel.readInbound(as: HTTPClientResponsePart.self),\n            .head(.init(version: .http1_1, status: .ok, headers: [\"content-length\": \"0\"]))\n        )\n        XCTAssertEqual(.end(nil), try channel.readInbound(as: HTTPClientResponsePart.self))\n        XCTAssertNil(try channel.readInbound(as: HTTPClientResponsePart.self))\n        XCTAssertNotNil(try channel.readOutbound())\n\n        XCTAssertEqual(1, eventCounter.writeCalls)\n        XCTAssertEqual(1, eventCounter.flushCalls)\n        XCTAssertEqual(continueCount + 2, eventCounter.channelReadCalls)  // continues + .head & .end\n        XCTAssertEqual(continueCount + 1, eventCounter.channelReadCompleteCalls)\n        XCTAssertEqual([\"channelReadComplete\", \"channelRead\", \"write\", \"flush\"], eventCounter.allTriggeredEvents())\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testDropContinueThanForwardResponse() {\n        let eventCounter = EventCounterHandler()\n        let decoder = HTTPResponseDecoder(leftOverBytesStrategy: .dropBytes, informationalResponseStrategy: .drop)\n        let responseDecoder = ByteToMessageHandler(decoder)\n        let channel = EmbeddedChannel(handler: responseDecoder)\n        XCTAssertNoThrow(try channel.pipeline.addHandler(eventCounter).wait())\n\n        let requestHead: HTTPClientRequestPart = .head(.init(version: .http1_1, method: .POST, uri: \"/\"))\n        XCTAssertNoThrow(try channel.writeOutbound(requestHead))\n        var buffer = channel.allocator.buffer(capacity: 128)\n        buffer.writeString(\"HTTP/1.1 100 continue\\r\\n\\r\\nHTTP/1.1 200 ok\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertEqual(\n            try channel.readInbound(as: HTTPClientResponsePart.self),\n            .head(.init(version: .http1_1, status: .ok, headers: [\"content-length\": \"0\"]))\n        )\n        XCTAssertEqual(.end(nil), try channel.readInbound(as: HTTPClientResponsePart.self))\n        XCTAssertNil(try channel.readInbound(as: HTTPClientResponsePart.self))\n        XCTAssertNotNil(try channel.readOutbound())\n\n        XCTAssertEqual(1, eventCounter.writeCalls)\n        XCTAssertEqual(1, eventCounter.flushCalls)\n        XCTAssertEqual(2, eventCounter.channelReadCalls)  // .head & .end\n        XCTAssertEqual(1, eventCounter.channelReadCompleteCalls)\n        XCTAssertEqual([\"channelReadComplete\", \"channelRead\", \"write\", \"flush\"], eventCounter.allTriggeredEvents())\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testRefusesRequestSmugglingAttempt() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        // This is a request smuggling attempt caused by duplicating the Transfer-Encoding and Content-Length headers.\n        var buffer = channel.allocator.buffer(capacity: 256)\n        buffer.writeString(\n            \"POST /foo HTTP/1.1\\r\\n\" + \"Host: localhost\\r\\n\" + \"Content-length: 1\\r\\n\"\n                + \"Transfer-Encoding: gzip, chunked\\r\\n\\r\\n\" + \"3\\r\\na=1\\r\\n0\\r\\n\\r\\n\"\n        )\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertEqual(.unknown, error as? HTTPParserError)\n        }\n\n        self.loop.run()\n    }\n\n    func testTrimsTrailingOWS() throws {\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder())))\n\n        var buffer = channel.allocator.buffer(capacity: 64)\n        buffer.writeStaticString(\"GET / HTTP/1.1\\r\\nHost: localhost\\r\\nFoo: bar \\r\\nBaz: Boz\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        let request = try assertNoThrowWithValue(channel.readInbound(as: HTTPServerRequestPart.self))\n        guard case .some(.head(let head)) = request else {\n            XCTFail(\"Unexpected first message: \\(String(describing: request))\")\n            return\n        }\n        XCTAssertEqual(head.headers[canonicalForm: \"Foo\"], [\"bar\"])\n        guard case .some(.end) = try assertNoThrowWithValue(channel.readInbound(as: HTTPServerRequestPart.self)) else {\n            XCTFail(\"Unexpected last message\")\n            return\n        }\n    }\n\n    func testMassiveChunkDoesNotBufferAndGivesUsHoweverMuchIsAvailable() {\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n\n        var buffer = self.channel.allocator.buffer(capacity: 64)\n        buffer.writeString(\n            \"POST / HTTP/1.1\\r\\nHost: localhost\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\" + \"FFFFFFFFFFFFF\\r\\nfoo\"\n        )\n\n        XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n\n        var maybeHead: HTTPServerRequestPart?\n        var maybeBodyChunk: HTTPServerRequestPart?\n\n        XCTAssertNoThrow(maybeHead = try self.channel.readInbound())\n        XCTAssertNoThrow(maybeBodyChunk = try self.channel.readInbound())\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n\n        guard case .some(.head(let head)) = maybeHead, case .some(.body(let body)) = maybeBodyChunk else {\n            XCTFail(\"didn't receive head & body\")\n            return\n        }\n\n        XCTAssertEqual(.POST, head.method)\n        XCTAssertEqual(\"foo\", String(decoding: body.readableBytesView, as: Unicode.UTF8.self))\n\n        XCTAssertThrowsError(try self.channel.finish()) { error in\n            XCTAssertEqual(.invalidEOFState, error as? HTTPParserError)\n        }\n    }\n\n    func testDecodingLongHeaderFieldNames() {\n        // Our maximum field size is 80kB, so we're going to write an 80kB + 1 byte field name to confirm it fails.\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n\n        var buffer = ByteBuffer(string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n\n        buffer.clear()\n        buffer.writeRepeatingByte(UInt8(ascii: \"x\"), count: 1024)\n\n        for _ in 0..<80 {\n            XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n            XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n        }\n\n        let lastByte = buffer.readSlice(length: 1)!\n        XCTAssertThrowsError(try self.channel.writeInbound(lastByte)) { error in\n            XCTAssertEqual(error as? HTTPParserError, .headerOverflow)\n        }\n\n        // We know we'll see an error, we can safely drop it.\n        _ = try? self.channel.finish()\n    }\n\n    func testDecodingLongHeaderFieldValues() {\n        // Our maximum field size is 80kB, so we're going to write an 80kB + 1 byte field value to confirm it fails.\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n\n        var buffer = ByteBuffer(string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\nx: \")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n\n        buffer.clear()\n        buffer.writeRepeatingByte(UInt8(ascii: \"x\"), count: 1024)\n\n        for _ in 0..<80 {\n            XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n            XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n        }\n\n        let lastByte = buffer.readSlice(length: 1)!\n        XCTAssertThrowsError(try self.channel.writeInbound(lastByte)) { error in\n            XCTAssertEqual(error as? HTTPParserError, .headerOverflow)\n        }\n\n        // We know we'll see an error, we can safely drop it.\n        _ = try? self.channel.finish()\n    }\n\n    func testDecodingLongURLs() {\n        // Our maximum field size is 80kB, so we're going to write an 80kB + 1 byte URL to confirm it fails.\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n\n        var buffer = ByteBuffer(string: \"GET \")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n\n        buffer.clear()\n        buffer.writeRepeatingByte(UInt8(ascii: \"x\"), count: 1024)\n\n        for _ in 0..<80 {\n            XCTAssertNoThrow(try self.channel.writeInbound(buffer))\n            XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: HTTPServerRequestPart.self)))\n        }\n\n        let lastByte = buffer.readSlice(length: 1)!\n        XCTAssertThrowsError(try self.channel.writeInbound(lastByte)) { error in\n            XCTAssertEqual(error as? HTTPParserError, .headerOverflow)\n        }\n\n        // We know we'll see an error, we can safely drop it.\n        _ = try? self.channel.finish()\n    }\n\n    func testDecodingRTSPQueries() {\n        let queries = [\n            \"DESCRIBE\", \"ANNOUNCE\", \"SETUP\", \"PLAY\", \"PAUSE\",\n            \"TEARDOWN\", \"GET_PARAMETER\", \"SET_PARAMETER\", \"REDIRECT\",\n            \"RECORD\", \"FLUSH\",\n        ]\n\n        for query in queries {\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            defer {\n                _ = try? channel.finish()\n            }\n\n            let bytes = ByteBuffer(string: \"\\(query) / RTSP/1.1\\r\\nHost: example.com\\r\\nContent-Length: 0\\r\\n\\r\\n\")\n            XCTAssertNoThrow(try channel.writeInbound(bytes), \"Error writing \\(query)\")\n\n            var maybeHead: HTTPServerRequestPart? = nil\n            var maybeEnd: HTTPServerRequestPart? = nil\n\n            XCTAssertNoThrow(maybeHead = try channel.readInbound())\n            XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n\n            guard case .some(.head(let head)) = maybeHead, case .some(.end(nil)) = maybeEnd else {\n                XCTFail(\"Did not receive correct bytes for \\(query)\")\n                continue\n            }\n\n            XCTAssertEqual(head.method, .RAW(value: query))\n        }\n    }\n\n    func testDecodingInvalidHeaderFieldNames() throws {\n        // The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n        // characters as the following:\n        //\n        // ```\n        // field-name     = token\n        //\n        // token          = 1*tchar\n        //\n        // tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        //                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        //                / DIGIT / ALPHA\n        //                ; any VCHAR, except delimiters\n        let weirdAllowedFieldName = \"!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n        let goodRequest = ByteBuffer(\n            string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\(weirdAllowedFieldName): present\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try self.channel.writeInbound(goodRequest))\n\n        var maybeHead: HTTPServerRequestPart?\n        var maybeEnd: HTTPServerRequestPart?\n\n        XCTAssertNoThrow(maybeHead = try self.channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try self.channel.readInbound())\n        guard case .some(.head(let head)) = maybeHead, case .some(.end) = maybeEnd else {\n            XCTFail(\"didn't receive head & end\")\n            return\n        }\n        XCTAssertEqual(head.headers[weirdAllowedFieldName], [\"present\"])\n\n        // Now confirm all other bytes are rejected.\n        for byte in UInt8(0)...UInt8(255) {\n            // Skip bytes that we already believe are allowed, or that will affect the parse.\n            if weirdAllowedFieldName.utf8.contains(byte) || byte == UInt8(ascii: \":\") {\n                continue\n            }\n            let forbiddenFieldName = weirdAllowedFieldName + String(decoding: [byte], as: UTF8.self)\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            let badRequest = ByteBuffer(\n                string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\(forbiddenFieldName): present\\r\\n\\r\\n\"\n            )\n\n            XCTAssertThrowsError(\n                try channel.writeInbound(badRequest),\n                \"Incorrectly tolerated character in header field name: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n    }\n\n    func testDecodingInvalidTrailerFieldNames() throws {\n        // The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n        // characters as the following:\n        //\n        // ```\n        // field-name     = token\n        //\n        // token          = 1*tchar\n        //\n        // tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        //                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        //                / DIGIT / ALPHA\n        //                ; any VCHAR, except delimiters\n        let weirdAllowedFieldName = \"!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\n        let request = ByteBuffer(\n            string: \"POST / HTTP/1.1\\r\\nHost: example.com\\r\\nTransfer-Encoding: chunked\\r\\n\\r\\n0\\r\\n\"\n        )\n\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n        let goodTrailers = ByteBuffer(string: \"\\(weirdAllowedFieldName): present\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(request))\n        XCTAssertNoThrow(try self.channel.writeInbound(goodTrailers))\n\n        var maybeHead: HTTPServerRequestPart?\n        var maybeEnd: HTTPServerRequestPart?\n\n        XCTAssertNoThrow(maybeHead = try self.channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try self.channel.readInbound())\n        guard case .some(.head) = maybeHead, case .some(.end(.some(let trailers))) = maybeEnd else {\n            XCTFail(\"didn't receive head & end\")\n            return\n        }\n        XCTAssertEqual(trailers[weirdAllowedFieldName], [\"present\"])\n\n        // Now confirm all other bytes are rejected.\n        for byte in UInt8(0)...UInt8(255) {\n            // Skip bytes that we already believe are allowed, or that will affect the parse.\n            if weirdAllowedFieldName.utf8.contains(byte) || byte == UInt8(ascii: \":\") {\n                continue\n            }\n            let forbiddenFieldName = weirdAllowedFieldName + String(decoding: [byte], as: UTF8.self)\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            let badTrailers = ByteBuffer(string: \"\\(forbiddenFieldName): present\\r\\n\\r\\n\")\n\n            XCTAssertNoThrow(try channel.writeInbound(request))\n\n            XCTAssertThrowsError(\n                try channel.writeInbound(badTrailers),\n                \"Incorrectly tolerated character in trailer field name: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n    }\n\n    func testDecodingInvalidHeaderFieldValues() throws {\n        // We reject all ASCII control characters except HTAB and tolerate everything else.\n        let weirdAllowedFieldValue =\n            \"!\\\" \\t#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n        let goodRequest = ByteBuffer(\n            string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\nWeird-Field: \\(weirdAllowedFieldValue)\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try self.channel.writeInbound(goodRequest))\n\n        var maybeHead: HTTPServerRequestPart?\n        var maybeEnd: HTTPServerRequestPart?\n\n        XCTAssertNoThrow(maybeHead = try self.channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try self.channel.readInbound())\n        guard case .some(.head(let head)) = maybeHead, case .some(.end) = maybeEnd else {\n            XCTFail(\"didn't receive head & end\")\n            return\n        }\n        XCTAssertEqual(head.headers[\"Weird-Field\"], [weirdAllowedFieldValue])\n\n        // Now confirm all other bytes in the ASCII range are rejected.\n        for byte in UInt8(0)..<UInt8(128) {\n            // Skip bytes that we already believe are allowed, or that will affect the parse.\n            if weirdAllowedFieldValue.utf8.contains(byte) || byte == UInt8(ascii: \"\\r\") || byte == UInt8(ascii: \"\\n\") {\n                continue\n            }\n            let forbiddenFieldValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            let badRequest = ByteBuffer(\n                string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\nWeird-Field: \\(forbiddenFieldValue)\\r\\n\\r\\n\"\n            )\n\n            XCTAssertThrowsError(\n                try channel.writeInbound(badRequest),\n                \"Incorrectly tolerated character in header field value: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n\n        // All the bytes outside the ASCII range are fine though.\n        for byte in UInt8(128)...UInt8(255) {\n            let evenWeirderAllowedValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            let weirdGoodRequest = ByteBuffer(\n                string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\nWeird-Field: \\(evenWeirderAllowedValue)\\r\\n\\r\\n\"\n            )\n\n            XCTAssertNoThrow(try channel.writeInbound(weirdGoodRequest))\n            XCTAssertNoThrow(maybeHead = try channel.readInbound())\n            XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n            guard case .some(.head(let head)) = maybeHead, case .some(.end) = maybeEnd else {\n                XCTFail(\"didn't receive head & end for \\(byte)\")\n                return\n            }\n            XCTAssertEqual(head.headers[\"Weird-Field\"], [evenWeirderAllowedValue])\n\n            _ = try? channel.finish()\n        }\n    }\n\n    func testDecodingInvalidTrailerFieldValues() throws {\n        // We reject all ASCII control characters except HTAB and tolerate everything else.\n        let weirdAllowedFieldValue =\n            \"!\\\" \\t#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n\n        let request = ByteBuffer(\n            string: \"POST / HTTP/1.1\\r\\nHost: example.com\\r\\nTransfer-Encoding: chunked\\r\\n\\r\\n0\\r\\n\"\n        )\n\n        XCTAssertNoThrow(\n            try self.channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n        )\n        let goodTrailers = ByteBuffer(string: \"Weird-Field: \\(weirdAllowedFieldValue)\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(request))\n        XCTAssertNoThrow(try self.channel.writeInbound(goodTrailers))\n\n        var maybeHead: HTTPServerRequestPart?\n        var maybeEnd: HTTPServerRequestPart?\n\n        XCTAssertNoThrow(maybeHead = try self.channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try self.channel.readInbound())\n        guard case .some(.head) = maybeHead, case .some(.end(.some(let trailers))) = maybeEnd else {\n            XCTFail(\"didn't receive head & end\")\n            return\n        }\n        XCTAssertEqual(trailers[\"Weird-Field\"], [weirdAllowedFieldValue])\n\n        // Now confirm all other bytes in the ASCII range are rejected.\n        for byte in UInt8(0)..<UInt8(128) {\n            // Skip bytes that we already believe are allowed, or that will affect the parse.\n            if weirdAllowedFieldValue.utf8.contains(byte) || byte == UInt8(ascii: \"\\r\") || byte == UInt8(ascii: \"\\n\") {\n                continue\n            }\n            let forbiddenFieldValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            let badTrailers = ByteBuffer(string: \"Weird-Field: \\(forbiddenFieldValue)\\r\\n\\r\\n\")\n\n            XCTAssertNoThrow(try channel.writeInbound(request))\n\n            XCTAssertThrowsError(\n                try channel.writeInbound(badTrailers),\n                \"Incorrectly tolerated character in trailer field value: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n\n        // All the bytes outside the ASCII range are fine though.\n        for byte in UInt8(128)...UInt8(255) {\n            let evenWeirderAllowedValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n            let channel = EmbeddedChannel(handler: ByteToMessageHandler(HTTPRequestDecoder()))\n            let weirdGoodTrailers = ByteBuffer(string: \"Weird-Field: \\(evenWeirderAllowedValue)\\r\\n\\r\\n\")\n\n            XCTAssertNoThrow(try channel.writeInbound(request))\n            XCTAssertNoThrow(try channel.writeInbound(weirdGoodTrailers))\n            XCTAssertNoThrow(maybeHead = try channel.readInbound())\n            XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n            guard case .some(.head) = maybeHead, case .some(.end(.some(let trailers))) = maybeEnd else {\n                XCTFail(\"didn't receive head & end for \\(byte)\")\n                return\n            }\n            XCTAssertEqual(trailers[\"Weird-Field\"], [evenWeirderAllowedValue])\n\n            _ = try? channel.finish()\n        }\n    }\n\n    func testDecodeAfterHEADResponse() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n        defer {\n            _ = try? channel.finish()\n        }\n\n        let headRequest = HTTPRequestHead(version: .http1_1, method: .HEAD, uri: \"/\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(headRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        // Send a response.\n        let goodResponse = ByteBuffer(string: \"HTTP/1.1 200 OK\\r\\nServer: foo\\r\\nContent-Length: 4\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(goodResponse))\n\n        var maybeParsedHead: HTTPClientResponsePart?\n        var maybeEnd: HTTPClientResponsePart?\n\n        XCTAssertNoThrow(maybeParsedHead = try channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n        guard case .some(.head(let head)) = maybeParsedHead else {\n            XCTFail(\"Expected head, got \\(String(describing: maybeParsedHead))\")\n            return\n        }\n        guard case .some(.end(nil)) = maybeEnd else {\n            XCTFail(\"Expected end, got \\(String(describing: maybeEnd))\")\n            return\n        }\n        XCTAssertEqual(head.status, .ok)\n\n        // Send a GET request\n        let secondHeadRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(secondHeadRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        // Send a response.\n        let goodResponseWithContent = ByteBuffer(\n            string: \"HTTP/1.1 200 OK\\r\\nServer: foo\\r\\nContent-Length: 4\\r\\n\\r\\nGood\"\n        )\n        XCTAssertNoThrow(try channel.writeInbound(goodResponseWithContent))\n\n        var maybeBody: HTTPClientResponsePart?\n\n        XCTAssertNoThrow(maybeParsedHead = try channel.readInbound())\n        XCTAssertNoThrow(maybeBody = try channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n        guard case .some(.head(let secondHead)) = maybeParsedHead else {\n            XCTFail(\"Expected head, got \\(String(describing: maybeParsedHead))\")\n            return\n        }\n        guard case .some(.body(let body)) = maybeBody else {\n            XCTFail(\"Expected body, got \\(String(describing: maybeBody))\")\n            return\n        }\n        guard case .some(.end(nil)) = maybeEnd else {\n            XCTFail(\"Expected end, got \\(String(describing: maybeEnd))\")\n            return\n        }\n        XCTAssertEqual(secondHead.status, .ok)\n        XCTAssertEqual(body, ByteBuffer(string: \"Good\"))\n\n        // Should not throw.\n        channel.pipeline.fireChannelActive()\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n    }\n\n    func testDecodeAfterHEADResponseChunked() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n        defer {\n            _ = try? channel.finish()\n        }\n\n        let headRequest = HTTPRequestHead(version: .http1_1, method: .HEAD, uri: \"/\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(headRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        // Send a response.\n        let goodResponse = ByteBuffer(string: \"HTTP/1.1 200 OK\\r\\nServer: foo\\r\\nTransfer-Encoding: chunked\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(goodResponse))\n\n        var maybeParsedHead: HTTPClientResponsePart?\n        var maybeEnd: HTTPClientResponsePart?\n\n        XCTAssertNoThrow(maybeParsedHead = try channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n        guard case .some(.head(let head)) = maybeParsedHead else {\n            XCTFail(\"Expected head, got \\(String(describing: maybeParsedHead))\")\n            return\n        }\n        guard case .some(.end(nil)) = maybeEnd else {\n            XCTFail(\"Expected end, got \\(String(describing: maybeEnd))\")\n            return\n        }\n        XCTAssertEqual(head.status, .ok)\n\n        // Send a GET request\n        let secondHeadRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(secondHeadRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        // Send a response.\n        let goodResponseWithContent = ByteBuffer(\n            string: \"HTTP/1.1 200 OK\\r\\nServer: foo\\r\\nContent-Length: 4\\r\\n\\r\\nGood\"\n        )\n        XCTAssertNoThrow(try channel.writeInbound(goodResponseWithContent))\n\n        var maybeBody: HTTPClientResponsePart?\n\n        XCTAssertNoThrow(maybeParsedHead = try channel.readInbound())\n        XCTAssertNoThrow(maybeBody = try channel.readInbound())\n        XCTAssertNoThrow(maybeEnd = try channel.readInbound())\n        guard case .some(.head(let secondHead)) = maybeParsedHead else {\n            XCTFail(\"Expected head, got \\(String(describing: maybeParsedHead))\")\n            return\n        }\n        guard case .some(.body(let body)) = maybeBody else {\n            XCTFail(\"Expected body, got \\(String(describing: maybeBody))\")\n            return\n        }\n        guard case .some(.end(nil)) = maybeEnd else {\n            XCTFail(\"Expected end, got \\(String(describing: maybeEnd))\")\n            return\n        }\n        XCTAssertEqual(secondHead.status, .ok)\n        XCTAssertEqual(body, ByteBuffer(string: \"Good\"))\n\n        // Should not throw.\n        channel.pipeline.fireChannelActive()\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPHeaderValidationTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport NIOEmbedded\nimport NIOHTTP1\nimport XCTest\n\nfinal class HTTPHeaderValidationTests: XCTestCase {\n    func testEncodingInvalidHeaderFieldNamesInRequests() throws {\n        // The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n        // characters as the following:\n        //\n        // ```\n        // field-name     = token\n        //\n        // token          = 1*tchar\n        //\n        // tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        //                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        //                / DIGIT / ALPHA\n        //                ; any VCHAR, except delimiters\n        let weirdAllowedFieldName = \"!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n        let headers = HTTPHeaders([(\"Host\", \"example.com\"), (weirdAllowedFieldName, \"present\")])\n        let goodRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\", headers: headers)\n        let goodRequestBytes = ByteBuffer(\n            string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\(weirdAllowedFieldName): present\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        var maybeReceivedBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeReceivedBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeReceivedBytes, goodRequestBytes)\n\n        // Now confirm all other bytes are rejected.\n        for byte in UInt8(0)...UInt8(255) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldName.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldName = weirdAllowedFieldName + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n            let headers = HTTPHeaders([(\"Host\", \"example.com\"), (forbiddenFieldName, \"present\")])\n            let badRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\", headers: headers)\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPClientRequestPart.head(badRequest)),\n                \"Incorrectly tolerated character in header field name: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidTrailerFieldNamesInRequests() throws {\n        // The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n        // characters as the following:\n        //\n        // ```\n        // field-name     = token\n        //\n        // token          = 1*tchar\n        //\n        // tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        //                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        //                / DIGIT / ALPHA\n        //                ; any VCHAR, except delimiters\n        let weirdAllowedFieldName = \"!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n        let headers = HTTPHeaders([(\"Host\", \"example.com\"), (\"Transfer-Encoding\", \"chunked\")])\n        let goodRequest = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/\", headers: headers)\n        let goodRequestBytes = ByteBuffer(\n            string: \"POST / HTTP/1.1\\r\\nHost: example.com\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\"\n        )\n        let goodTrailers = ByteBuffer(string: \"0\\r\\n\\(weirdAllowedFieldName): present\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end([weirdAllowedFieldName: \"present\"])))\n\n        var maybeRequestHeadBytes: ByteBuffer?\n        var maybeRequestEndBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeRequestHeadBytes = try channel.readOutbound())\n        XCTAssertNoThrow(maybeRequestEndBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeRequestHeadBytes, goodRequestBytes)\n        XCTAssertEqual(maybeRequestEndBytes, goodTrailers)\n\n        // Now confirm all other bytes are rejected.\n        for byte in UInt8(0)...UInt8(255) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldName.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldName = weirdAllowedFieldName + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPClientRequestPart.end([forbiddenFieldName: \"present\"])),\n                \"Incorrectly tolerated character in trailer field name: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidHeaderFieldValuesInRequests() throws {\n        // We reject all ASCII control characters except HTAB and tolerate everything else.\n        let weirdAllowedFieldValue =\n            \"!\\\" \\t#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n        let headers = HTTPHeaders([(\"Host\", \"example.com\"), (\"Weird-Value\", weirdAllowedFieldValue)])\n        let goodRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\", headers: headers)\n        let goodRequestBytes = ByteBuffer(\n            string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\nWeird-Value: \\(weirdAllowedFieldValue)\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n\n        var maybeBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeBytes, goodRequestBytes)\n\n        // Now confirm all other bytes in the ASCII range are rejected.\n        for byte in UInt8(0)..<UInt8(128) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldValue.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n            let headers = HTTPHeaders([(\"Host\", \"example.com\"), (\"Weird-Value\", forbiddenFieldValue)])\n            let badRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\", headers: headers)\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPClientRequestPart.head(badRequest)),\n                \"Incorrectly tolerated character in header field value: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n\n        // All the bytes outside the ASCII range are fine though.\n        for byte in UInt8(128)...UInt8(255) {\n            let evenWeirderAllowedValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n            let headers = HTTPHeaders([(\"Host\", \"example.com\"), (\"Weird-Value\", evenWeirderAllowedValue)])\n            let goodRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\", headers: headers)\n            let goodRequestBytes = ByteBuffer(\n                string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\nWeird-Value: \\(evenWeirderAllowedValue)\\r\\n\\r\\n\"\n            )\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n\n            var maybeBytes: ByteBuffer?\n\n            XCTAssertNoThrow(maybeBytes = try channel.readOutbound())\n            XCTAssertEqual(maybeBytes, goodRequestBytes)\n\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidTrailerFieldValuesInRequests() throws {\n        // We reject all ASCII control characters except HTAB and tolerate everything else.\n        let weirdAllowedFieldValue =\n            \"!\\\" \\t#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n        let headers = HTTPHeaders([(\"Host\", \"example.com\"), (\"Transfer-Encoding\", \"chunked\")])\n        let goodRequest = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/\", headers: headers)\n        let goodRequestBytes = ByteBuffer(\n            string: \"POST / HTTP/1.1\\r\\nHost: example.com\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\"\n        )\n        let goodTrailers = ByteBuffer(string: \"0\\r\\nWeird-Value: \\(weirdAllowedFieldValue)\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end([\"Weird-Value\": weirdAllowedFieldValue])))\n\n        var maybeRequestHeadBytes: ByteBuffer?\n        var maybeRequestEndBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeRequestHeadBytes = try channel.readOutbound())\n        XCTAssertNoThrow(maybeRequestEndBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeRequestHeadBytes, goodRequestBytes)\n        XCTAssertEqual(maybeRequestEndBytes, goodTrailers)\n\n        // Now confirm all other bytes in the ASCII range are rejected.\n        for byte in UInt8(0)..<UInt8(128) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldValue.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPClientRequestPart.end([\"Weird-Value\": forbiddenFieldValue])),\n                \"Incorrectly tolerated character in trailer field value: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n\n        // All the bytes outside the ASCII range are fine though.\n        for byte in UInt8(128)...UInt8(255) {\n            let evenWeirderAllowedValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.addHTTPClientHandlers()\n\n            let weirdGoodTrailers = ByteBuffer(string: \"0\\r\\nWeird-Value: \\(evenWeirderAllowedValue)\\r\\n\\r\\n\")\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(goodRequest)))\n            XCTAssertNoThrow(\n                try channel.writeOutbound(HTTPClientRequestPart.end([\"Weird-Value\": evenWeirderAllowedValue]))\n            )\n            XCTAssertNoThrow(maybeRequestHeadBytes = try channel.readOutbound())\n            XCTAssertNoThrow(maybeRequestEndBytes = try channel.readOutbound())\n            XCTAssertEqual(maybeRequestHeadBytes, goodRequestBytes)\n            XCTAssertEqual(maybeRequestEndBytes, weirdGoodTrailers)\n\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidHeaderFieldNamesInResponses() throws {\n        // The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n        // characters as the following:\n        //\n        // ```\n        // field-name     = token\n        //\n        // token          = 1*tchar\n        //\n        // tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        //                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        //                / DIGIT / ALPHA\n        //                ; any VCHAR, except delimiters\n        let weirdAllowedFieldName = \"!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n        try channel.primeForResponse()\n\n        let headers = HTTPHeaders([(\"Content-Length\", \"0\"), (weirdAllowedFieldName, \"present\")])\n        let goodResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n        let goodResponseBytes = ByteBuffer(\n            string: \"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\n\\(weirdAllowedFieldName): present\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        var maybeReceivedBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeReceivedBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeReceivedBytes, goodResponseBytes)\n\n        // Now confirm all other bytes are rejected.\n        for byte in UInt8(0)...UInt8(255) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldName.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldName = weirdAllowedFieldName + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n            try channel.primeForResponse()\n\n            let headers = HTTPHeaders([(\"Content-Length\", \"0\"), (forbiddenFieldName, \"present\")])\n            let badResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPServerResponsePart.head(badResponse)),\n                \"Incorrectly tolerated character in header field name: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidTrailerFieldNamesInResponses() throws {\n        // The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#fields.values) defines the valid\n        // characters as the following:\n        //\n        // ```\n        // field-name     = token\n        //\n        // token          = 1*tchar\n        //\n        // tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        //                / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        //                / DIGIT / ALPHA\n        //                ; any VCHAR, except delimiters\n        let weirdAllowedFieldName = \"!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n        try channel.primeForResponse()\n\n        let headers = HTTPHeaders([(\"Transfer-Encoding\", \"chunked\")])\n        let goodResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n        let goodResponseBytes = ByteBuffer(string: \"HTTP/1.1 200 OK\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n        let goodTrailers = ByteBuffer(string: \"0\\r\\n\\(weirdAllowedFieldName): present\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end([weirdAllowedFieldName: \"present\"])))\n\n        var maybeRequestHeadBytes: ByteBuffer?\n        var maybeRequestEndBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeRequestHeadBytes = try channel.readOutbound())\n        XCTAssertNoThrow(maybeRequestEndBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeRequestHeadBytes, goodResponseBytes)\n        XCTAssertEqual(maybeRequestEndBytes, goodTrailers)\n\n        // Now confirm all other bytes are rejected.\n        for byte in UInt8(0)...UInt8(255) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldName.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldName = weirdAllowedFieldName + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n            try channel.primeForResponse()\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPServerResponsePart.end([forbiddenFieldName: \"present\"])),\n                \"Incorrectly tolerated character in trailer field name: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidHeaderFieldValuesInResponses() throws {\n        // We reject all ASCII control characters except HTAB and tolerate everything else.\n        let weirdAllowedFieldValue =\n            \"!\\\" \\t#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n        try channel.primeForResponse()\n\n        let headers = HTTPHeaders([(\"Content-Length\", \"0\"), (\"Weird-Value\", weirdAllowedFieldValue)])\n        let goodResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n        let goodResponseBytes = ByteBuffer(\n            string: \"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\nWeird-Value: \\(weirdAllowedFieldValue)\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n\n        var maybeBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeBytes, goodResponseBytes)\n\n        // Now confirm all other bytes in the ASCII range are rejected.\n        for byte in UInt8(0)..<UInt8(128) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldValue.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n            try channel.primeForResponse()\n\n            let headers = HTTPHeaders([(\"Content-Length\", \"0\"), (\"Weird-Value\", forbiddenFieldValue)])\n            let badResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPServerResponsePart.head(badResponse)),\n                \"Incorrectly tolerated character in header field value: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n\n        // All the bytes outside the ASCII range are fine though.\n        for byte in UInt8(128)...UInt8(255) {\n            let evenWeirderAllowedValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n            try channel.primeForResponse()\n\n            let headers = HTTPHeaders([(\"Content-Length\", \"0\"), (\"Weird-Value\", evenWeirderAllowedValue)])\n            let goodResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n            let goodResponseBytes = ByteBuffer(\n                string: \"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\nWeird-Value: \\(evenWeirderAllowedValue)\\r\\n\\r\\n\"\n            )\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n\n            var maybeBytes: ByteBuffer?\n\n            XCTAssertNoThrow(maybeBytes = try channel.readOutbound())\n            XCTAssertEqual(maybeBytes, goodResponseBytes)\n\n            _ = try? channel.finish()\n        }\n    }\n\n    func testEncodingInvalidTrailerFieldValuesInResponses() throws {\n        // We reject all ASCII control characters except HTAB and tolerate everything else.\n        let weirdAllowedFieldValue =\n            \"!\\\" \\t#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n        try channel.primeForResponse()\n\n        let headers = HTTPHeaders([(\"Transfer-Encoding\", \"chunked\")])\n        let goodResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n        let goodResponseBytes = ByteBuffer(string: \"HTTP/1.1 200 OK\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n        let goodTrailers = ByteBuffer(string: \"0\\r\\nWeird-Value: \\(weirdAllowedFieldValue)\\r\\n\\r\\n\")\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end([\"Weird-Value\": weirdAllowedFieldValue])))\n\n        var maybeResponseHeadBytes: ByteBuffer?\n        var maybeResponseEndBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeResponseHeadBytes = try channel.readOutbound())\n        XCTAssertNoThrow(maybeResponseEndBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeResponseHeadBytes, goodResponseBytes)\n        XCTAssertEqual(maybeResponseEndBytes, goodTrailers)\n\n        // Now confirm all other bytes in the ASCII range are rejected.\n        for byte in UInt8(0)..<UInt8(128) {\n            // Skip bytes that we already believe are allowed.\n            if weirdAllowedFieldValue.utf8.contains(byte) {\n                continue\n            }\n            let forbiddenFieldValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n            try channel.primeForResponse()\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n\n            XCTAssertThrowsError(\n                try channel.writeOutbound(HTTPServerResponsePart.end([\"Weird-Value\": forbiddenFieldValue])),\n                \"Incorrectly tolerated character in trailer field value: \\(String(decoding: [byte], as: UTF8.self))\"\n            ) { error in\n                XCTAssertEqual(error as? HTTPParserError, .invalidHeaderToken)\n            }\n            _ = try? channel.finish()\n        }\n\n        // All the bytes outside the ASCII range are fine though.\n        for byte in UInt8(128)...UInt8(255) {\n            let evenWeirderAllowedValue = weirdAllowedFieldValue + String(decoding: [byte], as: UTF8.self)\n\n            let channel = EmbeddedChannel()\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n            try channel.primeForResponse()\n\n            let weirdGoodTrailers = ByteBuffer(string: \"0\\r\\nWeird-Value: \\(evenWeirderAllowedValue)\\r\\n\\r\\n\")\n\n            XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(goodResponse)))\n            XCTAssertNoThrow(\n                try channel.writeOutbound(HTTPServerResponsePart.end([\"Weird-Value\": evenWeirderAllowedValue]))\n            )\n            XCTAssertNoThrow(maybeResponseHeadBytes = try channel.readOutbound())\n            XCTAssertNoThrow(maybeResponseEndBytes = try channel.readOutbound())\n            XCTAssertEqual(maybeResponseHeadBytes, goodResponseBytes)\n            XCTAssertEqual(maybeResponseEndBytes, weirdGoodTrailers)\n\n            _ = try? channel.finish()\n        }\n    }\n\n    func testResponseIsDroppedIfHeadersInvalid() throws {\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: false)\n        try channel.primeForResponse()\n\n        func assertReadHead(from channel: EmbeddedChannel) throws {\n            if case .head = try channel.readInbound(as: HTTPServerRequestPart.self) {\n                ()\n            } else {\n                XCTFail(\"Expected 'head'\")\n            }\n        }\n\n        func assertReadEnd(from channel: EmbeddedChannel) throws {\n            if case .end = try channel.readInbound(as: HTTPServerRequestPart.self) {\n                ()\n            } else {\n                XCTFail(\"Expected 'end'\")\n            }\n        }\n\n        // Read the first request.\n        try assertReadHead(from: channel)\n        try assertReadEnd(from: channel)\n        XCTAssertNil(try channel.readInbound(as: HTTPServerRequestPart.self))\n\n        // Respond with bad headers; they should cause an error and result in the rest of the\n        // response being dropped.\n        let head = HTTPResponseHead(version: .http1_1, status: .ok, headers: [\":pseudo-header\": \"not-here\"])\n        XCTAssertThrowsError(try channel.writeOutbound(HTTPServerResponsePart.head(head)))\n        XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertThrowsError(try channel.writeOutbound(HTTPServerResponsePart.body(.byteBuffer(ByteBuffer()))))\n        XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertThrowsError(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n        XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self))\n    }\n\n    func testDisablingValidationClientSide() throws {\n        let invalidHeaderName = \"HeaderNameWith\\\"Quote\"\n        let invalidHeaderValue = \"HeaderValueWith\\rCR\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHTTPClientHandlers(enableOutboundHeaderValidation: false)\n\n        let headers = HTTPHeaders([\n            (\"Host\", \"example.com\"), (\"Transfer-Encoding\", \"chunked\"), (invalidHeaderName, invalidHeaderValue),\n        ])\n        let toleratedRequest = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/\", headers: headers)\n        let toleratedRequestBytes = ByteBuffer(\n            string:\n                \"POST / HTTP/1.1\\r\\nHost: example.com\\r\\n\\(invalidHeaderName): \\(invalidHeaderValue)\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\"\n        )\n        let toleratedTrailerBytes = ByteBuffer(\n            string:\n                \"0\\r\\nHost: example.com\\r\\nTransfer-Encoding: chunked\\r\\n\\(invalidHeaderName): \\(invalidHeaderValue)\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(toleratedRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(headers)))\n\n        var maybeReceivedHeadBytes: ByteBuffer?\n        var maybeReceivedTrailerBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeReceivedHeadBytes = try channel.readOutbound())\n        XCTAssertNoThrow(maybeReceivedTrailerBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeReceivedHeadBytes, toleratedRequestBytes)\n        XCTAssertEqual(maybeReceivedTrailerBytes, toleratedTrailerBytes)\n    }\n\n    func testDisablingValidationServerSide() throws {\n        let invalidHeaderName = \"HeaderNameWith\\\"Quote\"\n        let invalidHeaderValue = \"HeaderValueWith\\rCR\"\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.configureHTTPServerPipeline(\n            withErrorHandling: false,\n            withOutboundHeaderValidation: false\n        )\n        try channel.primeForResponse()\n\n        let headers = HTTPHeaders([\n            (\"Host\", \"example.com\"), (\"Transfer-Encoding\", \"chunked\"), (invalidHeaderName, invalidHeaderValue),\n        ])\n        let toleratedRequest = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n        let toleratedRequestBytes = ByteBuffer(\n            string:\n                \"HTTP/1.1 200 OK\\r\\nHost: example.com\\r\\n\\(invalidHeaderName): \\(invalidHeaderValue)\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\"\n        )\n        let toleratedTrailerBytes = ByteBuffer(\n            string:\n                \"0\\r\\nHost: example.com\\r\\nTransfer-Encoding: chunked\\r\\n\\(invalidHeaderName): \\(invalidHeaderValue)\\r\\n\\r\\n\"\n        )\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(toleratedRequest)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(headers)))\n\n        var maybeReceivedHeadBytes: ByteBuffer?\n        var maybeReceivedTrailerBytes: ByteBuffer?\n\n        XCTAssertNoThrow(maybeReceivedHeadBytes = try channel.readOutbound())\n        XCTAssertNoThrow(maybeReceivedTrailerBytes = try channel.readOutbound())\n        XCTAssertEqual(maybeReceivedHeadBytes, toleratedRequestBytes)\n        XCTAssertEqual(maybeReceivedTrailerBytes, toleratedTrailerBytes)\n    }\n}\n\nextension EmbeddedChannel {\n    fileprivate func primeForResponse() throws {\n        let request = ByteBuffer(string: \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n\")\n        try self.writeInbound(request)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPHeadersTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOHTTP1\n\nclass HTTPHeadersTest: XCTestCase {\n    func testCasePreservedButInsensitiveLookup() {\n        let originalHeaders = [\n            (\"User-Agent\", \"1\"),\n            (\"host\", \"2\"),\n            (\"X-SOMETHING\", \"3\"),\n            (\"SET-COOKIE\", \"foo=bar\"),\n            (\"Set-Cookie\", \"buz=cux\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n\n        // looking up headers value is case-insensitive\n        XCTAssertEqual([\"1\"], headers[\"User-Agent\"])\n        XCTAssertEqual([\"1\"], headers[\"User-agent\"])\n        XCTAssertEqual([\"2\"], headers[\"Host\"])\n        XCTAssertEqual([\"foo=bar\", \"buz=cux\"], headers[\"set-cookie\"])\n\n        for (key, value) in headers {\n            switch key {\n            case \"User-Agent\":\n                XCTAssertEqual(\"1\", value)\n            case \"host\":\n                XCTAssertEqual(\"2\", value)\n            case \"X-SOMETHING\":\n                XCTAssertEqual(\"3\", value)\n            case \"SET-COOKIE\":\n                XCTAssertEqual(\"foo=bar\", value)\n            case \"Set-Cookie\":\n                XCTAssertEqual(\"buz=cux\", value)\n            default:\n                XCTFail(\"Unexpected key: \\(key)\")\n            }\n        }\n    }\n\n    func testDictionaryLiteralAlternative() {\n        let headers: HTTPHeaders = [\n            \"User-Agent\": \"1\",\n            \"host\": \"2\",\n            \"X-SOMETHING\": \"3\",\n            \"SET-COOKIE\": \"foo=bar\",\n            \"Set-Cookie\": \"buz=cux\",\n        ]\n\n        // looking up headers value is case-insensitive\n        XCTAssertEqual([\"1\"], headers[\"User-Agent\"])\n        XCTAssertEqual([\"1\"], headers[\"User-agent\"])\n        XCTAssertEqual([\"2\"], headers[\"Host\"])\n        XCTAssertEqual([\"foo=bar\", \"buz=cux\"], headers[\"set-cookie\"])\n\n        for (key, value) in headers {\n            switch key {\n            case \"User-Agent\":\n                XCTAssertEqual(\"1\", value)\n            case \"host\":\n                XCTAssertEqual(\"2\", value)\n            case \"X-SOMETHING\":\n                XCTAssertEqual(\"3\", value)\n            case \"SET-COOKIE\":\n                XCTAssertEqual(\"foo=bar\", value)\n            case \"Set-Cookie\":\n                XCTAssertEqual(\"buz=cux\", value)\n            default:\n                XCTFail(\"Unexpected key: \\(key)\")\n            }\n        }\n    }\n\n    func testWriteHeadersSeparately() {\n        let originalHeaders = [\n            (\"User-Agent\", \"1\"),\n            (\"host\", \"2\"),\n            (\"X-SOMETHING\", \"3\"),\n            (\"X-Something\", \"4\"),\n            (\"SET-COOKIE\", \"foo=bar\"),\n            (\"Set-Cookie\", \"buz=cux\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n        let channel = EmbeddedChannel()\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.write(headers: headers)\n\n        let writtenBytes = buffer.getString(at: buffer.readerIndex, length: buffer.readableBytes)!\n        XCTAssertTrue(writtenBytes.contains(\"User-Agent: 1\\r\\n\"))\n        XCTAssertTrue(writtenBytes.contains(\"host: 2\\r\\n\"))\n        XCTAssertTrue(writtenBytes.contains(\"X-SOMETHING: 3\\r\\n\"))\n        XCTAssertTrue(writtenBytes.contains(\"X-Something: 4\\r\\n\"))\n        XCTAssertTrue(writtenBytes.contains(\"SET-COOKIE: foo=bar\\r\\n\"))\n        XCTAssertTrue(writtenBytes.contains(\"Set-Cookie: buz=cux\\r\\n\"))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRevealHeadersSeparately() {\n        let originalHeaders = [\n            (\"User-Agent\", \"1\"),\n            (\"host\", \"2\"),\n            (\"X-SOMETHING\", \"3, 4\"),\n            (\"X-Something\", \"5\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n        XCTAssertEqual(headers[canonicalForm: \"user-agent\"], [\"1\"])\n        XCTAssertEqual(headers[canonicalForm: \"host\"], [\"2\"])\n        XCTAssertEqual(headers[canonicalForm: \"x-something\"], [\"3\", \"4\", \"5\"])\n        XCTAssertEqual(headers[canonicalForm: \"foo\"], [])\n    }\n\n    func testSubscriptDoesntSplitHeaders() {\n        let originalHeaders = [\n            (\"User-Agent\", \"1\"),\n            (\"host\", \"2\"),\n            (\"X-SOMETHING\", \"3, 4\"),\n            (\"X-Something\", \"5\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n        XCTAssertEqual(headers[\"user-agent\"], [\"1\"])\n        XCTAssertEqual(headers[\"host\"], [\"2\"])\n        XCTAssertEqual(headers[\"x-something\"], [\"3, 4\", \"5\"])\n        XCTAssertEqual(headers[\"foo\"], [])\n    }\n\n    func testCanonicalisationDoesntHappenForSetCookie() {\n        let originalHeaders = [\n            (\"User-Agent\", \"1\"),\n            (\"host\", \"2\"),\n            (\"Set-Cookie\", \"foo=bar; expires=Sun, 17-Mar-2013 13:49:50 GMT\"),\n            (\"Set-Cookie\", \"buz=cux; expires=Fri, 13 Oct 2017 21:21:41 GMT\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n        XCTAssertEqual(headers[canonicalForm: \"user-agent\"], [\"1\"])\n        XCTAssertEqual(headers[canonicalForm: \"host\"], [\"2\"])\n        XCTAssertEqual(\n            headers[canonicalForm: \"set-cookie\"],\n            [\n                \"foo=bar; expires=Sun, 17-Mar-2013 13:49:50 GMT\",\n                \"buz=cux; expires=Fri, 13 Oct 2017 21:21:41 GMT\",\n            ]\n        )\n    }\n\n    func testTrimWhitespaceWorksOnEmptyString() {\n        let expected = \"\"\n        let actual = String(\"\".trimASCIIWhitespace())\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testTrimWhitespaceWorksOnOnlyWhitespace() {\n        let expected = \"\"\n        for wsString in [\" \", \"\\t\", \"  \\t\\t \\t  \"] {\n            let actual = String(wsString.trimASCIIWhitespace())\n            XCTAssertEqual(expected, actual)\n        }\n    }\n\n    func testTrimWorksWithCharactersInTheMiddleAndWhitespaceAround() {\n        let expected = \"x\"\n        let actual = String(\"         x\\t  \".trimASCIIWhitespace())\n        XCTAssertEqual(expected, actual)\n    }\n\n    func testContains() {\n        let originalHeaders = [\n            (\"X-Header\", \"1\"),\n            (\"X-SomeHeader\", \"3\"),\n            (\"X-Header\", \"2\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n        XCTAssertTrue(headers.contains(name: \"x-header\"))\n        XCTAssertTrue(headers.contains(name: \"X-Header\"))\n        XCTAssertFalse(headers.contains(name: \"X-NonExistingHeader\"))\n    }\n\n    func testFirst() throws {\n        let headers = HTTPHeaders([\n            (\":method\", \"GET\"),\n            (\"foo\", \"bar\"),\n            (\"foo\", \"baz\"),\n            (\"custom-key\", \"value-1,value-2\"),\n        ])\n\n        XCTAssertEqual(headers.first(name: \":method\"), \"GET\")\n        XCTAssertEqual(headers.first(name: \"Foo\"), \"bar\")\n        XCTAssertEqual(headers.first(name: \"custom-key\"), \"value-1,value-2\")\n        XCTAssertNil(headers.first(name: \"not-present\"))\n    }\n\n    func testKeepAliveStateStartsWithClose() {\n        var headers = HTTPHeaders([(\"Connection\", \"close\")])\n\n        XCTAssertEqual(\"close\", headers[\"connection\"].first)\n        XCTAssertFalse(headers.isKeepAlive(version: .http1_1))\n\n        headers.replaceOrAdd(name: \"connection\", value: \"keep-alive\")\n\n        XCTAssertEqual(\"keep-alive\", headers[\"connection\"].first)\n        XCTAssertTrue(headers.isKeepAlive(version: .http1_1))\n\n        headers.remove(name: \"connection\")\n        XCTAssertTrue(headers.isKeepAlive(version: .http1_1))\n        XCTAssertFalse(headers.isKeepAlive(version: .http1_0))\n    }\n\n    func testKeepAliveStateStartsWithKeepAlive() {\n        var headers = HTTPHeaders([(\"Connection\", \"keep-alive\")])\n\n        XCTAssertEqual(\"keep-alive\", headers[\"connection\"].first)\n        XCTAssertTrue(headers.isKeepAlive(version: .http1_1))\n\n        headers.replaceOrAdd(name: \"connection\", value: \"close\")\n\n        XCTAssertEqual(\"close\", headers[\"connection\"].first)\n        XCTAssertFalse(headers.isKeepAlive(version: .http1_1))\n\n        headers.remove(name: \"connection\")\n        XCTAssertTrue(headers.isKeepAlive(version: .http1_1))\n        XCTAssertFalse(headers.isKeepAlive(version: .http1_0))\n    }\n\n    func testKeepAliveStateHasKeepAlive() {\n        let headers = HTTPHeaders([\n            (\"Connection\", \"other, keEP-alive\"),\n            (\"Content-Type\", \"text/html\"),\n            (\"Connection\", \"server, x-options\"),\n        ])\n\n        XCTAssertTrue(headers.isKeepAlive(version: .http1_1))\n    }\n\n    func testKeepAliveStateHasClose() {\n        let headers = HTTPHeaders([\n            (\"Connection\", \"x-options,  other\"),\n            (\"Content-Type\", \"text/html\"),\n            (\"Connection\", \"server,     clOse\"),\n        ])\n\n        XCTAssertFalse(headers.isKeepAlive(version: .http1_1))\n    }\n\n    func testRandomAccess() {\n        let originalHeaders = [\n            (\"X-first\", \"one\"),\n            (\"X-second\", \"two\"),\n        ]\n        let headers = HTTPHeaders(originalHeaders)\n\n        XCTAssertEqual(headers[headers.startIndex].name, originalHeaders.first?.0)\n        XCTAssertEqual(headers[headers.startIndex].value, originalHeaders.first?.1)\n        XCTAssertEqual(headers[headers.index(before: headers.endIndex)].name, originalHeaders.last?.0)\n        XCTAssertEqual(headers[headers.index(before: headers.endIndex)].value, originalHeaders.last?.1)\n\n        let beforeLast = headers[headers.index(before: headers.endIndex)]\n        XCTAssertEqual(beforeLast.name, originalHeaders[originalHeaders.endIndex - 1].0)\n        XCTAssertEqual(beforeLast.value, originalHeaders[originalHeaders.endIndex - 1].1)\n\n        let afterFirst = headers[headers.index(after: headers.startIndex)]\n        XCTAssertEqual(afterFirst.name, originalHeaders[originalHeaders.startIndex + 1].0)\n        XCTAssertEqual(afterFirst.value, originalHeaders[originalHeaders.startIndex + 1].1)\n    }\n\n    func testCanBeSeededWithKeepAliveState() {\n        // we may later on decide that this test doesn't make sense but for now we want to keep the seeding behaviour.\n        let headersSeededWithClose = HTTPHeaders([], keepAliveState: .close)\n        XCTAssertEqual(false, headersSeededWithClose.isKeepAlive(version: .init(major: 0, minor: 0)))\n\n        let headersSeededWithKeepAlive = HTTPHeaders([], keepAliveState: .keepAlive)\n        XCTAssertEqual(true, headersSeededWithKeepAlive.isKeepAlive(version: .init(major: 0, minor: 0)))\n    }\n\n    func testSeedDominatesActualValue() {\n        // we may later on decide that this test doesn't make sense but for now we want to keep the seeding behaviour\n        let headersSeededWithClose = HTTPHeaders([], keepAliveState: .close)\n        XCTAssertEqual(false, headersSeededWithClose.isKeepAlive(version: .http1_1))\n\n        let headersSeededWithKeepAlive = HTTPHeaders([], keepAliveState: .keepAlive)\n        XCTAssertEqual(true, headersSeededWithKeepAlive.isKeepAlive(version: .http1_0))\n    }\n\n    func testSeedDominatesEvenAfterMutation() {\n        // we may later on decide that this test doesn't make sense but for now we want to keep the seeding behaviour\n        var headersSeededWithClose = HTTPHeaders([], keepAliveState: .close)\n        headersSeededWithClose.add(name: \"foo\", value: \"bar\")\n        headersSeededWithClose.add(name: \"bar\", value: \"qux\")\n        headersSeededWithClose.remove(name: \"bar\")\n        XCTAssertEqual(false, headersSeededWithClose.isKeepAlive(version: .http1_1))\n\n        var headersSeededWithKeepAlive = HTTPHeaders([], keepAliveState: .keepAlive)\n        headersSeededWithKeepAlive.add(name: \"foo\", value: \"bar\")\n        headersSeededWithKeepAlive.add(name: \"bar\", value: \"qux\")\n        headersSeededWithKeepAlive.remove(name: \"bar\")\n        XCTAssertEqual(true, headersSeededWithKeepAlive.isKeepAlive(version: .http1_0))\n    }\n\n    func testSeedGetsUpdatedToDefaultOnConnectionHeaderModification() {\n        var headersSeededWithClose = HTTPHeaders([], keepAliveState: .close)\n        headersSeededWithClose.add(name: \"connection\", value: \"bar\")\n        XCTAssertEqual(true, headersSeededWithClose.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, headersSeededWithClose.isKeepAlive(version: .http1_0))\n\n        var headersSeededWithKeepAlive = HTTPHeaders([], keepAliveState: .keepAlive)\n        headersSeededWithKeepAlive.add(name: \"connection\", value: \"bar\")\n        XCTAssertEqual(true, headersSeededWithKeepAlive.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, headersSeededWithKeepAlive.isKeepAlive(version: .http1_0))\n    }\n\n    func testSeedGetsUpdatedToWhateverTheHeaderSaysIfPresent() {\n        var headersSeededWithClose = HTTPHeaders([], keepAliveState: .close)\n        headersSeededWithClose.add(name: \"connection\", value: \"bar,keep-alive,true\")\n        XCTAssertEqual(true, headersSeededWithClose.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(true, headersSeededWithClose.isKeepAlive(version: .http1_0))\n\n        var headersSeededWithKeepAlive = HTTPHeaders([], keepAliveState: .keepAlive)\n        headersSeededWithKeepAlive.add(name: \"connection\", value: \"bar,close,true\")\n        XCTAssertEqual(false, headersSeededWithKeepAlive.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, headersSeededWithKeepAlive.isKeepAlive(version: .http1_0))\n    }\n\n    func testWeDefaultToCloseIfDoesNotMakeSense() {\n        var nonSenseInOneHeaderCK = HTTPHeaders([])\n        nonSenseInOneHeaderCK.add(name: \"connection\", value: \"close,keep-alive\")\n        XCTAssertEqual(false, nonSenseInOneHeaderCK.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, nonSenseInOneHeaderCK.isKeepAlive(version: .http1_0))\n\n        var nonSenseInMultipleHeadersCK = HTTPHeaders([])\n        nonSenseInMultipleHeadersCK.add(name: \"connection\", value: \"close\")\n        nonSenseInMultipleHeadersCK.add(name: \"connection\", value: \"keep-alive\")\n        XCTAssertEqual(false, nonSenseInMultipleHeadersCK.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, nonSenseInMultipleHeadersCK.isKeepAlive(version: .http1_0))\n\n        var nonSenseInOneHeaderKC = HTTPHeaders([])\n        nonSenseInOneHeaderKC.add(name: \"connection\", value: \"keep-alive,close\")\n        XCTAssertEqual(false, nonSenseInOneHeaderKC.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, nonSenseInOneHeaderKC.isKeepAlive(version: .http1_0))\n\n        var nonSenseInMultipleHeadersKC = HTTPHeaders([])\n        nonSenseInMultipleHeadersKC.add(name: \"connection\", value: \"keep-alive\")\n        nonSenseInMultipleHeadersKC.add(name: \"connection\", value: \"close\")\n        XCTAssertEqual(false, nonSenseInMultipleHeadersKC.isKeepAlive(version: .http1_1))\n        XCTAssertEqual(false, nonSenseInMultipleHeadersKC.isKeepAlive(version: .http1_0))\n    }\n\n    func testAddingSequenceOfPairs() {\n        var headers = HTTPHeaders([], keepAliveState: .keepAlive)\n        let fooBar = [(\"foo\", \"bar\"), (\"bar\", \"qux\"), (\"connection\", \"foo\")]\n        headers.add(contentsOf: fooBar)\n\n        XCTAssertEqual([\"bar\"], headers[\"foo\"])\n        XCTAssertEqual([\"qux\"], headers[\"bar\"])\n        XCTAssertEqual(.unknown, headers.keepAliveState)\n    }\n\n    func testAddingOtherHTTPHeader() {\n        var fooBarHeaders = HTTPHeaders([(\"foo\", \"bar\"), (\"bar\", \"qux\")], keepAliveState: .keepAlive)\n        let bazHeaders = HTTPHeaders([(\"bar\", \"baz\"), (\"baz\", \"bazzy\")], keepAliveState: .unknown)\n        fooBarHeaders.add(contentsOf: bazHeaders)\n\n        XCTAssertEqual([\"bar\"], fooBarHeaders[\"foo\"])\n        XCTAssertEqual([\"qux\", \"baz\"], fooBarHeaders[\"bar\"])\n        XCTAssertEqual([\"bazzy\"], fooBarHeaders[\"baz\"])\n        XCTAssertEqual(.unknown, fooBarHeaders.keepAliveState)\n    }\n\n    func testCapacity() {\n        // no headers\n        var headers = HTTPHeaders()\n        XCTAssertEqual(headers.capacity, 0)\n        // reserve capacity\n        headers.reserveCapacity(5)\n        XCTAssertEqual(headers.capacity, 5)\n\n        // initialize with some headers\n        headers = HTTPHeaders([(\"foo\", \"bar\")])\n        XCTAssertEqual(headers.capacity, 1)\n        // reserve more capacity\n        headers.reserveCapacity(4)\n        XCTAssertEqual(headers.capacity, 4)\n    }\n\n    func testHTTPHeadersDescription() {\n        let originalHeaders = [\n            (\"User-Agent\", \"1\"),\n            (\"host\", \"2\"),\n            (\"X-SOMETHING\", \"3\"),\n            (\"SET-COOKIE\", \"foo=bar\"),\n            (\"Set-Cookie\", \"buz=cux\"),\n        ]\n\n        let headers = HTTPHeaders(originalHeaders)\n\n        let expectedOutput = \"\"\"\n            User-Agent: 1; \\\n            host: 2; \\\n            X-SOMETHING: 3; \\\n            SET-COOKIE: foo=bar; \\\n            Set-Cookie: buz=cux\n            \"\"\"\n\n        XCTAssertEqual(expectedOutput, headers.description)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPRequestEncoderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOHTTP1\n\nextension ByteBuffer {\n    fileprivate func assertContainsOnly(_ string: String) {\n        let innerData = self.getString(at: self.readerIndex, length: self.readableBytes)!\n        XCTAssertEqual(innerData, string)\n    }\n}\n\nextension HTTPRequestEncoder.Configuration {\n    fileprivate static let noFramingTransformation: HTTPRequestEncoder.Configuration = {\n        var config = HTTPRequestEncoder.Configuration()\n        config.automaticallySetFramingHeaders = false\n        return config\n    }()\n}\n\nclass HTTPRequestEncoderTests: XCTestCase {\n    private func sendRequest(\n        withMethod method: HTTPMethod,\n        andHeaders headers: HTTPHeaders,\n        configuration: HTTPRequestEncoder.Configuration = .init()\n    ) throws -> ByteBuffer {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder(configuration: configuration))\n        var request = HTTPRequestHead(version: .http1_1, method: method, uri: \"/uri\")\n        request.headers = headers\n        try channel.writeOutbound(HTTPClientRequestPart.head(request))\n        if let buffer = try channel.readOutbound(as: ByteBuffer.self) {\n            return buffer\n        } else {\n            fatalError(\"Could not read ByteBuffer from channel\")\n        }\n    }\n\n    func testNoAutoHeadersForHEAD() throws {\n        let writtenData = try sendRequest(withMethod: .HEAD, andHeaders: HTTPHeaders())\n        writtenData.assertContainsOnly(\"HEAD /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testNoAutoHeadersForGET() throws {\n        let writtenData = try sendRequest(withMethod: .GET, andHeaders: HTTPHeaders())\n        writtenData.assertContainsOnly(\"GET /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testNoAutoHeadersForPOSTWhenDisabled() throws {\n        let writtenData = try sendRequest(\n            withMethod: .POST,\n            andHeaders: HTTPHeaders(),\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"POST /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testGETContentHeadersLeftAlone() throws {\n        var headers = HTTPHeaders([(\"content-length\", \"17\")])\n        var writtenData = try sendRequest(withMethod: .GET, andHeaders: headers)\n        writtenData.assertContainsOnly(\"GET /uri HTTP/1.1\\r\\ncontent-length: 17\\r\\n\\r\\n\")\n\n        headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        writtenData = try sendRequest(withMethod: .GET, andHeaders: headers)\n        writtenData.assertContainsOnly(\"GET /uri HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n    }\n\n    func testContentLengthHeadersForHEAD() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = try sendRequest(withMethod: .HEAD, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HEAD /uri HTTP/1.1\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n    }\n\n    func testTransferEncodingHeadersForHEAD() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = try sendRequest(withMethod: .HEAD, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HEAD /uri HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n    }\n\n    func testNoContentLengthHeadersForTRACE() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = try sendRequest(withMethod: .TRACE, andHeaders: headers)\n        writtenData.assertContainsOnly(\"TRACE /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testAllowContentLengthHeadersWhenForced_forTRACE() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = try sendRequest(\n            withMethod: .TRACE,\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"TRACE /uri HTTP/1.1\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n    }\n\n    func testNoTransferEncodingHeadersForTRACE() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = try sendRequest(withMethod: .TRACE, andHeaders: headers)\n        writtenData.assertContainsOnly(\"TRACE /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testAllowTransferEncodingHeadersWhenForced_forTRACE() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = try sendRequest(\n            withMethod: .TRACE,\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"TRACE /uri HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n    }\n\n    func testNoChunkedEncodingForHTTP10() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n\n        // This request contains neither Transfer-Encoding: chunked or Content-Length.\n        let request = HTTPRequestHead(version: .http1_0, method: .GET, uri: \"/uri\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(request)))\n        let writtenData = try channel.readOutbound(as: ByteBuffer.self)!\n        let writtenResponse = writtenData.getString(at: writtenData.readerIndex, length: writtenData.readableBytes)!\n        XCTAssertEqual(writtenResponse, \"GET /uri HTTP/1.0\\r\\n\\r\\n\")\n    }\n\n    func testBody() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder())\n        var request = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/uri\")\n        request.headers.add(name: \"content-length\", value: \"4\")\n\n        var buf = channel.allocator.buffer(capacity: 4)\n        buf.writeStaticString(\"test\")\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(request)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.body(.byteBuffer(buf))))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        assertOutboundContainsOnly(channel, \"POST /uri HTTP/1.1\\r\\ncontent-length: 4\\r\\n\\r\\n\")\n        assertOutboundContainsOnly(channel, \"test\")\n        assertOutboundContainsOnly(channel, \"\")\n    }\n\n    func testCONNECT() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        let uri = \"server.example.com:80\"\n        try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder())\n        var request = HTTPRequestHead(version: .http1_1, method: .CONNECT, uri: uri)\n        request.headers.add(name: \"Host\", value: uri)\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.head(request)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n\n        assertOutboundContainsOnly(channel, \"CONNECT \\(uri) HTTP/1.1\\r\\nHost: \\(uri)\\r\\n\\r\\n\")\n        assertOutboundContainsOnly(channel, \"\")\n    }\n\n    func testChunkedEncodingIsTheDefault() {\n        let channel = EmbeddedChannel(handler: HTTPRequestEncoder())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        var expected = channel.allocator.buffer(capacity: 32)\n\n        XCTAssertNoThrow(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    .init(\n                        version: .http1_1,\n                        method: .POST,\n                        uri: \"/\"\n                    )\n                )\n            )\n        )\n        expected.writeString(\"POST / HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        buffer.writeString(\"foo\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.body(.byteBuffer(buffer))))\n\n        expected.clear()\n        expected.writeString(\"3\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n        expected.clear()\n        expected.writeString(\"foo\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n        expected.clear()\n        expected.writeString(\"\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        expected.clear()\n        expected.writeString(\"0\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testChunkedEncodingCanBetEnabled() {\n        let channel = EmbeddedChannel(handler: HTTPRequestEncoder())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        var expected = channel.allocator.buffer(capacity: 32)\n\n        XCTAssertNoThrow(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    .init(\n                        version: .http1_1,\n                        method: .POST,\n                        uri: \"/\",\n                        headers: [\"TrAnSfEr-encoding\": \"chuNKED\"]\n                    )\n                )\n            )\n        )\n        expected.writeString(\"POST / HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        buffer.writeString(\"foo\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.body(.byteBuffer(buffer))))\n\n        expected.clear()\n        expected.writeString(\"3\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n        expected.clear()\n        expected.writeString(\"foo\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n        expected.clear()\n        expected.writeString(\"\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        expected.clear()\n        expected.writeString(\"0\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end(nil)))\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testChunkedEncodingDealsWithZeroLengthChunks() {\n        let channel = EmbeddedChannel(handler: HTTPRequestEncoder())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        var expected = channel.allocator.buffer(capacity: 32)\n\n        XCTAssertNoThrow(\n            try channel.writeOutbound(\n                HTTPClientRequestPart.head(\n                    .init(\n                        version: .http1_1,\n                        method: .POST,\n                        uri: \"/\"\n                    )\n                )\n            )\n        )\n        expected.writeString(\"POST / HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        buffer.clear()\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.body(.byteBuffer(buffer))))\n        XCTAssertNoThrow(XCTAssertEqual(0, try channel.readOutbound(as: ByteBuffer.self)?.readableBytes))\n\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPClientRequestPart.end([\"foo\": \"bar\"])))\n\n        expected.clear()\n        expected.writeString(\"0\\r\\nfoo: bar\\r\\n\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testChunkedEncodingWorksIfNoPromisesAreAttachedToTheWrites() {\n        let channel = EmbeddedChannel(handler: HTTPRequestEncoder())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        var expected = channel.allocator.buffer(capacity: 32)\n\n        channel.write(\n            HTTPClientRequestPart.head(\n                .init(\n                    version: .http1_1,\n                    method: .POST,\n                    uri: \"/\"\n                )\n            ),\n            promise: nil\n        )\n        channel.flush()\n        expected.writeString(\"POST / HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        buffer.writeString(\"foo\")\n        channel.write(HTTPClientRequestPart.body(.byteBuffer(buffer)), promise: nil)\n        channel.flush()\n\n        expected.clear()\n        expected.writeString(\"3\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n        expected.clear()\n        expected.writeString(\"foo\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n        expected.clear()\n        expected.writeString(\"\\r\\n\")\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        expected.clear()\n        expected.writeString(\"0\\r\\n\\r\\n\")\n        channel.write(HTTPClientRequestPart.end(nil), promise: nil)\n        channel.flush()\n        XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_withFutures() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        try channel.pipeline.addHTTPClientHandlers(encoderConfiguration: .noFramingTransformation).wait()\n        let request = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/uri\")\n        try channel.writeOutbound(HTTPClientRequestPart.head(request))\n        guard let buffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        buffer.assertContainsOnly(\"POST /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_syncOperations() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        try channel.pipeline.syncOperations.addHTTPClientHandlers(encoderConfiguration: .noFramingTransformation)\n        let request = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/uri\")\n        try channel.writeOutbound(HTTPClientRequestPart.head(request))\n        guard let buffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        buffer.assertContainsOnly(\"POST /uri HTTP/1.1\\r\\n\\r\\n\")\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_sendWithoutChunked() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        try channel.pipeline.addHTTPClientHandlers(encoderConfiguration: .noFramingTransformation).wait()\n        let request = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/uri\")\n        try channel.writeOutbound(HTTPClientRequestPart.head(request))\n        guard let headBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        headBuffer.assertContainsOnly(\"POST /uri HTTP/1.1\\r\\n\\r\\n\")\n\n        let body = ByteBuffer(string: \"hello world!\")\n        try channel.writeOutbound(HTTPClientRequestPart.body(.byteBuffer(body)))\n        guard let bodyBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(bodyBuffer, body)\n\n        try channel.writeOutbound(HTTPClientRequestPart.end(nil))\n        guard let trailerBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(trailerBuffer.readableBytes, 0)\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_sendWithChunked() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        try channel.pipeline.addHTTPClientHandlers(encoderConfiguration: .noFramingTransformation).wait()\n        let request = HTTPRequestHead(\n            version: .http1_1,\n            method: .POST,\n            uri: \"/uri\",\n            headers: [\"transfer-encoding\": \"chunked\"]\n        )\n        try channel.writeOutbound(HTTPClientRequestPart.head(request))\n        guard let headBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        headBuffer.assertContainsOnly(\"POST /uri HTTP/1.1\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n\n        let body = ByteBuffer(string: \"hello world!\")\n        try channel.writeOutbound(HTTPClientRequestPart.body(.byteBuffer(body)))\n        guard let prefixBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        guard let bodyBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        guard let suffixBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(prefixBuffer, ByteBuffer(string: \"c\\r\\n\"))\n        XCTAssertEqual(bodyBuffer, body)\n        XCTAssertEqual(suffixBuffer, ByteBuffer(string: \"\\r\\n\"))\n\n        try channel.writeOutbound(HTTPClientRequestPart.end(nil))\n        guard let trailerBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(trailerBuffer, ByteBuffer(string: \"0\\r\\n\\r\\n\"))\n    }\n\n    private func assertOutboundContainsOnly(_ channel: EmbeddedChannel, _ expected: String) {\n        XCTAssertNoThrow(\n            XCTAssertNotNil(\n                try channel.readOutbound(as: ByteBuffer.self).map { buffer in\n                    buffer.assertContainsOnly(expected)\n                },\n                \"couldn't read ByteBuffer\"\n            )\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPResponseEncoderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOHTTP1\n\nextension ByteBuffer {\n    fileprivate func assertContainsOnly(_ string: String) {\n        let innerData = self.getString(at: self.readerIndex, length: self.readableBytes)!\n        XCTAssertEqual(innerData, string)\n    }\n}\n\nextension HTTPResponseEncoder.Configuration {\n    fileprivate static let noFramingTransformation: HTTPResponseEncoder.Configuration = {\n        var config = HTTPResponseEncoder.Configuration()\n        config.automaticallySetFramingHeaders = false\n        return config\n    }()\n}\n\nclass HTTPResponseEncoderTests: XCTestCase {\n    private func sendResponse(\n        withStatus status: HTTPResponseStatus,\n        andHeaders headers: HTTPHeaders,\n        configuration: HTTPResponseEncoder.Configuration = .init()\n    ) -> ByteBuffer {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(HTTPResponseEncoder(configuration: configuration))\n        )\n        var switchingResponse = HTTPResponseHead(version: .http1_1, status: status)\n        switchingResponse.headers = headers\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(switchingResponse)))\n        do {\n            if let buffer = try channel.readOutbound(as: ByteBuffer.self) {\n                return buffer\n            } else {\n                fatalError(\"Could not read ByteBuffer from channel\")\n            }\n        } catch {\n            XCTFail(\"unexpected error: \\(error)\")\n            var buf = channel.allocator.buffer(capacity: 16)\n            buf.writeString(\"unexpected error: \\(error)\")\n            return buf\n        }\n    }\n\n    func testNoAutoHeadersFor101() throws {\n        let writtenData = sendResponse(withStatus: .switchingProtocols, andHeaders: HTTPHeaders())\n        writtenData.assertContainsOnly(\"HTTP/1.1 101 Switching Protocols\\r\\n\\r\\n\")\n    }\n\n    func testNoAutoHeadersForCustom1XX() throws {\n        let headers = HTTPHeaders([(\"Link\", \"</styles.css>; rel=preload; as=style\")])\n        let writtenData = sendResponse(withStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"), andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 103 Early Hints\\r\\nLink: </styles.css>; rel=preload; as=style\\r\\n\\r\\n\")\n    }\n\n    func testNoAutoHeadersFor204() throws {\n        let writtenData = sendResponse(withStatus: .noContent, andHeaders: HTTPHeaders())\n        writtenData.assertContainsOnly(\"HTTP/1.1 204 No Content\\r\\n\\r\\n\")\n    }\n\n    func testNoAutoHeadersWhenDisabled() throws {\n        let writtenData = sendResponse(\n            withStatus: .ok,\n            andHeaders: HTTPHeaders(),\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"HTTP/1.1 200 OK\\r\\n\\r\\n\")\n    }\n\n    func testNoContentLengthHeadersFor101() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = sendResponse(withStatus: .switchingProtocols, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 101 Switching Protocols\\r\\n\\r\\n\")\n    }\n\n    func testAllowContentLengthHeadersWhenForced_for101() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = sendResponse(\n            withStatus: .switchingProtocols,\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"HTTP/1.1 101 Switching Protocols\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n    }\n\n    func testNoContentLengthHeadersForCustom1XX() throws {\n        let headers = HTTPHeaders([(\"Link\", \"</styles.css>; rel=preload; as=style\"), (\"content-length\", \"0\")])\n        let writtenData = sendResponse(withStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"), andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 103 Early Hints\\r\\nLink: </styles.css>; rel=preload; as=style\\r\\n\\r\\n\")\n    }\n\n    func testAllowContentLengthHeadersWhenForced_forCustom1XX() throws {\n        let headers = HTTPHeaders([(\"Link\", \"</styles.css>; rel=preload; as=style\"), (\"content-length\", \"0\")])\n        let writtenData = sendResponse(\n            withStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"),\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\n            \"HTTP/1.1 103 Early Hints\\r\\nLink: </styles.css>; rel=preload; as=style\\r\\ncontent-length: 0\\r\\n\\r\\n\"\n        )\n    }\n\n    func testNoContentLengthHeadersFor204() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = sendResponse(withStatus: .noContent, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 204 No Content\\r\\n\\r\\n\")\n    }\n\n    func testAllowContentLengthHeadersWhenForced_For204() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = sendResponse(\n            withStatus: .noContent,\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"HTTP/1.1 204 No Content\\r\\ncontent-length: 0\\r\\n\\r\\n\")\n    }\n\n    func testNoContentLengthHeadersFor304() throws {\n        let headers = HTTPHeaders([(\"content-length\", \"0\")])\n        let writtenData = sendResponse(withStatus: .notModified, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 304 Not Modified\\r\\n\\r\\n\")\n    }\n\n    func testNoTransferEncodingHeadersFor101() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(withStatus: .switchingProtocols, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 101 Switching Protocols\\r\\n\\r\\n\")\n    }\n\n    func testAllowTransferEncodingHeadersWhenForced_for101() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(\n            withStatus: .switchingProtocols,\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"HTTP/1.1 101 Switching Protocols\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n    }\n\n    func testNoTransferEncodingHeadersForCustom1XX() throws {\n        let headers = HTTPHeaders([(\"Link\", \"</styles.css>; rel=preload; as=style\"), (\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(withStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"), andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 103 Early Hints\\r\\nLink: </styles.css>; rel=preload; as=style\\r\\n\\r\\n\")\n    }\n\n    func testAllowTransferEncodingHeadersWhenForced_forCustom1XX() throws {\n        let headers = HTTPHeaders([(\"Link\", \"</styles.css>; rel=preload; as=style\"), (\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(\n            withStatus: .custom(code: 103, reasonPhrase: \"Early Hints\"),\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\n            \"HTTP/1.1 103 Early Hints\\r\\nLink: </styles.css>; rel=preload; as=style\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\"\n        )\n    }\n\n    func testNoTransferEncodingHeadersFor204() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(withStatus: .noContent, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 204 No Content\\r\\n\\r\\n\")\n    }\n\n    func testAllowTransferEncodingHeadersWhenForced_for204() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(\n            withStatus: .noContent,\n            andHeaders: headers,\n            configuration: .noFramingTransformation\n        )\n        writtenData.assertContainsOnly(\"HTTP/1.1 204 No Content\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n    }\n\n    func testNoTransferEncodingHeadersFor304() throws {\n        let headers = HTTPHeaders([(\"transfer-encoding\", \"chunked\")])\n        let writtenData = sendResponse(withStatus: .notModified, andHeaders: headers)\n        writtenData.assertContainsOnly(\"HTTP/1.1 304 Not Modified\\r\\n\\r\\n\")\n    }\n\n    func testNoChunkedEncodingForHTTP10() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPResponseEncoder()))\n\n        // This response contains neither Transfer-Encoding: chunked or Content-Length.\n        let response = HTTPResponseHead(version: .http1_0, status: .ok)\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(response)))\n        guard let b = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Could not read byte buffer\")\n            return\n        }\n        let writtenResponse = b.getString(at: b.readerIndex, length: b.readableBytes)!\n        XCTAssertEqual(writtenResponse, \"HTTP/1.0 200 OK\\r\\n\\r\\n\")\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_withFuture() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(withEncoderConfiguration: .noFramingTransformation).wait()\n        )\n        let request = ByteBuffer(string: \"GET / HTTP/1.1\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(request))\n\n        let response = HTTPResponseHead(version: .http1_1, status: .ok)\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(response)))\n\n        guard let buffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Could not read buffer\")\n            return\n        }\n\n        buffer.assertContainsOnly(\"HTTP/1.1 200 OK\\r\\n\\r\\n\")\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_syncOperations() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(\n                withEncoderConfiguration: .noFramingTransformation\n            )\n        )\n        let request = ByteBuffer(string: \"GET / HTTP/1.1\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(request))\n\n        let response = HTTPResponseHead(version: .http1_1, status: .ok)\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(response)))\n\n        guard let buffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Could not read buffer\")\n            return\n        }\n\n        buffer.assertContainsOnly(\"HTTP/1.1 200 OK\\r\\n\\r\\n\")\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_sendWithoutChunked() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(\n                withEncoderConfiguration: .noFramingTransformation\n            )\n        )\n        let request = ByteBuffer(string: \"GET / HTTP/1.1\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(request))\n\n        let response = HTTPResponseHead(version: .http1_1, status: .ok)\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(response)))\n\n        guard let buffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Could not read buffer\")\n            return\n        }\n\n        buffer.assertContainsOnly(\"HTTP/1.1 200 OK\\r\\n\\r\\n\")\n\n        let body = ByteBuffer(string: \"hello world!\")\n        try channel.writeOutbound(HTTPServerResponsePart.body(.byteBuffer(body)))\n        guard let bodyBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(bodyBuffer, body)\n\n        try channel.writeOutbound(HTTPServerResponsePart.end(nil))\n        guard let trailerBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(trailerBuffer.readableBytes, 0)\n    }\n\n    func testFullPipelineCanDisableFramingHeaders_sendWithChunked() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.configureHTTPServerPipeline(\n                withEncoderConfiguration: .noFramingTransformation\n            )\n        )\n        let request = ByteBuffer(string: \"GET / HTTP/1.1\\r\\n\\r\\n\")\n        XCTAssertNoThrow(try channel.writeInbound(request))\n\n        let response = HTTPResponseHead(version: .http1_1, status: .ok, headers: [\"transfer-encoding\": \"chunked\"])\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(response)))\n\n        guard let buffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Could not read buffer\")\n            return\n        }\n\n        buffer.assertContainsOnly(\"HTTP/1.1 200 OK\\r\\ntransfer-encoding: chunked\\r\\n\\r\\n\")\n\n        let body = ByteBuffer(string: \"hello world!\")\n        try channel.writeOutbound(HTTPServerResponsePart.body(.byteBuffer(body)))\n        guard let prefixBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        guard let bodyBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        guard let suffixBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(prefixBuffer, ByteBuffer(string: \"c\\r\\n\"))\n        XCTAssertEqual(bodyBuffer, body)\n        XCTAssertEqual(suffixBuffer, ByteBuffer(string: \"\\r\\n\"))\n\n        try channel.writeOutbound(HTTPServerResponsePart.end(nil))\n        guard let trailerBuffer = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"Unable to read buffer\")\n            return\n        }\n        XCTAssertEqual(trailerBuffer, ByteBuffer(string: \"0\\r\\n\\r\\n\"))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPResponseStatusTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOHTTP1\nimport XCTest\n\nclass HTTPResponseStatusTests: XCTestCase {\n    func testHTTPResponseStatusFromStatusCode() {\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 100), .continue)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 101), .switchingProtocols)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 102), .processing)\n\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 200), .ok)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 201), .created)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 202), .accepted)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 203), .nonAuthoritativeInformation)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 204), .noContent)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 205), .resetContent)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 206), .partialContent)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 207), .multiStatus)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 208), .alreadyReported)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 226), .imUsed)\n\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 300), .multipleChoices)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 301), .movedPermanently)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 302), .found)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 303), .seeOther)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 304), .notModified)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 305), .useProxy)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 307), .temporaryRedirect)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 308), .permanentRedirect)\n\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 400), .badRequest)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 401), .unauthorized)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 402), .paymentRequired)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 403), .forbidden)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 404), .notFound)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 405), .methodNotAllowed)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 406), .notAcceptable)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 407), .proxyAuthenticationRequired)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 408), .requestTimeout)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 409), .conflict)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 410), .gone)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 411), .lengthRequired)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 412), .preconditionFailed)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 413), .payloadTooLarge)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 414), .uriTooLong)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 415), .unsupportedMediaType)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 416), .rangeNotSatisfiable)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 417), .expectationFailed)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 418), .imATeapot)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 421), .misdirectedRequest)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 422), .unprocessableEntity)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 423), .locked)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 424), .failedDependency)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 426), .upgradeRequired)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 428), .preconditionRequired)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 429), .tooManyRequests)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 431), .requestHeaderFieldsTooLarge)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 451), .unavailableForLegalReasons)\n\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 500), .internalServerError)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 501), .notImplemented)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 502), .badGateway)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 503), .serviceUnavailable)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 504), .gatewayTimeout)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 505), .httpVersionNotSupported)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 506), .variantAlsoNegotiates)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 507), .insufficientStorage)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 508), .loopDetected)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 510), .notExtended)\n        XCTAssertEqual(HTTPResponseStatus(statusCode: 511), .networkAuthenticationRequired)\n    }\n\n    func testHTTPResponseStatusCodeAndReason() {\n        XCTAssertEqual(\"\\(HTTPResponseStatus.ok)\", \"200 OK\")\n        XCTAssertEqual(\"\\(HTTPResponseStatus.imATeapot)\", \"418 I'm a teapot\")\n        XCTAssertEqual(\n            \"\\(HTTPResponseStatus.custom(code: 347, reasonPhrase: \"I like ice cream\"))\",\n            \"347 I like ice cream\"\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPServerClientTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOFoundationCompat\nimport NIOPosix\nimport XCTest\n\n@testable import NIOHTTP1\n\nextension Array where Array.Element == ByteBuffer {\n    public func allAsBytes() -> [UInt8] {\n        var out: [UInt8] = []\n        out.reserveCapacity(self.reduce(0, { $0 + $1.readableBytes }))\n        for bb in self {\n            bb.withUnsafeReadableBytes { ptr in\n                out.append(contentsOf: ptr)\n            }\n        }\n        return out\n    }\n\n    public func allAsString() -> String? {\n        String(decoding: self.allAsBytes(), as: Unicode.UTF8.self)\n    }\n}\n\n// Must be unchecked because of inheritance.\ninternal class ArrayAccumulationHandler<T>: ChannelInboundHandler, @unchecked Sendable {\n    typealias InboundIn = T\n    private let received: NIOLockedValueBox<[T]>\n    private let allDoneBlock: DispatchWorkItem\n\n    init(completion: @escaping ([T]) -> Void) {\n        let received = NIOLockedValueBox<[T]>([])\n        self.received = received\n        self.allDoneBlock = DispatchWorkItem {\n            completion(received.withLockedValue { $0 })\n        }\n    }\n\n    final func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.received.withLockedValue { $0.append(Self.unwrapInboundIn(data)) }\n    }\n\n    final func channelUnregistered(context: ChannelHandlerContext) {\n        self.allDoneBlock.perform()\n    }\n\n    final func syncWaitForCompletion() {\n        self.allDoneBlock.wait()\n    }\n}\n\nclass HTTPServerClientTest: XCTestCase {\n    // needs to be something reasonably large and odd so it has good odds producing incomplete writes even on the loopback interface\n    private static let massiveResponseLength = 1 * 1024 * 1024 + 7\n    private static let massiveResponseBytes: [UInt8] = {\n        Array(repeating: 0xff, count: HTTPServerClientTest.massiveResponseLength)\n    }()\n\n    enum SendMode {\n        case byteBuffer\n        case fileRegion\n    }\n\n    private class SimpleHTTPServer: ChannelInboundHandler {\n        typealias InboundIn = HTTPServerRequestPart\n        typealias OutboundOut = HTTPServerResponsePart\n\n        private let mode: SendMode\n        private var files: [String] = Array()\n        private var seenEnd: Bool = false\n        private var sentEnd: Bool = false\n        private var isOpen: Bool = true\n\n        init(_ mode: SendMode) {\n            self.mode = mode\n        }\n\n        private func outboundBody(_ buffer: ByteBuffer) -> (body: HTTPServerResponsePart, destructor: () -> Void) {\n            switch mode {\n            case .byteBuffer:\n                return (.body(.byteBuffer(buffer)), { () in })\n            case .fileRegion:\n                let filePath: String = \"\\(temporaryDirectory)/\\(UUID().uuidString)\"\n                files.append(filePath)\n\n                let content = buffer.getData(at: 0, length: buffer.readableBytes)!\n                XCTAssertNoThrow(try content.write(to: URL(fileURLWithPath: filePath)))\n                let fh = try! NIOFileHandle(_deprecatedPath: filePath)\n                let region = FileRegion(\n                    fileHandle: fh,\n                    readerIndex: 0,\n                    endIndex: buffer.readableBytes\n                )\n                return (.body(.fileRegion(region)), { try! fh.close() })\n            }\n        }\n\n        public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            let loopBoundContext = context.loopBound\n            switch Self.unwrapInboundIn(data) {\n            case .head(let req):\n                switch req.uri {\n                case \"/helloworld\":\n                    let replyString = \"Hello World!\\r\\n\"\n                    var head = HTTPResponseHead(version: req.version, status: .ok)\n                    head.headers.add(name: \"Content-Length\", value: \"\\(replyString.utf8.count)\")\n                    head.headers.add(name: \"Connection\", value: \"close\")\n                    let r = HTTPServerResponsePart.head(head)\n                    context.write(Self.wrapOutboundOut(r), promise: nil)\n                    var b = context.channel.allocator.buffer(capacity: replyString.count)\n                    b.writeString(replyString)\n\n                    let outbound = self.outboundBody(b)\n                    context.write(Self.wrapOutboundOut(outbound.body)).assumeIsolated().whenComplete {\n                        (_: Result<Void, Error>) in\n                        outbound.destructor()\n                    }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                case \"/count-to-ten\":\n                    var head = HTTPResponseHead(version: req.version, status: .ok)\n                    head.headers.add(name: \"Connection\", value: \"close\")\n                    let r = HTTPServerResponsePart.head(head)\n                    context.write(Self.wrapOutboundOut(r)).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    var b = context.channel.allocator.buffer(capacity: 1024)\n                    for i in 1...10 {\n                        b.clear()\n                        b.writeString(\"\\(i)\")\n\n                        let outbound = self.outboundBody(b)\n                        context.write(Self.wrapOutboundOut(outbound.body)).recover { error in\n                            XCTFail(\"unexpected error \\(error)\")\n                        }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                            outbound.destructor()\n                        }\n                    }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                case \"/trailers\":\n                    var head = HTTPResponseHead(version: req.version, status: .ok)\n                    head.headers.add(name: \"Connection\", value: \"close\")\n                    head.headers.add(name: \"Transfer-Encoding\", value: \"chunked\")\n                    let r = HTTPServerResponsePart.head(head)\n                    context.write(Self.wrapOutboundOut(r)).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    var b = context.channel.allocator.buffer(capacity: 1024)\n                    for i in 1...10 {\n                        b.clear()\n                        b.writeString(\"\\(i)\")\n\n                        let outbound = self.outboundBody(b)\n                        context.write(Self.wrapOutboundOut(outbound.body)).recover { error in\n                            XCTFail(\"unexpected error \\(error)\")\n                        }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                            outbound.destructor()\n                        }\n                    }\n\n                    var trailers = HTTPHeaders()\n                    trailers.add(name: \"X-URL-Path\", value: \"/trailers\")\n                    trailers.add(name: \"X-Should-Trail\", value: \"sure\")\n                    context.write(Self.wrapOutboundOut(.end(trailers))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n\n                case \"/massive-response\":\n                    var buf = context.channel.allocator.buffer(capacity: HTTPServerClientTest.massiveResponseLength)\n                    buf.reserveCapacity(HTTPServerClientTest.massiveResponseLength)\n                    buf.writeBytes(HTTPServerClientTest.massiveResponseBytes)\n                    var head = HTTPResponseHead(version: req.version, status: .ok)\n                    head.headers.add(name: \"Connection\", value: \"close\")\n                    head.headers.add(name: \"Content-Length\", value: \"\\(HTTPServerClientTest.massiveResponseLength)\")\n                    let r = HTTPServerResponsePart.head(head)\n                    context.write(Self.wrapOutboundOut(r)).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    let outbound = self.outboundBody(buf)\n                    context.writeAndFlush(Self.wrapOutboundOut(outbound.body)).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        outbound.destructor()\n                    }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                case \"/head\":\n                    var head = HTTPResponseHead(version: req.version, status: .ok)\n                    head.headers.add(name: \"Connection\", value: \"close\")\n                    head.headers.add(name: \"Content-Length\", value: \"5000\")\n                    context.write(Self.wrapOutboundOut(.head(head))).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                case \"/204\":\n                    var head = HTTPResponseHead(version: req.version, status: .noContent)\n                    head.headers.add(name: \"Connection\", value: \"keep-alive\")\n                    context.write(Self.wrapOutboundOut(.head(head))).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                case \"/no-headers\":\n                    let replyString = \"Hello World!\\r\\n\"\n                    let head = HTTPResponseHead(version: req.version, status: .ok)\n                    let r = HTTPServerResponsePart.head(head)\n                    context.write(Self.wrapOutboundOut(r), promise: nil)\n                    var b = context.channel.allocator.buffer(capacity: replyString.count)\n                    b.writeString(replyString)\n\n                    let outbound = self.outboundBody(b)\n                    context.write(Self.wrapOutboundOut(outbound.body)).assumeIsolated().whenComplete {\n                        (_: Result<Void, Error>) in\n                        outbound.destructor()\n                    }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                case \"/zero-length-body-part\":\n\n                    let r = HTTPServerResponsePart.head(.init(version: req.version, status: .ok))\n                    context.write(Self.wrapOutboundOut(r)).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n\n                    context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(ByteBuffer())))).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    context.writeAndFlush(Self.wrapOutboundOut(.body(.byteBuffer(ByteBuffer(string: \"Hello World\")))))\n                        .whenFailure { error in\n                            XCTFail(\"unexpected error \\(error)\")\n                        }\n                    context.write(Self.wrapOutboundOut(.end(nil))).recover { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                        let context = loopBoundContext.value\n                        self.sentEnd = true\n                        self.maybeClose(context: context)\n                    }\n                default:\n                    XCTFail(\"received request to unknown URI \\(req.uri)\")\n                }\n            case .end(let trailers):\n                XCTAssertNil(trailers)\n                seenEnd = true\n            default:\n                XCTFail(\"wrong\")\n            }\n        }\n\n        public func channelReadComplete(context: ChannelHandlerContext) {\n            context.flush()\n        }\n\n        // We should only close the connection when the remote peer has sent the entire request\n        // and we have sent our entire response.\n        private func maybeClose(context: ChannelHandlerContext) {\n            if sentEnd && seenEnd && self.isOpen {\n                self.isOpen = false\n                context.close().whenFailure { error in\n                    XCTFail(\"unexpected error \\(error)\")\n                }\n            }\n        }\n    }\n\n    func testSimpleGetByteBuffer() throws {\n        try testSimpleGet(.byteBuffer)\n    }\n\n    func testSimpleGetFileRegion() throws {\n        try testSimpleGet(.fileRegion)\n    }\n\n    // @unchecked because of inheritance.\n    private final class HTTPClientResponsePartAssertHandler: ArrayAccumulationHandler<HTTPClientResponsePart>,\n        @unchecked Sendable\n    {\n        public init(\n            _ expectedVersion: HTTPVersion,\n            _ expectedStatus: HTTPResponseStatus,\n            _ expectedHeaders: HTTPHeaders,\n            _ expectedBody: String?,\n            _ expectedTrailers: HTTPHeaders? = nil\n        ) {\n            super.init { parts in\n                guard parts.count >= 2 else {\n                    XCTFail(\"only \\(parts.count) parts\")\n                    return\n                }\n                if case .head(let h) = parts[0] {\n                    XCTAssertEqual(expectedVersion, h.version)\n                    XCTAssertEqual(expectedStatus, h.status)\n                    XCTAssertEqual(expectedHeaders, h.headers)\n                } else {\n                    XCTFail(\"unexpected type on index 0 \\(parts[0])\")\n                }\n\n                var i = 1\n                var bytes: [UInt8] = []\n                while i < parts.count - 1 {\n                    if case .body(let bb) = parts[i] {\n                        bb.withUnsafeReadableBytes { ptr in\n                            bytes.append(contentsOf: ptr)\n                        }\n                    } else {\n                        XCTFail(\"unexpected type on index \\(i) \\(parts[i])\")\n                    }\n                    i += 1\n                }\n\n                XCTAssertEqual(expectedBody, String(decoding: bytes, as: Unicode.UTF8.self))\n\n                if case .end(let trailers) = parts[parts.count - 1] {\n                    XCTAssertEqual(expectedTrailers, trailers)\n                } else {\n                    XCTFail(\"unexpected type on index \\(parts.count - 1) \\(parts[parts.count - 1])\")\n                }\n            }\n        }\n    }\n\n    private func testSimpleGet(\n        _ mode: SendMode,\n        httpVersion: HTTPVersion = .http1_1,\n        uri: String = \"/helloworld\",\n        expectedHeaders maybeExpectedHeaders: HTTPHeaders? = nil\n    ) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let expectedHeaders = maybeExpectedHeaders ?? HTTPHeaders([(\"content-length\", \"14\"), (\"connection\", \"close\")])\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n                // Set the handlers that are appled to the accepted Channels\n                .childChannelInitializer { channel in\n                    // Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.\n                    channel.eventLoop.makeCompletedFuture {\n                        let sync = channel.pipeline.syncOperations\n                        try sync.configureHTTPServerPipeline(withPipeliningAssistance: false)\n                        let httpHandler = SimpleHTTPServer(mode)\n                        try sync.addHandlers(httpHandler)\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let accumulation = HTTPClientResponsePartAssertHandler(httpVersion, .ok, expectedHeaders, \"Hello World!\\r\\n\")\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let sync = channel.pipeline.syncOperations\n                        try sync.addHTTPClientHandlers()\n                        try sync.addHandler(accumulation)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let head = HTTPRequestHead(version: httpVersion, method: .GET, uri: uri, headers: [\"Host\": \"apple.com\"])\n        try clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n\n        accumulation.syncWaitForCompletion()\n    }\n\n    func testSimpleGetChunkedEncodingByteBuffer() throws {\n        try testSimpleGetChunkedEncoding(.byteBuffer)\n    }\n\n    func testSimpleGetChunkedEncodingFileRegion() throws {\n        try testSimpleGetChunkedEncoding(.fileRegion)\n    }\n\n    private func testSimpleGetChunkedEncoding(_ mode: SendMode) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        var expectedHeaders = HTTPHeaders()\n        expectedHeaders.add(name: \"transfer-encoding\", value: \"chunked\")\n        expectedHeaders.add(name: \"connection\", value: \"close\")\n\n        let accumulation = HTTPClientResponsePartAssertHandler(.http1_1, .ok, expectedHeaders, \"12345678910\")\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n                // Set the handlers that are appled to the accepted Channels\n                .childChannelInitializer { channel in\n                    // Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.\n                    channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false).flatMap {\n                        channel.eventLoop.makeCompletedFuture {\n                            let httpHandler = SimpleHTTPServer(mode)\n                            return try channel.pipeline.syncOperations.addHandler(httpHandler)\n                        }\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHTTPClientHandlers().flatMap {\n                        channel.pipeline.addHandler(accumulation)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let head = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/count-to-ten\",\n            headers: [\"Host\": \"apple.com\"]\n        )\n        try clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n        accumulation.syncWaitForCompletion()\n    }\n\n    func testSimpleGetTrailersByteBuffer() throws {\n        try testSimpleGetTrailers(.byteBuffer)\n    }\n\n    func testSimpleGetTrailersFileRegion() throws {\n        try testSimpleGetTrailers(.fileRegion)\n    }\n\n    func testSimpleGetChunkedEncodingWithZeroLengthBodyPart() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        var expectedHeaders = HTTPHeaders()\n        expectedHeaders.add(name: \"transfer-encoding\", value: \"chunked\")\n\n        let accumulation = HTTPClientResponsePartAssertHandler(.http1_1, .ok, expectedHeaders, \"Hello World\")\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n                // Set the handlers that are appled to the accepted Channels\n                .childChannelInitializer { channel in\n                    // Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.\n                    channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: true).flatMap {\n                        channel.eventLoop.makeCompletedFuture {\n                            let httpHandler = SimpleHTTPServer(.byteBuffer)\n                            return try channel.pipeline.syncOperations.addHandler(httpHandler)\n                        }\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHTTPClientHandlers().flatMap {\n                        channel.pipeline.addHandler(accumulation)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let head = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/zero-length-body-part\",\n            headers: [\"Host\": \"apple.com\"]\n        )\n        try clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n        accumulation.syncWaitForCompletion()\n    }\n\n    private func testSimpleGetTrailers(_ mode: SendMode) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        var expectedHeaders = HTTPHeaders()\n        expectedHeaders.add(name: \"transfer-encoding\", value: \"chunked\")\n        expectedHeaders.add(name: \"connection\", value: \"close\")\n\n        var expectedTrailers = HTTPHeaders()\n        expectedTrailers.add(name: \"x-url-path\", value: \"/trailers\")\n        expectedTrailers.add(name: \"x-should-trail\", value: \"sure\")\n\n        let accumulation = HTTPClientResponsePartAssertHandler(\n            .http1_1,\n            .ok,\n            expectedHeaders,\n            \"12345678910\",\n            expectedTrailers\n        )\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false).flatMap {\n                        channel.eventLoop.makeCompletedFuture {\n                            let httpHandler = SimpleHTTPServer(mode)\n                            return try channel.pipeline.syncOperations.addHandler(httpHandler)\n                        }\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHTTPClientHandlers().flatMap {\n                        channel.pipeline.addHandler(accumulation)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let head = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/trailers\", headers: [\"Host\": \"apple.com\"])\n        try clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n\n        accumulation.syncWaitForCompletion()\n    }\n\n    func testMassiveResponseByteBuffer() throws {\n        try testMassiveResponse(.byteBuffer)\n    }\n\n    func testMassiveResponseFileRegion() throws {\n        try testMassiveResponse(.fileRegion)\n    }\n\n    func testMassiveResponse(_ mode: SendMode) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let accumulation = ArrayAccumulationHandler<ByteBuffer> { bbs in\n            let expectedSuffix = HTTPServerClientTest.massiveResponseBytes\n            let actual = bbs.allAsBytes()\n            XCTAssertGreaterThan(actual.count, expectedSuffix.count)\n            let actualSuffix = actual[(actual.count - expectedSuffix.count)..<actual.count]\n            XCTAssertEqual(expectedSuffix.count, actualSuffix.count)\n            XCTAssert(expectedSuffix.elementsEqual(actualSuffix))\n        }\n        let numBytes = 16 * 1024\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n                // Set the handlers that are appled to the accepted Channels\n                .childChannelInitializer { channel in\n                    // Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.\n                    channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false).flatMap {\n                        channel.eventLoop.makeCompletedFuture {\n                            let httpHandler = SimpleHTTPServer(mode)\n                            return try channel.pipeline.syncOperations.addHandler(httpHandler)\n                        }\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer({ $0.pipeline.addHandler(accumulation) })\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n        buffer.writeStaticString(\"GET /massive-response HTTP/1.1\\r\\nHost: nio.net\\r\\n\\r\\n\")\n\n        try clientChannel.writeAndFlush(buffer).wait()\n        accumulation.syncWaitForCompletion()\n    }\n\n    func testHead() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        var expectedHeaders = HTTPHeaders()\n        expectedHeaders.add(name: \"content-length\", value: \"5000\")\n        expectedHeaders.add(name: \"connection\", value: \"close\")\n\n        let accumulation = HTTPClientResponsePartAssertHandler(.http1_1, .ok, expectedHeaders, \"\")\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false).flatMap {\n                        channel.eventLoop.makeCompletedFuture {\n                            let httpHandler = SimpleHTTPServer(.byteBuffer)\n                            return try channel.pipeline.syncOperations.addHandler(httpHandler)\n                        }\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHTTPClientHandlers().flatMap {\n                        channel.pipeline.addHandler(accumulation)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let head = HTTPRequestHead(version: .http1_1, method: .HEAD, uri: \"/head\", headers: [\"Host\": \"apple.com\"])\n        try clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n\n        accumulation.syncWaitForCompletion()\n    }\n\n    func test204() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        var expectedHeaders = HTTPHeaders()\n        expectedHeaders.add(name: \"connection\", value: \"keep-alive\")\n\n        let accumulation = HTTPClientResponsePartAssertHandler(.http1_1, .noContent, expectedHeaders, \"\")\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false).flatMap {\n                        channel.eventLoop.makeCompletedFuture {\n                            let httpHandler = SimpleHTTPServer(.byteBuffer)\n                            return try channel.pipeline.syncOperations.addHandler(httpHandler)\n                        }\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHTTPClientHandlers().flatMap {\n                        channel.pipeline.addHandler(accumulation)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let head = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/204\", headers: [\"Host\": \"apple.com\"])\n        try clientChannel.eventLoop.flatSubmit {\n            let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n            clientChannel.pipeline.syncOperations.write(NIOAny(HTTPClientRequestPart.head(head)), promise: nil)\n            clientChannel.pipeline.syncOperations.writeAndFlush(\n                NIOAny(HTTPClientRequestPart.end(nil)),\n                promise: promise\n            )\n            return promise.futureResult\n        }.wait()\n\n        accumulation.syncWaitForCompletion()\n    }\n\n    func testNoResponseHeaders() {\n        XCTAssertNoThrow(\n            try self.testSimpleGet(\n                .byteBuffer,\n                httpVersion: .http1_0,\n                uri: \"/no-headers\",\n                expectedHeaders: [:]\n            )\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPServerPipelineHandlerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOHTTP1\n\nprivate final class ReadRecorder: ChannelInboundHandler {\n    typealias InboundIn = HTTPServerRequestPart\n\n    enum Event: Equatable {\n        case channelRead(InboundIn)\n        case halfClose\n\n        static func == (lhs: Event, rhs: Event) -> Bool {\n            switch (lhs, rhs) {\n            case (.channelRead(let b1), .channelRead(let b2)):\n                return b1 == b2\n            case (.halfClose, .halfClose):\n                return true\n            default:\n                return false\n            }\n        }\n    }\n\n    public var reads: [Event] = []\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.reads.append(.channelRead(Self.unwrapInboundIn(data)))\n        context.fireChannelRead(data)\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch event {\n        case let evt as ChannelEvent where evt == ChannelEvent.inputClosed:\n            self.reads.append(.halfClose)\n        default:\n            context.fireUserInboundEventTriggered(event)\n        }\n    }\n}\n\nprivate final class WriteRecorder: ChannelOutboundHandler {\n    typealias OutboundIn = HTTPServerResponsePart\n\n    public var writes: [HTTPServerResponsePart] = []\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.writes.append(Self.unwrapOutboundIn(data))\n\n        context.write(data, promise: promise)\n    }\n}\n\nprivate final class ReadCountingHandler: ChannelOutboundHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Any\n\n    public var readCount = 0\n\n    func read(context: ChannelHandlerContext) {\n        self.readCount += 1\n        context.read()\n    }\n}\n\nprivate final class QuiesceEventRecorder: ChannelInboundHandler {\n    typealias InboundIn = Any\n    typealias InboundOut = Any\n\n    public var quiesceCount = 0\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        if event is ChannelShouldQuiesceEvent {\n            quiesceCount += 1\n        }\n        context.fireUserInboundEventTriggered(event)\n    }\n}\n\n// This handler drops close mode output. This is because EmbeddedChannel doesn't support it,\n// and tests here don't require that it does anything sensible.\nprivate final class CloseOutputSuppressor: ChannelOutboundHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Any\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        if mode == .output {\n            promise?.succeed()\n        } else {\n            context.close(mode: mode, promise: promise)\n        }\n    }\n}\n\nclass HTTPServerPipelineHandlerTest: XCTestCase {\n    var channel: EmbeddedChannel! = nil\n    var requestHead: HTTPRequestHead! = nil\n    var responseHead: HTTPResponseHead! = nil\n    fileprivate var readRecorder: ReadRecorder! = nil\n    fileprivate var readCounter: ReadCountingHandler! = nil\n    fileprivate var writeRecorder: WriteRecorder! = nil\n    fileprivate var pipelineHandler: HTTPServerPipelineHandler! = nil\n    fileprivate var quiesceEventRecorder: QuiesceEventRecorder! = nil\n\n    override func setUp() {\n        self.channel = EmbeddedChannel()\n        self.readRecorder = ReadRecorder()\n        self.readCounter = ReadCountingHandler()\n        self.writeRecorder = WriteRecorder()\n        self.pipelineHandler = HTTPServerPipelineHandler()\n        self.quiesceEventRecorder = QuiesceEventRecorder()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(CloseOutputSuppressor()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.readCounter))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPResponseEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.writeRecorder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.pipelineHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.readRecorder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.quiesceEventRecorder))\n\n        self.requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/path\")\n        self.requestHead.headers.add(name: \"Host\", value: \"example.com\")\n\n        self.responseHead = HTTPResponseHead(version: .http1_1, status: .ok)\n        self.responseHead.headers.add(name: \"Server\", value: \"SwiftNIO\")\n\n        // this activates the channel\n        XCTAssertNoThrow(try self.channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 1)).wait())\n    }\n\n    override func tearDown() {\n        if let channel = self.channel {\n            XCTAssertNoThrow(try channel.finish(acceptAlreadyClosed: true))\n            self.channel = nil\n        }\n        self.requestHead = nil\n        self.responseHead = nil\n        self.readRecorder = nil\n        self.readCounter = nil\n        self.writeRecorder = nil\n        self.pipelineHandler = nil\n        self.quiesceEventRecorder = nil\n    }\n\n    func testBasicBufferingBehaviour() throws {\n        // Send in 3 requests at once.\n        for _ in 0..<3 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // Only one request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Unblock by sending a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // Two requests should have made it through now.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now send the last response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // Now all three.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n    }\n\n    func testReadCallsAreSuppressedWhenPipelining() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send in a request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Call read again, twice. This should not change the number.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // This should have automatically triggered a call to read(), but only one.\n        XCTAssertEqual(self.readCounter.readCount, 2)\n    }\n\n    func testReadCallsAreSuppressedWhenUnbufferingIfThereIsStillBufferedData() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send in two requests.\n        for _ in 0..<2 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // Call read again, twice. This should not change the number.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // This should have not triggered a call to read.\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Try calling read some more.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Now send in the last response, and see the read go through.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n        XCTAssertEqual(self.readCounter.readCount, 2)\n    }\n\n    func testServerCanRespondEarly() throws {\n        // Send in the first part of a request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        // This is still moving forward: we can read.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Now the server sends a response immediately.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // We're still moving forward and can read.\n        XCTAssertEqual(self.readCounter.readCount, 1)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 2)\n\n        // The client response completes.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // We can still read.\n        XCTAssertEqual(self.readCounter.readCount, 2)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 3)\n    }\n\n    func testPipelineHandlerWillBufferHalfClose() throws {\n        // Send in 2 requests at once.\n        for _ in 0..<3 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // Now half-close the connection.\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n\n        // Only one request should have made it through, no half-closure yet.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Unblock by sending a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // Two requests should have made it through now.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now send the last response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // Now the half-closure should be delivered.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .halfClose,\n            ]\n        )\n    }\n\n    func testPipelineHandlerWillDeliverHalfCloseEarly() throws {\n        // Send in a request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Now send a new request but half-close the connection before we get .end.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n\n        // Only one request should have made it through, no half-closure yet.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Unblock by sending a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // The second request head, followed by the half-close, should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .halfClose,\n            ]\n        )\n    }\n\n    func testAReadIsNotIssuedWhenUnbufferingAHalfCloseAfterRequestComplete() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send in two requests and then half-close.\n        for _ in 0..<2 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n\n        // Call read again, twice. This should not change the number.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // This should have not triggered a call to read.\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Now send in the last response. This should also not issue a read.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n        XCTAssertEqual(self.readCounter.readCount, 1)\n    }\n\n    func testHalfCloseWhileWaitingForResponseIsPassedAlongIfNothingElseBuffered() throws {\n        // Send in 2 requests at once.\n        for _ in 0..<2 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // Only one request should have made it through, no half-closure yet.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Unblock by sending a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // Two requests should have made it through now. Still no half-closure.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now send the half-closure.\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n\n        // The half-closure should be delivered immediately.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .halfClose,\n            ]\n        )\n    }\n\n    func testRecursiveChannelReadInvocationsDoNotCauseIssues() throws {\n        func makeRequestHead(uri: String) -> HTTPRequestHead {\n            var requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: uri)\n            requestHead.headers.add(name: \"Host\", value: \"example.com\")\n            return requestHead\n        }\n\n        class VerifyOrderHandler: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n            typealias OutboundOut = HTTPServerResponsePart\n\n            enum NextExpectedMessageType {\n                case head\n                case end\n            }\n            enum State {\n                case req1HeadExpected\n                case req1EndExpected\n                case req2HeadExpected\n                case req2EndExpected\n                case req3HeadExpected\n                case req3EndExpected\n                case reqBoomHeadExpected\n                case reqBoomEndExpected\n\n                case done\n            }\n            var state: State = .req1HeadExpected\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let req = Self.unwrapInboundIn(data)\n                switch req {\n                case .head(let head):\n                    // except for \"req_1\", we always send the .end straight away\n                    var sendEnd = true\n                    switch head.uri {\n                    case \"/req_1\":\n                        XCTAssertEqual(.req1HeadExpected, self.state)\n                        self.state = .req1EndExpected\n                        // for req_1, we don't send the end straight away to force the others to be buffered\n                        sendEnd = false\n                    case \"/req_2\":\n                        XCTAssertEqual(.req2HeadExpected, self.state)\n                        self.state = .req2EndExpected\n                    case \"/req_3\":\n                        XCTAssertEqual(.req3HeadExpected, self.state)\n                        self.state = .req3EndExpected\n                    case \"/req_boom\":\n                        XCTAssertEqual(.reqBoomHeadExpected, self.state)\n                        self.state = .reqBoomEndExpected\n                    default:\n                        XCTFail(\"didn't expect \\(head)\")\n                    }\n                    context.write(\n                        Self.wrapOutboundOut(.head(HTTPResponseHead(version: .http1_1, status: .ok))),\n                        promise: nil\n                    )\n                    if sendEnd {\n                        context.write(Self.wrapOutboundOut(.end(nil)), promise: nil)\n                    }\n                    context.flush()\n                case .end:\n                    switch self.state {\n                    case .req1EndExpected:\n                        self.state = .req2HeadExpected\n                    case .req2EndExpected:\n                        self.state = .req3HeadExpected\n\n                        // this will cause `channelRead` to be recursively called and we need to make sure everything then still works\n                        try! (context.channel as! EmbeddedChannel).writeInbound(\n                            HTTPServerRequestPart.head(\n                                HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/req_boom\")\n                            )\n                        )\n                        try! (context.channel as! EmbeddedChannel).writeInbound(HTTPServerRequestPart.end(nil))\n                    case .req3EndExpected:\n                        self.state = .reqBoomHeadExpected\n                    case .reqBoomEndExpected:\n                        self.state = .done\n                    default:\n                        XCTFail(\"illegal state for end: \\(self.state)\")\n                    }\n                case .body:\n                    XCTFail(\"we don't send any bodies\")\n                }\n            }\n        }\n\n        let handler = VerifyOrderHandler()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        for f in 1...3 {\n            XCTAssertNoThrow(\n                try self.channel.writeInbound(HTTPServerRequestPart.head(makeRequestHead(uri: \"/req_\\(f)\")))\n            )\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // now we should have delivered the first request, with the second and third buffered because req_1's .end\n        // doesn't get sent by the handler (instead we'll do that below)\n        XCTAssertEqual(.req2HeadExpected, handler.state)\n\n        // finish 1st request, that will send through the 2nd one which will then write the 'req_boom' request\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        XCTAssertEqual(.done, handler.state)\n    }\n\n    func testQuiescingEventWhenInitiallyIdle() throws {\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingEventWhenIdleAfterARequest() throws {\n        // Send through one request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // The request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // No further events should have happened.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingInTheMiddleOfARequestNoResponseBitsYet() throws {\n        // Send through only the head.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [.channelRead(HTTPServerRequestPart.head(self.requestHead))]\n        )\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n\n        // Now send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // still missing the request .end\n        XCTAssertTrue(self.channel.isActive)\n\n        var reqWithConnectionClose: HTTPResponseHead = self.responseHead\n        reqWithConnectionClose.headers.add(name: \"connection\", value: \"close\")\n        XCTAssertEqual(\n            [\n                HTTPServerResponsePart.head(reqWithConnectionClose),\n                HTTPServerResponsePart.end(nil),\n            ],\n            self.writeRecorder.writes\n        )\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingAfterHavingReceivedRequestButBeforeResponseWasSent() throws {\n        // Send through a full request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n\n        // Now send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        XCTAssertFalse(self.channel.isActive)\n\n        var reqWithConnectionClose: HTTPResponseHead = self.responseHead\n        reqWithConnectionClose.headers.add(name: \"connection\", value: \"close\")\n        XCTAssertEqual(\n            [\n                HTTPServerResponsePart.head(reqWithConnectionClose),\n                HTTPServerResponsePart.end(nil),\n            ],\n            self.writeRecorder.writes\n        )\n\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingAfterHavingReceivedRequestAndResponseHeadButNoResponseEndYet() throws {\n        // Send through a full request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now send the response .head.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n\n        // Now send the response .end.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n        XCTAssertFalse(self.channel.isActive)\n\n        XCTAssertEqual(\n            [\n                HTTPServerResponsePart.head(self.responseHead),\n                HTTPServerResponsePart.end(nil),\n            ],\n            self.writeRecorder.writes\n        )\n\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingAfterRequestAndResponseHeadsButBeforeAnyEndsThenRequestEndBeforeResponseEnd() throws {\n        // Send through a request .head.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [.channelRead(HTTPServerRequestPart.head(self.requestHead))]\n        )\n\n        // Now send the response .head.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n\n        // Request .end.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n        XCTAssertTrue(self.channel.isActive)\n\n        // Response .end.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n        XCTAssertFalse(self.channel.isActive)\n\n        XCTAssertEqual(\n            [\n                HTTPServerResponsePart.head(self.responseHead),\n                HTTPServerResponsePart.end(nil),\n            ],\n            self.writeRecorder.writes\n        )\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingAfterRequestAndResponseHeadsButBeforeAnyEndsThenRequestEndAfterResponseEnd() throws {\n        // Send through a request .head.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [.channelRead(HTTPServerRequestPart.head(self.requestHead))]\n        )\n\n        // Now send the response .head.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n\n        // Response .end.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n        XCTAssertTrue(self.channel.isActive)\n\n        // Request .end.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        XCTAssertFalse(self.channel.isActive)\n\n        XCTAssertEqual(\n            [\n                HTTPServerResponsePart.head(self.responseHead),\n                HTTPServerResponsePart.end(nil),\n            ],\n            self.writeRecorder.writes\n        )\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testQuiescingAfterHavingReceivedOneRequestButBeforeResponseWasSentWithMoreRequestsInTheBuffer() throws {\n        // Send through a full request and buffer a few more\n        for _ in 0..<3 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // Check that only one request came through\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        XCTAssertTrue(self.channel.isActive)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n\n        // Now send a response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        XCTAssertFalse(self.channel.isActive)\n\n        var reqWithConnectionClose: HTTPResponseHead = self.responseHead\n        reqWithConnectionClose.headers.add(name: \"connection\", value: \"close\")\n\n        // check that only one response (with connection: close) came through\n        XCTAssertEqual(\n            [\n                HTTPServerResponsePart.head(reqWithConnectionClose),\n                HTTPServerResponsePart.end(nil),\n            ],\n            self.writeRecorder.writes\n        )\n\n        // Check that only one request came through\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        XCTAssertFalse(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testParserErrorOnly() throws {\n        class VerifyOrderHandler: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n            typealias OutboundOut = HTTPServerResponsePart\n\n            enum State {\n                case errorExpected\n                case done\n            }\n            var state: State = .errorExpected\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                XCTAssertEqual(HTTPParserError.unknown, error as? HTTPParserError)\n                XCTAssertEqual(.errorExpected, self.state)\n                self.state = .done\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTFail(\"no requests expected\")\n            }\n        }\n\n        let handler = VerifyOrderHandler()\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(HTTPServerProtocolErrorHandler()))\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(handler))\n\n        self.channel.pipeline.fireErrorCaught(HTTPParserError.unknown)\n\n        XCTAssertEqual(.done, handler.state)\n    }\n\n    func testLegitRequestFollowedByParserErrorArrivingWhilstResponseOutstanding() throws {\n        func makeRequestHead(uri: String) -> HTTPRequestHead {\n            var requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: uri)\n            requestHead.headers.add(name: \"Host\", value: \"example.com\")\n            return requestHead\n        }\n\n        class VerifyOrderHandler: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n            typealias OutboundOut = HTTPServerResponsePart\n\n            enum State {\n                case reqHeadExpected\n                case reqEndExpected\n                case errorExpected\n                case done\n            }\n            var state: State = .reqHeadExpected\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                XCTAssertEqual(HTTPParserError.closedConnection, error as? HTTPParserError)\n                XCTAssertEqual(.errorExpected, self.state)\n                self.state = .done\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let loopBoundContext = context.loopBound\n                switch Self.unwrapInboundIn(data) {\n                case .head:\n                    // We dispatch this to the event loop so that it doesn't happen immediately but rather can be\n                    // run from the driving test code whenever it wants by running the EmbeddedEventLoop.\n                    context.eventLoop.execute {\n                        let context = loopBoundContext.value\n                        context.writeAndFlush(\n                            Self.wrapOutboundOut(\n                                .head(\n                                    .init(\n                                        version: .http1_1,\n                                        status: .ok\n                                    )\n                                )\n                            ),\n                            promise: nil\n                        )\n                    }\n                    XCTAssertEqual(.reqHeadExpected, self.state)\n                    self.state = .reqEndExpected\n                case .body:\n                    XCTFail(\"no body expected\")\n                case .end:\n                    // We dispatch this to the event loop so that it doesn't happen immediately but rather can be\n                    // run from the driving test code whenever it wants by running the EmbeddedEventLoop.\n                    context.eventLoop.execute {\n                        let context = loopBoundContext.value\n                        context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n                    }\n                    XCTAssertEqual(.reqEndExpected, self.state)\n                    self.state = .errorExpected\n                }\n            }\n        }\n\n        let handler = VerifyOrderHandler()\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(HTTPServerProtocolErrorHandler()))\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(handler))\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(makeRequestHead(uri: \"/one\"))))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        self.channel.pipeline.fireErrorCaught(HTTPParserError.closedConnection)\n\n        // let's now run the HTTP responses that we enqueued earlier on.\n        (self.channel.eventLoop as! EmbeddedEventLoop).run()\n        XCTAssertEqual(.done, handler.state)\n    }\n\n    func testRemovingWithResponseOutstandingTriggersRead() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send in a request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Call read again, twice. This should not change the number.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Remove the handler.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(self.pipelineHandler).wait())\n\n        // This should have automatically triggered a call to read(), but only one.\n        XCTAssertEqual(self.readCounter.readCount, 2)\n\n        // Incidentally we shouldn't have fired a quiesce event.\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testRemovingWithPartialResponseOutstandingTriggersRead() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send in a request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Call read again, twice. This should not change the number.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send a partial response, which should not trigger a read.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Remove the handler.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(self.pipelineHandler).wait())\n\n        // This should have automatically triggered a call to read(), but only one.\n        XCTAssertEqual(self.readCounter.readCount, 2)\n\n        // Incidentally we shouldn't have fired a quiesce event.\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n    }\n\n    func testRemovingWithBufferedRequestForwards() throws {\n        // Send in a request, and part of another.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        // Only one request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Remove the handler.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(self.pipelineHandler).wait())\n\n        // The extra data should have been forwarded.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n            ]\n        )\n    }\n\n    func testQuiescingInAResponseThenRemovedFiresEventAndReads() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send through a request and part of another.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        // Only one request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Now quiesce the channel.\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Call read again, twice. This should not lead to reads, as we're waiting for the end.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Now remove the handler.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(self.pipelineHandler).wait())\n\n        // Channel should be open, but the quiesce event should have fired, and read\n        // shouldn't have been called as we aren't expecting more data.\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 1)\n        XCTAssertEqual(self.readCounter.readCount, 1)\n    }\n\n    func testQuiescingInAResponseThenRemovedFiresEventAndDoesntRead() throws {\n        // First, call read() and check it makes it through.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Send through just the head.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [.channelRead(HTTPServerRequestPart.head(self.requestHead))]\n        )\n\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n        XCTAssertEqual(self.readCounter.readCount, 1)\n        self.channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // Call read again, twice. This should pass through.\n        self.channel.read()\n        self.channel.read()\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 0)\n        XCTAssertEqual(self.readCounter.readCount, 3)\n\n        // Now remove the handler.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(self.pipelineHandler).wait())\n\n        // Channel should be open, but the quiesce event should have fired, and read\n        // shouldn't be (as it passed through.\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertEqual(self.quiesceEventRecorder.quiesceCount, 1)\n        XCTAssertEqual(self.readCounter.readCount, 3)\n    }\n\n    func testServerCanRespondContinue() throws {\n        // Send in the first part of a request.\n        var expect100ContinueHead = self.requestHead!\n        expect100ContinueHead.headers.replaceOrAdd(name: \"expect\", value: \"100-continue\")\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(expect100ContinueHead)))\n\n        var continueResponse = self.responseHead\n        continueResponse!.status = .continue\n\n        // Now the server sends a continue response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(continueResponse!)))\n\n        // The client response completes.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Now the server sends the final response.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n    }\n\n    func testServerCanRespondProcessingMultipleTimes() throws {\n        // Send in a request.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // We haven't completed our response, so no more reading\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        var processResponse: HTTPResponseHead = self.responseHead!\n        processResponse.status = .processing\n\n        // Now the server sends multiple processing responses.\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(processResponse)))\n\n        // We are processing... Reading not allowed\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        // Continue processing...\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(processResponse)))\n\n        // We are processing... Reading not allowed\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        // Continue processing...\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(processResponse)))\n\n        // We are processing... Reading not allowed\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        // Now send the actual response!\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n\n        // This should have triggered a read\n        XCTAssertEqual(self.readCounter.readCount, 1)\n    }\n\n    func testServerCloseOutputForcesReadsBackOn() throws {\n        // Send in a request\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Reads are blocked.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now the server sends close output\n        XCTAssertNoThrow(try channel.close(mode: .output).wait())\n\n        // This unblocked the read and further reads can continue.\n        XCTAssertEqual(self.readCounter.readCount, 1)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 2)\n    }\n\n    func testCloseOutputAlwaysAllowsReads() throws {\n        // Send in a request\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Reads are blocked.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Now the server sends close output\n        XCTAssertNoThrow(try channel.close(mode: .output).wait())\n\n        // This unblocked the read and further reads can continue.\n        XCTAssertEqual(self.readCounter.readCount, 1)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 2)\n\n        // New requests can come in, but are dropped.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Reads keep working.\n        XCTAssertEqual(self.readCounter.readCount, 2)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 3)\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n    }\n\n    func testCloseOutputFirstIsOkEvenIfItsABitWeird() throws {\n        // Server sends close output first\n        XCTAssertNoThrow(try channel.close(mode: .output).wait())\n\n        // Send in a request\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Reads are unblocked.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 1)\n\n        // But the data is dropped.\n        XCTAssertEqual(self.readRecorder.reads, [])\n\n        // New requests can come in, and are dropped.\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Reads keep working.\n        XCTAssertEqual(self.readCounter.readCount, 1)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 2)\n\n        XCTAssertEqual(self.readRecorder.reads, [])\n    }\n\n    func testPipelinedRequestsAreDroppedWhenWeSendCloseOutput() throws {\n        // Send in three requests\n        for _ in 0..<3 {\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n            XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        }\n\n        // Reads are blocked and only one request was read.\n        XCTAssertEqual(self.readCounter.readCount, 0)\n        self.channel.read()\n        XCTAssertEqual(self.readCounter.readCount, 0)\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n\n        // Server sends close mode output. The buffered requests are dropped.\n        XCTAssertNoThrow(try channel.close(mode: .output).wait())\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(HTTPServerRequestPart.head(self.requestHead)),\n                .channelRead(HTTPServerRequestPart.end(nil)),\n            ]\n        )\n    }\n\n    func testWritesAfterCloseOutputAreDropped() throws {\n        // Send in a request\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Server sends a head.\n        XCTAssertNoThrow(try self.channel.writeOutbound(HTTPServerResponsePart.head(self.responseHead)))\n\n        // Now the server sends close output\n        XCTAssertNoThrow(try channel.close(mode: .output).wait())\n\n        // Now, in error, the server sends .body and .end. Both pass unannounced.\n        XCTAssertNoThrow(try self.channel.writeOutbound(HTTPServerResponsePart.body(.byteBuffer(ByteBuffer()))))\n        XCTAssertNoThrow(try self.channel.writeOutbound(HTTPServerResponsePart.end(nil)))\n    }\n\n    func testSendingHeadTwiceGivesError() throws {\n        self.pipelineHandler.failOnPreconditions = false\n        // Sending a head once is normal\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        // Sending a head twice is an error\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead))) { error in\n            XCTAssertEqual(\n                error as? HTTPServerPipelineHandler.ConnectionStateError,\n                .preconditionViolated(message: \"received request head in state requestAndResponseEndPending\")\n            )\n        }\n    }\n\n    func testServerRespondToNothing() {\n        self.pipelineHandler.failOnPreconditions = false\n\n        // Writing an end whilst in state idle is an error\n        XCTAssertThrowsError(try self.channel.writeOutbound(HTTPServerResponsePart.end(nil))) { error in\n            XCTAssertEqual(\n                error as? HTTPServerPipelineHandler.ConnectionStateError,\n                .preconditionViolated(message: \"Unexpectedly received a response in state idle\")\n            )\n        }\n\n        // Calling finish surfaces the error again\n        XCTAssertThrowsError(try self.channel.finish()) { error in\n            XCTAssertEqual(\n                error as? HTTPServerPipelineHandler.ConnectionStateError,\n                .preconditionViolated(message: \"Unexpectedly received a response in state idle\")\n            )\n        }\n    }\n\n    func testServerRequestEndFirstIsError() {\n        self.pipelineHandler.failOnPreconditions = false\n        // End sending a request which was never started\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.end(nil))) { error in\n            XCTAssertEqual(\n                error as? HTTPServerPipelineHandler.ConnectionStateError,\n                .preconditionViolated(message: \"Received second request\")\n            )\n        }\n    }\n\n    func testForcefulShutdownWhenViolatedPrecondition() {\n        self.pipelineHandler.failOnPreconditions = false\n\n        // End sending a request which was never started\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.end(nil))) { error in\n            XCTAssertEqual(\n                error as? HTTPServerPipelineHandler.ConnectionStateError,\n                .preconditionViolated(message: \"Received second request\")\n            )\n        }\n        // The handler should now refuse further io, and forcefully shutdown\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        self.channel.embeddedEventLoop.run()\n\n        // Ensure the channel is closed\n        XCTAssertNoThrow(try self.channel.closeFuture.wait())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPServerProtocolErrorHandlerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOHTTP1\nimport XCTest\n\nclass HTTPServerProtocolErrorHandlerTest: XCTestCase {\n    func testHandlesBasicErrors() throws {\n        final class CloseOnHTTPErrorHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                if let error = error as? HTTPParserError {\n                    context.fireErrorCaught(error)\n                    context.close(promise: nil)\n                }\n            }\n        }\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.pipeline.configureHTTPServerPipeline(withErrorHandling: true).wait())\n        XCTAssertNoThrow(try channel.pipeline.addHandler(CloseOnHTTPErrorHandler()).wait())\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"GET / HTTP/1.1\\r\\nContent-Length: -4\\r\\n\\r\\n\")\n        do {\n            try channel.writeInbound(buffer)\n        } catch HTTPParserError.invalidContentLength {\n            // This error is expected\n        }\n        channel.embeddedEventLoop.run()\n\n        // The channel should be closed at this stage.\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n\n        // We expect exactly one ByteBuffer in the output.\n        guard var written = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"No writes\")\n            return\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n\n        // Check the response.\n        assertResponseIs(\n            response: written.readString(length: written.readableBytes)!,\n            expectedResponseLine: \"HTTP/1.1 400 Bad Request\",\n            expectedResponseHeaders: [\"Connection: close\", \"Content-Length: 0\"]\n        )\n    }\n\n    func testIgnoresNonParserErrors() throws {\n        enum DummyError: Error {\n            case error\n        }\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.pipeline.configureHTTPServerPipeline(withErrorHandling: true).wait())\n\n        channel.pipeline.fireErrorCaught(DummyError.error)\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertEqual(DummyError.error, error as? DummyError)\n        }\n\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testDoesNotSendAResponseIfResponseHasAlreadyStarted() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false, withErrorHandling: true)\n                .wait()\n        )\n        let res = HTTPServerResponsePart.head(\n            .init(\n                version: .http1_1,\n                status: .ok,\n                headers: .init([(\"Content-Length\", \"0\")])\n            )\n        )\n        XCTAssertNoThrow(try channel.writeOutbound(res))\n        // now we have started a response but it's not complete yet, let's inject a parser error\n        channel.pipeline.fireErrorCaught(HTTPParserError.invalidEOFState)\n        var allOutbound = try channel.readAllOutboundBuffers()\n        let allOutboundString = allOutbound.readString(length: allOutbound.readableBytes)\n        // there should be no HTTP/1.1 400 or anything in here\n        XCTAssertEqual(\"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\n\\r\\n\", allOutboundString)\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertEqual(.invalidEOFState, error as? HTTPParserError)\n        }\n    }\n\n    func testCanHandleErrorsWhenResponseHasStarted() throws {\n        enum NextExpectedState {\n            case head\n            case end\n            case none\n        }\n        class DelayWriteHandler: ChannelInboundHandler {\n            typealias InboundIn = HTTPServerRequestPart\n            typealias OutboundOut = HTTPServerResponsePart\n\n            private var nextExpected: NextExpectedState = .head\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let req = Self.unwrapInboundIn(data)\n                switch req {\n                case .head:\n                    XCTAssertEqual(.head, self.nextExpected)\n                    self.nextExpected = .end\n                    let res = HTTPServerResponsePart.head(\n                        .init(\n                            version: .http1_1,\n                            status: .ok,\n                            headers: .init([(\"Content-Length\", \"0\")])\n                        )\n                    )\n                    context.writeAndFlush(Self.wrapOutboundOut(res), promise: nil)\n                default:\n                    XCTAssertEqual(.end, self.nextExpected)\n                    self.nextExpected = .none\n                }\n            }\n\n        }\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.configureHTTPServerPipeline(withErrorHandling: true))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(DelayWriteHandler()))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\nGET / HT\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(try channel.close().wait())\n        channel.embeddedEventLoop.run()\n\n        // The channel should be closed at this stage.\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n\n        // We expect exactly one ByteBuffer in the output.\n        guard var written = try channel.readOutbound(as: ByteBuffer.self) else {\n            XCTFail(\"No writes\")\n            return\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n\n        // Check the response.\n        assertResponseIs(\n            response: written.readString(length: written.readableBytes)!,\n            expectedResponseLine: \"HTTP/1.1 200 OK\",\n            expectedResponseHeaders: [\"Content-Length: 0\"]\n        )\n    }\n\n    func testDoesSendAResponseIfInformationalHeaderWasSent() throws {\n        let channel = EmbeddedChannel()\n        defer { XCTAssertNoThrow(try channel.finish(acceptAlreadyClosed: false)) }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false, withErrorHandling: true)\n                .wait()\n        )\n        XCTAssertNoThrow(try channel.connect(to: .makeAddressResolvingHost(\"127.0.0.1\", port: 0)).wait())\n\n        // Send an head that expects a continue informational response\n        let reqHeadBytes = \"POST / HTTP/1.1\\r\\nTransfer-Encoding: chunked\\r\\nExpect: 100-continue\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(ByteBuffer(string: reqHeadBytes)))\n        let expectedHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .POST,\n            uri: \"/\",\n            headers: [\"Transfer-Encoding\": \"chunked\", \"Expect\": \"100-continue\"]\n        )\n        XCTAssertEqual(try channel.readInbound(as: HTTPServerRequestPart.self), .head(expectedHead))\n\n        // Respond with continue informational response\n        let continueResponse = HTTPResponseHead(version: .http1_1, status: .continue)\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(continueResponse)))\n        XCTAssertEqual(\n            try channel.readOutbound(as: ByteBuffer.self),\n            ByteBuffer(string: \"HTTP/1.1 100 Continue\\r\\n\\r\\n\")\n        )\n\n        // Expects a hex digit... But receives garbage\n        XCTAssertThrowsError(try channel.writeInbound(ByteBuffer(string: \"xyz\"))) {\n            XCTAssertEqual($0 as? HTTPParserError, .invalidChunkSize)\n        }\n\n        // Receive a bad request\n        XCTAssertEqual(\n            try channel.readOutbound(as: ByteBuffer.self),\n            ByteBuffer(string: \"HTTP/1.1 400 Bad Request\\r\\nConnection: close\\r\\nContent-Length: 0\\r\\n\\r\\n\")\n        )\n    }\n\n    func testDoesNotSendAResponseIfRealHeaderWasSentAfterInformationalHeader() throws {\n        let channel = EmbeddedChannel()\n        defer { XCTAssertNoThrow(try channel.finish(acceptAlreadyClosed: false)) }\n\n        XCTAssertNoThrow(try channel.connect(to: .makeAddressResolvingHost(\"127.0.0.1\", port: 0)).wait())\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(withPipeliningAssistance: false, withErrorHandling: true)\n                .wait()\n        )\n\n        // Send an head that expects a continue informational response\n        let reqHeadBytes = \"POST / HTTP/1.1\\r\\nTransfer-Encoding: chunked\\r\\nExpect: 100-continue\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(ByteBuffer(string: reqHeadBytes)))\n        let expectedHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .POST,\n            uri: \"/\",\n            headers: [\"Transfer-Encoding\": \"chunked\", \"Expect\": \"100-continue\"]\n        )\n        XCTAssertEqual(try channel.readInbound(as: HTTPServerRequestPart.self), .head(expectedHead))\n\n        // Respond with continue informational response\n        let continueResponse = HTTPResponseHead(version: .http1_1, status: .continue)\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(continueResponse)))\n        XCTAssertEqual(\n            try channel.readOutbound(as: ByteBuffer.self),\n            ByteBuffer(string: \"HTTP/1.1 100 Continue\\r\\n\\r\\n\")\n        )\n\n        // Send a a chunk\n        XCTAssertNoThrow(try channel.writeInbound(ByteBuffer(string: \"6\\r\\nfoobar\\r\\n\")))\n\n        // Server responds with an actual head, even though request has not finished yet\n        let acceptedResponse = HTTPResponseHead(version: .http1_1, status: .accepted, headers: [\"Content-Length\": \"20\"])\n        XCTAssertNoThrow(try channel.writeOutbound(HTTPServerResponsePart.head(acceptedResponse)))\n        XCTAssertEqual(\n            try channel.readOutbound(as: ByteBuffer.self),\n            ByteBuffer(string: \"HTTP/1.1 202 Accepted\\r\\nContent-Length: 20\\r\\n\\r\\n\")\n        )\n\n        // Client sends garbage chunk\n        XCTAssertThrowsError(try channel.writeInbound(ByteBuffer(string: \"xyz\"))) {\n            XCTAssertEqual($0 as? HTTPParserError, .invalidChunkSize)\n        }\n\n        XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self))\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOHTTP1\n@testable import NIOPosix\n\nextension ChannelPipeline {\n    fileprivate func assertDoesNotContainUpgrader() throws {\n        try self.assertDoesNotContain(handlerType: HTTPServerUpgradeHandler.self)\n    }\n\n    func assertDoesNotContain<Handler: ChannelHandler & _NIOCoreSendableMetatype>(\n        handlerType: Handler.Type,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        do {\n            try self.context(handlerType: handlerType)\n                .map { context in\n                    XCTFail(\"Found handler: \\(context.handler)\", file: (file), line: line)\n                }.wait()\n        } catch ChannelPipelineError.notFound {\n            // Nothing to see here\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    fileprivate func assertContainsUpgrader() {\n        do {\n            _ = try self.containsHandler(type: NIOTypedHTTPServerUpgradeHandler<Bool>.self).wait()\n        } catch {\n            self.assertContains(handlerType: HTTPServerUpgradeHandler.self)\n        }\n    }\n\n    func assertContains<Handler: ChannelHandler & _NIOCoreSendableMetatype>(handlerType: Handler.Type) {\n        XCTAssertNoThrow(try self.containsHandler(type: handlerType).wait(), \"did not find handler\")\n    }\n\n    fileprivate func removeUpgrader() throws {\n        try self.context(handlerType: HTTPServerUpgradeHandler.self).flatMap {\n            self.syncOperations.removeHandler(context: $0)\n        }.wait()\n    }\n\n    // Waits up to 1 second for the upgrader to be removed by polling the pipeline\n    // every 50ms checking for the handler.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    fileprivate func waitForUpgraderToBeRemoved() throws {\n        for _ in 0..<20 {\n            do {\n                _ = try self.containsHandler(type: HTTPServerUpgradeHandler.self).wait()\n                // handler present, keep waiting\n                usleep(50)\n            } catch ChannelPipelineError.notFound {\n                // Checking if the typed variant is present\n                do {\n                    _ = try self.containsHandler(type: NIOTypedHTTPServerUpgradeHandler<Bool>.self).wait()\n                    // handler present, keep waiting\n                    usleep(50)\n                } catch ChannelPipelineError.notFound {\n                    // No upgrader, we're good.\n                    return\n                }\n            }\n        }\n\n        XCTFail(\"Upgrader never removed\")\n    }\n}\n\nextension EmbeddedChannel {\n    func readAllOutboundBuffers() throws -> ByteBuffer {\n        var buffer = self.allocator.buffer(capacity: 100)\n        while var writtenData = try self.readOutbound(as: ByteBuffer.self) {\n            buffer.writeBuffer(&writtenData)\n        }\n\n        return buffer\n    }\n\n    func readAllOutboundString() throws -> String {\n        var buffer = try self.readAllOutboundBuffers()\n        return buffer.readString(length: buffer.readableBytes)!\n    }\n}\n\nprivate typealias UpgradeCompletionHandler = @Sendable (ChannelHandlerContext) -> Void\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nprivate func serverHTTPChannelWithAutoremoval(\n    group: EventLoopGroup,\n    pipelining: Bool,\n    upgraders: [any TypedAndUntypedHTTPServerProtocolUpgrader],\n    extraHandlers: [ChannelHandler & Sendable],\n    _ upgradeCompletionHandler: @escaping UpgradeCompletionHandler\n) throws -> (Channel, EventLoopFuture<Channel>) {\n    let p = group.next().makePromise(of: Channel.self)\n    let c = try ServerBootstrap(group: group)\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .childChannelInitializer { channel in\n            p.succeed(channel)\n            let upgradeConfig = (upgraders: upgraders, completionHandler: upgradeCompletionHandler)\n            return channel.pipeline.configureHTTPServerPipeline(\n                withPipeliningAssistance: pipelining,\n                withServerUpgrade: upgradeConfig\n            ).flatMap {\n                let futureResults = extraHandlers.map { channel.pipeline.addHandler($0) }\n                return EventLoopFuture.andAllSucceed(futureResults, on: channel.eventLoop)\n            }\n        }.bind(host: \"127.0.0.1\", port: 0).wait()\n    return (c, p.futureResult)\n}\n\nprivate class SingleHTTPResponseAccumulator: ChannelInboundHandler {\n    typealias InboundIn = ByteBuffer\n\n    private var receiveds: [InboundIn] = []\n    private let allDoneBlock: ([InboundIn]) -> Void\n\n    init(completion: @escaping ([InboundIn]) -> Void) {\n        self.allDoneBlock = completion\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let buffer = Self.unwrapInboundIn(data)\n        self.receiveds.append(buffer)\n        if let finalBytes = buffer.getBytes(at: buffer.writerIndex - 4, length: 4),\n            finalBytes == [0x0D, 0x0A, 0x0D, 0x0A]\n        {\n            self.allDoneBlock(self.receiveds)\n        }\n    }\n}\n\nprivate class ExplodingHandler: ChannelInboundHandler {\n    typealias InboundIn = Any\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        XCTFail(\"Received unexpected read\")\n    }\n}\n\nprivate func connectedClientChannel(group: EventLoopGroup, serverAddress: SocketAddress) throws -> Channel {\n    try ClientBootstrap(group: group)\n        .connect(to: serverAddress)\n        .wait()\n}\n\ninternal func assertResponseIs(response: String, expectedResponseLine: String, expectedResponseHeaders: [String]) {\n    var lines = response.split(separator: \"\\r\\n\", omittingEmptySubsequences: false).map { String($0) }\n\n    // We never expect a response body here. This means we need the last two entries to be empty strings.\n    XCTAssertEqual(\"\", lines.removeLast())\n    XCTAssertEqual(\"\", lines.removeLast())\n\n    // Check the response line is correct.\n    let actualResponseLine = lines.removeFirst()\n    XCTAssertEqual(expectedResponseLine, actualResponseLine)\n\n    // For each header, find it in the actual response headers and remove it.\n    for expectedHeader in expectedResponseHeaders {\n        guard let index = lines.firstIndex(of: expectedHeader) else {\n            XCTFail(\"Could not find header \\\"\\(expectedHeader)\\\"\")\n            return\n        }\n        lines.remove(at: index)\n    }\n\n    // That should be all the headers.\n    XCTAssertEqual(lines.count, 0)\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nprotocol TypedAndUntypedHTTPServerProtocolUpgrader: HTTPServerProtocolUpgrader, NIOTypedHTTPServerProtocolUpgrader\nwhere UpgradeResult == Bool {}\n\nprivate final class ExplodingUpgrader: TypedAndUntypedHTTPServerProtocolUpgrader, Sendable {\n    let supportedProtocol: String\n    let requiredUpgradeHeaders: [String]\n\n    private enum Explosion: Error {\n        case KABOOM\n    }\n\n    init(forProtocol `protocol`: String, requiringHeaders: [String] = []) {\n        self.supportedProtocol = `protocol`\n        self.requiredUpgradeHeaders = requiringHeaders\n    }\n\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        XCTFail(\"buildUpgradeResponse called\")\n        return channel.eventLoop.makeFailedFuture(Explosion.KABOOM)\n    }\n\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        XCTFail(\"upgrade called\")\n        return context.eventLoop.makeSucceededFuture(())\n    }\n\n    func upgrade(channel: Channel, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Bool> {\n        XCTFail(\"upgrade called\")\n        return channel.eventLoop.makeSucceededFuture(true)\n    }\n}\n\nprivate final class UpgraderSaysNo: TypedAndUntypedHTTPServerProtocolUpgrader, Sendable {\n    let supportedProtocol: String\n    let requiredUpgradeHeaders: [String] = []\n\n    enum No: Error {\n        case no\n    }\n\n    init(forProtocol `protocol`: String) {\n        self.supportedProtocol = `protocol`\n    }\n\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        channel.eventLoop.makeFailedFuture(No.no)\n    }\n\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        XCTFail(\"upgrade called\")\n        return context.eventLoop.makeSucceededFuture(())\n    }\n\n    func upgrade(channel: Channel, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Bool> {\n        XCTFail(\"upgrade called\")\n        return channel.eventLoop.makeSucceededFuture(true)\n    }\n}\n\nprivate final class SuccessfulUpgrader: TypedAndUntypedHTTPServerProtocolUpgrader, Sendable {\n    let supportedProtocol: String\n    let requiredUpgradeHeaders: [String]\n    private let onUpgradeComplete: @Sendable (HTTPRequestHead) -> Void\n    private let buildUpgradeResponseFuture: @Sendable (Channel, HTTPHeaders) -> EventLoopFuture<HTTPHeaders>\n\n    init(\n        forProtocol `protocol`: String,\n        requiringHeaders headers: [String],\n        buildUpgradeResponseFuture: @escaping @Sendable (Channel, HTTPHeaders) -> EventLoopFuture<HTTPHeaders>,\n        onUpgradeComplete: @escaping @Sendable (HTTPRequestHead) -> Void\n    ) {\n        self.supportedProtocol = `protocol`\n        self.requiredUpgradeHeaders = headers\n        self.onUpgradeComplete = onUpgradeComplete\n        self.buildUpgradeResponseFuture = buildUpgradeResponseFuture\n    }\n\n    convenience init(\n        forProtocol `protocol`: String,\n        requiringHeaders headers: [String],\n        onUpgradeComplete: @escaping @Sendable (HTTPRequestHead) -> Void\n    ) {\n        self.init(\n            forProtocol: `protocol`,\n            requiringHeaders: headers,\n            buildUpgradeResponseFuture: { $0.eventLoop.makeSucceededFuture($1) },\n            onUpgradeComplete: onUpgradeComplete\n        )\n    }\n\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        var headers = initialResponseHeaders\n        headers.add(name: \"X-Upgrade-Complete\", value: \"true\")\n        return self.buildUpgradeResponseFuture(channel, headers)\n    }\n\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        self.onUpgradeComplete(upgradeRequest)\n        return context.eventLoop.makeSucceededFuture(())\n    }\n\n    func upgrade(channel: Channel, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Bool> {\n        self.onUpgradeComplete(upgradeRequest)\n        return channel.eventLoop.makeSucceededFuture(true)\n    }\n}\n\nprivate final class DelayedUnsuccessfulUpgrader: TypedAndUntypedHTTPServerProtocolUpgrader, Sendable {\n    let supportedProtocol: String\n    let requiredUpgradeHeaders: [String]\n\n    private let upgradePromise: EventLoopPromise<Bool>\n\n    init(forProtocol `protocol`: String, eventLoop: EventLoop) {\n        self.supportedProtocol = `protocol`\n        self.upgradePromise = eventLoop.makePromise()\n        self.requiredUpgradeHeaders = []\n    }\n\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        channel.eventLoop.makeSucceededFuture([:])\n    }\n\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        self.upgradePromise.futureResult.map { _ in }\n    }\n\n    func unblockUpgrade(withError error: Error) {\n        self.upgradePromise.fail(error)\n    }\n\n    func upgrade(channel: Channel, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Bool> {\n        self.upgradePromise.futureResult\n    }\n}\n\nprivate final class UpgradeDelayer: TypedAndUntypedHTTPServerProtocolUpgrader, Sendable {\n    let supportedProtocol: String\n    let requiredUpgradeHeaders: [String] = []\n\n    private let upgradePromise: EventLoopPromise<Bool>\n    private let upgradeRequestedPromise: EventLoopPromise<Void>\n\n    /// - Parameters:\n    ///   - protocol: The protocol this upgrader knows how to support.\n    ///   - upgradeRequestedPromise: Will be fulfilled when upgrade() is called\n    init(forProtocol `protocol`: String, upgradeRequestedPromise: EventLoopPromise<Void>, eventLoop: any EventLoop) {\n        self.supportedProtocol = `protocol`\n        self.upgradePromise = eventLoop.makePromise()\n        self.upgradeRequestedPromise = upgradeRequestedPromise\n    }\n\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        var headers = initialResponseHeaders\n        headers.add(name: \"X-Upgrade-Complete\", value: \"true\")\n        return channel.eventLoop.makeSucceededFuture(headers)\n    }\n\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        upgradeRequestedPromise.succeed()\n        return self.upgradePromise.futureResult.map { _ in }\n    }\n\n    func unblockUpgrade() {\n        self.upgradePromise.succeed(true)\n    }\n\n    func upgrade(channel: Channel, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Bool> {\n        self.upgradeRequestedPromise.succeed()\n        return self.upgradePromise.futureResult\n    }\n}\n\nprivate final class UpgradeResponseDelayer: HTTPServerProtocolUpgrader, Sendable {\n    let supportedProtocol: String\n    let requiredUpgradeHeaders: [String] = []\n\n    private let buildUpgradeResponseHandler: @Sendable () -> EventLoopFuture<Void>\n\n    init(\n        forProtocol `protocol`: String,\n        buildUpgradeResponseHandler: @escaping @Sendable () -> EventLoopFuture<Void>\n    ) {\n        self.supportedProtocol = `protocol`\n        self.buildUpgradeResponseHandler = buildUpgradeResponseHandler\n    }\n\n    func buildUpgradeResponse(\n        channel: Channel,\n        upgradeRequest: HTTPRequestHead,\n        initialResponseHeaders: HTTPHeaders\n    ) -> EventLoopFuture<HTTPHeaders> {\n        self.buildUpgradeResponseHandler().map {\n            var headers = initialResponseHeaders\n            headers.add(name: \"X-Upgrade-Complete\", value: \"true\")\n            return headers\n        }\n    }\n\n    func upgrade(context: ChannelHandlerContext, upgradeRequest: HTTPRequestHead) -> EventLoopFuture<Void> {\n        context.eventLoop.makeSucceededFuture(())\n    }\n}\n\nprivate final class UserEventSaver<EventType: Sendable>: ChannelInboundHandler, Sendable {\n    typealias InboundIn = Any\n\n    private let _events = NIOLockedValueBox<[EventType]>([])\n\n    var events: [EventType] {\n        self._events.withLockedValue { $0 }\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        self._events.withLockedValue { $0.append(event as! EventType) }\n        context.fireUserInboundEventTriggered(event)\n    }\n}\n\nprivate final class ErrorSaver: ChannelInboundHandler, Sendable {\n    typealias InboundIn = Any\n    typealias InboundOut = Any\n\n    private let _errors = NIOLockedValueBox<[any Error]>([])\n\n    var errors: [Error] {\n        self._errors.withLockedValue { $0 }\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self._errors.withLockedValue { $0.append(error) }\n        context.fireErrorCaught(error)\n    }\n}\n\nprivate final class DataRecorder<T: Sendable>: ChannelInboundHandler, Sendable {\n    typealias InboundIn = T\n\n    private let data = NIOLockedValueBox<[T]>([])\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let datum = Self.unwrapInboundIn(data)\n        self.data.withLockedValue { $0.append(datum) }\n    }\n\n    // Must be called from inside the event loop on pain of death!\n    func receivedData() -> [T] {\n        self.data.withLockedValue { $0 }\n    }\n}\n\nprivate class ReentrantReadOnChannelReadCompleteHandler: ChannelInboundHandler {\n    typealias InboundIn = Any\n    typealias InboundOut = Any\n\n    private var didRead = false\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        // Make sure we only do this once.\n        if !self.didRead {\n            self.didRead = true\n            let data = context.channel.allocator.buffer(string: \"re-entrant read from channelReadComplete!\")\n\n            // Please never do this.\n            context.channel.pipeline.fireChannelRead(data)\n        }\n        context.fireChannelReadComplete()\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nclass HTTPServerUpgradeTestCase: XCTestCase {\n\n    static let eventLoop = MultiThreadedEventLoopGroup.singleton.next()\n\n    fileprivate func setUpTestWithAutoremoval(\n        pipelining: Bool = false,\n        upgraders: [any TypedAndUntypedHTTPServerProtocolUpgrader],\n        extraHandlers: [ChannelHandler & Sendable],\n        notUpgradingHandler: (@Sendable (Channel) -> EventLoopFuture<Bool>)? = nil,\n        upgradeErrorHandler: (@Sendable (Error) -> Void)? = nil,\n        _ upgradeCompletionHandler: @escaping UpgradeCompletionHandler\n    ) throws -> (Channel, Channel, Channel) {\n        let (serverChannel, connectedServerChannelFuture) = try serverHTTPChannelWithAutoremoval(\n            group: Self.eventLoop,\n            pipelining: pipelining,\n            upgraders: upgraders,\n            extraHandlers: extraHandlers,\n            upgradeCompletionHandler\n        )\n        let clientChannel = try connectedClientChannel(\n            group: Self.eventLoop,\n            serverAddress: serverChannel.localAddress!\n        )\n        return (serverChannel, clientChannel, try connectedServerChannelFuture.wait())\n    }\n\n    func testUpgradeWithoutUpgrade() throws {\n        let (server, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [ExplodingUpgrader(forProtocol: \"myproto\")],\n            extraHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            XCTFail(\"upgrade completed\")\n        }\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        let request = \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // At this time the channel pipeline should not contain our handler: it should have removed itself.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgradeAfterInitialRequest() throws {\n        let (server, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [ExplodingUpgrader(forProtocol: \"myproto\")],\n            extraHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            XCTFail(\"upgrade completed\")\n        }\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        // This request fires a subsequent upgrade in immediately. It should also be ignored.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\nOPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nConnection: upgrade\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // At this time the channel pipeline should not contain our handler: it should have removed itself.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgradeHandlerBarfsOnUnexpectedOrdering() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertEqual(true, try? channel.finish().isClean)\n        }\n\n        let handler = HTTPServerUpgradeHandler(\n            upgraders: [ExplodingUpgrader(forProtocol: \"myproto\")],\n            httpEncoder: HTTPResponseEncoder(),\n            extraHTTPHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            XCTFail(\"upgrade completed\")\n        }\n        let data = HTTPServerRequestPart.body(channel.allocator.buffer(string: \"hello\"))\n\n        XCTAssertNoThrow(try channel.pipeline.addHandler(handler).wait())\n\n        XCTAssertThrowsError(try channel.writeInbound(data)) { error in\n            XCTAssertEqual(.invalidHTTPOrdering, error as? HTTPServerUpgradeErrors)\n        }\n\n        // The handler removed itself from the pipeline and passed the unexpected\n        // data on.\n        try channel.pipeline.assertDoesNotContainUpgrader()\n        let receivedData: HTTPServerRequestPart = try channel.readInbound()!\n        XCTAssertEqual(data, receivedData)\n    }\n\n    func testSimpleUpgradeSucceeds() throws {\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssert(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { (context) in\n            // This is called before the upgrader gets called.\n            XCTAssertNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n    }\n\n    func testUpgradeRequiresCorrectHeaders() throws {\n        let (server, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [ExplodingUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"])],\n            extraHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            XCTFail(\"upgrade completed\")\n        }\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        let request = \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: upgrade\\r\\nUpgrade: myproto\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // At this time the channel pipeline should not contain our handler: it should have removed itself.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgradeRequiresHeadersInConnection() throws {\n        let (server, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [ExplodingUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"])],\n            extraHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            XCTFail(\"upgrade completed\")\n        }\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        // This request is missing a 'Kafkaesque' connection header.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: upgrade\\r\\nUpgrade: myproto\\r\\nKafkaesque: true\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // At this time the channel pipeline should not contain our handler: it should have removed itself.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgradeOnlyHandlesKnownProtocols() throws {\n        let (server, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [ExplodingUpgrader(forProtocol: \"myproto\")],\n            extraHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            XCTFail(\"upgrade completed\")\n        }\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        let request = \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: upgrade\\r\\nUpgrade: something-else\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // At this time the channel pipeline should not contain our handler: it should have removed itself.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgradeRespectsClientPreference() throws {\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let explodingUpgrader = ExplodingUpgrader(forProtocol: \"exploder\")\n        let successfulUpgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssert(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [explodingUpgrader, successfulUpgrader],\n            extraHandlers: []\n        ) { context in\n            // This is called before the upgrader gets called.\n            XCTAssertNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto, exploder\\r\\nKafkaesque: yup\\r\\nConnection: upgrade, kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgradeFiresUserEvent() throws {\n        // The user event is fired last, so we don't see it until both other callbacks\n        // have fired.\n        let eventSaver = UnsafeTransfer(UserEventSaver<HTTPServerUpgradeEvents>())\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: []) { req in\n            XCTAssertEqual(eventSaver.wrappedValue.events.count, 0)\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: [eventSaver.wrappedValue]\n        ) { context in\n            XCTAssertEqual(eventSaver.wrappedValue.events.count, 0)\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade,kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we should have received one user event. We schedule this onto the\n        // event loop to guarantee thread safety.\n        XCTAssertNoThrow(\n            try connectedServer.eventLoop.scheduleTask(deadline: .now()) {\n                XCTAssertEqual(eventSaver.wrappedValue.events.count, 1)\n                if case .upgradeComplete(let proto, let req) = eventSaver.wrappedValue.events[0] {\n                    XCTAssertEqual(proto, \"myproto\")\n                    XCTAssertEqual(req.method, .OPTIONS)\n                    XCTAssertEqual(req.uri, \"*\")\n                    XCTAssertEqual(req.version, .http1_1)\n                } else {\n                    XCTFail(\"Unexpected event: \\(eventSaver.wrappedValue.events[0])\")\n                }\n            }.futureResult.wait()\n        )\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testUpgraderCanRejectUpgradeForPersonalReasons() throws {\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let explodingUpgrader = UpgraderSaysNo(forProtocol: \"noproto\")\n        let successfulUpgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssert(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n        let errorCatcher = ErrorSaver()\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [explodingUpgrader, successfulUpgrader],\n            extraHandlers: [errorCatcher]\n        ) { context in\n            // This is called before the upgrader gets called.\n            XCTAssertNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: noproto,myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade, kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n\n        // And we want to confirm we saved the error.\n        XCTAssertEqual(errorCatcher.errors.count, 1)\n\n        switch errorCatcher.errors[0] {\n        case UpgraderSaysNo.No.no:\n            break\n        default:\n            XCTFail(\"Unexpected error: \\(errorCatcher.errors[0])\")\n        }\n    }\n\n    func testUpgradeIsCaseInsensitive() throws {\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"WeIrDcAsE\"]) { req in }\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { context in\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nWeirdcase: yup\\r\\nConnection: upgrade,weirdcase\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testDelayedUpgradeBehaviour() throws {\n        let upgradeRequestPromise = Self.eventLoop.makePromise(of: Void.self)\n        let upgrader = UpgradeDelayer(\n            forProtocol: \"myproto\",\n            upgradeRequestedPromise: upgradeRequestPromise,\n            eventLoop: Self.eventLoop\n        )\n        let (server, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { context in }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n\n        let clientHandlerAdded = client.pipeline.eventLoop.submit {\n            let clientHandler = SingleHTTPResponseAccumulator { buffers in\n                let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                    separator: \"\"\n                )\n                assertResponseIs(\n                    response: resultString,\n                    expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                    expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n                )\n                completePromise.succeed(())\n            }\n\n            return try client.pipeline.syncOperations.addHandler(clientHandler)\n        }\n        XCTAssertNoThrow(try clientHandlerAdded.wait())\n\n        // This request is safe to upgrade.\n        let request = \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nConnection: upgrade\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Ok, we don't think this upgrade should have succeeded yet, but neither should it have failed. We want to\n        // dispatch onto the server event loop and check that the channel still contains the upgrade handler.\n        connectedServer.pipeline.assertContainsUpgrader()\n\n        // Wait for the upgrade function to be called\n        try upgradeRequestPromise.futureResult.wait()\n        // Ok, let's unblock the upgrade now. The machinery should do its thing.\n        try server.eventLoop.submit {\n            upgrader.unblockUpgrade()\n        }.wait()\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n        client.close(promise: nil)\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testBuffersInboundDataDuringDelayedUpgrade() throws {\n        let upgradeRequestPromise = Self.eventLoop.makePromise(of: Void.self)\n        let upgrader = UpgradeDelayer(\n            forProtocol: \"myproto\",\n            upgradeRequestedPromise: upgradeRequestPromise,\n            eventLoop: Self.eventLoop\n        )\n        let dataRecorder = DataRecorder<ByteBuffer>()\n\n        let (server, client, _) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: [dataRecorder]\n        ) { context in }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade, but is immediately followed by non-HTTP data.\n        let request = \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nConnection: upgrade\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Ok, send the application data in.\n        let appData = \"supersecretawesome data definitely not http\\r\\nawesome\\r\\ndata\\ryeah\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: appData)).wait())\n\n        // Now we need to wait a little bit before we move forward. This needs to give time for the\n        // I/O to settle. 100ms should be plenty to handle that I/O.\n        try server.eventLoop.scheduleTask(in: .milliseconds(100)) {\n            upgrader.unblockUpgrade()\n        }.futureResult.wait()\n\n        client.close(promise: nil)\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // Let's check that the data recorder saw everything.\n        let data = try server.eventLoop.submit {\n            dataRecorder.receivedData()\n        }.wait()\n        let resultString = data.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n            separator: \"\"\n        )\n        XCTAssertEqual(resultString, appData)\n    }\n\n    func testDelayedUpgradeResponse() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let upgradeRequested = NIOLockedValueBox(false)\n\n        let delayedPromise = channel.eventLoop.makePromise(of: Void.self)\n        let delayedUpgrader = UpgradeResponseDelayer(forProtocol: \"myproto\") {\n            XCTAssertFalse(upgradeRequested.withLockedValue { $0 })\n            upgradeRequested.withLockedValue { $0 = true }\n            return delayedPromise.futureResult\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(\n                withServerUpgrade: (upgraders: [delayedUpgrader], completionHandler: { context in })\n            ).wait()\n        )\n\n        // Let's send in an upgrade request.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: request)))\n\n        // Upgrade has been requested but not proceeded.\n        XCTAssertTrue(upgradeRequested.withLockedValue { $0 })\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(try XCTAssertNil(channel.readOutbound(as: ByteBuffer.self)))\n\n        // Ok, now we can upgrade. Upgrader should be out of the pipeline, and we should have seen the 101 response.\n        delayedPromise.succeed(())\n        channel.embeddedEventLoop.run()\n        XCTAssertNoThrow(try channel.pipeline.assertDoesNotContainUpgrader())\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try channel.readAllOutboundString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"X-Upgrade-Complete: true\",\n                    \"upgrade: myproto\",\n                    \"connection: upgrade\",\n                ]\n            )\n        )\n    }\n\n    func testChainsDelayedUpgradesAppropriately() throws {\n        enum No: Error {\n            case no\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        let upgradingProtocol = NIOLockedValueBox(\"\")\n\n        let failingProtocolPromise = channel.eventLoop.makePromise(of: Void.self)\n        let failingProtocolUpgrader = UpgradeResponseDelayer(forProtocol: \"failingProtocol\") {\n            XCTAssertEqual(upgradingProtocol.withLockedValue { $0 }, \"\")\n            upgradingProtocol.withLockedValue { $0 = \"failingProtocol\" }\n            return failingProtocolPromise.futureResult\n        }\n\n        let myprotoPromise = channel.eventLoop.makePromise(of: Void.self)\n        let myprotoUpgrader = UpgradeResponseDelayer(forProtocol: \"myproto\") {\n            XCTAssertEqual(upgradingProtocol.withLockedValue { $0 }, \"failingProtocol\")\n            upgradingProtocol.withLockedValue { $0 = \"myproto\" }\n            return myprotoPromise.futureResult\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(\n                withServerUpgrade: (\n                    upgraders: [myprotoUpgrader, failingProtocolUpgrader], completionHandler: { context in }\n                )\n            ).wait()\n        )\n\n        // Let's send in an upgrade request.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: failingProtocol, myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: request)))\n\n        // Upgrade has been requested but not proceeded for the failing protocol.\n        XCTAssertEqual(upgradingProtocol.withLockedValue { $0 }, \"failingProtocol\")\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n\n        // Ok, now we'll fail the promise. This will catch an error, but the upgrade won't happen: instead, the second handler will be fired.\n        failingProtocolPromise.fail(No.no)\n        XCTAssertEqual(upgradingProtocol.withLockedValue { $0 }, \"myproto\")\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertEqual(.no, error as? No)\n        }\n\n        // Ok, now we can upgrade. Upgrader should be out of the pipeline, and we should have seen the 101 response.\n        myprotoPromise.succeed(())\n        channel.embeddedEventLoop.run()\n        XCTAssertNoThrow(try channel.pipeline.assertDoesNotContainUpgrader())\n        assertResponseIs(\n            response: try channel.readAllOutboundString(),\n            expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n            expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n        )\n    }\n\n    func testDelayedUpgradeResponseDeliversFullRequest() throws {\n        enum No: Error {\n            case no\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        let upgradeRequested = NIOLockedValueBox(false)\n\n        let delayedPromise = channel.eventLoop.makePromise(of: Void.self)\n        let delayedUpgrader = UpgradeResponseDelayer(forProtocol: \"myproto\") {\n            XCTAssertFalse(upgradeRequested.withLockedValue { $0 })\n            upgradeRequested.withLockedValue { $0 = true }\n            return delayedPromise.futureResult\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(\n                withServerUpgrade: (upgraders: [delayedUpgrader], completionHandler: { context in })\n            ).wait()\n        )\n\n        // Let's send in an upgrade request.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: request)))\n\n        // Upgrade has been requested but not proceeded.\n        XCTAssertTrue(upgradeRequested.withLockedValue { $0 })\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n\n        // Ok, now we fail the upgrade. This fires an error, and then delivers the original request.\n        delayedPromise.fail(No.no)\n        XCTAssertNoThrow(try channel.pipeline.assertDoesNotContainUpgrader())\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertEqual(.no, error as? No)\n        }\n\n        switch try channel.readInbound(as: HTTPServerRequestPart.self) {\n        case .some(.head):\n            // ok\n            break\n        case let t:\n            XCTFail(\"Expected .head, got \\(String(describing: t))\")\n        }\n\n        switch try channel.readInbound(as: HTTPServerRequestPart.self) {\n        case .some(.end):\n            // ok\n            break\n        case let t:\n            XCTFail(\"Expected .head, got \\(String(describing: t))\")\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound(as: HTTPServerRequestPart.self)))\n    }\n\n    func testDelayedUpgradeResponseDeliversFullRequestAndPendingBits() throws {\n        enum No: Error {\n            case no\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        let upgradeRequested = NIOLockedValueBox(false)\n\n        let delayedPromise = channel.eventLoop.makePromise(of: Void.self)\n        let delayedUpgrader = UpgradeResponseDelayer(forProtocol: \"myproto\") {\n            XCTAssertFalse(upgradeRequested.withLockedValue { $0 })\n            upgradeRequested.withLockedValue { $0 = true }\n            return delayedPromise.futureResult\n        }\n\n        // Here we're disabling the pipeline handler, because otherwise it makes this test case impossible to reach.\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(\n                withPipeliningAssistance: false,\n                withServerUpgrade: (upgraders: [delayedUpgrader], completionHandler: { context in })\n            ).wait()\n        )\n\n        // Let's send in an upgrade request.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: request)))\n\n        // Upgrade has been requested but not proceeded.\n        XCTAssertTrue(upgradeRequested.withLockedValue { $0 })\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n\n        // We now need to inject an extra buffered request. To do this we grab the context for the HTTPRequestDecoder and inject some reads.\n        XCTAssertNoThrow(\n            try channel.pipeline.context(handlerType: ByteToMessageHandler<HTTPRequestDecoder>.self).map { context in\n                let requestHead = HTTPServerRequestPart.head(.init(version: .http1_1, method: .GET, uri: \"/test\"))\n                context.fireChannelRead(NIOAny(requestHead))\n                context.fireChannelRead(NIOAny(HTTPServerRequestPart.end(nil)))\n            }.wait()\n        )\n\n        // Ok, now we fail the upgrade. This fires an error, and then delivers the original request and the buffered one.\n        delayedPromise.fail(No.no)\n        XCTAssertNoThrow(try channel.pipeline.assertDoesNotContainUpgrader())\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertEqual(.no, error as? No)\n        }\n\n        switch try channel.readInbound(as: HTTPServerRequestPart.self) {\n        case .some(.head(let h)):\n            XCTAssertEqual(h.method, .OPTIONS)\n        case let t:\n            XCTFail(\"Expected .head, got \\(String(describing: t))\")\n        }\n\n        switch try channel.readInbound(as: HTTPServerRequestPart.self) {\n        case .some(.end):\n            // ok\n            break\n        case let t:\n            XCTFail(\"Expected .head, got \\(String(describing: t))\")\n        }\n\n        switch try channel.readInbound(as: HTTPServerRequestPart.self) {\n        case .some(.head(let h)):\n            XCTAssertEqual(h.method, .GET)\n        case let t:\n            XCTFail(\"Expected .head, got \\(String(describing: t))\")\n        }\n\n        switch try channel.readInbound(as: HTTPServerRequestPart.self) {\n        case .some(.end):\n            // ok\n            break\n        case let t:\n            XCTFail(\"Expected .head, got \\(String(describing: t))\")\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound(as: HTTPServerRequestPart.self)))\n    }\n\n    func testRemovesAllHTTPRelatedHandlersAfterUpgrade() throws {\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: []) { req in }\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            pipelining: true,\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { context in }\n\n        // First, validate the pipeline is right.\n        connectedServer.pipeline.assertContains(handlerType: ByteToMessageHandler<HTTPRequestDecoder>.self)\n        connectedServer.pipeline.assertContains(handlerType: HTTPResponseEncoder.self)\n        connectedServer.pipeline.assertContains(handlerType: HTTPServerPipelineHandler.self)\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try connectedServer.pipeline.waitForUpgraderToBeRemoved())\n\n        // At this time we should validate that none of the HTTP handlers in the pipeline exist.\n        XCTAssertNoThrow(\n            try connectedServer.pipeline.assertDoesNotContain(\n                handlerType: ByteToMessageHandler<HTTPRequestDecoder>.self\n            )\n        )\n        XCTAssertNoThrow(try connectedServer.pipeline.assertDoesNotContain(handlerType: HTTPResponseEncoder.self))\n        XCTAssertNoThrow(try connectedServer.pipeline.assertDoesNotContain(handlerType: HTTPServerPipelineHandler.self))\n    }\n\n    func testUpgradeWithUpgradePayloadInlineWithRequestWorks() throws {\n        enum ReceivedTheWrongThingError: Error { case error }\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        class CheckWeReadInlineAndExtraData: ChannelDuplexHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundIn = Never\n            typealias OutboundOut = Never\n\n            enum State {\n                case fresh\n                case added\n                case inlineDataRead\n                case extraDataRead\n                case closed\n            }\n\n            private let firstByteDonePromise: EventLoopPromise<Void>\n            private let secondByteDonePromise: EventLoopPromise<Void>\n            private let allDonePromise: EventLoopPromise<Void>\n            private var state = State.fresh\n\n            init(\n                firstByteDonePromise: EventLoopPromise<Void>,\n                secondByteDonePromise: EventLoopPromise<Void>,\n                allDonePromise: EventLoopPromise<Void>\n            ) {\n                self.firstByteDonePromise = firstByteDonePromise\n                self.secondByteDonePromise = secondByteDonePromise\n                self.allDonePromise = allDonePromise\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                XCTAssertEqual(.fresh, self.state)\n                self.state = .added\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buf = Self.unwrapInboundIn(data)\n                XCTAssertEqual(1, buf.readableBytes)\n                let stringRead = buf.readString(length: buf.readableBytes)\n                switch self.state {\n                case .added:\n                    XCTAssertEqual(\"A\", stringRead)\n                    self.state = .inlineDataRead\n                    if stringRead == .some(\"A\") {\n                        self.firstByteDonePromise.succeed(())\n                    } else {\n                        self.firstByteDonePromise.fail(ReceivedTheWrongThingError.error)\n                    }\n                case .inlineDataRead:\n                    XCTAssertEqual(\"B\", stringRead)\n                    self.state = .extraDataRead\n                    context.channel.close(promise: nil)\n                    if stringRead == .some(\"B\") {\n                        self.secondByteDonePromise.succeed(())\n                    } else {\n                        self.secondByteDonePromise.fail(ReceivedTheWrongThingError.error)\n                    }\n                default:\n                    XCTFail(\"channel read in wrong state \\(self.state)\")\n                }\n            }\n\n            func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n                XCTAssertEqual(.extraDataRead, self.state)\n                self.state = .closed\n                context.close(mode: mode, promise: promise)\n\n                self.allDonePromise.succeed(())\n            }\n        }\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssert(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let promiseGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try promiseGroup.syncShutdownGracefully())\n        }\n        let firstByteDonePromise = promiseGroup.next().makePromise(of: Void.self)\n        let secondByteDonePromise = promiseGroup.next().makePromise(of: Void.self)\n        let allDonePromise = promiseGroup.next().makePromise(of: Void.self)\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { (context) in\n            // This is called before the upgrader gets called.\n            XCTAssertNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            try! context.channel.pipeline.syncOperations.addHandler(\n                CheckWeReadInlineAndExtraData(\n                    firstByteDonePromise: firstByteDonePromise,\n                    secondByteDonePromise: secondByteDonePromise,\n                    allDonePromise: allDonePromise\n                )\n            )\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        var request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        request += \"A\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        XCTAssertNoThrow(try firstByteDonePromise.futureResult.wait() as Void)\n\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: \"B\")).wait())\n\n        XCTAssertNoThrow(try secondByteDonePromise.futureResult.wait() as Void)\n\n        XCTAssertNoThrow(try allDonePromise.futureResult.wait() as Void)\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n\n        XCTAssertNoThrow(try allDonePromise.futureResult.wait())\n    }\n\n    func testDeliversBytesWhenRemovedDuringPartialUpgrade() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let upgradeRequestPromise = Self.eventLoop.makePromise(of: Void.self)\n        let delayer = UpgradeDelayer(\n            forProtocol: \"myproto\",\n            upgradeRequestedPromise: upgradeRequestPromise,\n            eventLoop: Self.eventLoop\n        )\n        defer {\n            delayer.unblockUpgrade()\n        }\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(\n                withServerUpgrade: (upgraders: [delayer], completionHandler: { context in })\n            ).wait()\n        )\n\n        // Let's send in an upgrade request.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: request)))\n        channel.embeddedEventLoop.run()\n\n        // Upgrade has been requested but not proceeded.\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(try XCTAssertNil(channel.readInbound(as: ByteBuffer.self)))\n\n        // The 101 has been sent.\n        guard var responseBuffer = try assertNoThrowWithValue(channel.readOutbound(as: ByteBuffer.self)) else {\n            XCTFail(\"did not send response\")\n            return\n        }\n        XCTAssertNoThrow(try XCTAssertNil(channel.readOutbound(as: ByteBuffer.self)))\n        assertResponseIs(\n            response: responseBuffer.readString(length: responseBuffer.readableBytes)!,\n            expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n            expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n        )\n\n        // Now send in some more bytes.\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: \"B\")))\n        XCTAssertNoThrow(try XCTAssertNil(channel.readInbound(as: ByteBuffer.self)))\n\n        // Now we're going to remove the handler.\n        XCTAssertNoThrow(try channel.pipeline.removeUpgrader())\n\n        // This should have delivered the pending bytes and the buffered request, and in all ways have behaved\n        // as though upgrade simply failed.\n        XCTAssertEqual(\n            try assertNoThrowWithValue(channel.readInbound(as: ByteBuffer.self)),\n            channel.allocator.buffer(string: \"B\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.assertDoesNotContainUpgrader())\n        XCTAssertNoThrow(try XCTAssertNil(channel.readOutbound(as: ByteBuffer.self)))\n    }\n\n    func testDeliversBytesWhenReentrantlyCalledInChannelReadCompleteOnRemoval() throws {\n        // This is a very specific test: we want to make sure that even the very last gasp of the HTTPServerUpgradeHandler\n        // can still deliver bytes if it gets them.\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let upgradeRequestPromise = Self.eventLoop.makePromise(of: Void.self)\n        let delayer = UpgradeDelayer(\n            forProtocol: \"myproto\",\n            upgradeRequestedPromise: upgradeRequestPromise,\n            eventLoop: Self.eventLoop\n        )\n        defer {\n            delayer.unblockUpgrade()\n        }\n\n        XCTAssertNoThrow(\n            try channel.pipeline.configureHTTPServerPipeline(\n                withServerUpgrade: (upgraders: [delayer], completionHandler: { context in })\n            ).wait()\n        )\n\n        // Let's send in an upgrade request.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: request)))\n        channel.embeddedEventLoop.run()\n\n        // Upgrade has been requested but not proceeded.\n        channel.pipeline.assertContainsUpgrader()\n        XCTAssertNoThrow(try XCTAssertNil(channel.readInbound(as: ByteBuffer.self)))\n\n        // The 101 has been sent.\n        guard var responseBuffer = try assertNoThrowWithValue(channel.readOutbound(as: ByteBuffer.self)) else {\n            XCTFail(\"did not send response\")\n            return\n        }\n        XCTAssertNoThrow(try XCTAssertNil(channel.readOutbound(as: ByteBuffer.self)))\n        assertResponseIs(\n            response: responseBuffer.readString(length: responseBuffer.readableBytes)!,\n            expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n            expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n        )\n\n        // Now send in some more bytes.\n        XCTAssertNoThrow(try channel.writeInbound(channel.allocator.buffer(string: \"B\")))\n        XCTAssertNoThrow(try XCTAssertNil(channel.readInbound(as: ByteBuffer.self)))\n\n        // Ok, now we put in a special handler that does a weird readComplete hook thing.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ReentrantReadOnChannelReadCompleteHandler()))\n\n        // Now we're going to remove the upgrade handler.\n        XCTAssertNoThrow(try channel.pipeline.removeUpgrader())\n\n        // We should have received B and then the re-entrant read in that order.\n        XCTAssertEqual(\n            try assertNoThrowWithValue(channel.readInbound(as: ByteBuffer.self)),\n            channel.allocator.buffer(string: \"B\")\n        )\n        XCTAssertEqual(\n            try assertNoThrowWithValue(channel.readInbound(as: ByteBuffer.self)),\n            channel.allocator.buffer(string: \"re-entrant read from channelReadComplete!\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.assertDoesNotContainUpgrader())\n        XCTAssertNoThrow(try XCTAssertNil(channel.readOutbound(as: ByteBuffer.self)))\n    }\n\n    func testWeTolerateUpgradeFuturesFromWrongEventLoops() throws {\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n        let otherELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try otherELG.syncShutdownGracefully())\n        }\n        let upgrader = SuccessfulUpgrader(\n            forProtocol: \"myproto\",\n            requiringHeaders: [\"kafkaesque\"]\n        ) {\n            // this is the wrong EL\n            otherELG.next().makeSucceededFuture($1)\n        } onUpgradeComplete: { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssert(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { (context) in\n            // This is called before the upgrader gets called.\n            XCTAssertNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n    }\n\n    func testFailingToRemoveExtraHandlersThrowsError() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try? channel.finish())\n        }\n\n        let encoder = HTTPResponseEncoder()\n        let handlers: [RemovableChannelHandler] = [HTTPServerPipelineHandler(), HTTPServerProtocolErrorHandler()]\n        let upgradeHandler = HTTPServerUpgradeHandler(\n            upgraders: [SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [], onUpgradeComplete: { _ in })],\n            httpEncoder: encoder,\n            extraHTTPHandlers: handlers,\n            upgradeCompletionHandler: { _ in }\n        )\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(encoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandlers(handlers))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(upgradeHandler))\n\n        let userEventSaver = UserEventSaver<HTTPServerUpgradeEvents>()\n        let dataRecorder = DataRecorder<HTTPServerRequestPart>()\n        XCTAssertNoThrow(try channel.pipeline.addHandler(userEventSaver).wait())\n        XCTAssertNoThrow(try channel.pipeline.addHandler(dataRecorder).wait())\n\n        // Remove one of the extra handlers.\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(handlers.last!).wait())\n\n        let head = HTTPServerRequestPart.head(\n            .init(version: .http1_1, method: .GET, uri: \"/foo\", headers: [\"upgrade\": \"myproto\"])\n        )\n        XCTAssertNoThrow(try channel.writeInbound(head))\n        XCTAssertThrowsError(try channel.writeInbound(HTTPServerRequestPart.end(nil))) { error in\n            XCTAssertEqual(error as? ChannelPipelineError, .notFound)\n        }\n\n        // Upgrade didn't complete, so no user event.\n        XCTAssertTrue(userEventSaver.events.isEmpty)\n        // Nothing should have been forwarded.\n        XCTAssertTrue(dataRecorder.receivedData().isEmpty)\n        // The upgrade handler should still be in the pipeline.\n        channel.pipeline.assertContainsUpgrader()\n    }\n\n    func testFailedUpgradeResponseWriteThrowsError() throws {\n        final class FailAllWritesHandler: ChannelOutboundHandler {\n            typealias OutboundIn = NIOAny\n            struct FailAllWritesError: Error {}\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                promise?.fail(FailAllWritesError())\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try? channel.finish())\n        }\n\n        let encoder = HTTPResponseEncoder()\n        let handler = HTTPServerUpgradeHandler(\n            upgraders: [SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: []) { _ in }],\n            httpEncoder: encoder,\n            extraHTTPHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            ()\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(FailAllWritesHandler()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(encoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        let userEventSaver = UserEventSaver<HTTPServerUpgradeEvents>()\n        let dataRecorder = DataRecorder<HTTPServerRequestPart>()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(userEventSaver))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(dataRecorder))\n\n        let head = HTTPServerRequestPart.head(\n            .init(version: .http1_1, method: .GET, uri: \"/foo\", headers: [\"upgrade\": \"myproto\"])\n        )\n        XCTAssertNoThrow(try channel.writeInbound(head))\n        XCTAssertThrowsError(try channel.writeInbound(HTTPServerRequestPart.end(nil))) { error in\n            XCTAssert(error is FailAllWritesHandler.FailAllWritesError)\n        }\n\n        // Upgrade didn't complete, so no user event.\n        XCTAssertTrue(userEventSaver.events.isEmpty)\n        // Nothing should have been forwarded.\n        XCTAssertTrue(dataRecorder.receivedData().isEmpty)\n        // The upgrade handler should still be in the pipeline.\n        channel.pipeline.assertContainsUpgrader()\n    }\n\n    func testFailedUpgraderThrowsError() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try? channel.finish())\n        }\n\n        struct ImAfraidICantDoThatDave: Error {}\n\n        let upgrader = DelayedUnsuccessfulUpgrader(forProtocol: \"myproto\", eventLoop: channel.eventLoop)\n        let encoder = HTTPResponseEncoder()\n        let handler = HTTPServerUpgradeHandler(\n            upgraders: [upgrader],\n            httpEncoder: encoder,\n            extraHTTPHandlers: []\n        ) { (_: ChannelHandlerContext) in\n            // no-op.\n            ()\n        }\n\n        let userEventSaver = UserEventSaver<HTTPServerUpgradeEvents>()\n        let dataRecorder = DataRecorder<HTTPServerRequestPart>()\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(encoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(userEventSaver))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(dataRecorder))\n\n        let head = HTTPServerRequestPart.head(\n            .init(version: .http1_1, method: .GET, uri: \"/foo\", headers: [\"upgrade\": \"myproto\"])\n        )\n        XCTAssertNoThrow(try channel.writeInbound(head))\n        XCTAssertNoThrow(try channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Write another head, on a successful upgrade it will be unbuffered.\n        XCTAssertNoThrow(try channel.writeInbound(head))\n\n        // Unblock the upgrade.\n        upgrader.unblockUpgrade(withError: ImAfraidICantDoThatDave())\n\n        // Upgrade didn't complete, so no user event.\n        XCTAssertTrue(userEventSaver.events.isEmpty)\n        // Nothing should have been forwarded.\n        XCTAssertTrue(dataRecorder.receivedData().isEmpty)\n        // The upgrade handler should still be in the pipeline.\n        channel.pipeline.assertContainsUpgrader()\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal class TypedHTTPServerUpgradeTestCase: HTTPServerUpgradeTestCase {\n    fileprivate override func setUpTestWithAutoremoval(\n        pipelining: Bool = false,\n        upgraders: [any TypedAndUntypedHTTPServerProtocolUpgrader],\n        extraHandlers: [ChannelHandler & Sendable],\n        notUpgradingHandler: (@Sendable (Channel) -> EventLoopFuture<Bool>)? = nil,\n        upgradeErrorHandler: (@Sendable (Error) -> Void)? = nil,\n        _ upgradeCompletionHandler: @escaping UpgradeCompletionHandler\n    ) throws -> (Channel, Channel, Channel) {\n        let connectionChannelPromise = Self.eventLoop.makePromise(of: Channel.self)\n        let serverChannelFuture = ServerBootstrap(group: Self.eventLoop)\n            .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n            .childChannelOption(ChannelOptions.allowRemoteHalfClosure, value: true)\n            .childChannelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    connectionChannelPromise.succeed(channel)\n                    var configuration = NIOUpgradableHTTPServerPipelineConfiguration(\n                        upgradeConfiguration: .init(\n                            upgraders: upgraders.map { $0 as! any NIOTypedHTTPServerProtocolUpgrader<Bool> },\n                            notUpgradingCompletionHandler: {\n                                notUpgradingHandler?($0) ?? $0.eventLoop.makeSucceededFuture(false)\n                            }\n                        )\n                    )\n                    configuration.enablePipelining = pipelining\n                    return try channel.pipeline.syncOperations.configureUpgradableHTTPServerPipeline(\n                        configuration: configuration\n                    )\n                    .flatMap { result in\n                        if result {\n                            return channel.pipeline.context(handlerType: NIOTypedHTTPServerUpgradeHandler<Bool>.self)\n                                .map {\n                                    upgradeCompletionHandler($0)\n                                }\n                        } else {\n                            return channel.eventLoop.makeSucceededVoidFuture()\n                        }\n                    }\n                    .flatMapErrorThrowing { error in\n                        upgradeErrorHandler?(error)\n                        throw error\n                    }\n                }\n                .flatMap { _ in\n                    let futureResults = extraHandlers.map { channel.pipeline.addHandler($0) }\n                    return EventLoopFuture.andAllSucceed(futureResults, on: channel.eventLoop)\n                }\n            }.bind(host: \"127.0.0.1\", port: 0)\n        let clientChannel = try connectedClientChannel(\n            group: Self.eventLoop,\n            serverAddress: serverChannelFuture.wait().localAddress!\n        )\n        return (try serverChannelFuture.wait(), clientChannel, try connectionChannelPromise.futureResult.wait())\n    }\n\n    func testNotUpgrading() throws {\n        let notUpgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { _ in }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { channel in\n            notUpgraderCbFired.wrappedValue = true\n            // We're closing the connection now.\n            channel.close(promise: nil)\n            return channel.eventLoop.makeSucceededFuture(true)\n        } _: { _ in\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            XCTAssertEqual(resultString, \"\")\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: notmyproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that the not upgrader got called.\n        XCTAssert(notUpgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n    }\n\n    // - MARK: The following tests are all overridden from the base class since they slightly differ in behaviour\n\n    override func testSimpleUpgradeSucceeds() throws {\n        // This test is different since we call the completionHandler after the upgrader\n        // modified the pipeline in the typed version.\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            // This is called before completion block.\n            upgradeRequest.wrappedValue = req\n            upgradeHandlerCbFired.wrappedValue = true\n\n            XCTAssert(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { (context) in\n            // This is called before the upgrader gets called.\n            XCTAssertNotNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n    }\n\n    override func testUpgradeRespectsClientPreference() throws {\n        // This test is different since we call the completionHandler after the upgrader\n        // modified the pipeline in the typed version.\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let explodingUpgrader = ExplodingUpgrader(forProtocol: \"exploder\")\n        let successfulUpgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssertFalse(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [explodingUpgrader, successfulUpgrader],\n            extraHandlers: []\n        ) { context in\n            // This is called before the upgrader gets called.\n            XCTAssertNotNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto, exploder\\r\\nKafkaesque: yup\\r\\nConnection: upgrade, kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    override func testUpgraderCanRejectUpgradeForPersonalReasons() throws {\n        // This test is different since we call the completionHandler after the upgrader\n        // modified the pipeline in the typed version.\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        let explodingUpgrader = UpgraderSaysNo(forProtocol: \"noproto\")\n        let successfulUpgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssertFalse(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n        let errorCatcher = ErrorSaver()\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [explodingUpgrader, successfulUpgrader],\n            extraHandlers: [errorCatcher]\n        ) { context in\n            // This is called before the upgrader gets called.\n            XCTAssertNotNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: noproto,myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade, kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n\n        // And we want to confirm we saved the error.\n        XCTAssertEqual(errorCatcher.errors.count, 1)\n\n        switch errorCatcher.errors[0] {\n        case UpgraderSaysNo.No.no:\n            break\n        default:\n            XCTFail(\"Unexpected error: \\(errorCatcher.errors[0])\")\n        }\n    }\n\n    override func testUpgradeWithUpgradePayloadInlineWithRequestWorks() throws {\n        // This test is different since we call the completionHandler after the upgrader\n        // modified the pipeline in the typed version.\n        enum ReceivedTheWrongThingError: Error { case error }\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n\n        class CheckWeReadInlineAndExtraData: ChannelDuplexHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundIn = Never\n            typealias OutboundOut = Never\n\n            enum State {\n                case fresh\n                case added\n                case inlineDataRead\n                case extraDataRead\n                case closed\n            }\n\n            private let firstByteDonePromise: EventLoopPromise<Void>\n            private let secondByteDonePromise: EventLoopPromise<Void>\n            private let allDonePromise: EventLoopPromise<Void>\n            private var state = State.fresh\n\n            init(\n                firstByteDonePromise: EventLoopPromise<Void>,\n                secondByteDonePromise: EventLoopPromise<Void>,\n                allDonePromise: EventLoopPromise<Void>\n            ) {\n                self.firstByteDonePromise = firstByteDonePromise\n                self.secondByteDonePromise = secondByteDonePromise\n                self.allDonePromise = allDonePromise\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                XCTAssertEqual(.fresh, self.state)\n                self.state = .added\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buf = Self.unwrapInboundIn(data)\n                XCTAssertEqual(1, buf.readableBytes)\n                let stringRead = buf.readString(length: buf.readableBytes)\n                switch self.state {\n                case .added:\n                    XCTAssertEqual(\"A\", stringRead)\n                    self.state = .inlineDataRead\n                    if stringRead == .some(\"A\") {\n                        self.firstByteDonePromise.succeed(())\n                    } else {\n                        self.firstByteDonePromise.fail(ReceivedTheWrongThingError.error)\n                    }\n                case .inlineDataRead:\n                    XCTAssertEqual(\"B\", stringRead)\n                    self.state = .extraDataRead\n                    context.channel.close(promise: nil)\n                    if stringRead == .some(\"B\") {\n                        self.secondByteDonePromise.succeed(())\n                    } else {\n                        self.secondByteDonePromise.fail(ReceivedTheWrongThingError.error)\n                    }\n                default:\n                    XCTFail(\"channel read in wrong state \\(self.state)\")\n                }\n            }\n\n            func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n                XCTAssertEqual(.extraDataRead, self.state)\n                self.state = .closed\n                context.close(mode: mode, promise: promise)\n\n                self.allDonePromise.succeed(())\n            }\n        }\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssertFalse(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let promiseGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try promiseGroup.syncShutdownGracefully())\n        }\n        let firstByteDonePromise = promiseGroup.next().makePromise(of: Void.self)\n        let secondByteDonePromise = promiseGroup.next().makePromise(of: Void.self)\n        let allDonePromise = promiseGroup.next().makePromise(of: Void.self)\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { (context) in\n            // This is called before the upgrader gets called.\n            XCTAssertNotNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            try! context.channel.pipeline.syncOperations.addHandler(\n                CheckWeReadInlineAndExtraData(\n                    firstByteDonePromise: firstByteDonePromise,\n                    secondByteDonePromise: secondByteDonePromise,\n                    allDonePromise: allDonePromise\n                )\n            )\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        var request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        request += \"A\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        XCTAssertNoThrow(try firstByteDonePromise.futureResult.wait() as Void)\n\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: \"B\")).wait())\n\n        XCTAssertNoThrow(try secondByteDonePromise.futureResult.wait() as Void)\n\n        XCTAssertNoThrow(try allDonePromise.futureResult.wait() as Void)\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n\n        XCTAssertNoThrow(try allDonePromise.futureResult.wait())\n    }\n\n    override func testWeTolerateUpgradeFuturesFromWrongEventLoops() throws {\n        // This test is different since we call the completionHandler after the upgrader\n        // modified the pipeline in the typed version.\n        let upgradeRequest = UnsafeMutableTransferBox<HTTPRequestHead?>(nil)\n        let upgradeHandlerCbFired = UnsafeMutableTransferBox(false)\n        let upgraderCbFired = UnsafeMutableTransferBox(false)\n        let otherELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try otherELG.syncShutdownGracefully())\n        }\n\n        let upgrader = SuccessfulUpgrader(\n            forProtocol: \"myproto\",\n            requiringHeaders: [\"kafkaesque\"]\n        ) {\n            // this is the wrong EL\n            otherELG.next().makeSucceededFuture($1)\n        } onUpgradeComplete: { req in\n            upgradeRequest.wrappedValue = req\n            XCTAssertFalse(upgradeHandlerCbFired.wrappedValue)\n            upgraderCbFired.wrappedValue = true\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: []\n        ) { (context) in\n            // This is called before the upgrader gets called.\n            XCTAssertNotNil(upgradeRequest.wrappedValue)\n            upgradeHandlerCbFired.wrappedValue = true\n\n            // We're closing the connection now.\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we want to assert that everything got called. Their own callbacks assert\n        // that the ordering was correct.\n        XCTAssert(upgradeHandlerCbFired.wrappedValue)\n        XCTAssert(upgraderCbFired.wrappedValue)\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.assertDoesNotContainUpgrader()\n    }\n\n    override func testUpgradeFiresUserEvent() throws {\n        // This test is different since we call the completionHandler after the upgrader\n        // modified the pipeline in the typed version.\n        let eventSaver = UnsafeTransfer(UserEventSaver<HTTPServerUpgradeEvents>())\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: []) { req in\n            XCTAssertEqual(eventSaver.wrappedValue.events.count, 0)\n        }\n\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: [eventSaver.wrappedValue]\n        ) { context in\n            XCTAssertEqual(eventSaver.wrappedValue.events.count, 1)\n            context.close(promise: nil)\n        }\n\n        let completePromise = Self.eventLoop.makePromise(of: Void.self)\n        let clientHandler = ArrayAccumulationHandler<ByteBuffer> { buffers in\n            let resultString = buffers.map { $0.getString(at: $0.readerIndex, length: $0.readableBytes)! }.joined(\n                separator: \"\"\n            )\n            assertResponseIs(\n                response: resultString,\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\"X-Upgrade-Complete: true\", \"upgrade: myproto\", \"connection: upgrade\"]\n            )\n            completePromise.succeed(())\n        }\n        XCTAssertNoThrow(try client.pipeline.addHandler(clientHandler).wait())\n\n        // This request is safe to upgrade.\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade,kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n\n        // Let the machinery do its thing.\n        XCTAssertNoThrow(try completePromise.futureResult.wait())\n\n        // At this time we should have received one user event. We schedule this onto the\n        // event loop to guarantee thread safety.\n        XCTAssertNoThrow(\n            try connectedServer.eventLoop.scheduleTask(deadline: .now()) {\n                XCTAssertEqual(eventSaver.wrappedValue.events.count, 1)\n                if case .upgradeComplete(let proto, let req) = eventSaver.wrappedValue.events[0] {\n                    XCTAssertEqual(proto, \"myproto\")\n                    XCTAssertEqual(req.method, .OPTIONS)\n                    XCTAssertEqual(req.uri, \"*\")\n                    XCTAssertEqual(req.version, .http1_1)\n                } else {\n                    XCTFail(\"Unexpected event: \\(eventSaver.wrappedValue.events[0])\")\n                }\n            }.futureResult.wait()\n        )\n\n        // We also want to confirm that the upgrade handler is no longer in the pipeline.\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n    }\n\n    func testHalfClosure() throws {\n        let errorCaught = UnsafeMutableTransferBox<Bool>(false)\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { req in\n            XCTFail(\"Upgrade cannot be successful if we don't send any data to server\")\n        }\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: [],\n            upgradeErrorHandler: { error in\n                switch error {\n                case ChannelError.inputClosed:\n                    errorCaught.wrappedValue = true\n                default:\n                    break\n                }\n            },\n            { _ in }\n        )\n\n        try client.close(mode: .output).wait()\n        try connectedServer.closeFuture.wait()\n        XCTAssertEqual(errorCaught.wrappedValue, true)\n    }\n\n    /// Test that send a request and closing immediately performs a successful upgrade\n    func testSendRequestCloseImmediately() throws {\n        let upgradePerformed = UnsafeMutableTransferBox<Bool>(false)\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { _ in\n            upgradePerformed.wrappedValue = true\n        }\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: [],\n            upgradeErrorHandler: { error in\n                XCTFail(\"Error: \\(error)\")\n            },\n            { _ in }\n        )\n\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n        try client.close(mode: .output).wait()\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n        XCTAssertEqual(upgradePerformed.wrappedValue, true)\n    }\n\n    /// Test that sending an unfinished upgrade request and closing immediately throws\n    /// an input closed error\n    func testSendUnfinishedRequestCloseImmediately() throws {\n        let errorCaught = UnsafeMutableTransferBox<Bool>(false)\n\n        let upgrader = SuccessfulUpgrader(forProtocol: \"myproto\", requiringHeaders: [\"kafkaesque\"]) { _ in\n        }\n        let (_, client, connectedServer) = try setUpTestWithAutoremoval(\n            upgraders: [upgrader],\n            extraHandlers: [],\n            upgradeErrorHandler: { error in\n                switch error {\n                case ChannelError.inputClosed:\n                    errorCaught.wrappedValue = true\n                default:\n                    XCTFail(\"Error: \\(error)\")\n                }\n            },\n            { _ in }\n        )\n\n        let request =\n            \"OPTIONS * HTTP/1.1\\r\\nHost: localhost\\r\\ncontent-length: 10\\r\\nUpgrade: myproto\\r\\nKafkaesque: yup\\r\\nConnection: upgrade\\r\\nConnection: kafkaesque\\r\\n\\r\\n\"\n        XCTAssertNoThrow(try client.writeAndFlush(client.allocator.buffer(string: request)).wait())\n        try client.close(mode: .output).wait()\n        try connectedServer.pipeline.waitForUpgraderToBeRemoved()\n        XCTAssertEqual(errorCaught.wrappedValue, true)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOHTTP1\n\nprivate final class TestChannelInboundHandler: ChannelInboundHandler {\n    public typealias InboundIn = HTTPServerRequestPart\n    public typealias InboundOut = HTTPServerRequestPart\n\n    private let body: (HTTPServerRequestPart) -> HTTPServerRequestPart\n\n    init(_ body: @escaping (HTTPServerRequestPart) -> HTTPServerRequestPart) {\n        self.body = body\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        context.fireChannelRead(Self.wrapInboundOut(self.body(Self.unwrapInboundIn(data))))\n    }\n}\n\nclass HTTPTest: XCTestCase {\n\n    func checkHTTPRequest(_ expected: HTTPRequestHead, body: String? = nil, trailers: HTTPHeaders? = nil) throws {\n        try checkHTTPRequests([expected], body: body, trailers: trailers)\n    }\n\n    func checkHTTPRequests(_ expecteds: [HTTPRequestHead], body: String? = nil, trailers: HTTPHeaders? = nil) throws {\n        func httpRequestStrForRequest(_ req: HTTPRequestHead) -> String {\n            var s = \"\\(req.method) \\(req.uri) HTTP/\\(req.version.major).\\(req.version.minor)\\r\\n\"\n            for (k, v) in req.headers {\n                s += \"\\(k): \\(v)\\r\\n\"\n            }\n            if trailers != nil {\n                s += \"Transfer-Encoding: chunked\\r\\n\"\n                s += \"\\r\\n\"\n                if let body = body {\n                    s += String(body.utf8.count, radix: 16)\n                    s += \"\\r\\n\"\n                    s += body\n                    s += \"\\r\\n\"\n                }\n                s += \"0\\r\\n\"\n                if let trailers = trailers {\n                    for (k, v) in trailers {\n                        s += \"\\(k): \\(v)\\r\\n\"\n                    }\n                }\n                s += \"\\r\\n\"\n            } else if let body = body {\n                let bodyData = body.data(using: .utf8)!\n                s += \"Content-Length: \\(bodyData.count)\\r\\n\"\n                s += \"\\r\\n\"\n                s += body\n            } else {\n                s += \"\\r\\n\"\n            }\n            return s\n        }\n\n        func sendAndCheckRequests(\n            _ expecteds: [HTTPRequestHead],\n            body: String?,\n            trailers: HTTPHeaders?,\n            sendStrategy: (String, EmbeddedChannel) -> EventLoopFuture<Void>\n        ) throws -> String? {\n            var step = 0\n            var index = 0\n            let channel = EmbeddedChannel()\n            defer {\n                XCTAssertNoThrow(try channel.finish())\n            }\n            try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(HTTPRequestDecoder()))\n            var bodyData: [UInt8]? = nil\n            var allBodyDatas: [[UInt8]] = []\n            try channel.pipeline.syncOperations.addHandler(\n                TestChannelInboundHandler { reqPart in\n                    switch reqPart {\n                    case .head(var req):\n                        XCTAssertEqual((index * 2), step)\n                        req.headers.remove(name: \"Content-Length\")\n                        req.headers.remove(name: \"Transfer-Encoding\")\n                        XCTAssertEqual(expecteds[index], req)\n                        step += 1\n                    case .body(var buffer):\n                        if bodyData == nil {\n                            bodyData = buffer.readBytes(length: buffer.readableBytes)!\n                        } else {\n                            bodyData!.append(contentsOf: buffer.readBytes(length: buffer.readableBytes)!)\n                        }\n                    case .end(let receivedTrailers):\n                        XCTAssertEqual(trailers, receivedTrailers)\n                        step += 1\n                        XCTAssertEqual(((index + 1) * 2), step)\n                    }\n                    return reqPart\n                }\n            )\n\n            var writeFutures: [EventLoopFuture<Void>] = []\n            for expected in expecteds {\n                writeFutures.append(sendStrategy(httpRequestStrForRequest(expected), channel))\n                index += 1\n                if let bodyData = bodyData {\n                    allBodyDatas.append(bodyData)\n                }\n                bodyData = nil\n            }\n            channel.pipeline.flush()\n            XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(writeFutures, on: channel.eventLoop).wait())\n            XCTAssertEqual(2 * expecteds.count, step)\n\n            if body != nil {\n                XCTAssertGreaterThan(allBodyDatas.count, 0)\n                let firstBodyData = allBodyDatas[0]\n                for bodyData in allBodyDatas {\n                    XCTAssertEqual(firstBodyData, bodyData)\n                }\n                return String(decoding: firstBodyData, as: Unicode.UTF8.self)\n            } else {\n                XCTAssertEqual(0, allBodyDatas.count, \"left with \\(allBodyDatas)\")\n                return nil\n            }\n        }\n\n        // send all bytes in one go\n        let bd1 = try sendAndCheckRequests(\n            expecteds,\n            body: body,\n            trailers: trailers,\n            sendStrategy: { (reqString, chan) in\n                chan.eventLoop.makeSucceededFuture(()).flatMapThrowing {\n                    var buf = chan.allocator.buffer(capacity: 1024)\n                    buf.writeString(reqString)\n                    try chan.writeInbound(buf)\n                }\n            }\n        )\n\n        // send the bytes one by one\n        let bd2 = try sendAndCheckRequests(\n            expecteds,\n            body: body,\n            trailers: trailers,\n            sendStrategy: { (reqString, chan) in\n                var writeFutures: [EventLoopFuture<Void>] = []\n                for c in reqString {\n                    var buf = chan.allocator.buffer(capacity: 1024)\n\n                    buf.writeString(\"\\(c)\")\n                    writeFutures.append(\n                        chan.eventLoop.makeSucceededFuture(()).flatMapThrowing { [buf] in\n                            try chan.writeInbound(buf)\n                        }\n                    )\n                }\n                return EventLoopFuture.andAllSucceed(writeFutures, on: chan.eventLoop)\n            }\n        )\n\n        XCTAssertEqual(bd1, bd2)\n        XCTAssertEqual(body, bd1)\n    }\n\n    func testHTTPSimpleNoHeaders() throws {\n        try checkHTTPRequest(HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\"))\n    }\n\n    func testHTTPSimple1Header() throws {\n        var req = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/hello/world\")\n        req.headers.add(name: \"foo\", value: \"bar\")\n        try checkHTTPRequest(req)\n    }\n\n    func testHTTPSimpleSomeHeader() throws {\n        var req = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/foo/bar/buz?qux=quux\")\n        req.headers.add(name: \"foo\", value: \"bar\")\n        req.headers.add(name: \"qux\", value: \"quuux\")\n        try checkHTTPRequest(req)\n    }\n\n    func testHTTPPipelining() throws {\n        var req1 = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/foo/bar/buz?qux=quux\")\n        req1.headers.add(name: \"foo\", value: \"bar\")\n        req1.headers.add(name: \"qux\", value: \"quuux\")\n        var req2 = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\")\n        req2.headers.add(name: \"a\", value: \"b\")\n        req2.headers.add(name: \"C\", value: \"D\")\n\n        try checkHTTPRequests([req1, req2])\n        try checkHTTPRequests(Array(repeating: req1, count: 10))\n    }\n\n    func testHTTPBody() throws {\n        try checkHTTPRequest(\n            HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\"),\n            body: \"hello world\"\n        )\n    }\n\n    func test1ByteHTTPBody() throws {\n        try checkHTTPRequest(\n            HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/\"),\n            body: \"1\"\n        )\n    }\n\n    func testHTTPPipeliningWithBody() throws {\n        try checkHTTPRequests(\n            Array(\n                repeating: HTTPRequestHead(\n                    version: .http1_1,\n                    method: .GET,\n                    uri: \"/\"\n                ),\n                count: 20\n            ),\n            body: \"1\"\n        )\n    }\n\n    func testChunkedBody() throws {\n        var trailers = HTTPHeaders()\n        trailers.add(name: \"X-Key\", value: \"X-Value\")\n        trailers.add(name: \"Something\", value: \"Else\")\n        try checkHTTPRequest(\n            HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/\"),\n            body: \"100\",\n            trailers: trailers\n        )\n    }\n\n    func testHTTPRequestHeadCoWWorks() throws {\n        let headers = HTTPHeaders([(\"foo\", \"bar\")])\n        var httpReq = HTTPRequestHead(version: .http1_1, method: .GET, uri: \"/uri\")\n        httpReq.headers = headers\n\n        var modVersion = httpReq\n        modVersion.version = .http2\n        XCTAssertEqual(.http1_1, httpReq.version)\n        XCTAssertEqual(.http2, modVersion.version)\n\n        var modMethod = httpReq\n        modMethod.method = .POST\n        XCTAssertEqual(.GET, httpReq.method)\n        XCTAssertEqual(.POST, modMethod.method)\n\n        var modURI = httpReq\n        modURI.uri = \"/changed\"\n        XCTAssertEqual(\"/uri\", httpReq.uri)\n        XCTAssertEqual(\"/changed\", modURI.uri)\n\n        var modHeaders = httpReq\n        modHeaders.headers.add(name: \"qux\", value: \"quux\")\n        XCTAssertEqual(httpReq.headers, headers)\n        XCTAssertNotEqual(httpReq, modHeaders)\n        modHeaders.headers.remove(name: \"foo\")\n        XCTAssertEqual(httpReq.headers, headers)\n        XCTAssertNotEqual(httpReq, modHeaders)\n        modHeaders.headers.remove(name: \"qux\")\n        modHeaders.headers.add(name: \"foo\", value: \"bar\")\n        XCTAssertEqual(httpReq, modHeaders)\n    }\n\n    func testHTTPResponseHeadCoWWorks() throws {\n        let headers = HTTPHeaders([(\"foo\", \"bar\")])\n        let httpRes = HTTPResponseHead(version: .http1_1, status: .ok, headers: headers)\n\n        var modVersion = httpRes\n        modVersion.version = .http2\n        XCTAssertEqual(.http1_1, httpRes.version)\n        XCTAssertEqual(.http2, modVersion.version)\n\n        var modStatus = httpRes\n        modStatus.status = .notFound\n        XCTAssertEqual(.ok, httpRes.status)\n        XCTAssertEqual(.notFound, modStatus.status)\n\n        var modHeaders = httpRes\n        modHeaders.headers.add(name: \"qux\", value: \"quux\")\n        XCTAssertEqual(httpRes.headers, headers)\n        XCTAssertNotEqual(httpRes, modHeaders)\n        modHeaders.headers.remove(name: \"foo\")\n        XCTAssertEqual(httpRes.headers, headers)\n        XCTAssertNotEqual(httpRes, modHeaders)\n        modHeaders.headers.remove(name: \"qux\")\n        modHeaders.headers.add(name: \"foo\", value: \"bar\")\n        XCTAssertEqual(httpRes, modHeaders)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/HTTPTypesTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOHTTP1\nimport XCTest\n\nfinal class HTTPTypesTest: XCTestCase {\n\n    func testConvertToString() {\n        XCTAssertEqual(HTTPMethod.GET.rawValue, \"GET\")\n        XCTAssertEqual(HTTPMethod.PUT.rawValue, \"PUT\")\n        XCTAssertEqual(HTTPMethod.ACL.rawValue, \"ACL\")\n        XCTAssertEqual(HTTPMethod.HEAD.rawValue, \"HEAD\")\n        XCTAssertEqual(HTTPMethod.POST.rawValue, \"POST\")\n        XCTAssertEqual(HTTPMethod.COPY.rawValue, \"COPY\")\n        XCTAssertEqual(HTTPMethod.LOCK.rawValue, \"LOCK\")\n        XCTAssertEqual(HTTPMethod.MOVE.rawValue, \"MOVE\")\n        XCTAssertEqual(HTTPMethod.BIND.rawValue, \"BIND\")\n        XCTAssertEqual(HTTPMethod.LINK.rawValue, \"LINK\")\n        XCTAssertEqual(HTTPMethod.PATCH.rawValue, \"PATCH\")\n        XCTAssertEqual(HTTPMethod.TRACE.rawValue, \"TRACE\")\n        XCTAssertEqual(HTTPMethod.MKCOL.rawValue, \"MKCOL\")\n        XCTAssertEqual(HTTPMethod.MERGE.rawValue, \"MERGE\")\n        XCTAssertEqual(HTTPMethod.PURGE.rawValue, \"PURGE\")\n        XCTAssertEqual(HTTPMethod.NOTIFY.rawValue, \"NOTIFY\")\n        XCTAssertEqual(HTTPMethod.SEARCH.rawValue, \"SEARCH\")\n        XCTAssertEqual(HTTPMethod.UNLOCK.rawValue, \"UNLOCK\")\n        XCTAssertEqual(HTTPMethod.REBIND.rawValue, \"REBIND\")\n        XCTAssertEqual(HTTPMethod.UNBIND.rawValue, \"UNBIND\")\n        XCTAssertEqual(HTTPMethod.REPORT.rawValue, \"REPORT\")\n        XCTAssertEqual(HTTPMethod.DELETE.rawValue, \"DELETE\")\n        XCTAssertEqual(HTTPMethod.UNLINK.rawValue, \"UNLINK\")\n        XCTAssertEqual(HTTPMethod.CONNECT.rawValue, \"CONNECT\")\n        XCTAssertEqual(HTTPMethod.MSEARCH.rawValue, \"MSEARCH\")\n        XCTAssertEqual(HTTPMethod.OPTIONS.rawValue, \"OPTIONS\")\n        XCTAssertEqual(HTTPMethod.PROPFIND.rawValue, \"PROPFIND\")\n        XCTAssertEqual(HTTPMethod.CHECKOUT.rawValue, \"CHECKOUT\")\n        XCTAssertEqual(HTTPMethod.PROPPATCH.rawValue, \"PROPPATCH\")\n        XCTAssertEqual(HTTPMethod.SUBSCRIBE.rawValue, \"SUBSCRIBE\")\n        XCTAssertEqual(HTTPMethod.MKCALENDAR.rawValue, \"MKCALENDAR\")\n        XCTAssertEqual(HTTPMethod.MKACTIVITY.rawValue, \"MKACTIVITY\")\n        XCTAssertEqual(HTTPMethod.UNSUBSCRIBE.rawValue, \"UNSUBSCRIBE\")\n        XCTAssertEqual(HTTPMethod.SOURCE.rawValue, \"SOURCE\")\n        XCTAssertEqual(HTTPMethod.RAW(value: \"SOMETHINGELSE\").rawValue, \"SOMETHINGELSE\")\n    }\n\n    func testConvertFromString() {\n        XCTAssertEqual(HTTPMethod(rawValue: \"GET\"), .GET)\n        XCTAssertEqual(HTTPMethod(rawValue: \"PUT\"), .PUT)\n        XCTAssertEqual(HTTPMethod(rawValue: \"ACL\"), .ACL)\n        XCTAssertEqual(HTTPMethod(rawValue: \"HEAD\"), .HEAD)\n        XCTAssertEqual(HTTPMethod(rawValue: \"POST\"), .POST)\n        XCTAssertEqual(HTTPMethod(rawValue: \"COPY\"), .COPY)\n        XCTAssertEqual(HTTPMethod(rawValue: \"LOCK\"), .LOCK)\n        XCTAssertEqual(HTTPMethod(rawValue: \"MOVE\"), .MOVE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"BIND\"), .BIND)\n        XCTAssertEqual(HTTPMethod(rawValue: \"LINK\"), .LINK)\n        XCTAssertEqual(HTTPMethod(rawValue: \"PATCH\"), .PATCH)\n        XCTAssertEqual(HTTPMethod(rawValue: \"TRACE\"), .TRACE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"MKCOL\"), .MKCOL)\n        XCTAssertEqual(HTTPMethod(rawValue: \"MERGE\"), .MERGE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"PURGE\"), .PURGE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"NOTIFY\"), .NOTIFY)\n        XCTAssertEqual(HTTPMethod(rawValue: \"SEARCH\"), .SEARCH)\n        XCTAssertEqual(HTTPMethod(rawValue: \"UNLOCK\"), .UNLOCK)\n        XCTAssertEqual(HTTPMethod(rawValue: \"REBIND\"), .REBIND)\n        XCTAssertEqual(HTTPMethod(rawValue: \"UNBIND\"), .UNBIND)\n        XCTAssertEqual(HTTPMethod(rawValue: \"REPORT\"), .REPORT)\n        XCTAssertEqual(HTTPMethod(rawValue: \"DELETE\"), .DELETE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"UNLINK\"), .UNLINK)\n        XCTAssertEqual(HTTPMethod(rawValue: \"CONNECT\"), .CONNECT)\n        XCTAssertEqual(HTTPMethod(rawValue: \"MSEARCH\"), .MSEARCH)\n        XCTAssertEqual(HTTPMethod(rawValue: \"OPTIONS\"), .OPTIONS)\n        XCTAssertEqual(HTTPMethod(rawValue: \"PROPFIND\"), .PROPFIND)\n        XCTAssertEqual(HTTPMethod(rawValue: \"CHECKOUT\"), .CHECKOUT)\n        XCTAssertEqual(HTTPMethod(rawValue: \"PROPPATCH\"), .PROPPATCH)\n        XCTAssertEqual(HTTPMethod(rawValue: \"SUBSCRIBE\"), .SUBSCRIBE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"MKCALENDAR\"), .MKCALENDAR)\n        XCTAssertEqual(HTTPMethod(rawValue: \"MKACTIVITY\"), .MKACTIVITY)\n        XCTAssertEqual(HTTPMethod(rawValue: \"UNSUBSCRIBE\"), .UNSUBSCRIBE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"SOURCE\"), .SOURCE)\n        XCTAssertEqual(HTTPMethod(rawValue: \"SOMETHINGELSE\"), HTTPMethod.RAW(value: \"SOMETHINGELSE\"))\n    }\n\n    func testConvertFromStringToExplicitValue() {\n        switch HTTPMethod(rawValue: \"GET\") {\n        case .RAW(value: \"GET\"):\n            XCTFail(\"Expected \\\"GET\\\" to map to explicit .GET value and not .RAW(value: \\\"GET\\\")\")\n        case .GET:\n            break  // everything is awesome\n        default:\n            XCTFail(\"Unexpected case\")\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/NIOHTTPObjectAggregatorTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOHTTP1\nimport NIOTestUtils\nimport XCTest\n\nprivate final class ReadRecorder<T: Equatable>: ChannelInboundHandler, RemovableChannelHandler {\n    typealias InboundIn = T\n\n    enum Event: Equatable {\n        case channelRead(InboundIn)\n        case httpFrameTooLongEvent\n        case httpExpectationFailedEvent\n\n        static func == (lhs: Event, rhs: Event) -> Bool {\n            switch (lhs, rhs) {\n            case (.channelRead(let b1), .channelRead(let b2)):\n                return b1 == b2\n            case (.httpFrameTooLongEvent, .httpFrameTooLongEvent):\n                return true\n            case (.httpExpectationFailedEvent, .httpExpectationFailedEvent):\n                return true\n            default:\n                return false\n            }\n        }\n    }\n\n    public var reads: [Event] = []\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.reads.append(.channelRead(Self.unwrapInboundIn(data)))\n        context.fireChannelRead(data)\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        switch event {\n        case let evt as NIOHTTPObjectAggregatorEvent where evt == NIOHTTPObjectAggregatorEvent.httpFrameTooLong:\n            self.reads.append(.httpFrameTooLongEvent)\n        case let evt as NIOHTTPObjectAggregatorEvent where evt == NIOHTTPObjectAggregatorEvent.httpExpectationFailed:\n            self.reads.append(.httpExpectationFailedEvent)\n        default:\n            context.fireUserInboundEventTriggered(event)\n        }\n    }\n\n    func clear() {\n        self.reads.removeAll(keepingCapacity: true)\n    }\n}\n\nprivate final class WriteRecorder: ChannelOutboundHandler, RemovableChannelHandler {\n    typealias OutboundIn = HTTPServerResponsePart\n\n    public var writes: [HTTPServerResponsePart] = []\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.writes.append(Self.unwrapOutboundIn(data))\n\n        context.write(data, promise: promise)\n    }\n\n    func clear() {\n        self.writes.removeAll(keepingCapacity: true)\n    }\n}\n\nextension ByteBuffer {\n    fileprivate func assertContainsOnly(_ string: String) {\n        let innerData = self.getString(at: self.readerIndex, length: self.readableBytes)!\n        XCTAssertEqual(innerData, string)\n    }\n}\n\nprivate func asHTTPResponseHead(_ response: HTTPServerResponsePart) -> HTTPResponseHead? {\n    switch response {\n    case .head(let resHead):\n        return resHead\n    default:\n        return nil\n    }\n}\n\nclass NIOHTTPServerRequestAggregatorTest: XCTestCase {\n    var channel: EmbeddedChannel! = nil\n    var requestHead: HTTPRequestHead! = nil\n    var responseHead: HTTPResponseHead! = nil\n    fileprivate var readRecorder: ReadRecorder<NIOHTTPServerRequestFull>! = nil\n    fileprivate var writeRecorder: WriteRecorder! = nil\n    fileprivate var aggregatorHandler: NIOHTTPServerRequestAggregator! = nil\n\n    override func setUp() {\n        self.channel = EmbeddedChannel()\n        self.readRecorder = ReadRecorder()\n        self.writeRecorder = WriteRecorder()\n        self.aggregatorHandler = NIOHTTPServerRequestAggregator(maxContentLength: 1024 * 1024)\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPResponseEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.writeRecorder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.aggregatorHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.readRecorder))\n\n        self.requestHead = HTTPRequestHead(version: .http1_1, method: .PUT, uri: \"/path\")\n        self.requestHead.headers.add(name: \"Host\", value: \"example.com\")\n        self.requestHead.headers.add(name: \"X-Test\", value: \"True\")\n\n        self.responseHead = HTTPResponseHead(version: .http1_1, status: .ok)\n        self.responseHead.headers.add(name: \"Server\", value: \"SwiftNIO\")\n\n        // this activates the channel\n        XCTAssertNoThrow(try self.channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 1)).wait())\n    }\n\n    /// Modify pipeline setup to use aggregator with a smaller `maxContentLength`\n    private func resetSmallHandler(maxContentLength: Int) {\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.removeHandler(self.readRecorder!).wait())\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.removeHandler(self.aggregatorHandler!).wait())\n        self.aggregatorHandler = NIOHTTPServerRequestAggregator(maxContentLength: maxContentLength)\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(self.aggregatorHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.readRecorder))\n    }\n\n    override func tearDown() {\n        if let channel = self.channel {\n            XCTAssertNoThrow(try channel.finish(acceptAlreadyClosed: true))\n            self.channel = nil\n        }\n        self.requestHead = nil\n        self.responseHead = nil\n        self.readRecorder = nil\n        self.writeRecorder = nil\n        self.aggregatorHandler = nil\n    }\n\n    func testAggregateNoBody() {\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Only one request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [.channelRead(NIOHTTPServerRequestFull(head: self.requestHead, body: nil))]\n        )\n    }\n\n    func testAggregateWithBody() {\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"hello\")\n                )\n            )\n        )\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Only one request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(\n                    NIOHTTPServerRequestFull(\n                        head: self.requestHead,\n                        body: channel.allocator.buffer(string: \"hello\")\n                    )\n                )\n            ]\n        )\n    }\n\n    func testAggregateChunkedBody() {\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"hello\")\n                )\n            )\n        )\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"world\")\n                )\n            )\n        )\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        // Only one request should have made it through.\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(\n                    NIOHTTPServerRequestFull(\n                        head: self.requestHead,\n                        body: channel.allocator.buffer(string: \"helloworld\")\n                    )\n                )\n            ]\n        )\n    }\n\n    func testAggregateWithTrailer() {\n        var reqWithChunking: HTTPRequestHead = self.requestHead\n        reqWithChunking.headers.add(name: \"transfer-encoding\", value: \"chunked\")\n        reqWithChunking.headers.add(name: \"Trailer\", value: \"X-Trailer\")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(reqWithChunking)))\n\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"hello\")\n                )\n            )\n        )\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"world\")\n                )\n            )\n        )\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.end(\n                    HTTPHeaders.init([(\"X-Trailer\", \"true\")])\n                )\n            )\n        )\n\n        reqWithChunking.headers.remove(name: \"Trailer\")\n        reqWithChunking.headers.add(name: \"X-Trailer\", value: \"true\")\n\n        // Trailer headers should get moved to normal ones\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(\n                    NIOHTTPServerRequestFull(\n                        head: reqWithChunking,\n                        body: channel.allocator.buffer(string: \"helloworld\")\n                    )\n                )\n            ]\n        )\n    }\n\n    func testOversizeRequest() {\n        resetSmallHandler(maxContentLength: 4)\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(self.requestHead)))\n        XCTAssertTrue(channel.isActive)\n\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"he\")\n                )\n            )\n        )\n        XCTAssertEqual(self.writeRecorder.writes, [])\n\n        XCTAssertThrowsError(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(string: \"llo\")\n                )\n            )\n        ) { error in\n            XCTAssertEqual(NIOHTTPObjectAggregatorError.frameTooLong, error as? NIOHTTPObjectAggregatorError)\n        }\n\n        let resTooLarge = HTTPResponseHead(\n            version: .http1_1,\n            status: .payloadTooLarge,\n            headers: HTTPHeaders([(\"Content-Length\", \"0\"), (\"connection\", \"close\")])\n        )\n\n        XCTAssertEqual(\n            self.writeRecorder.writes,\n            [\n                HTTPServerResponsePart.head(resTooLarge),\n                HTTPServerResponsePart.end(nil),\n            ]\n        )\n\n        XCTAssertFalse(channel.isActive)\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.end(nil))) { error in\n            XCTAssertEqual(NIOHTTPObjectAggregatorError.connectionClosed, error as? NIOHTTPObjectAggregatorError)\n        }\n    }\n\n    func testOversizedRequestWithoutKeepAlive() {\n        resetSmallHandler(maxContentLength: 4)\n\n        // send an HTTP/1.0 request with no keep-alive header\n        let requestHead: HTTPRequestHead = HTTPRequestHead(\n            version: .http1_0,\n            method: .PUT,\n            uri: \"/path\",\n            headers: HTTPHeaders(\n                [(\"Host\", \"example.com\"), (\"X-Test\", \"True\"), (\"content-length\", \"5\")])\n        )\n\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.head(requestHead)))\n\n        let resTooLarge = HTTPResponseHead(\n            version: .http1_0,\n            status: .payloadTooLarge,\n            headers: HTTPHeaders([(\"Content-Length\", \"0\"), (\"connection\", \"close\")])\n        )\n\n        XCTAssertEqual(\n            self.writeRecorder.writes,\n            [\n                HTTPServerResponsePart.head(resTooLarge),\n                HTTPServerResponsePart.end(nil),\n            ]\n        )\n\n        // Connection should be closed right away\n        XCTAssertFalse(channel.isActive)\n\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.end(nil))) { error in\n            XCTAssertEqual(NIOHTTPObjectAggregatorError.connectionClosed, error as? NIOHTTPObjectAggregatorError)\n        }\n    }\n\n    func testOversizedRequestWithContentLength() {\n        resetSmallHandler(maxContentLength: 4)\n\n        // HTTP/1.1 uses Keep-Alive unless told otherwise\n        let requestHead: HTTPRequestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .PUT,\n            uri: \"/path\",\n            headers: HTTPHeaders(\n                [(\"Host\", \"example.com\"), (\"X-Test\", \"True\"), (\"content-length\", \"8\")])\n        )\n\n        resetSmallHandler(maxContentLength: 4)\n\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.head(requestHead)))\n\n        let response = asHTTPResponseHead(self.writeRecorder.writes.first!)!\n        XCTAssertEqual(response.status, .payloadTooLarge)\n        XCTAssertEqual(response.headers[canonicalForm: \"content-length\"], [\"0\"])\n        XCTAssertEqual(response.version, requestHead.version)\n\n        // Connection should be kept open\n        XCTAssertTrue(channel.isActive)\n\n        // An ill-behaved client may continue writing the request\n        let requestParts = [\n            HTTPServerRequestPart.body(channel.allocator.buffer(bytes: [1, 2, 3, 4])),\n            HTTPServerRequestPart.body(channel.allocator.buffer(bytes: [5, 6])),\n            HTTPServerRequestPart.body(channel.allocator.buffer(bytes: [7, 8])),\n        ]\n\n        for requestPart in requestParts {\n            XCTAssertThrowsError(try self.channel.writeInbound(requestPart))\n        }\n\n        // The aggregated message should not get passed up as it is too large.\n        // There should only be one \"frame too long\" event despite multiple writes\n        XCTAssertEqual(self.readRecorder.reads, [.httpFrameTooLongEvent])\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n        XCTAssertEqual(self.readRecorder.reads, [.httpFrameTooLongEvent])\n\n        // Write another request that is small enough\n        var secondReqWithContentLength: HTTPRequestHead = self.requestHead\n        secondReqWithContentLength.headers.replaceOrAdd(name: \"content-length\", value: \"2\")\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.head(secondReqWithContentLength)))\n\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(bytes: [1])\n                )\n            )\n        )\n        XCTAssertEqual(self.readRecorder.reads, [.httpFrameTooLongEvent])\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPServerRequestPart.body(\n                    channel.allocator.buffer(bytes: [2])\n                )\n            )\n        )\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPServerRequestPart.end(nil)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .httpFrameTooLongEvent,\n                .channelRead(\n                    NIOHTTPServerRequestFull(\n                        head: secondReqWithContentLength,\n                        body: channel.allocator.buffer(bytes: [1, 2])\n                    )\n                ),\n            ]\n        )\n    }\n}\n\nclass NIOHTTPClientResponseAggregatorTest: XCTestCase {\n    var channel: EmbeddedChannel! = nil\n    var requestHead: HTTPRequestHead! = nil\n    var responseHead: HTTPResponseHead! = nil\n    fileprivate var readRecorder: ReadRecorder<NIOHTTPClientResponseFull>! = nil\n    fileprivate var aggregatorHandler: NIOHTTPClientResponseAggregator! = nil\n\n    override func setUp() {\n        self.channel = EmbeddedChannel()\n        self.readRecorder = ReadRecorder()\n        self.aggregatorHandler = NIOHTTPClientResponseAggregator(maxContentLength: 1024 * 1024)\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(HTTPRequestEncoder()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.aggregatorHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(self.readRecorder))\n\n        self.requestHead = HTTPRequestHead(version: .http1_1, method: .PUT, uri: \"/path\")\n        self.requestHead.headers.add(name: \"Host\", value: \"example.com\")\n        self.requestHead.headers.add(name: \"X-Test\", value: \"True\")\n\n        self.responseHead = HTTPResponseHead(version: .http1_1, status: .ok)\n        self.responseHead.headers.add(name: \"Server\", value: \"SwiftNIO\")\n\n        // this activates the channel\n        XCTAssertNoThrow(try self.channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 1)).wait())\n    }\n\n    /// Modify pipeline setup to use aggregator with a smaller `maxContentLength`\n    private func resetSmallHandler(maxContentLength: Int) {\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.removeHandler(self.readRecorder!).wait())\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.removeHandler(self.aggregatorHandler!).wait())\n        self.aggregatorHandler = NIOHTTPClientResponseAggregator(maxContentLength: maxContentLength)\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(self.aggregatorHandler))\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(self.readRecorder!))\n    }\n\n    override func tearDown() {\n        if let channel = self.channel {\n            XCTAssertNoThrow(try channel.finish(acceptAlreadyClosed: true))\n            self.channel = nil\n        }\n        self.requestHead = nil\n        self.responseHead = nil\n        self.readRecorder = nil\n        self.aggregatorHandler = nil\n    }\n\n    func testOversizeResponseHead() {\n        resetSmallHandler(maxContentLength: 5)\n\n        var resHead: HTTPResponseHead = self.responseHead\n        resHead.headers.replaceOrAdd(name: \"content-length\", value: \"10\")\n\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPClientResponsePart.head(resHead)))\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPClientResponsePart.end(nil)))\n\n        // User event triggered\n        XCTAssertEqual(self.readRecorder.reads, [.httpFrameTooLongEvent])\n    }\n\n    func testOversizeResponse() {\n        resetSmallHandler(maxContentLength: 5)\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPClientResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"hello\")\n                )\n            )\n        )\n\n        XCTAssertThrowsError(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"world\")\n                )\n            )\n        )\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPClientResponsePart.end(nil)))\n\n        // User event triggered\n        XCTAssertEqual(self.readRecorder.reads, [.httpFrameTooLongEvent])\n    }\n\n    func testAggregatedResponse() {\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPClientResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"hello\")\n                )\n            )\n        )\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"world\")\n                )\n            )\n        )\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPClientResponsePart.end(HTTPHeaders([(\"X-Trail\", \"true\")]))))\n\n        var aggregatedHead: HTTPResponseHead = self.responseHead\n        aggregatedHead.headers.add(name: \"X-Trail\", value: \"true\")\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .channelRead(\n                    NIOHTTPClientResponseFull(\n                        head: aggregatedHead,\n                        body: self.channel.allocator.buffer(string: \"helloworld\")\n                    )\n                )\n            ]\n        )\n    }\n\n    func testOkAfterOversized() {\n        resetSmallHandler(maxContentLength: 4)\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPClientResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"hell\")\n                )\n            )\n        )\n        XCTAssertThrowsError(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"owor\")\n                )\n            )\n        )\n        XCTAssertThrowsError(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"ld\")\n                )\n            )\n        )\n        XCTAssertThrowsError(try self.channel.writeInbound(HTTPClientResponsePart.end(nil)))\n\n        // User event triggered\n        XCTAssertEqual(self.readRecorder.reads, [.httpFrameTooLongEvent])\n\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPClientResponsePart.head(self.responseHead)))\n        XCTAssertNoThrow(\n            try self.channel.writeInbound(\n                HTTPClientResponsePart.body(\n                    self.channel.allocator.buffer(string: \"test\")\n                )\n            )\n        )\n        XCTAssertNoThrow(try self.channel.writeInbound(HTTPClientResponsePart.end(nil)))\n\n        XCTAssertEqual(\n            self.readRecorder.reads,\n            [\n                .httpFrameTooLongEvent,\n                .channelRead(\n                    NIOHTTPClientResponseFull(\n                        head: self.responseHead,\n                        body: self.channel.allocator.buffer(string: \"test\")\n                    )\n                ),\n            ]\n        )\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOHTTP1Tests/TestUtils.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// NOTE: This file intentionally duplicates Tests/NIOPosixTests/TestUtils.swift\n// to avoid relying on symlinks, which do not work on all Windows setups.\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\n\nimport NIOConcurrencyHelpers\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOPosix\n\nextension System {\n    static var supportsIPv6: Bool {\n        do {\n            let ipv6Loopback = try SocketAddress.makeAddressResolvingHost(\"::1\", port: 0)\n            return try System.enumerateDevices().filter { $0.address == ipv6Loopback }.first != nil\n        } catch {\n            return false\n        }\n    }\n\n    static var supportsVsockLoopback: Bool {\n        #if os(Linux) || os(Android)\n        guard let modules = try? String(contentsOf: URL(fileURLWithPath: \"/proc/modules\"), encoding: .utf8) else {\n            return false\n        }\n        return modules.split(separator: \"\\n\").compactMap({ $0.split(separator: \" \").first }).contains(\"vsock_loopback\")\n        #else\n        return false\n        #endif\n    }\n}\n\nfunc withPipe(_ body: (NIOCore.NIOFileHandle, NIOCore.NIOFileHandle) throws -> [NIOCore.NIOFileHandle]) throws {\n    var fds: [Int32] = [-1, -1]\n    fds.withUnsafeMutableBufferPointer { ptr in\n        XCTAssertEqual(0, pipe(ptr.baseAddress!))\n    }\n    let readFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[0])\n    let writeFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[1])\n    var toClose: [NIOFileHandle] = [readFH, writeFH]\n    var error: Error? = nil\n    do {\n        toClose = try body(readFH, writeFH)\n    } catch let err {\n        error = err\n    }\n    for fileHandle in toClose {\n        XCTAssertNoThrow(try fileHandle.close())\n    }\n    if let error = error {\n        throw error\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc withPipe(\n    _ body: (NIOCore.NIOFileHandle, NIOCore.NIOFileHandle) async throws -> [NIOCore.NIOFileHandle]\n) async throws {\n    var fds: [Int32] = [-1, -1]\n    fds.withUnsafeMutableBufferPointer { ptr in\n        XCTAssertEqual(0, pipe(ptr.baseAddress!))\n    }\n    let readFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[0])\n    let writeFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[1])\n    var toClose: [NIOFileHandle] = [readFH, writeFH]\n    var error: Error? = nil\n    do {\n        toClose = try await body(readFH, writeFH)\n    } catch let err {\n        error = err\n    }\n    for fileHandle in toClose {\n        try fileHandle.close()\n    }\n    if let error = error {\n        throw error\n    }\n}\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\nfunc withTemporaryDirectory<T>(_ body: (String) throws -> T) rethrows -> T {\n    let dir = createTemporaryDirectory()\n    defer {\n        try? FileManager.default.removeItem(atPath: dir)\n    }\n    return try body(dir)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc withTemporaryDirectory<T>(_ body: (String) async throws -> T) async rethrows -> T {\n    let dir = createTemporaryDirectory()\n    defer {\n        try? FileManager.default.removeItem(atPath: dir)\n    }\n    return try await body(dir)\n}\n\n/// This function creates a filename that can be used for a temporary UNIX domain socket path.\n///\n/// If the temporary directory is too long to store a UNIX domain socket path, it will `chdir` into the temporary\n/// directory and return a short-enough path. The iOS simulator is known to have too long paths.\nfunc withTemporaryUnixDomainSocketPathName<T>(\n    directory: String = temporaryDirectory,\n    _ body: (String) throws -> T\n) throws -> T {\n    // this is racy but we're trying to create the shortest possible path so we can't add a directory...\n    let (fd, path) = openTemporaryFile()\n    try! Posix.close(descriptor: fd)\n    try! FileManager.default.removeItem(atPath: path)\n\n    let saveCurrentDirectory = FileManager.default.currentDirectoryPath\n    let restoreSavedCWD: Bool\n    let shortEnoughPath: String\n    do {\n        _ = try SocketAddress(unixDomainSocketPath: path)\n        // this seems to be short enough for a UDS\n        shortEnoughPath = path\n        restoreSavedCWD = false\n    } catch SocketAddressError.unixDomainSocketPathTooLong {\n        _ = FileManager.default.changeCurrentDirectoryPath(\n            URL(fileURLWithPath: path).deletingLastPathComponent().absoluteString\n        )\n        shortEnoughPath = URL(fileURLWithPath: path).lastPathComponent\n        restoreSavedCWD = true\n        print(\n            \"WARNING: Path '\\(path)' could not be used as UNIX domain socket path, using chdir & '\\(shortEnoughPath)'\"\n        )\n    }\n    defer {\n        if FileManager.default.fileExists(atPath: path) {\n            try? FileManager.default.removeItem(atPath: path)\n        }\n        if restoreSavedCWD {\n            _ = FileManager.default.changeCurrentDirectoryPath(saveCurrentDirectory)\n        }\n    }\n    return try body(shortEnoughPath)\n}\n\nfunc withTemporaryFile<T>(\n    content: String? = nil,\n    _ body: (NIOCore.NIOFileHandle, String) throws -> T\n) rethrows -> T {\n    let (fd, path) = openTemporaryFile()\n    let fileHandle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fd)\n    defer {\n        XCTAssertNoThrow(try fileHandle.close())\n        XCTAssertEqual(0, unlink(path))\n    }\n    if let content = content {\n        try Array(content.utf8).withUnsafeBufferPointer { ptr in\n            var toWrite = ptr.count\n            var start = ptr.baseAddress!\n            while toWrite > 0 {\n                let res = try Posix.write(descriptor: fd, pointer: start, size: toWrite)\n                switch res {\n                case .processed(let written):\n                    toWrite -= written\n                    start = start + written\n                case .wouldBlock:\n                    XCTFail(\"unexpectedly got .wouldBlock from a file\")\n                    continue\n                }\n            }\n            XCTAssertEqual(0, lseek(fd, 0, SEEK_SET))\n        }\n    }\n    return try body(fileHandle, path)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc withTemporaryFile<T>(\n    content: String? = nil,\n    _ body: @escaping (NIOCore.NIOFileHandle, String) async throws -> T\n) async rethrows -> T {\n    let (fd, path) = openTemporaryFile()\n    let fileHandle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fd)\n    defer {\n        XCTAssertNoThrow(try fileHandle.close())\n        XCTAssertEqual(0, unlink(path))\n    }\n    if let content = content {\n        try Array(content.utf8).withUnsafeBufferPointer { ptr in\n            var toWrite = ptr.count\n            var start = ptr.baseAddress!\n            while toWrite > 0 {\n                let res = try Posix.write(descriptor: fd, pointer: start, size: toWrite)\n                switch res {\n                case .processed(let written):\n                    toWrite -= written\n                    start = start + written\n                case .wouldBlock:\n                    XCTFail(\"unexpectedly got .wouldBlock from a file\")\n                    continue\n                }\n            }\n            XCTAssertEqual(0, lseek(fd, 0, SEEK_SET))\n        }\n    }\n    return try await body(fileHandle, path)\n}\nvar temporaryDirectory: String {\n    get {\n        #if targetEnvironment(simulator)\n        // Simulator temp directories are so long (and contain the user name) that they're not usable\n        // for UNIX Domain Socket paths (which are limited to 103 bytes).\n        return \"/tmp\"\n        #else\n        #if os(Linux)\n        return \"/tmp\"\n        #else\n        if #available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) {\n            return FileManager.default.temporaryDirectory.path\n        } else {\n            return \"/tmp\"\n        }\n        #endif  // os\n        #endif  // targetEnvironment\n    }\n}\n\nfunc createTemporaryDirectory() -> String {\n    let template = \"\\(temporaryDirectory)/.NIOTests-temp-dir_XXXXXX\"\n\n    var templateBytes = template.utf8 + [0]\n    let templateBytesCount = templateBytes.count\n    templateBytes.withUnsafeMutableBufferPointer { ptr in\n        ptr.baseAddress!.withMemoryRebound(to: Int8.self, capacity: templateBytesCount) {\n            (ptr: UnsafeMutablePointer<Int8>) in\n            let ret = mkdtemp(ptr)\n            XCTAssertNotNil(ret)\n        }\n    }\n    templateBytes.removeLast()\n    return String(decoding: templateBytes, as: Unicode.UTF8.self)\n}\n\nfunc openTemporaryFile() -> (CInt, String) {\n    let template = \"\\(temporaryDirectory)/nio_XXXXXX\"\n    var templateBytes = template.utf8 + [0]\n    let templateBytesCount = templateBytes.count\n    let fd = templateBytes.withUnsafeMutableBufferPointer { ptr in\n        ptr.baseAddress!.withMemoryRebound(to: Int8.self, capacity: templateBytesCount) {\n            (ptr: UnsafeMutablePointer<Int8>) in\n            mkstemp(ptr)\n        }\n    }\n    templateBytes.removeLast()\n    return (fd, String(decoding: templateBytes, as: Unicode.UTF8.self))\n}\n\nextension Channel {\n    func syncCloseAcceptingAlreadyClosed() throws {\n        do {\n            try self.close().wait()\n        } catch ChannelError.alreadyClosed {\n            // we're happy with this one\n        } catch let e {\n            throw e\n        }\n    }\n}\n\nfinal class ByteCountingHandler: ChannelInboundHandler, RemovableChannelHandler {\n    typealias InboundIn = ByteBuffer\n\n    private let numBytes: Int\n    private let promise: EventLoopPromise<ByteBuffer>\n    private var buffer: ByteBuffer!\n\n    init(numBytes: Int, promise: EventLoopPromise<ByteBuffer>) {\n        self.numBytes = numBytes\n        self.promise = promise\n    }\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        buffer = context.channel.allocator.buffer(capacity: numBytes)\n        if self.numBytes == 0 {\n            self.promise.succeed(buffer)\n        }\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var currentBuffer = Self.unwrapInboundIn(data)\n        buffer.writeBuffer(&currentBuffer)\n\n        if buffer.readableBytes == numBytes {\n            promise.succeed(buffer)\n        }\n    }\n\n    func assertReceived(buffer: ByteBuffer) throws {\n        let received = try promise.futureResult.wait()\n        XCTAssertEqual(buffer, received)\n    }\n}\n\nfinal class NonAcceptingServerSocket: ServerSocket {\n    private var errors: [Int32]\n\n    init(errors: [Int32]) throws {\n        // Reverse so it's cheaper to remove errors.\n        self.errors = errors.reversed()\n        try super.init(protocolFamily: .inet, setNonBlocking: true)\n    }\n\n    override func accept(setNonBlocking: Bool) throws -> Socket? {\n        if let err = self.errors.last {\n            _ = self.errors.removeLast()\n            throw IOError(errnoCode: err, reason: \"accept\")\n        }\n        return nil\n    }\n}\n\nfunc assertSetGetOptionOnOpenAndClosed<Option: ChannelOption>(\n    channel: Channel,\n    option: Option,\n    value: Option.Value\n) throws {\n    _ = try channel.setOption(option, value: value).wait()\n    _ = try channel.getOption(option).wait()\n    try channel.close().wait()\n    try channel.closeFuture.wait()\n\n    do {\n        _ = try channel.setOption(option, value: value).wait()\n        // We're okay with no error\n    } catch let err as ChannelError where err == .ioOnClosedChannel {\n        // as well as already closed channels.\n    }\n\n    do {\n        _ = try channel.getOption(option).wait()\n        // We're okay with no error\n    } catch let err as ChannelError where err == .ioOnClosedChannel {\n        // as well as already closed channels.\n    }\n}\n\nfunc assertNoThrowWithValue<T>(\n    _ body: @autoclosure () throws -> T,\n    defaultValue: T? = nil,\n    message: String? = nil,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws -> T {\n    do {\n        return try body()\n    } catch {\n        XCTFail(\"\\(message.map { $0 + \": \" } ?? \"\")unexpected error \\(error) thrown\", file: (file), line: line)\n        if let defaultValue = defaultValue {\n            return defaultValue\n        } else {\n            throw error\n        }\n    }\n}\n\nfunc resolverDebugInformation(\n    eventLoop: EventLoop,\n    host: String,\n    previouslyReceivedResult: SocketAddress\n) throws -> String {\n    func printSocketAddress(_ socketAddress: SocketAddress) -> String {\n        switch socketAddress {\n        case .unixDomainSocket(_):\n            return \"uds\"\n        case .v4(let sa):\n            return __testOnly_addressDescription(sa.address)\n        case .v6(let sa):\n            return __testOnly_addressDescription(sa.address)\n        }\n    }\n    let res = GetaddrinfoResolver(loop: eventLoop, aiSocktype: .stream, aiProtocol: .tcp)\n    let ipv6Results = try assertNoThrowWithValue(res.initiateAAAAQuery(host: host, port: 0).wait()).map(\n        printSocketAddress\n    )\n    let ipv4Results = try assertNoThrowWithValue(res.initiateAQuery(host: host, port: 0).wait()).map(printSocketAddress)\n\n    return \"\"\"\n        when trying to resolve '\\(host)' we've got the following results:\n        - previous try: \\(printSocketAddress(previouslyReceivedResult))\n        - all results:\n        IPv4: \\(ipv4Results)\n        IPv6: \\(ipv6Results)\n        \"\"\"\n}\n\nfunc assert(\n    _ condition: @autoclosure () -> Bool,\n    within time: TimeAmount,\n    testInterval: TimeAmount? = nil,\n    _ message: String = \"condition not satisfied in time\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let testInterval = testInterval ?? TimeAmount.nanoseconds(time.nanoseconds / 5)\n    let endTime = NIODeadline.now() + time\n\n    repeat {\n        if condition() { return }\n        usleep(UInt32(testInterval.nanoseconds / 1000))\n    } while NIODeadline.now() < endTime\n\n    if !condition() {\n        XCTFail(message, file: (file), line: line)\n    }\n}\n\nfunc getBoolSocketOption(\n    channel: Channel,\n    level: NIOBSDSocket.OptionLevel,\n    name: NIOBSDSocket.Option,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws -> Bool {\n    try assertNoThrowWithValue(\n        channel.getOption(ChannelOptions.Types.SocketOption(level: level, name: name)),\n        file: (file),\n        line: line\n    ).wait() != 0\n}\n\nfunc assertSuccess<Value>(_ result: Result<Value, Error>, file: StaticString = #filePath, line: UInt = #line) {\n    guard case .success = result else { return XCTFail(\"Expected result to be successful\", file: (file), line: line) }\n}\n\nfunc assertFailure<Value>(_ result: Result<Value, Error>, file: StaticString = #filePath, line: UInt = #line) {\n    guard case .failure = result else { return XCTFail(\"Expected result to be a failure\", file: (file), line: line) }\n}\n\n/// Fulfills the promise when the respective event is first received.\n///\n/// - Note: Once this is used more widely and shows value, we might want to put it into `NIOTestUtils`.\nfinal class FulfillOnFirstEventHandler: ChannelDuplexHandler, Sendable {\n    typealias InboundIn = Any\n    typealias OutboundIn = Any\n\n    struct ExpectedEventMissing: Error {}\n\n    private let channelRegisteredPromise: EventLoopPromise<Void>?\n    private let channelUnregisteredPromise: EventLoopPromise<Void>?\n    private let channelActivePromise: EventLoopPromise<Void>?\n    private let channelInactivePromise: EventLoopPromise<Void>?\n    private let channelReadPromise: EventLoopPromise<Void>?\n    private let channelReadCompletePromise: EventLoopPromise<Void>?\n    private let channelWritabilityChangedPromise: EventLoopPromise<Void>?\n    private let userInboundEventTriggeredPromise: EventLoopPromise<Void>?\n    private let errorCaughtPromise: EventLoopPromise<Void>?\n    private let registerPromise: EventLoopPromise<Void>?\n    private let bindPromise: EventLoopPromise<Void>?\n    private let connectPromise: EventLoopPromise<Void>?\n    private let writePromise: EventLoopPromise<Void>?\n    private let flushPromise: EventLoopPromise<Void>?\n    private let readPromise: EventLoopPromise<Void>?\n    private let closePromise: EventLoopPromise<Void>?\n    private let triggerUserOutboundEventPromise: EventLoopPromise<Void>?\n\n    init(\n        channelRegisteredPromise: EventLoopPromise<Void>? = nil,\n        channelUnregisteredPromise: EventLoopPromise<Void>? = nil,\n        channelActivePromise: EventLoopPromise<Void>? = nil,\n        channelInactivePromise: EventLoopPromise<Void>? = nil,\n        channelReadPromise: EventLoopPromise<Void>? = nil,\n        channelReadCompletePromise: EventLoopPromise<Void>? = nil,\n        channelWritabilityChangedPromise: EventLoopPromise<Void>? = nil,\n        userInboundEventTriggeredPromise: EventLoopPromise<Void>? = nil,\n        errorCaughtPromise: EventLoopPromise<Void>? = nil,\n        registerPromise: EventLoopPromise<Void>? = nil,\n        bindPromise: EventLoopPromise<Void>? = nil,\n        connectPromise: EventLoopPromise<Void>? = nil,\n        writePromise: EventLoopPromise<Void>? = nil,\n        flushPromise: EventLoopPromise<Void>? = nil,\n        readPromise: EventLoopPromise<Void>? = nil,\n        closePromise: EventLoopPromise<Void>? = nil,\n        triggerUserOutboundEventPromise: EventLoopPromise<Void>? = nil\n    ) {\n        self.channelRegisteredPromise = channelRegisteredPromise\n        self.channelUnregisteredPromise = channelUnregisteredPromise\n        self.channelActivePromise = channelActivePromise\n        self.channelInactivePromise = channelInactivePromise\n        self.channelReadPromise = channelReadPromise\n        self.channelReadCompletePromise = channelReadCompletePromise\n        self.channelWritabilityChangedPromise = channelWritabilityChangedPromise\n        self.userInboundEventTriggeredPromise = userInboundEventTriggeredPromise\n        self.errorCaughtPromise = errorCaughtPromise\n        self.registerPromise = registerPromise\n        self.bindPromise = bindPromise\n        self.connectPromise = connectPromise\n        self.writePromise = writePromise\n        self.flushPromise = flushPromise\n        self.readPromise = readPromise\n        self.closePromise = closePromise\n        self.triggerUserOutboundEventPromise = triggerUserOutboundEventPromise\n    }\n\n    func handlerRemoved(context: ChannelHandlerContext) {\n        self.channelRegisteredPromise?.fail(ExpectedEventMissing())\n        self.channelUnregisteredPromise?.fail(ExpectedEventMissing())\n        self.channelActivePromise?.fail(ExpectedEventMissing())\n        self.channelInactivePromise?.fail(ExpectedEventMissing())\n        self.channelReadPromise?.fail(ExpectedEventMissing())\n        self.channelReadCompletePromise?.fail(ExpectedEventMissing())\n        self.channelWritabilityChangedPromise?.fail(ExpectedEventMissing())\n        self.userInboundEventTriggeredPromise?.fail(ExpectedEventMissing())\n        self.errorCaughtPromise?.fail(ExpectedEventMissing())\n        self.registerPromise?.fail(ExpectedEventMissing())\n        self.bindPromise?.fail(ExpectedEventMissing())\n        self.connectPromise?.fail(ExpectedEventMissing())\n        self.writePromise?.fail(ExpectedEventMissing())\n        self.flushPromise?.fail(ExpectedEventMissing())\n        self.readPromise?.fail(ExpectedEventMissing())\n        self.closePromise?.fail(ExpectedEventMissing())\n        self.triggerUserOutboundEventPromise?.fail(ExpectedEventMissing())\n    }\n\n    func channelRegistered(context: ChannelHandlerContext) {\n        self.channelRegisteredPromise?.succeed(())\n        context.fireChannelRegistered()\n    }\n\n    func channelUnregistered(context: ChannelHandlerContext) {\n        self.channelUnregisteredPromise?.succeed(())\n        context.fireChannelUnregistered()\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        self.channelActivePromise?.succeed(())\n        context.fireChannelActive()\n    }\n\n    func channelInactive(context: ChannelHandlerContext) {\n        self.channelInactivePromise?.succeed(())\n        context.fireChannelInactive()\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.channelReadPromise?.succeed(())\n        context.fireChannelRead(data)\n    }\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        self.channelReadCompletePromise?.succeed(())\n        context.fireChannelReadComplete()\n    }\n\n    func channelWritabilityChanged(context: ChannelHandlerContext) {\n        self.channelWritabilityChangedPromise?.succeed(())\n        context.fireChannelWritabilityChanged()\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        self.userInboundEventTriggeredPromise?.succeed(())\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.errorCaughtPromise?.succeed(())\n        context.fireErrorCaught(error)\n    }\n\n    func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        self.registerPromise?.succeed(())\n        context.register(promise: promise)\n    }\n\n    func bind(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.bindPromise?.succeed(())\n        context.bind(to: to, promise: promise)\n    }\n\n    func connect(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.connectPromise?.succeed(())\n        context.connect(to: to, promise: promise)\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.writePromise?.succeed(())\n        context.write(data, promise: promise)\n    }\n\n    func flush(context: ChannelHandlerContext) {\n        self.flushPromise?.succeed(())\n        context.flush()\n    }\n\n    func read(context: ChannelHandlerContext) {\n        self.readPromise?.succeed(())\n        context.read()\n    }\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.closePromise?.succeed(())\n        context.close(mode: mode, promise: promise)\n    }\n\n    func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {\n        self.triggerUserOutboundEventPromise?.succeed(())\n        context.triggerUserOutboundEvent(event, promise: promise)\n    }\n}\n\nfunc forEachActiveChannelType<T>(\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: @escaping (Channel) throws -> T\n) throws -> [T] {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        XCTAssertNoThrow(try group.syncShutdownGracefully())\n    }\n    let channelEL = group.next()\n\n    let lock = NIOLock()\n    var ret: [T] = []\n    _ = try forEachCrossConnectedStreamChannelPair(file: (file), line: line) {\n        (chan1: Channel, chan2: Channel) throws -> Void in\n        var innerRet: [T] = [try body(chan1)]\n        if let parent = chan1.parent {\n            innerRet.append(try body(parent))\n        }\n        lock.withLock {\n            ret.append(contentsOf: innerRet)\n        }\n    }\n\n    // UDP\n    let udpChannel = DatagramBootstrap(group: channelEL)\n        .channelInitializer { channel in\n            XCTAssert(channel.eventLoop.inEventLoop)\n            return channelEL.makeSucceededFuture(())\n        }\n        .bind(host: \"127.0.0.1\", port: 0)\n    defer {\n        XCTAssertNoThrow(try udpChannel.wait().syncCloseAcceptingAlreadyClosed())\n    }\n\n    return try lock.withLock {\n        ret.append(try body(udpChannel.wait()))\n        return ret\n    }\n}\n\nfunc withTCPServerChannel<R>(\n    bindTarget: SocketAddress? = nil,\n    group: EventLoopGroup,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel) throws -> R\n) throws -> R {\n    let server = try ServerBootstrap(group: group)\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .bind(to: bindTarget ?? .init(ipAddress: \"127.0.0.1\", port: 0))\n        .wait()\n    do {\n        let result = try body(server)\n        try server.close().wait()\n        return result\n    } catch {\n        try? server.close().wait()\n        throw error\n    }\n}\n\nfunc withCrossConnectedSockAddrChannels<R>(\n    bindTarget: SocketAddress,\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    let serverGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        XCTAssertNoThrow(try serverGroup.syncShutdownGracefully())\n    }\n    let clientGroup: MultiThreadedEventLoopGroup\n    if forceSeparateEventLoops {\n        clientGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    } else {\n        clientGroup = serverGroup\n    }\n    defer {\n        // this may fail if clientGroup === serverGroup\n        try? clientGroup.syncShutdownGracefully()\n    }\n    let serverChannelEL = serverGroup.next()\n    let clientChannelEL = clientGroup.next()\n\n    let tcpAcceptedChannel = serverChannelEL.makePromise(of: Channel.self)\n    let tcpServerChannel = try assertNoThrowWithValue(\n        ServerBootstrap(group: serverChannelEL)\n            .childChannelInitializer { channel in\n                let accepted = channel.eventLoop.makePromise(of: Void.self)\n                accepted.futureResult.map {\n                    channel\n                }.cascade(to: tcpAcceptedChannel)\n                return channel.pipeline.addHandler(FulfillOnFirstEventHandler(channelActivePromise: accepted))\n            }\n            .bind(to: bindTarget)\n            .wait(),\n        file: (file),\n        line: line\n    )\n    defer {\n        XCTAssertNoThrow(try tcpServerChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    let tcpClientChannel = try assertNoThrowWithValue(\n        ClientBootstrap(group: clientChannelEL)\n            .channelInitializer { channel in\n                XCTAssert(channel.eventLoop.inEventLoop)\n                return channel.eventLoop.makeSucceededFuture(())\n            }\n            .connect(to: tcpServerChannel.localAddress!)\n            .wait()\n    )\n    defer {\n        XCTAssertNoThrow(try tcpClientChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    return try body(try tcpAcceptedChannel.futureResult.wait(), tcpClientChannel)\n}\n\nfunc withCrossConnectedTCPChannels<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    try withCrossConnectedSockAddrChannels(\n        bindTarget: .init(ipAddress: \"127.0.0.1\", port: 0),\n        forceSeparateEventLoops: forceSeparateEventLoops,\n        body\n    )\n}\n\nfunc withCrossConnectedUnixDomainSocketChannels<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    try withTemporaryDirectory { tempDir in\n        let bindTarget = try SocketAddress(unixDomainSocketPath: tempDir + \"/s\")\n        return try withCrossConnectedSockAddrChannels(\n            bindTarget: bindTarget,\n            forceSeparateEventLoops: forceSeparateEventLoops,\n            body\n        )\n    }\n}\n\nfunc withCrossConnectedPipeChannels<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    let channel1Group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        XCTAssertNoThrow(try channel1Group.syncShutdownGracefully(), file: (file), line: line)\n    }\n    let channel2Group: MultiThreadedEventLoopGroup\n    if forceSeparateEventLoops {\n        channel2Group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    } else {\n        channel2Group = channel1Group\n    }\n    defer {\n        // may fail if pipe1Group == pipe2Group\n        try? channel2Group.syncShutdownGracefully()\n    }\n\n    var result: R? = nil\n\n    XCTAssertNoThrow(\n        try withPipe { pipe1Read, pipe1Write -> [NIOFileHandle] in\n            try withPipe { pipe2Read, pipe2Write -> [NIOFileHandle] in\n                try pipe1Read.withUnsafeFileDescriptor { pipe1Read in\n                    try pipe1Write.withUnsafeFileDescriptor { pipe1Write in\n                        try pipe2Read.withUnsafeFileDescriptor { pipe2Read in\n                            try pipe2Write.withUnsafeFileDescriptor { pipe2Write in\n                                let channel1 = try NIOPipeBootstrap(group: channel1Group)\n                                    .takingOwnershipOfDescriptors(input: pipe1Read, output: pipe2Write)\n                                    .wait()\n                                defer {\n                                    XCTAssertNoThrow(try channel1.syncCloseAcceptingAlreadyClosed())\n                                }\n                                let channel2 = try NIOPipeBootstrap(group: channel2Group)\n                                    .takingOwnershipOfDescriptors(input: pipe2Read, output: pipe1Write)\n                                    .wait()\n                                defer {\n                                    XCTAssertNoThrow(try channel2.syncCloseAcceptingAlreadyClosed())\n                                }\n                                result = try body(channel1, channel2)\n                            }\n                        }\n                    }\n                }\n                XCTAssertNoThrow(try pipe1Read.takeDescriptorOwnership(), file: (file), line: line)\n                XCTAssertNoThrow(try pipe1Write.takeDescriptorOwnership(), file: (file), line: line)\n                XCTAssertNoThrow(try pipe2Read.takeDescriptorOwnership(), file: (file), line: line)\n                XCTAssertNoThrow(try pipe2Write.takeDescriptorOwnership(), file: (file), line: line)\n                return []\n            }\n            return []  // the channels are closing the pipes\n        },\n        file: (file),\n        line: line\n    )\n    return result!\n}\n\nfunc forEachCrossConnectedStreamChannelPair<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> [R] {\n    let r1 = try withCrossConnectedTCPChannels(forceSeparateEventLoops: forceSeparateEventLoops, body)\n    let r2 = try withCrossConnectedPipeChannels(forceSeparateEventLoops: forceSeparateEventLoops, body)\n    let r3 = try withCrossConnectedUnixDomainSocketChannels(forceSeparateEventLoops: forceSeparateEventLoops, body)\n    return [r1, r2, r3]\n}\n\nextension EventLoopFuture {\n    var isFulfilled: Bool {\n        if self.eventLoop.inEventLoop {\n            // Easy, we're on the EventLoop. Let's just use our knowledge that we run completed future callbacks\n            // immediately.\n            var fulfilled = false\n            self.assumeIsolated().whenComplete { _ in\n                fulfilled = true\n            }\n            return fulfilled\n        } else {\n            let fulfilledBox = NIOLockedValueBox(false)\n            let group = DispatchGroup()\n\n            group.enter()\n            self.eventLoop.execute {\n                let isFulfilled = self.isFulfilled  // This will now enter the above branch.\n                fulfilledBox.withLockedValue {\n                    $0 = isFulfilled\n                }\n                group.leave()\n            }\n            group.wait()  // this is very nasty but this is for tests only, so...\n            return fulfilledBox.withLockedValue { $0 }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/AcceptBackoffHandlerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOCore\nimport NIOEmbedded\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOPosix\n\nfinal class AcceptBackoffHandlerTest: XCTestCase {\n    @Sendable\n    static func defaultBackoffProvider(error: IOError) -> TimeAmount? {\n        AcceptBackoffHandler.defaultBackoffProvider(error: error)\n    }\n\n    private let acceptHandlerName = \"AcceptBackoffHandler\"\n\n    public func testECONNABORTED() throws {\n        try assertBackoffRead(error: ECONNABORTED)\n    }\n\n    public func testEMFILE() throws {\n        try assertBackoffRead(error: EMFILE)\n    }\n\n    public func testENFILE() throws {\n        try assertBackoffRead(error: ENFILE)\n    }\n\n    public func testENOBUFS() throws {\n        try assertBackoffRead(error: ENOBUFS)\n    }\n\n    public func testENOMEM() throws {\n        try assertBackoffRead(error: ENOMEM)\n    }\n\n    private func assertBackoffRead(error: Int32) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next() as! SelectableEventLoop\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        // Only used from EL\n        let readCountHandler = try! loop.submit {\n            NIOLoopBound(ReadCountHandler(), eventLoop: loop)\n        }.wait()\n        let serverChannel = try setupChannel(\n            eventLoop: loop,\n            readCountHandler: readCountHandler,\n            backoffProvider: { _ in .milliseconds(100) },\n            errors: [error]\n        )\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.submit {\n                serverChannel.readable()\n                serverChannel.read()\n                return readCountHandler.value.readCount\n            }.wait()\n        )\n\n        // Inspect the read count after our scheduled backoff elapsed.\n        XCTAssertEqual(\n            1,\n            try serverChannel.eventLoop.scheduleTask(in: .milliseconds(100)) {\n                readCountHandler.value.readCount\n            }.futureResult.wait()\n        )\n\n        // The read should go through as the scheduled read happened\n        XCTAssertEqual(\n            2,\n            try serverChannel.eventLoop.submit {\n                serverChannel.read()\n                return readCountHandler.value.readCount\n            }.wait()\n        )\n\n        XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    public func testRemovalTriggerReadWhenPreviousReadScheduled() throws {\n        try assertRemoval(read: true)\n    }\n\n    public func testRemovalTriggerNoReadWhenPreviousNoReadScheduled() throws {\n        try assertRemoval(read: false)\n    }\n\n    private func assertRemoval(read: Bool) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next() as! SelectableEventLoop\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let readCountHandler = try! loop.submit {\n            NIOLoopBound(ReadCountHandler(), eventLoop: loop)\n        }.wait()\n        let serverChannel = try setupChannel(\n            eventLoop: loop,\n            readCountHandler: readCountHandler,\n            backoffProvider: { err in\n                .hours(1)\n            },\n            errors: [ENFILE]\n        )\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.submit {\n                serverChannel.readable()\n                if read {\n                    serverChannel.read()\n                }\n                return readCountHandler.value.readCount\n            }.wait()\n        )\n\n        XCTAssertNoThrow(try serverChannel.pipeline.removeHandler(name: acceptHandlerName).wait())\n\n        if read {\n            // Removal should have triggered a read.\n            XCTAssertEqual(\n                1,\n                try serverChannel.eventLoop.submit {\n                    readCountHandler.value.readCount\n                }.wait()\n            )\n        } else {\n            // Removal should have triggered no read.\n            XCTAssertEqual(\n                0,\n                try serverChannel.eventLoop.submit {\n                    readCountHandler.value.readCount\n                }.wait()\n            )\n        }\n        XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    public func testNotScheduleReadIfAlreadyScheduled() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next() as! SelectableEventLoop\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let readCountHandler = try! loop.submit {\n            NIOLoopBound(ReadCountHandler(), eventLoop: loop)\n        }.wait()\n        let serverChannel = try setupChannel(\n            eventLoop: loop,\n            readCountHandler: readCountHandler,\n            backoffProvider: { err in\n                .milliseconds(10)\n            },\n            errors: [ENFILE]\n        )\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.submit {\n                serverChannel.readable()\n                serverChannel.read()\n                serverChannel.read()\n                return readCountHandler.value.readCount\n            }.wait()\n        )\n\n        // Inspect the read count after our scheduled backoff elapsed multiple times. This should still only have triggered one read as we should only ever\n        // schedule one read.\n        XCTAssertEqual(\n            1,\n            try serverChannel.eventLoop.scheduleTask(in: .milliseconds(500)) {\n                readCountHandler.value.readCount\n            }.futureResult.wait()\n        )\n\n        // The read should go through as the scheduled read happened\n        XCTAssertEqual(\n            2,\n            try serverChannel.eventLoop.submit {\n                serverChannel.read()\n                return readCountHandler.value.readCount\n            }.wait()\n        )\n\n        XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    public func testChannelInactiveCancelScheduled() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next() as! SelectableEventLoop\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class InactiveVerificationHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n\n            private let promise: EventLoopPromise<Void>\n\n            init(promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            public func channelInactive(context: ChannelHandlerContext) {\n                promise.succeed(())\n            }\n\n            func waitForInactive() throws {\n                try promise.futureResult.wait()\n            }\n        }\n\n        let readCountHandler = try! loop.submit {\n            NIOLoopBound(ReadCountHandler(), eventLoop: loop)\n        }.wait()\n\n        let serverChannel = try setupChannel(\n            eventLoop: loop,\n            readCountHandler: readCountHandler,\n            backoffProvider: { err in\n                .milliseconds(10)\n            },\n            errors: [ENFILE]\n        )\n\n        let inactivePromise = serverChannel.eventLoop.makePromise(of: Void.self)\n        let configured = loop.submit {\n            let inactiveVerificationHandler = InactiveVerificationHandler(promise: inactivePromise)\n            try serverChannel.pipeline.syncOperations.addHandler(inactiveVerificationHandler)\n        }\n        XCTAssertNoThrow(try configured.wait())\n\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.submit {\n                serverChannel.readable()\n                serverChannel.read()\n                // Close the channel, this should also take care of cancel the scheduled read.\n                serverChannel.close(promise: nil)\n                return readCountHandler.value.readCount\n            }.wait()\n        )\n\n        // Inspect the read count after our scheduled backoff elapsed multiple times. This should have triggered no read as the channel was closed.\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.scheduleTask(in: .milliseconds(500)) {\n                readCountHandler.value.readCount\n            }.futureResult.wait()\n        )\n\n        XCTAssertNoThrow(try inactivePromise.futureResult.wait())\n    }\n\n    public func testSecondErrorUpdateScheduledRead() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next() as! SelectableEventLoop\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let readCountHandler = try! loop.submit {\n            NIOLoopBound(ReadCountHandler(), eventLoop: loop)\n        }.wait()\n\n        let backoffProviderCalled = ManagedAtomic(0)\n        let serverChannel = try setupChannel(\n            eventLoop: loop,\n            readCountHandler: readCountHandler,\n            backoffProvider: { err in\n                if backoffProviderCalled.loadThenWrappingIncrement(ordering: .relaxed) == 0 {\n                    return .seconds(1)\n                }\n                return .seconds(2)\n            },\n            errors: [ENFILE, EMFILE]\n        )\n\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.submit {\n                serverChannel.readable()\n                serverChannel.read()\n                let readCount = readCountHandler.value.readCount\n                // Directly trigger a read again without going through the pipeline. This will allow us to use serverChannel.readable()\n                serverChannel._channelCore.read0()\n                serverChannel.readable()\n                return readCount\n            }.wait()\n        )\n\n        // This should have not fired a read yet as we updated the scheduled read because we received two errors.\n        XCTAssertEqual(\n            0,\n            try serverChannel.eventLoop.scheduleTask(in: .seconds(1)) {\n                readCountHandler.value.readCount\n            }.futureResult.wait()\n        )\n\n        // This should have fired now as the updated scheduled read task should have been complete by now\n        XCTAssertEqual(\n            1,\n            try serverChannel.eventLoop.scheduleTask(in: .seconds(1)) {\n                readCountHandler.value.readCount\n            }.futureResult.wait()\n        )\n\n        XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n\n        XCTAssertEqual(2, backoffProviderCalled.load(ordering: .relaxed))\n    }\n\n    func testNotForwardingIOError() throws {\n        let loop = EmbeddedEventLoop()\n        let acceptBackOffHandler = AcceptBackoffHandler(shouldForwardIOErrorCaught: false)\n        let eventCounterHandler = EventCounterHandler()\n        let channel = EmbeddedChannel(handlers: [acceptBackOffHandler, eventCounterHandler], loop: loop)\n\n        channel.pipeline.fireErrorCaught(IOError(errnoCode: 1, reason: \"test\"))\n        XCTAssertEqual(eventCounterHandler.errorCaughtCalls, 0)\n        channel.pipeline.fireErrorCaught(ChannelError.alreadyClosed)\n        XCTAssertEqual(eventCounterHandler.errorCaughtCalls, 1)\n    }\n\n    private final class ReadCountHandler: ChannelOutboundHandler {\n        typealias OutboundIn = NIOAny\n        typealias OutboundOut = NIOAny\n\n        var readCount = 0\n\n        func read(context: ChannelHandlerContext) {\n            readCount += 1\n            context.read()\n        }\n    }\n\n    private func setupChannel(\n        eventLoop: SelectableEventLoop,\n        readCountHandler: NIOLoopBound<ReadCountHandler>,\n        backoffProvider: @escaping @Sendable (IOError) -> TimeAmount? = AcceptBackoffHandlerTest.defaultBackoffProvider,\n        errors: [Int32]\n    ) throws -> ServerSocketChannel {\n        let socket = try NonAcceptingServerSocket(errors: errors)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerSocketChannel(\n                serverSocket: socket,\n                eventLoop: eventLoop,\n                group: eventLoop\n            )\n        )\n\n        XCTAssertNoThrow(try serverChannel.setOption(.autoRead, value: false).wait())\n\n        let configured = eventLoop.submit { [acceptHandlerName = self.acceptHandlerName] in\n            let sync = serverChannel.pipeline.syncOperations\n            try sync.addHandler(readCountHandler.value)\n            try sync.addHandler(\n                AcceptBackoffHandler(backoffProvider: backoffProvider),\n                name: acceptHandlerName\n            )\n        }\n\n        XCTAssertNoThrow(try configured.wait())\n\n        XCTAssertNoThrow(\n            try eventLoop.flatSubmit {\n                // this is pretty delicate at the moment:\n                // `bind` must be _synchronously_ follow `register`, otherwise in our current implementation, `epoll` will\n                // send us `EPOLLHUP`. To have it run synchronously, we need to invoke the `flatMap` on the eventloop that the\n                // `register` will succeed.\n                serverChannel.register().flatMap { () -> EventLoopFuture<()> in\n                    serverChannel.bind(to: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n                }\n            }.wait() as Void\n        )\n        return serverChannel\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/AsyncChannelBootstrapTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOTLS\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOPosix\n\nprivate final class IPHeaderRemoverHandler: ChannelInboundHandler {\n    typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    typealias InboundOut = AddressedEnvelope<ByteBuffer>\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var data = Self.unwrapInboundIn(data)\n        let header = data.data.readIPv4Header()\n        assert(header != nil)\n        context.fireChannelRead(Self.wrapInboundOut(data))\n    }\n}\n\nprivate final class LineDelimiterCoder: ByteToMessageDecoder, MessageToByteEncoder {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = ByteBuffer\n\n    private let newLine = \"\\n\".utf8.first!\n    private let inboundID: UInt8?\n    private let outboundID: UInt8?\n\n    init(inboundID: UInt8? = nil, outboundID: UInt8? = nil) {\n        self.inboundID = inboundID\n        self.outboundID = outboundID\n    }\n\n    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        let readable = buffer.withUnsafeReadableBytes { $0.firstIndex(of: self.newLine) }\n        if let readable = readable {\n            if let id = self.inboundID {\n                let data = buffer.readSlice(length: readable - 1)!\n                let inboundID = buffer.readInteger(as: UInt8.self)!\n                buffer.moveReaderIndex(forwardBy: 1)\n\n                if id == inboundID {\n                    context.fireChannelRead(Self.wrapInboundOut(data))\n                }\n                return .continue\n            } else {\n                context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: readable)!))\n                buffer.moveReaderIndex(forwardBy: 1)\n                return .continue\n            }\n        }\n        return .needMoreData\n    }\n\n    func encode(data: ByteBuffer, out: inout ByteBuffer) throws {\n        out.writeImmutableBuffer(data)\n        if let id = self.outboundID {\n            out.writeInteger(id)\n        }\n        out.writeString(\"\\n\")\n    }\n}\n\nprivate final class TLSUserEventHandler: ChannelInboundHandler, RemovableChannelHandler {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = ByteBuffer\n    enum ALPN: String {\n        case string\n        case byte\n        case unknown\n    }\n\n    private var proposedALPN: ALPN?\n\n    init(\n        proposedALPN: ALPN? = nil\n    ) {\n        self.proposedALPN = proposedALPN\n    }\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        guard context.channel.isActive else {\n            return\n        }\n\n        if let proposedALPN = self.proposedALPN {\n            self.proposedALPN = nil\n            context.writeAndFlush(.init(ByteBuffer(string: \"negotiate-alpn:\\(proposedALPN.rawValue)\")), promise: nil)\n        }\n        context.fireChannelActive()\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        if let proposedALPN = self.proposedALPN {\n            context.writeAndFlush(.init(ByteBuffer(string: \"negotiate-alpn:\\(proposedALPN.rawValue)\")), promise: nil)\n        }\n        context.fireChannelActive()\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let buffer = Self.unwrapInboundIn(data)\n        let string = String(buffer: buffer)\n\n        if string.hasPrefix(\"negotiate-alpn:\") {\n            let alpn = String(string.dropFirst(15))\n            context.writeAndFlush(.init(ByteBuffer(string: \"alpn:\\(alpn)\")), promise: nil)\n            context.fireUserInboundEventTriggered(TLSUserEvent.handshakeCompleted(negotiatedProtocol: alpn))\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n        } else if string.hasPrefix(\"alpn:\") {\n            context.fireUserInboundEventTriggered(\n                TLSUserEvent.handshakeCompleted(negotiatedProtocol: String(string.dropFirst(5)))\n            )\n            context.pipeline.syncOperations.removeHandler(self, promise: nil)\n        } else {\n            context.fireChannelRead(data)\n        }\n    }\n}\n\nprivate final class ByteBufferToStringHandler: ChannelDuplexHandler {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = String\n    typealias OutboundIn = String\n    typealias OutboundOut = ByteBuffer\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let buffer = Self.unwrapInboundIn(data)\n        context.fireChannelRead(Self.wrapInboundOut(String(buffer: buffer)))\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let buffer = ByteBuffer(string: Self.unwrapOutboundIn(data))\n        context.write(.init(buffer), promise: promise)\n    }\n}\n\nprivate final class ByteBufferToByteHandler: ChannelDuplexHandler {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = UInt8\n    typealias OutboundIn = UInt8\n    typealias OutboundOut = ByteBuffer\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var buffer = Self.unwrapInboundIn(data)\n        let byte = buffer.readInteger(as: UInt8.self)!\n        context.fireChannelRead(Self.wrapInboundOut(byte))\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let buffer = ByteBuffer(integer: Self.unwrapOutboundIn(data))\n        context.write(.init(buffer), promise: promise)\n    }\n}\n\nprivate final class AddressedEnvelopingHandler: ChannelDuplexHandler {\n    typealias InboundIn = AddressedEnvelope<ByteBuffer>\n    typealias InboundOut = ByteBuffer\n    typealias OutboundIn = ByteBuffer\n    typealias OutboundOut = Any\n\n    var remoteAddress: SocketAddress?\n\n    init(remoteAddress: SocketAddress? = nil) {\n        self.remoteAddress = remoteAddress\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let envelope = Self.unwrapInboundIn(data)\n        self.remoteAddress = envelope.remoteAddress\n\n        context.fireChannelRead(Self.wrapInboundOut(envelope.data))\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let buffer = Self.unwrapOutboundIn(data)\n        if let remoteAddress = self.remoteAddress {\n            context.write(\n                Self.wrapOutboundOut(AddressedEnvelope(remoteAddress: remoteAddress, data: buffer)),\n                promise: promise\n            )\n            return\n        }\n\n        context.write(Self.wrapOutboundOut(buffer), promise: promise)\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfinal class AsyncChannelBootstrapTests: XCTestCase {\n    var group: MultiThreadedEventLoopGroup!\n\n    enum NegotiationResult {\n        case string(NIOAsyncChannel<String, String>)\n        case byte(NIOAsyncChannel<UInt8, UInt8>)\n    }\n\n    struct ProtocolNegotiationError: Error {}\n\n    enum StringOrByte: Hashable {\n        case string(String)\n        case byte(UInt8)\n    }\n\n    // MARK: Server/Client Bootstrap\n\n    func testServerClientBootstrap_withAsyncChannel_andHostPort() async throws {\n        let eventLoopGroup = self.group!\n\n        let channel = try await ServerBootstrap(group: eventLoopGroup)\n            .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n            .childChannelOption(.autoRead, value: true)\n            .bind(\n                host: \"127.0.0.1\",\n                port: 0\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture { () -> NIOAsyncChannel<String, String> in\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(\n                        wrappingChannelSynchronously: channel,\n                        configuration: .init(\n                            inboundType: String.self,\n                            outboundType: String.self\n                        )\n                    )\n                }\n            }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            let (stream, continuation) = AsyncStream<StringOrByte>.makeStream()\n            var iterator = stream.makeAsyncIterator()\n\n            group.addTask {\n                try await withThrowingTaskGroup(of: Void.self) { _ in\n                    try await channel.executeThenClose { inbound in\n                        for try await childChannel in inbound {\n                            try await childChannel.executeThenClose { childChannelInbound, _ in\n                                for try await value in childChannelInbound {\n                                    continuation.yield(.string(value))\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            let stringChannel = try await self.makeClientChannel(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!\n            )\n            try await stringChannel.executeThenClose { _, outbound in\n                try await outbound.write(\"hello\")\n            }\n\n            await XCTAsyncAssertEqual(await iterator.next(), .string(\"hello\"))\n\n            group.cancelAll()\n        }\n    }\n\n    func testAsyncChannelProtocolNegotiation() async throws {\n        let eventLoopGroup = self.group!\n\n        let channel: NIOAsyncChannel<EventLoopFuture<NegotiationResult>, Never> = try await ServerBootstrap(\n            group: eventLoopGroup\n        )\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .childChannelOption(.autoRead, value: true)\n        .bind(\n            host: \"127.0.0.1\",\n            port: 0\n        ) { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try Self.configureProtocolNegotiationHandlers(channel: channel)\n            }\n        }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            let (stream, continuation) = AsyncStream<StringOrByte>.makeStream()\n            var serverIterator = stream.makeAsyncIterator()\n\n            group.addTask {\n                try await withThrowingTaskGroup(of: Void.self) { group in\n                    try await channel.executeThenClose { inbound in\n                        for try await negotiationResult in inbound {\n                            group.addTask {\n                                switch try await negotiationResult.get() {\n                                case .string(let channel):\n                                    try await channel.executeThenClose { inbound, _ in\n                                        for try await value in inbound {\n                                            continuation.yield(.string(value))\n                                        }\n                                    }\n                                case .byte(let channel):\n                                    try await channel.executeThenClose { inbound, _ in\n                                        for try await value in inbound {\n                                            continuation.yield(.byte(value))\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            let stringNegotiationResultFuture = try await self.makeClientChannelWithProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedALPN: .string\n            )\n            let stringNegotiationResult = try await stringNegotiationResultFuture.get()\n            switch stringNegotiationResult {\n            case .string(let stringChannel):\n                try await stringChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(\"hello\")\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .string(\"hello\"))\n            case .byte:\n                preconditionFailure()\n            }\n\n            let byteNegotiationResultFuture = try await self.makeClientChannelWithProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedALPN: .byte\n            )\n            let byteNegotiationResult = try await byteNegotiationResultFuture.get()\n            switch byteNegotiationResult {\n            case .string:\n                preconditionFailure()\n            case .byte(let byteChannel):\n                try await byteChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(UInt8(8))\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .byte(8))\n            }\n\n            group.cancelAll()\n        }\n    }\n\n    func testAsyncChannelNestedProtocolNegotiation() async throws {\n        let eventLoopGroup = self.group!\n\n        let channel: NIOAsyncChannel<EventLoopFuture<EventLoopFuture<NegotiationResult>>, Never> =\n            try await ServerBootstrap(group: eventLoopGroup)\n            .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n            .bind(\n                host: \"127.0.0.1\",\n                port: 0\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try Self.configureNestedProtocolNegotiationHandlers(channel: channel)\n                }\n            }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            let (stream, continuation) = AsyncStream<StringOrByte>.makeStream()\n            var serverIterator = stream.makeAsyncIterator()\n\n            group.addTask {\n                try await withThrowingTaskGroup(of: Void.self) { group in\n                    try await channel.executeThenClose { inbound in\n                        for try await negotiationResult in inbound {\n                            group.addTask {\n                                switch try await negotiationResult.get().get() {\n                                case .string(let channel):\n                                    try await channel.executeThenClose { inbound, _ in\n                                        for try await value in inbound {\n                                            continuation.yield(.string(value))\n                                        }\n                                    }\n                                case .byte(let channel):\n                                    try await channel.executeThenClose { inbound, _ in\n                                        for try await value in inbound {\n                                            continuation.yield(.byte(value))\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            let stringStringNegotiationResult = try await self.makeClientChannelWithNestedProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedOuterALPN: .string,\n                proposedInnerALPN: .string\n            )\n            switch try await stringStringNegotiationResult.get().get() {\n            case .string(let stringChannel):\n                try await stringChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(\"hello\")\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .string(\"hello\"))\n            case .byte:\n                preconditionFailure()\n            }\n\n            let byteStringNegotiationResult = try await self.makeClientChannelWithNestedProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedOuterALPN: .byte,\n                proposedInnerALPN: .string\n            )\n            switch try await byteStringNegotiationResult.get().get() {\n            case .string(let stringChannel):\n                try await stringChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(\"hello\")\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .string(\"hello\"))\n            case .byte:\n                preconditionFailure()\n            }\n\n            let byteByteNegotiationResult = try await self.makeClientChannelWithNestedProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedOuterALPN: .byte,\n                proposedInnerALPN: .byte\n            )\n            switch try await byteByteNegotiationResult.get().get() {\n            case .string:\n                preconditionFailure()\n            case .byte(let byteChannel):\n                try await byteChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(UInt8(8))\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .byte(8))\n            }\n\n            let stringByteNegotiationResult = try await self.makeClientChannelWithNestedProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedOuterALPN: .string,\n                proposedInnerALPN: .byte\n            )\n            switch try await stringByteNegotiationResult.get().get() {\n            case .string:\n                preconditionFailure()\n            case .byte(let byteChannel):\n                try await byteChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(UInt8(8))\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .byte(8))\n            }\n\n            group.cancelAll()\n        }\n    }\n\n    func testAsyncChannelProtocolNegotiation_whenFails() async throws {\n        final class CollectingHandler: ChannelInboundHandler {\n            typealias InboundIn = Channel\n\n            private let channels: NIOLockedValueBox<[Channel]>\n\n            init(channels: NIOLockedValueBox<[Channel]>) {\n                self.channels = channels\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let channel = Self.unwrapInboundIn(data)\n\n                self.channels.withLockedValue { $0.append(channel) }\n\n                context.fireChannelRead(data)\n            }\n        }\n\n        let eventLoopGroup = self.group!\n        let channels = NIOLockedValueBox<[Channel]>([Channel]())\n\n        let channel: NIOAsyncChannel<EventLoopFuture<NegotiationResult>, Never> = try await ServerBootstrap(\n            group: eventLoopGroup\n        )\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .serverChannelInitializer { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try channel.pipeline.syncOperations.addHandler(CollectingHandler(channels: channels))\n            }\n        }\n        .childChannelOption(.autoRead, value: true)\n        .bind(\n            host: \"127.0.0.1\",\n            port: 0\n        ) { channel in\n            channel.eventLoop.makeCompletedFuture {\n                try Self.configureProtocolNegotiationHandlers(channel: channel)\n            }\n        }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            let (stream, continuation) = AsyncStream<StringOrByte>.makeStream()\n            var serverIterator = stream.makeAsyncIterator()\n\n            group.addTask {\n                try await withThrowingTaskGroup(of: Void.self) { group in\n                    try await channel.executeThenClose { inbound in\n                        for try await negotiationResult in inbound {\n                            group.addTask {\n                                switch try await negotiationResult.get() {\n                                case .string(let channel):\n                                    try await channel.executeThenClose { inbound, _ in\n                                        for try await value in inbound {\n                                            continuation.yield(.string(value))\n                                        }\n                                    }\n                                case .byte(let channel):\n                                    try await channel.executeThenClose { inbound, _ in\n                                        for try await value in inbound {\n                                            continuation.yield(.byte(value))\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            let failedProtocolNegotiation = try await self.makeClientChannelWithProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedALPN: .unknown\n            )\n            await XCTAssertThrowsError {\n                try await failedProtocolNegotiation.get()\n            }\n\n            // Let's check that we can still open a new connection\n            let stringNegotiationResult = try await self.makeClientChannelWithProtocolNegotiation(\n                eventLoopGroup: eventLoopGroup,\n                port: channel.channel.localAddress!.port!,\n                proposedALPN: .string\n            )\n            switch try await stringNegotiationResult.get() {\n            case .string(let stringChannel):\n                try await stringChannel.executeThenClose { _, outbound in\n                    // This is the actual content\n                    try await outbound.write(\"hello\")\n                }\n                await XCTAsyncAssertEqual(await serverIterator.next(), .string(\"hello\"))\n            case .byte:\n                preconditionFailure()\n            }\n\n            let failedInboundChannel = channels.withLockedValue { channels -> Channel in\n                XCTAssertEqual(channels.count, 2)\n                return channels[0]\n            }\n\n            // We are waiting here to make sure the channel got closed\n            try await failedInboundChannel.closeFuture.get()\n\n            group.cancelAll()\n        }\n    }\n\n    func testClientBootstrap_connectFails() async throws {\n        // Beyond verifying the connect throws, this test allows us to check that 'NIOAsyncChannel'\n        // doesn't crash on deinit when we never return it to the user.\n        await XCTAssertThrowsError {\n            try await ClientBootstrap(\n                group: .singletonMultiThreadedEventLoopGroup\n            ).connect(unixDomainSocketPath: \"testClientBootstrapConnectFails\") { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try NIOAsyncChannel(\n                        wrappingChannelSynchronously: channel,\n                        configuration: .init(\n                            inboundType: ByteBuffer.self,\n                            outboundType: ByteBuffer.self\n                        )\n                    )\n                }\n            }\n        }\n    }\n\n    func testServerClientBootstrap_withAsyncChannel_clientConnectedSocket() async throws {\n        let eventLoopGroup = self.group!\n\n        let channel = try await ServerBootstrap(group: eventLoopGroup)\n            .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n            .childChannelOption(.autoRead, value: true)\n            .bind(\n                host: \"127.0.0.1\",\n                port: 0\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture { () -> NIOAsyncChannel<String, String> in\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(\n                        wrappingChannelSynchronously: channel,\n                        configuration: .init(\n                            inboundType: String.self,\n                            outboundType: String.self\n                        )\n                    )\n                }\n            }\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            let (stream, continuation) = AsyncStream<StringOrByte>.makeStream()\n            var iterator = stream.makeAsyncIterator()\n\n            group.addTask {\n                try await withThrowingTaskGroup(of: Void.self) { _ in\n                    try await channel.executeThenClose { inbound in\n                        for try await childChannel in inbound {\n                            try await childChannel.executeThenClose { childChannelInbound, _ in\n                                for try await value in childChannelInbound {\n                                    continuation.yield(.string(value))\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            let s = try Socket(protocolFamily: .inet, type: .stream)\n            XCTAssert(try s.connect(to: channel.channel.localAddress!))\n            let fd = try s.takeDescriptorOwnership()\n\n            let stringChannel = try await self.makeClientChannel(\n                eventLoopGroup: eventLoopGroup,\n                fileDescriptor: fd\n            )\n            try await stringChannel.executeThenClose { _, outbound in\n                try await outbound.write(\"hello\")\n            }\n\n            await XCTAsyncAssertEqual(await iterator.next(), .string(\"hello\"))\n\n            group.cancelAll()\n        }\n    }\n\n    // MARK: Datagram Bootstrap\n\n    func testDatagramBootstrap_withAsyncChannel_andHostPort() async throws {\n        let eventLoopGroup = self.group!\n\n        let serverChannel = try await self.makeUDPServerChannel(eventLoopGroup: eventLoopGroup)\n        let clientChannel = try await self.makeUDPClientChannel(\n            eventLoopGroup: eventLoopGroup,\n            port: serverChannel.channel.localAddress!.port!\n        )\n        try await serverChannel.executeThenClose { serverChannelInbound, serverChannelOutbound in\n            try await clientChannel.executeThenClose { clientChannelInbound, clientChannelOutbound in\n                var serverInboundIterator = serverChannelInbound.makeAsyncIterator()\n                var clientInboundIterator = clientChannelInbound.makeAsyncIterator()\n\n                try await clientChannelOutbound.write(\"request\")\n                try await XCTAsyncAssertEqual(try await serverInboundIterator.next(), \"request\")\n\n                try await serverChannelOutbound.write(\"response\")\n                try await XCTAsyncAssertEqual(try await clientInboundIterator.next(), \"response\")\n            }\n        }\n    }\n\n    func testDatagramBootstrap_withProtocolNegotiation_andHostPort() async throws {\n        let eventLoopGroup = self.group!\n\n        // We are creating a channel here to get a random port from the system\n        let channel = try await DatagramBootstrap(group: eventLoopGroup)\n            .bind(\n                to: .init(ipAddress: \"127.0.0.1\", port: 0),\n                channelInitializer: { channel -> EventLoopFuture<Channel> in\n                    channel.eventLoop.makeSucceededFuture(channel)\n                }\n            )\n\n        let port = channel.localAddress!.port!\n        try await channel.close()\n\n        try await withThrowingTaskGroup(of: EventLoopFuture<NegotiationResult>.self) { group in\n            group.addTask {\n                // We have to use a fixed port here since we only get the channel once protocol negotiation is done\n                try await Self.makeUDPServerChannelWithProtocolNegotiation(\n                    eventLoopGroup: eventLoopGroup,\n                    port: port\n                )\n            }\n\n            // We need to sleep here since we can only connect the client after the server started.\n            try await Task.sleep(nanoseconds: 100_000_000)\n\n            group.addTask {\n                // We have to use a fixed port here since we only get the channel once protocol negotiation is done\n                try await Self.makeUDPClientChannelWithProtocolNegotiation(\n                    eventLoopGroup: eventLoopGroup,\n                    port: port,\n                    proposedALPN: .string\n                )\n            }\n\n            let firstNegotiationResult = try await group.next()\n            let secondNegotiationResult = try await group.next()\n\n            switch (try await firstNegotiationResult?.get(), try await secondNegotiationResult?.get()) {\n            case (.string(let firstChannel), .string(let secondChannel)):\n                try await firstChannel.executeThenClose { firstChannelInbound, firstChannelOutbound in\n                    try await secondChannel.executeThenClose { secondChannelInbound, secondChannelOutbound in\n                        var firstInboundIterator = firstChannelInbound.makeAsyncIterator()\n                        var secondInboundIterator = secondChannelInbound.makeAsyncIterator()\n\n                        try await firstChannelOutbound.write(\"request\")\n                        try await XCTAsyncAssertEqual(try await secondInboundIterator.next(), \"request\")\n\n                        try await secondChannelOutbound.write(\"response\")\n                        try await XCTAsyncAssertEqual(try await firstInboundIterator.next(), \"response\")\n                    }\n                }\n\n            default:\n                preconditionFailure()\n            }\n        }\n    }\n\n    func testDatagramBootstrap_connectFails() async throws {\n        // Beyond verifying the connect throws, this test allows us to check that 'NIOAsyncChannel'\n        // doesn't crash on deinit when we never return it to the user.\n        await XCTAssertThrowsError {\n            try await DatagramBootstrap(\n                group: .singletonMultiThreadedEventLoopGroup\n            ).connect(unixDomainSocketPath: \"testDatagramBootstrapConnectFails\") { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try NIOAsyncChannel(\n                        wrappingChannelSynchronously: channel,\n                        configuration: .init(\n                            inboundType: AddressedEnvelope<ByteBuffer>.self,\n                            outboundType: AddressedEnvelope<ByteBuffer>.self\n                        )\n                    )\n                }\n            }\n        }\n    }\n\n    // MARK: - Pipe Bootstrap\n\n    func testPipeBootstrap() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD, pipe2ReadFD, pipe2WriteFD) = self.makePipeFileDescriptors()\n        let channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>\n        let toChannel: NIOAsyncChannel<Never, ByteBuffer>\n        let fromChannel: NIOAsyncChannel<ByteBuffer, Never>\n\n        do {\n            channel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptors(\n                    input: pipe1ReadFD,\n                    output: pipe2WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD, pipe2ReadFD, pipe2WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            toChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD, pipe2ReadFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            fromChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    input: pipe2ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe2ReadFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await channel.executeThenClose { channelInbound, channelOutbound in\n            try await fromChannel.executeThenClose { fromChannelInbound, _ in\n                try await toChannel.executeThenClose { _, toChannelOutbound in\n                    var inboundIterator = channelInbound.makeAsyncIterator()\n                    var fromChannelInboundIterator = fromChannelInbound.makeAsyncIterator()\n\n                    try await toChannelOutbound.write(.init(string: \"Request\"))\n                    try await XCTAsyncAssertEqual(try await inboundIterator.next(), ByteBuffer(string: \"Request\"))\n\n                    let response = ByteBuffer(string: \"Response\")\n                    try await channelOutbound.write(response)\n                    try await XCTAsyncAssertEqual(try await fromChannelInboundIterator.next(), response)\n                }\n            }\n        }\n    }\n\n    func testPipeBootstrap_whenInputNil() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD) = self.makePipeFileDescriptors()\n        let channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>\n        let fromChannel: NIOAsyncChannel<ByteBuffer, Never>\n\n        do {\n            channel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            fromChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    input: pipe1ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await channel.executeThenClose { channelInbound, channelOutbound in\n            try await fromChannel.executeThenClose { fromChannelInbound, _ in\n                var inboundIterator = channelInbound.makeAsyncIterator()\n                var fromChannelInboundIterator = fromChannelInbound.makeAsyncIterator()\n\n                try await XCTAsyncAssertEqual(try await inboundIterator.next(), nil)\n\n                let response = ByteBuffer(string: \"Response\")\n                try await channelOutbound.write(response)\n                try await XCTAsyncAssertEqual(try await fromChannelInboundIterator.next(), response)\n            }\n        }\n    }\n\n    func testPipeBootstrap_whenOutputNil() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD) = self.makePipeFileDescriptors()\n        let channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>\n        let toChannel: NIOAsyncChannel<Never, ByteBuffer>\n\n        do {\n            channel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    input: pipe1ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n\n            throw error\n        }\n\n        do {\n            toChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await channel.executeThenClose { channelInbound, channelOutbound in\n            try await toChannel.executeThenClose { _, toChannelOutbound in\n                var inboundIterator = channelInbound.makeAsyncIterator()\n\n                try await toChannelOutbound.write(.init(string: \"Request\"))\n                try await XCTAsyncAssertEqual(try await inboundIterator.next(), ByteBuffer(string: \"Request\"))\n\n                let response = ByteBuffer(string: \"Response\")\n                await XCTAsyncAssertThrowsError(try await channelOutbound.write(response)) { error in\n                    XCTAssertEqual(error as? NIOAsyncWriterError, .alreadyFinished())\n                }\n            }\n        }\n    }\n\n    func testPipeBootstrap_withProtocolNegotiation() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD, pipe2ReadFD, pipe2WriteFD) = self.makePipeFileDescriptors()\n        let negotiationResult: EventLoopFuture<NegotiationResult>\n        let toChannel: NIOAsyncChannel<Never, ByteBuffer>\n        let fromChannel: NIOAsyncChannel<ByteBuffer, Never>\n\n        do {\n            negotiationResult = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptors(\n                    input: pipe1ReadFD,\n                    output: pipe2WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try Self.configureProtocolNegotiationHandlers(channel: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD, pipe2ReadFD, pipe2WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            toChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD, pipe2ReadFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            fromChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .takingOwnershipOfDescriptor(\n                    input: pipe2ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe2ReadFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await fromChannel.executeThenClose { fromChannelInbound, _ in\n            try await toChannel.executeThenClose { _, toChannelOutbound in\n                var fromChannelInboundIterator = fromChannelInbound.makeAsyncIterator()\n\n                try await toChannelOutbound.write(.init(string: \"alpn:string\\nHello\\n\"))\n                switch try await negotiationResult.get() {\n                case .string(let channel):\n                    try await channel.executeThenClose { channelInbound, channelOutbound in\n                        var inboundIterator = channelInbound.makeAsyncIterator()\n                        do {\n                            try await XCTAsyncAssertEqual(try await inboundIterator.next(), \"Hello\")\n\n                            let expectedResponse = ByteBuffer(string: \"Response\\n\")\n                            try await channelOutbound.write(\"Response\")\n                            let response = try await fromChannelInboundIterator.next()\n                            XCTAssertEqual(response, expectedResponse)\n                        } catch {\n                            // We only got to close the FDs that are not owned by the PipeChannel\n                            for fileDescriptor in [pipe1WriteFD, pipe2ReadFD] {\n                                try? SystemCalls.close(descriptor: fileDescriptor)\n                            }\n                            throw error\n                        }\n                    }\n\n                case .byte:\n                    fatalError()\n                }\n            }\n        }\n    }\n\n    func testPipeBootstrap_callsChannelInitializer() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD, pipe2ReadFD, pipe2WriteFD) = self.makePipeFileDescriptors()\n        let channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>\n        let toChannel: NIOAsyncChannel<Never, ByteBuffer>\n        let fromChannel: NIOAsyncChannel<ByteBuffer, Never>\n        let didCallChannelInitializer = NIOLockedValueBox(0)\n\n        do {\n            channel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptors(\n                    input: pipe1ReadFD,\n                    output: pipe2WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD, pipe2ReadFD, pipe2WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            toChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD, pipe2ReadFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            fromChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptor(\n                    input: pipe2ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe2ReadFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await channel.executeThenClose { channelInbound, channelOutbound in\n            try await fromChannel.executeThenClose { fromChannelInbound, _ in\n                try await toChannel.executeThenClose { _, toChannelOutbound in\n                    var inboundIterator = channelInbound.makeAsyncIterator()\n                    var fromChannelInboundIterator = fromChannelInbound.makeAsyncIterator()\n\n                    try await toChannelOutbound.write(.init(string: \"Request\"))\n                    try await XCTAsyncAssertEqual(try await inboundIterator.next(), ByteBuffer(string: \"Request\"))\n\n                    let response = ByteBuffer(string: \"Response\")\n                    try await channelOutbound.write(response)\n                    try await XCTAsyncAssertEqual(try await fromChannelInboundIterator.next(), response)\n                }\n            }\n        }\n\n        XCTAssertEqual(didCallChannelInitializer.withLockedValue { $0 }, 3)\n    }\n\n    func testPipeBootstrap_whenInputNil_callsChannelInitializer() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD) = self.makePipeFileDescriptors()\n        let channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>\n        let fromChannel: NIOAsyncChannel<ByteBuffer, Never>\n        let didCallChannelInitializer = NIOLockedValueBox(0)\n\n        do {\n            channel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        do {\n            fromChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptor(\n                    input: pipe1ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await channel.executeThenClose { channelInbound, channelOutbound in\n            try await fromChannel.executeThenClose { fromChannelInbound, _ in\n                var inboundIterator = channelInbound.makeAsyncIterator()\n                var fromChannelInboundIterator = fromChannelInbound.makeAsyncIterator()\n\n                try await XCTAsyncAssertEqual(try await inboundIterator.next(), nil)\n\n                let response = ByteBuffer(string: \"Response\")\n                try await channelOutbound.write(response)\n                try await XCTAsyncAssertEqual(try await fromChannelInboundIterator.next(), response)\n            }\n        }\n\n        XCTAssertEqual(didCallChannelInitializer.withLockedValue { $0 }, 2)\n    }\n\n    func testPipeBootstrap_whenOutputNil_callsChannelInitializer() async throws {\n        let eventLoopGroup = self.group!\n        let (pipe1ReadFD, pipe1WriteFD) = self.makePipeFileDescriptors()\n        let channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>\n        let toChannel: NIOAsyncChannel<Never, ByteBuffer>\n        let didCallChannelInitializer = NIOLockedValueBox(0)\n\n        do {\n            channel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptor(\n                    input: pipe1ReadFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1ReadFD, pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n\n            throw error\n        }\n\n        do {\n            toChannel = try await NIOPipeBootstrap(group: eventLoopGroup)\n                .channelInitializer { channel in\n                    didCallChannelInitializer.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .takingOwnershipOfDescriptor(\n                    output: pipe1WriteFD\n                ) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                    }\n                }\n        } catch {\n            for fileDescriptor in [pipe1WriteFD] {\n                try SystemCalls.close(descriptor: fileDescriptor)\n            }\n            throw error\n        }\n\n        try await channel.executeThenClose { channelInbound, channelOutbound in\n            try await toChannel.executeThenClose { _, toChannelOutbound in\n                var inboundIterator = channelInbound.makeAsyncIterator()\n\n                try await toChannelOutbound.write(.init(string: \"Request\"))\n                try await XCTAsyncAssertEqual(try await inboundIterator.next(), ByteBuffer(string: \"Request\"))\n\n                let response = ByteBuffer(string: \"Response\")\n                await XCTAsyncAssertThrowsError(try await channelOutbound.write(response)) { error in\n                    XCTAssertEqual(error as? NIOAsyncWriterError, .alreadyFinished())\n                }\n            }\n        }\n\n        XCTAssertEqual(didCallChannelInitializer.withLockedValue { $0 }, 2)\n    }\n\n    // MARK: RawSocket bootstrap\n\n    func testRawSocketBootstrap() async throws {\n        try XCTSkipIfUserHasNotEnoughRightsForRawSocketAPI()\n        let eventLoopGroup = self.group!\n\n        let serverChannel = try await self.makeRawSocketServerChannel(eventLoopGroup: eventLoopGroup)\n        let clientChannel = try await self.makeRawSocketClientChannel(eventLoopGroup: eventLoopGroup)\n\n        try await serverChannel.executeThenClose { serverChannelInbound, serverChannelOutbound in\n            try await clientChannel.executeThenClose { clientChannelInbound, clientChannelOutbound in\n                var serverInboundIterator = serverChannelInbound.makeAsyncIterator()\n                var clientInboundIterator = clientChannelInbound.makeAsyncIterator()\n\n                try await clientChannelOutbound.write(\"request\")\n                try await XCTAsyncAssertEqual(try await serverInboundIterator.next(), \"request\")\n\n                try await serverChannelOutbound.write(\"response\")\n                try await XCTAsyncAssertEqual(try await clientInboundIterator.next(), \"response\")\n            }\n        }\n    }\n\n    func testRawSocketBootstrap_withProtocolNegotiation() async throws {\n        try XCTSkipIfUserHasNotEnoughRightsForRawSocketAPI()\n        let eventLoopGroup = self.group!\n\n        try await withThrowingTaskGroup(of: EventLoopFuture<NegotiationResult>.self) { group in\n            group.addTask {\n                // We have to use a fixed port here since we only get the channel once protocol negotiation is done\n                try await Self.makeRawSocketServerChannelWithProtocolNegotiation(\n                    eventLoopGroup: eventLoopGroup\n                )\n            }\n\n            // We need to sleep here since we can only connect the client after the server started.\n            try await Task.sleep(nanoseconds: 100_000_000)\n\n            group.addTask {\n                try await Self.makeRawSocketClientChannelWithProtocolNegotiation(\n                    eventLoopGroup: eventLoopGroup,\n                    proposedALPN: .string\n                )\n            }\n\n            let firstNegotiationResult = try await group.next()\n            let secondNegotiationResult = try await group.next()\n\n            switch (try await firstNegotiationResult?.get(), try await secondNegotiationResult?.get()) {\n            case (.string(let firstChannel), .string(let secondChannel)):\n                try await firstChannel.executeThenClose { firstChannelInbound, firstChannelOutbound in\n                    try await secondChannel.executeThenClose { secondChannelInbound, secondChannelOutbound in\n                        var firstInboundIterator = firstChannelInbound.makeAsyncIterator()\n                        var secondInboundIterator = secondChannelInbound.makeAsyncIterator()\n\n                        try await firstChannelOutbound.write(\"request\")\n                        try await XCTAsyncAssertEqual(try await secondInboundIterator.next(), \"request\")\n\n                        try await secondChannelOutbound.write(\"response\")\n                        try await XCTAsyncAssertEqual(try await firstInboundIterator.next(), \"response\")\n                    }\n                }\n\n            default:\n                preconditionFailure()\n            }\n        }\n    }\n\n    // MARK: VSock\n\n    func testVSock() async throws {\n        try XCTSkipUnless(System.supportsVsockLoopback, \"No vsock loopback transport available\")\n        let eventLoopGroup = self.group!\n\n        let port = VsockAddress.Port(1234)\n\n        let serverChannel = try await ServerBootstrap(group: eventLoopGroup)\n            .bind(\n                to: VsockAddress(cid: .any, port: port)\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n                }\n            }\n\n        #if canImport(Darwin)\n        let connectAddress = VsockAddress(cid: .any, port: port)\n        #elseif os(Linux) || os(Android)\n        let connectAddress = VsockAddress(cid: .local, port: port)\n        #endif\n\n        try await withThrowingTaskGroup(of: Void.self) { group in\n            let (stream, continuation) = AsyncStream<StringOrByte>.makeStream()\n            var iterator = stream.makeAsyncIterator()\n\n            group.addTask {\n                try await withThrowingTaskGroup(of: Void.self) { _ in\n                    try await serverChannel.executeThenClose { inbound in\n                        for try await childChannel in inbound {\n                            try await childChannel.executeThenClose { childChannelInbound, _ in\n                                for try await value in childChannelInbound {\n                                    continuation.yield(.string(value))\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            let stringChannel = try await ClientBootstrap(group: eventLoopGroup)\n                .connect(to: connectAddress) { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                        try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                        try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                        return try NIOAsyncChannel<String, String>(wrappingChannelSynchronously: channel)\n                    }\n                }\n            try await stringChannel.executeThenClose { _, outbound in\n                try await outbound.write(\"hello\")\n            }\n\n            await XCTAsyncAssertEqual(await iterator.next(), .string(\"hello\"))\n\n            group.cancelAll()\n        }\n    }\n\n    // MARK: - Test Helpers\n\n    private func makePipeFileDescriptors() -> (\n        pipe1ReadFD: CInt, pipe1WriteFD: CInt, pipe2ReadFD: CInt, pipe2WriteFD: CInt\n    ) {\n        var pipe1FDs: [CInt] = [-1, -1]\n        pipe1FDs.withUnsafeMutableBufferPointer { ptr in\n            XCTAssertEqual(0, pipe(ptr.baseAddress!))\n        }\n        var pipe2FDs: [CInt] = [-1, -1]\n        pipe2FDs.withUnsafeMutableBufferPointer { ptr in\n            XCTAssertEqual(0, pipe(ptr.baseAddress!))\n        }\n        return (pipe1FDs[0], pipe1FDs[1], pipe2FDs[0], pipe2FDs[1])\n    }\n\n    private func makePipeFileDescriptors() -> (pipeReadFD: CInt, pipeWriteFD: CInt) {\n        var pipeFDs: [CInt] = [-1, -1]\n        pipeFDs.withUnsafeMutableBufferPointer { ptr in\n            XCTAssertEqual(0, pipe(ptr.baseAddress!))\n        }\n        return (pipeFDs[0], pipeFDs[1])\n    }\n\n    private func makeRawSocketServerChannel(\n        eventLoopGroup: EventLoopGroup\n    ) async throws -> NIOAsyncChannel<String, String> {\n        try await NIORawSocketBootstrap(group: eventLoopGroup)\n            .bind(\n                host: \"127.0.0.1\",\n                ipProtocol: .reservedForTesting\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(IPHeaderRemoverHandler())\n                    try channel.pipeline.syncOperations.addHandler(\n                        AddressedEnvelopingHandler(remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n                    )\n                    try channel.pipeline.syncOperations.addHandler(\n                        ByteToMessageHandler(LineDelimiterCoder(inboundID: 1))\n                    )\n                    try channel.pipeline.syncOperations.addHandler(\n                        MessageToByteHandler(LineDelimiterCoder(outboundID: 2))\n                    )\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                }\n            }\n    }\n\n    private func makeRawSocketClientChannel(\n        eventLoopGroup: EventLoopGroup\n    ) async throws -> NIOAsyncChannel<String, String> {\n        try await NIORawSocketBootstrap(group: eventLoopGroup)\n            .connect(\n                host: \"127.0.0.1\",\n                ipProtocol: .reservedForTesting\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(IPHeaderRemoverHandler())\n                    try channel.pipeline.syncOperations.addHandler(\n                        AddressedEnvelopingHandler(remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n                    )\n                    try channel.pipeline.syncOperations.addHandler(\n                        ByteToMessageHandler(LineDelimiterCoder(inboundID: 2))\n                    )\n                    try channel.pipeline.syncOperations.addHandler(\n                        MessageToByteHandler(LineDelimiterCoder(outboundID: 1))\n                    )\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                }\n            }\n    }\n\n    private static func makeRawSocketServerChannelWithProtocolNegotiation(\n        eventLoopGroup: EventLoopGroup\n    ) async throws -> EventLoopFuture<NegotiationResult> {\n        try await NIORawSocketBootstrap(group: eventLoopGroup)\n            .bind(\n                host: \"127.0.0.1\",\n                ipProtocol: .reservedForTesting\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(IPHeaderRemoverHandler())\n                    try channel.pipeline.syncOperations.addHandler(\n                        AddressedEnvelopingHandler(remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n                    )\n                    return try Self.configureProtocolNegotiationHandlers(\n                        channel: channel,\n                        proposedALPN: nil,\n                        inboundID: 1,\n                        outboundID: 2\n                    )\n                }\n            }\n    }\n\n    private static func makeRawSocketClientChannelWithProtocolNegotiation(\n        eventLoopGroup: EventLoopGroup,\n        proposedALPN: TLSUserEventHandler.ALPN\n    ) async throws -> EventLoopFuture<NegotiationResult> {\n        try await NIORawSocketBootstrap(group: eventLoopGroup)\n            .connect(\n                host: \"127.0.0.1\",\n                ipProtocol: .reservedForTesting\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(IPHeaderRemoverHandler())\n                    try channel.pipeline.syncOperations.addHandler(\n                        AddressedEnvelopingHandler(remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n                    )\n                    return try Self.configureProtocolNegotiationHandlers(\n                        channel: channel,\n                        proposedALPN: proposedALPN,\n                        inboundID: 2,\n                        outboundID: 1\n                    )\n                }\n            }\n    }\n\n    private func makeClientChannel(\n        eventLoopGroup: EventLoopGroup,\n        port: Int\n    ) async throws -> NIOAsyncChannel<String, String> {\n        try await ClientBootstrap(group: eventLoopGroup)\n            .connect(\n                to: .init(ipAddress: \"127.0.0.1\", port: port)\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(AddressedEnvelopingHandler())\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                }\n            }\n    }\n\n    private func makeClientChannel(\n        eventLoopGroup: EventLoopGroup,\n        fileDescriptor: CInt\n    ) async throws -> NIOAsyncChannel<String, String> {\n        try await ClientBootstrap(group: eventLoopGroup)\n            .withConnectedSocket(fileDescriptor) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(AddressedEnvelopingHandler())\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                }\n            }\n    }\n\n    private func makeClientChannelWithProtocolNegotiation(\n        eventLoopGroup: EventLoopGroup,\n        port: Int,\n        proposedALPN: TLSUserEventHandler.ALPN\n    ) async throws -> EventLoopFuture<NegotiationResult> {\n        try await ClientBootstrap(group: eventLoopGroup)\n            .connect(\n                to: .init(ipAddress: \"127.0.0.1\", port: port)\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try Self.configureProtocolNegotiationHandlers(channel: channel, proposedALPN: proposedALPN)\n                }\n            }\n    }\n\n    private func makeClientChannelWithNestedProtocolNegotiation(\n        eventLoopGroup: EventLoopGroup,\n        port: Int,\n        proposedOuterALPN: TLSUserEventHandler.ALPN,\n        proposedInnerALPN: TLSUserEventHandler.ALPN\n    ) async throws -> EventLoopFuture<EventLoopFuture<NegotiationResult>> {\n        try await ClientBootstrap(group: eventLoopGroup)\n            .connect(\n                to: .init(ipAddress: \"127.0.0.1\", port: port)\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try Self.configureNestedProtocolNegotiationHandlers(\n                        channel: channel,\n                        proposedOuterALPN: proposedOuterALPN,\n                        proposedInnerALPN: proposedInnerALPN\n                    )\n                }\n            }\n    }\n\n    private func makeUDPServerChannel(eventLoopGroup: EventLoopGroup) async throws -> NIOAsyncChannel<String, String> {\n        try await DatagramBootstrap(group: eventLoopGroup)\n            .bind(\n                host: \"127.0.0.1\",\n                port: 0\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(AddressedEnvelopingHandler())\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                }\n            }\n    }\n\n    private static func makeUDPServerChannelWithProtocolNegotiation(\n        eventLoopGroup: EventLoopGroup,\n        port: Int,\n        proposedALPN: TLSUserEventHandler.ALPN? = nil\n    ) async throws -> EventLoopFuture<NegotiationResult> {\n        try await DatagramBootstrap(group: eventLoopGroup)\n            .bind(\n                host: \"127.0.0.1\",\n                port: port\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(AddressedEnvelopingHandler())\n                    return try Self.configureProtocolNegotiationHandlers(channel: channel, proposedALPN: proposedALPN)\n                }\n            }\n    }\n\n    private func makeUDPClientChannel(\n        eventLoopGroup: EventLoopGroup,\n        port: Int\n    ) async throws -> NIOAsyncChannel<String, String> {\n        try await DatagramBootstrap(group: eventLoopGroup)\n            .connect(\n                host: \"127.0.0.1\",\n                port: port\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(AddressedEnvelopingHandler())\n                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n                    try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                    return try NIOAsyncChannel(wrappingChannelSynchronously: channel)\n                }\n            }\n    }\n\n    private static func makeUDPClientChannelWithProtocolNegotiation(\n        eventLoopGroup: EventLoopGroup,\n        port: Int,\n        proposedALPN: TLSUserEventHandler.ALPN\n    ) async throws -> EventLoopFuture<NegotiationResult> {\n        try await DatagramBootstrap(group: eventLoopGroup)\n            .connect(\n                host: \"127.0.0.1\",\n                port: port\n            ) { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(AddressedEnvelopingHandler())\n                    return try Self.configureProtocolNegotiationHandlers(channel: channel, proposedALPN: proposedALPN)\n                }\n            }\n    }\n\n    @discardableResult\n    private static func configureProtocolNegotiationHandlers(\n        channel: Channel,\n        proposedALPN: TLSUserEventHandler.ALPN? = nil,\n        inboundID: UInt8? = nil,\n        outboundID: UInt8? = nil\n    ) throws -> EventLoopFuture<NegotiationResult> {\n        try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder(inboundID: inboundID)))\n        try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder(outboundID: outboundID)))\n        try channel.pipeline.syncOperations.addHandler(TLSUserEventHandler(proposedALPN: proposedALPN))\n        return try self.addTypedApplicationProtocolNegotiationHandler(to: channel)\n    }\n\n    @discardableResult\n    private static func configureNestedProtocolNegotiationHandlers(\n        channel: Channel,\n        proposedOuterALPN: TLSUserEventHandler.ALPN? = nil,\n        proposedInnerALPN: TLSUserEventHandler.ALPN? = nil\n    ) throws -> EventLoopFuture<EventLoopFuture<NegotiationResult>> {\n        try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(LineDelimiterCoder()))\n        try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(LineDelimiterCoder()))\n        try channel.pipeline.syncOperations.addHandler(TLSUserEventHandler(proposedALPN: proposedOuterALPN))\n        let negotiationHandler = NIOTypedApplicationProtocolNegotiationHandler<EventLoopFuture<NegotiationResult>> {\n            alpnResult,\n            channel in\n            switch alpnResult {\n            case .negotiated(let alpn):\n                switch alpn {\n                case \"string\":\n                    return channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            TLSUserEventHandler(proposedALPN: proposedInnerALPN)\n                        )\n                        let negotiationFuture = try Self.addTypedApplicationProtocolNegotiationHandler(to: channel)\n\n                        return negotiationFuture\n                    }\n                case \"byte\":\n                    return channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            TLSUserEventHandler(proposedALPN: proposedInnerALPN)\n                        )\n                        let negotiationHandler = try Self.addTypedApplicationProtocolNegotiationHandler(to: channel)\n\n                        return negotiationHandler\n                    }\n                default:\n                    return channel.close().flatMapThrowing { throw ProtocolNegotiationError() }\n                }\n            case .fallback:\n                return channel.close().flatMapThrowing { throw ProtocolNegotiationError() }\n            }\n        }\n        try channel.pipeline.syncOperations.addHandler(negotiationHandler)\n        return negotiationHandler.protocolNegotiationResult\n    }\n\n    @discardableResult\n    private static func addTypedApplicationProtocolNegotiationHandler(\n        to channel: Channel\n    ) throws -> EventLoopFuture<NegotiationResult> {\n        let negotiationHandler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> {\n            alpnResult,\n            channel in\n            switch alpnResult {\n            case .negotiated(let alpn):\n                switch alpn {\n                case \"string\":\n                    return channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(ByteBufferToStringHandler())\n                        let asyncChannel = try NIOAsyncChannel<String, String>(\n                            wrappingChannelSynchronously: channel\n                        )\n\n                        return .string(asyncChannel)\n                    }\n                case \"byte\":\n                    return channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(ByteBufferToByteHandler())\n\n                        let asyncChannel = try NIOAsyncChannel<UInt8, UInt8>(\n                            wrappingChannelSynchronously: channel\n                        )\n\n                        return .byte(asyncChannel)\n                    }\n                default:\n                    return channel.close().flatMapThrowing { throw ProtocolNegotiationError() }\n                }\n            case .fallback:\n                return channel.close().flatMapThrowing { throw ProtocolNegotiationError() }\n            }\n        }\n\n        try channel.pipeline.syncOperations.addHandler(negotiationHandler)\n        return negotiationHandler.protocolNegotiationResult\n    }\n\n    override func setUp() {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 3)\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.group.syncShutdownGracefully())\n        self.group = nil\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension AsyncStream {\n    static func makeStream(\n        of elementType: Element.Type = Element.self,\n        bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded\n    ) -> (stream: AsyncStream<Element>, continuation: AsyncStream<Element>.Continuation) {\n        var continuation: AsyncStream<Element>.Continuation!\n        let stream = AsyncStream<Element>(bufferingPolicy: limit) { continuation = $0 }\n        return (stream: stream, continuation: continuation!)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertEqual<Element: Equatable>(\n    _ lhs: @autoclosure () async throws -> Element,\n    _ rhs: @autoclosure () async throws -> Element,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async rethrows {\n    let lhsResult = try await lhs()\n    let rhsResult = try await rhs()\n    XCTAssertEqual(lhsResult, rhsResult, file: file, line: line)\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nprivate func XCTAsyncAssertThrowsError<T>(\n    _ expression: @autoclosure () async throws -> T,\n    _ message: @autoclosure () -> String = \"\",\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ errorHandler: (_ error: Error) -> Void = { _ in }\n) async {\n    do {\n        _ = try await expression()\n        XCTFail(message(), file: file, line: line)\n    } catch {\n        errorHandler(error)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/BlockingIOThreadPoolTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport Foundation\nimport NIOCore\nimport NIOPosix\nimport XCTest\n\nclass BlockingIOThreadPoolTest: XCTestCase {\n    func testDoubleShutdownWorks() throws {\n        let threadPool = NIOThreadPool(numberOfThreads: 17)\n        threadPool.start()\n        try threadPool.syncShutdownGracefully()\n        try threadPool.syncShutdownGracefully()\n    }\n\n    func testStateCancelled() throws {\n        let threadPool = NIOThreadPool(numberOfThreads: 17)\n        let group = DispatchGroup()\n        group.enter()\n        threadPool.submit { state in\n            XCTAssertEqual(NIOThreadPool.WorkItemState.cancelled, state)\n            group.leave()\n        }\n        group.wait()\n        try threadPool.syncShutdownGracefully()\n    }\n\n    func testStateActive() throws {\n        let threadPool = NIOThreadPool(numberOfThreads: 17)\n        threadPool.start()\n        let group = DispatchGroup()\n        group.enter()\n        threadPool.submit { state in\n            XCTAssertEqual(NIOThreadPool.WorkItemState.active, state)\n            group.leave()\n        }\n        group.wait()\n        try threadPool.syncShutdownGracefully()\n    }\n\n    func testLoseLastReferenceAndShutdownWhileTaskStillRunning() throws {\n        let blockThreadSem = DispatchSemaphore(value: 0)\n        let allDoneSem = DispatchSemaphore(value: 0)\n\n        ({\n            let threadPool = NIOThreadPool(numberOfThreads: 2)\n            threadPool.start()\n            threadPool.submit { _ in\n                Foundation.Thread.sleep(forTimeInterval: 0.1)\n            }\n            threadPool.submit { _ in\n                blockThreadSem.wait()\n            }\n            threadPool.shutdownGracefully { error in\n                XCTAssertNil(error)\n                allDoneSem.signal()\n            }\n        })()\n        blockThreadSem.signal()\n        allDoneSem.wait()\n    }\n\n    func testDeadLockIfCalledOutWithLockHeld() throws {\n        let blockRunningSem = DispatchSemaphore(value: 0)\n        let blockOneThreadSem = DispatchSemaphore(value: 0)\n        let threadPool = NIOThreadPool(numberOfThreads: 1)\n        let allDone = DispatchSemaphore(value: 0)\n        threadPool.start()\n        // enqueue one that'll block the whole pool (1 thread only)\n        threadPool.submit { state in\n            XCTAssertEqual(state, .active)\n            blockRunningSem.signal()\n            blockOneThreadSem.wait()\n        }\n        blockRunningSem.wait()\n        // enqueue one that will be cancelled and then calls shutdown again which needs the lock\n        threadPool.submit { state in\n            XCTAssertEqual(state, .cancelled)\n            threadPool.shutdownGracefully { error in\n                XCTAssertNil(error)\n            }\n        }\n        threadPool.shutdownGracefully { error in\n            XCTAssertNil(error)\n            allDone.signal()\n        }\n        blockOneThreadSem.signal()  // that'll unblock the thread in the pool\n        allDone.wait()\n    }\n\n    func testPoolDoesGetReleasedWhenStoppedAndReferencedDropped() throws {\n        let taskRunningSem = DispatchSemaphore(value: 0)\n        let doneSem = DispatchSemaphore(value: 0)\n        let shutdownDoneSem = DispatchSemaphore(value: 0)\n        weak var weakThreadPool: NIOThreadPool? = nil\n        ({\n            let threadPool = NIOThreadPool(numberOfThreads: 1)\n            weakThreadPool = threadPool\n            threadPool.start()\n            threadPool.submit { state in\n                XCTAssertEqual(.active, state)\n                taskRunningSem.signal()\n                doneSem.wait()\n            }\n            taskRunningSem.wait()\n            threadPool.shutdownGracefully { error in\n                XCTAssertNil(error)\n                shutdownDoneSem.signal()\n            }\n        })()\n        XCTAssertNotNil(weakThreadPool)\n        doneSem.signal()\n        shutdownDoneSem.wait()\n        assert(weakThreadPool == nil, within: .seconds(1))\n    }\n\n    final class SomeClass: Sendable {\n        init() {}\n        func dummy() {}\n    }\n\n    func testClosureReferenceDroppedAfterSingleWorkItemExecution() throws {\n        let taskRunningSem = DispatchSemaphore(value: 0)\n        let doneSem = DispatchSemaphore(value: 0)\n        let threadPool = NIOThreadPool(numberOfThreads: 1)\n        threadPool.start()\n        weak var referencedObject: SomeClass? = nil\n        ({\n            let object = SomeClass()\n            referencedObject = object\n            threadPool.submit { state in\n                XCTAssertEqual(.active, state)\n                taskRunningSem.signal()\n                object.dummy()\n                doneSem.wait()\n            }\n        })()\n        taskRunningSem.wait()\n        doneSem.signal()\n        assert(referencedObject == nil, within: .seconds(1))\n        try threadPool.syncShutdownGracefully()\n    }\n\n    func testClosureReferencesDroppedAfterTwoConsecutiveWorkItemsExecution() throws {\n        let taskRunningSem = DispatchSemaphore(value: 0)\n        let doneSem = DispatchSemaphore(value: 0)\n        let threadPool = NIOThreadPool(numberOfThreads: 1)\n        threadPool.start()\n        weak var referencedObject1: SomeClass? = nil\n        weak var referencedObject2: SomeClass? = nil\n        ({\n            let object1 = SomeClass()\n            let object2 = SomeClass()\n            referencedObject1 = object1\n            referencedObject2 = object2\n            threadPool.submit { state in\n                XCTAssertEqual(.active, state)\n                taskRunningSem.signal()\n                object1.dummy()\n                doneSem.wait()\n            }\n            threadPool.submit { state in\n                XCTAssertEqual(.active, state)\n                taskRunningSem.signal()\n                object2.dummy()\n                doneSem.wait()\n            }\n        })()\n        taskRunningSem.wait()\n        doneSem.signal()\n        taskRunningSem.wait()\n        doneSem.signal()\n        assert(referencedObject1 == nil, within: .seconds(1))\n        assert(referencedObject2 == nil, within: .seconds(1))\n        try threadPool.syncShutdownGracefully()\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/BootstrapTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOPosix\n\nclass BootstrapTest: XCTestCase {\n    var group: MultiThreadedEventLoopGroup {\n        self.state.withLockedValue {\n            $0.group!\n        }\n    }\n\n    var groupBag: [MultiThreadedEventLoopGroup]? {\n        self.state.withLockedValue {\n            $0.groupBag\n        }\n    }\n\n    struct State {\n        var group: MultiThreadedEventLoopGroup?\n        var groupBag: [MultiThreadedEventLoopGroup]?\n\n        init() {\n            self.group = nil\n            self.groupBag = nil\n        }\n    }\n\n    private let state = NIOLockedValueBox<State>(State())\n\n    override func setUp() {\n        self.state.withLockedValue {\n            XCTAssertNil($0.group)\n            XCTAssertNil($0.groupBag)\n\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n            $0.group = group\n            $0.groupBag = []\n        }\n    }\n\n    override func tearDown() {\n        let group = try? assertNoThrowWithValue(\n            try self.state.withLockedValue { state -> MultiThreadedEventLoopGroup? in\n                guard let groupBag = state.groupBag else {\n                    XCTFail()\n                    return nil\n                }\n                for group in groupBag {\n                    XCTAssertNoThrow(try group.syncShutdownGracefully())\n                }\n                state.groupBag = nil\n                let group = state.group\n                state.group = nil\n                XCTAssertNotNil(group)\n                return group\n            }\n        )\n\n        XCTAssertNoThrow(try group?.syncShutdownGracefully())\n    }\n\n    static func freshEventLoop(_ state: NIOLockedValueBox<State>) -> EventLoop {\n        let group: MultiThreadedEventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        state.withLockedValue {\n            $0.groupBag!.append(group)\n        }\n        return group.next()\n    }\n\n    func testBootstrapsCallInitializersOnCorrectEventLoop() throws {\n        for numThreads in [\n            1,  // everything on one event loop\n            2,  // some stuff has shared event loops\n            5,  // everything on a different event loop\n        ] {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: numThreads)\n            defer {\n                XCTAssertNoThrow(try group.syncShutdownGracefully())\n            }\n\n            let childChannelDone = group.next().makePromise(of: Void.self)\n            let serverChannelDone = group.next().makePromise(of: Void.self)\n            let serverChannel = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .childChannelInitializer { channel in\n                        XCTAssert(channel.eventLoop.inEventLoop)\n                        childChannelDone.succeed(())\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }\n                    .serverChannelInitializer { channel in\n                        XCTAssert(channel.eventLoop.inEventLoop)\n                        serverChannelDone.succeed(())\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }\n                    .bind(host: \"localhost\", port: 0)\n                    .wait()\n            )\n            defer {\n                XCTAssertNoThrow(try serverChannel.close().wait())\n            }\n\n            let client = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .channelInitializer { channel in\n                        XCTAssert(channel.eventLoop.inEventLoop)\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }\n                    .connect(to: serverChannel.localAddress!)\n                    .wait(),\n                message:\n                    \"resolver debug info: \\(try! resolverDebugInformation(eventLoop: group.next(),host: \"localhost\", previouslyReceivedResult: serverChannel.localAddress!))\"\n            )\n            defer {\n                XCTAssertNoThrow(try client.syncCloseAcceptingAlreadyClosed())\n            }\n            XCTAssertNoThrow(try childChannelDone.futureResult.wait())\n            XCTAssertNoThrow(try serverChannelDone.futureResult.wait())\n        }\n    }\n\n    func testTCPBootstrapsTolerateFuturesFromDifferentEventLoopsReturnedInInitializers() throws {\n        let childChannelDone = Self.freshEventLoop(self.state).makePromise(of: Void.self)\n        let serverChannelDone = Self.freshEventLoop(self.state).makePromise(of: Void.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: Self.freshEventLoop(self.state))\n                .childChannelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    defer {\n                        childChannelDone.succeed(())\n                    }\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .serverChannelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    defer {\n                        serverChannelDone.succeed(())\n                    }\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let client = try assertNoThrowWithValue(\n            ClientBootstrap(group: Self.freshEventLoop(self.state))\n                .channelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try client.syncCloseAcceptingAlreadyClosed())\n        }\n        XCTAssertNoThrow(try childChannelDone.futureResult.wait())\n        XCTAssertNoThrow(try serverChannelDone.futureResult.wait())\n    }\n\n    func testUDPBootstrapToleratesFuturesFromDifferentEventLoopsReturnedInInitializers() throws {\n        XCTAssertNoThrow(\n            try DatagramBootstrap(group: Self.freshEventLoop(self.state))\n                .channelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n                .close()\n                .wait()\n        )\n    }\n\n    func testPreConnectedClientSocketToleratesFuturesFromDifferentEventLoopsReturnedInInitializers() throws {\n        var socketFDs: [CInt] = [-1, -1]\n        XCTAssertNoThrow(\n            try Posix.socketpair(\n                domain: .local,\n                type: .stream,\n                protocolSubtype: .default,\n                socketVector: &socketFDs\n            )\n        )\n        defer {\n            // 0 is closed together with the Channel below.\n            XCTAssertNoThrow(try NIOBSDSocket.close(socket: socketFDs[1]))\n        }\n\n        XCTAssertNoThrow(\n            try ClientBootstrap(group: Self.freshEventLoop(self.state))\n                .channelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .withConnectedSocket(socketFDs[0])\n                .wait()\n                .close()\n                .wait()\n        )\n    }\n\n    func testPreConnectedServerSocketToleratesFuturesFromDifferentEventLoopsReturnedInInitializers() throws {\n        let socket =\n            try NIOBSDSocket.socket(domain: .inet, type: .stream, protocolSubtype: .default)\n\n        let serverAddress = try assertNoThrowWithValue(SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0))\n        try serverAddress.withSockAddr { address, len in\n            try NIOBSDSocket.bind(\n                socket: socket,\n                address: address,\n                address_len: socklen_t(len)\n            )\n        }\n\n        let childChannelDone = Self.freshEventLoop(self.state).next().makePromise(of: Void.self)\n        let serverChannelDone = Self.freshEventLoop(self.state).next().makePromise(of: Void.self)\n\n        let serverChannel = try assertNoThrowWithValue(\n            try ServerBootstrap(group: Self.freshEventLoop(self.state))\n                .childChannelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    defer {\n                        childChannelDone.succeed(())\n                    }\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .serverChannelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    defer {\n                        serverChannelDone.succeed(())\n                    }\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .withBoundSocket(socket)\n                .wait()\n        )\n        let client = try assertNoThrowWithValue(\n            ClientBootstrap(group: Self.freshEventLoop(self.state))\n                .channelInitializer { [state] channel in\n                    XCTAssert(channel.eventLoop.inEventLoop)\n                    return Self.freshEventLoop(state).makeSucceededFuture(())\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try client.syncCloseAcceptingAlreadyClosed())\n        }\n        XCTAssertNoThrow(try childChannelDone.futureResult.wait())\n        XCTAssertNoThrow(try serverChannelDone.futureResult.wait())\n    }\n\n    func testTCPClientBootstrapAllowsConformanceCorrectly() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        func restrictBootstrapType(clientBootstrap: NIOClientTCPBootstrap) throws {\n            let serverAcceptedChannelPromise = group.next().makePromise(of: Channel.self)\n            let serverChannel = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .childChannelInitializer { channel in\n                        serverAcceptedChannelPromise.succeed(channel)\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }.bind(host: \"127.0.0.1\", port: 0).wait()\n            )\n\n            let clientChannel = try assertNoThrowWithValue(\n                clientBootstrap\n                    .channelInitializer({ (channel: Channel) in channel.eventLoop.makeSucceededFuture(()) })\n                    .connect(host: \"127.0.0.1\", port: serverChannel.localAddress!.port!).wait()\n            )\n\n            var buffer = clientChannel.allocator.buffer(capacity: 1)\n            buffer.writeString(\"a\")\n            try clientChannel.writeAndFlush(buffer).wait()\n\n            let serverAcceptedChannel = try serverAcceptedChannelPromise.futureResult.wait()\n\n            // Start shutting stuff down.\n            XCTAssertNoThrow(try clientChannel.close().wait())\n\n            // Wait for the close promises. These fire last.\n            XCTAssertNoThrow(\n                try EventLoopFuture.andAllSucceed(\n                    [\n                        clientChannel.closeFuture,\n                        serverAcceptedChannel.closeFuture,\n                    ],\n                    on: group.next()\n                ).wait()\n            )\n        }\n\n        let bootstrap = NIOClientTCPBootstrap(ClientBootstrap(group: group), tls: NIOInsecureNoTLS())\n        try restrictBootstrapType(clientBootstrap: bootstrap)\n    }\n\n    func testServerBootstrapBindTimeout() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        // Set a bindTimeout and call bind. Setting a bind timeout is currently unsupported\n        // by ServerBootstrap. We therefore expect the bind timeout to be ignored and bind to\n        // succeed, even with a minimal bind timeout.\n        let bootstrap = ServerBootstrap(group: group)\n            .bindTimeout(.nanoseconds(0))\n\n        let channel = try assertNoThrowWithValue(bootstrap.bind(host: \"127.0.0.1\", port: 0).wait())\n        XCTAssertNoThrow(try channel.close().wait())\n    }\n\n    func testServerBootstrapSetsChannelOptionsBeforeChannelInitializer() {\n        var channel: Channel? = nil\n        XCTAssertNoThrow(\n            channel = try ServerBootstrap(group: self.group)\n                .serverChannelOption(.autoRead, value: false)\n                .serverChannelInitializer { channel in\n                    channel.getOption(.autoRead).whenComplete { result in\n                        func workaround() {\n                            XCTAssertNoThrow(XCTAssertFalse(try result.get()))\n                        }\n                        workaround()\n                    }\n                    return channel.pipeline.addHandler(MakeSureAutoReadIsOffInChannelInitializer())\n                }\n                .bind(to: .init(ipAddress: \"127.0.0.1\", port: 0))\n                .wait()\n        )\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel?.close().wait())\n    }\n\n    func testClientBootstrapSetsChannelOptionsBeforeChannelInitializer() {\n        XCTAssertNoThrow(\n            try withTCPServerChannel(group: self.group) { server in\n                var channel: Channel? = nil\n                XCTAssertNoThrow(\n                    channel = try ClientBootstrap(group: self.group)\n                        .channelOption(.autoRead, value: false)\n                        .channelInitializer { channel in\n                            channel.getOption(.autoRead).whenComplete { result in\n                                func workaround() {\n                                    XCTAssertNoThrow(XCTAssertFalse(try result.get()))\n                                }\n                                workaround()\n                            }\n                            return channel.pipeline.addHandler(MakeSureAutoReadIsOffInChannelInitializer())\n                        }\n                        .connect(to: server.localAddress!)\n                        .wait()\n                )\n                XCTAssertNotNil(channel)\n                XCTAssertNoThrow(try channel?.close().wait())\n            }\n        )\n    }\n\n    func testPreConnectedSocketSetsChannelOptionsBeforeChannelInitializer() {\n        XCTAssertNoThrow(\n            try withTCPServerChannel(group: self.group) { server in\n                var maybeSocket: Socket? = nil\n                XCTAssertNoThrow(maybeSocket = try Socket(protocolFamily: .inet, type: .stream))\n                XCTAssertNoThrow(XCTAssertEqual(true, try maybeSocket?.connect(to: server.localAddress!)))\n                var maybeFD: CInt? = nil\n                XCTAssertNoThrow(maybeFD = try maybeSocket?.takeDescriptorOwnership())\n                guard let fd = maybeFD else {\n                    XCTFail(\"could not get a socket fd\")\n                    return\n                }\n\n                var channel: Channel? = nil\n                XCTAssertNoThrow(\n                    channel = try ClientBootstrap(group: self.group)\n                        .channelOption(.autoRead, value: false)\n                        .channelInitializer { channel in\n                            channel.getOption(.autoRead).whenComplete { result in\n                                func workaround() {\n                                    XCTAssertNoThrow(XCTAssertFalse(try result.get()))\n                                }\n                                workaround()\n                            }\n                            return channel.pipeline.addHandler(MakeSureAutoReadIsOffInChannelInitializer())\n                        }\n                        .withConnectedSocket(fd)\n                        .wait()\n                )\n                XCTAssertNotNil(channel)\n                XCTAssertNoThrow(try channel?.close().wait())\n            }\n        )\n    }\n\n    func testDatagramBootstrapSetsChannelOptionsBeforeChannelInitializer() {\n        var channel: Channel? = nil\n        XCTAssertNoThrow(\n            channel = try DatagramBootstrap(group: self.group)\n                .channelOption(.autoRead, value: false)\n                .channelInitializer { channel in\n                    channel.getOption(.autoRead).whenComplete { result in\n                        func workaround() {\n                            XCTAssertNoThrow(XCTAssertFalse(try result.get()))\n                        }\n                        workaround()\n                    }\n                    return channel.pipeline.addHandler(MakeSureAutoReadIsOffInChannelInitializer())\n                }\n                .bind(to: .init(ipAddress: \"127.0.0.1\", port: 0))\n                .wait()\n        )\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel?.close().wait())\n    }\n\n    func testPipeBootstrapSetsChannelOptionsBeforeChannelInitializer() {\n        XCTAssertNoThrow(\n            try withPipe { inPipe, outPipe in\n                var maybeInFD: CInt? = nil\n                var maybeOutFD: CInt? = nil\n                XCTAssertNoThrow(maybeInFD = try inPipe.takeDescriptorOwnership())\n                XCTAssertNoThrow(maybeOutFD = try outPipe.takeDescriptorOwnership())\n                guard let inFD = maybeInFD, let outFD = maybeOutFD else {\n                    XCTFail(\"couldn't get pipe fds\")\n                    return [inPipe, outPipe]\n                }\n                var channel: Channel? = nil\n                XCTAssertNoThrow(\n                    channel = try NIOPipeBootstrap(group: self.group)\n                        .channelOption(.autoRead, value: false)\n                        .channelInitializer { channel in\n                            channel.getOption(.autoRead).whenComplete { result in\n                                func workaround() {\n                                    XCTAssertNoThrow(XCTAssertFalse(try result.get()))\n                                }\n                                workaround()\n                            }\n                            return channel.pipeline.addHandler(MakeSureAutoReadIsOffInChannelInitializer())\n                        }\n                        .takingOwnershipOfDescriptors(input: inFD, output: outFD)\n                        .wait()\n                )\n                XCTAssertNotNil(channel)\n                XCTAssertNoThrow(try channel?.close().wait())\n                return []\n            }\n        )\n    }\n\n    func testPipeBootstrapInEventLoop() {\n        let testGrp = DispatchGroup()\n        testGrp.enter()\n\n        let eventLoop = self.group.next()\n\n        XCTAssertNoThrow(\n            try eventLoop.submit { [group = self.group] in\n                let pipe = Pipe()\n                defer {\n                    XCTAssertNoThrow(try pipe.fileHandleForReading.close())\n                    XCTAssertNoThrow(try pipe.fileHandleForWriting.close())\n                }\n                return NIOPipeBootstrap(group: group)\n                    .takingOwnershipOfDescriptors(\n                        input: dup(pipe.fileHandleForReading.fileDescriptor),\n                        output: dup(pipe.fileHandleForWriting.fileDescriptor)\n                    )\n                    .flatMap({ channel in\n                        channel.close()\n                    }).always({ _ in\n                        testGrp.leave()\n                    })\n            }.wait()\n        )\n        testGrp.wait()\n    }\n\n    func testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser() {\n        // It's unclear if this is the right solution, see https://github.com/apple/swift-nio/issues/1392\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        struct FoundHandlerThatWasNotSupposedToBeThereError: Error {}\n\n        var maybeServer: Channel? = nil\n        XCTAssertNoThrow(\n            maybeServer = try ServerBootstrap(group: group)\n                .serverChannelInitializer { channel in\n                    // Here, we test that we can't find the AcceptHandler\n                    channel.pipeline.context(name: \"AcceptHandler\").flatMap { context -> EventLoopFuture<Void> in\n                        XCTFail(\"unexpectedly found \\(context)\")\n                        return channel.eventLoop.makeFailedFuture(FoundHandlerThatWasNotSupposedToBeThereError())\n                    }.flatMapError { error -> EventLoopFuture<Void> in\n                        XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n                        if case .some(.notFound) = error as? ChannelPipelineError {\n                            return channel.eventLoop.makeSucceededFuture(())\n                        }\n                        return channel.eventLoop.makeFailedFuture(error)\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n\n        guard let server = maybeServer else {\n            XCTFail(\"couldn't bootstrap server\")\n            return\n        }\n\n        // But now, it should be there.\n        XCTAssertNoThrow(_ = try server.pipeline.containsHandler(name: \"AcceptHandler\").wait())\n        XCTAssertNoThrow(try server.close().wait())\n    }\n\n    func testClientBootstrapValidatesWorkingELGsCorrectly() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNotNil(ClientBootstrap(validatingGroup: elg))\n        XCTAssertNotNil(ClientBootstrap(validatingGroup: el))\n    }\n\n    func testClientBootstrapRejectsNotWorkingELGsCorrectly() {\n        let elg = EmbeddedEventLoop()\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNil(ClientBootstrap(validatingGroup: elg))\n        XCTAssertNil(ClientBootstrap(validatingGroup: el))\n    }\n\n    func testServerBootstrapValidatesWorkingELGsCorrectly() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNotNil(ServerBootstrap(validatingGroup: elg))\n        XCTAssertNotNil(ServerBootstrap(validatingGroup: el))\n        XCTAssertNotNil(ServerBootstrap(validatingGroup: elg, childGroup: elg))\n        XCTAssertNotNil(ServerBootstrap(validatingGroup: el, childGroup: el))\n    }\n\n    func testServerBootstrapRejectsNotWorkingELGsCorrectly() {\n        let correctELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try correctELG.syncShutdownGracefully())\n        }\n\n        let wrongELG = EmbeddedEventLoop()\n        defer {\n            XCTAssertNoThrow(try wrongELG.syncShutdownGracefully())\n        }\n        let wrongEL = wrongELG.next()\n        let correctEL = correctELG.next()\n\n        // both wrong\n        XCTAssertNil(ServerBootstrap(validatingGroup: wrongELG))\n        XCTAssertNil(ServerBootstrap(validatingGroup: wrongEL))\n        XCTAssertNil(ServerBootstrap(validatingGroup: wrongELG, childGroup: wrongELG))\n        XCTAssertNil(ServerBootstrap(validatingGroup: wrongEL, childGroup: wrongEL))\n\n        // group correct, child group wrong\n        XCTAssertNil(ServerBootstrap(validatingGroup: correctELG, childGroup: wrongELG))\n        XCTAssertNil(ServerBootstrap(validatingGroup: correctEL, childGroup: wrongEL))\n\n        // group wrong, child group correct\n        XCTAssertNil(ServerBootstrap(validatingGroup: wrongELG, childGroup: correctELG))\n        XCTAssertNil(ServerBootstrap(validatingGroup: wrongEL, childGroup: correctEL))\n    }\n\n    func testDatagramBootstrapValidatesWorkingELGsCorrectly() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNotNil(DatagramBootstrap(validatingGroup: elg))\n        XCTAssertNotNil(DatagramBootstrap(validatingGroup: el))\n    }\n\n    func testDatagramBootstrapRejectsNotWorkingELGsCorrectly() {\n        let elg = EmbeddedEventLoop()\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNil(DatagramBootstrap(validatingGroup: elg))\n        XCTAssertNil(DatagramBootstrap(validatingGroup: el))\n    }\n\n    func testNIOPipeBootstrapValidatesWorkingELGsCorrectly() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNotNil(NIOPipeBootstrap(validatingGroup: elg))\n        XCTAssertNotNil(NIOPipeBootstrap(validatingGroup: el))\n    }\n\n    func testNIOPipeBootstrapRejectsNotWorkingELGsCorrectly() {\n        let elg = EmbeddedEventLoop()\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.next()\n\n        XCTAssertNil(NIOPipeBootstrap(validatingGroup: elg))\n        XCTAssertNil(NIOPipeBootstrap(validatingGroup: el))\n    }\n\n    func testConvenienceOptionsAreEquivalentUniversalClient() throws {\n        func setAndGetOption<Option>(\n            option: Option,\n            _ applyOptions: (NIOClientTCPBootstrap) -> NIOClientTCPBootstrap\n        ) throws\n            -> Option.Value where Option: ChannelOption\n        {\n            let optionPromise = self.group.next().makePromise(of: Option.Value.self)\n            XCTAssertNoThrow(\n                try withTCPServerChannel(group: self.group) { server in\n                    var channel: Channel? = nil\n                    XCTAssertNoThrow(\n                        channel = try applyOptions(\n                            NIOClientTCPBootstrap(\n                                ClientBootstrap(group: self.group),\n                                tls: NIOInsecureNoTLS()\n                            )\n                        )\n                        .channelInitializer { channel in\n                            channel.getOption(option).cascade(to: optionPromise)\n                            return channel.eventLoop.makeSucceededFuture(())\n                        }\n                        .connect(to: server.localAddress!)\n                        .wait()\n                    )\n                    XCTAssertNotNil(channel)\n                    XCTAssertNoThrow(try channel?.close().wait())\n                }\n            )\n            return try optionPromise.futureResult.wait()\n        }\n\n        func checkOptionEquivalence<Option>(\n            longOption: Option,\n            setValue: Option.Value,\n            shortOption: ChannelOptions.TCPConvenienceOption\n        ) throws\n        where Option: ChannelOption, Option.Value: Equatable {\n            let longSetValue = try setAndGetOption(option: longOption) { bs in\n                bs.channelOption(longOption, value: setValue)\n            }\n            let shortSetValue = try setAndGetOption(option: longOption) { bs in\n                bs.channelConvenienceOptions([shortOption])\n            }\n            let unsetValue = try setAndGetOption(option: longOption) { $0 }\n\n            XCTAssertEqual(longSetValue, shortSetValue)\n            XCTAssertNotEqual(longSetValue, unsetValue)\n        }\n\n        try checkOptionEquivalence(\n            longOption: .socketOption(.so_reuseaddr),\n            setValue: 1,\n            shortOption: .allowLocalEndpointReuse\n        )\n        try checkOptionEquivalence(\n            longOption: .allowRemoteHalfClosure,\n            setValue: true,\n            shortOption: .allowRemoteHalfClosure\n        )\n        try checkOptionEquivalence(\n            longOption: .autoRead,\n            setValue: false,\n            shortOption: .disableAutoRead\n        )\n    }\n\n    func testClientBindWorksOnSocketsBoundToEitherIPv4OrIPv6Only() {\n        for isIPv4 in [true, false] {\n            guard System.supportsIPv6 || isIPv4 else {\n                continue  // need to skip IPv6 tests if we don't support it.\n            }\n            let localIP = isIPv4 ? \"127.0.0.1\" : \"::1\"\n            guard let serverLocalAddressChoice = try? SocketAddress(ipAddress: localIP, port: 0),\n                let clientLocalAddressWholeInterface = try? SocketAddress(ipAddress: localIP, port: 0),\n                let server1 =\n                    (try? ServerBootstrap(group: self.group)\n                        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                        .serverChannelOption(.maxMessagesPerRead, value: 1)\n                        .bind(to: serverLocalAddressChoice)\n                        .wait()),\n                let server2 =\n                    (try? ServerBootstrap(group: self.group)\n                        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                        .serverChannelOption(.maxMessagesPerRead, value: 1)\n                        .bind(to: serverLocalAddressChoice)\n                        .wait()),\n                let server1LocalAddress = server1.localAddress,\n                let server2LocalAddress = server2.localAddress\n            else {\n                XCTFail(\"can't boot servers even\")\n                return\n            }\n            defer {\n                XCTAssertNoThrow(try server1.close().wait())\n                XCTAssertNoThrow(try server2.close().wait())\n            }\n\n            // Try 1: Directly connect to 127.0.0.1, this won't do Happy Eyeballs.\n            XCTAssertNoThrow(\n                try ClientBootstrap(group: self.group)\n                    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .bind(to: clientLocalAddressWholeInterface)\n                    .connect(to: server1LocalAddress)\n                    .wait()\n                    .close()\n                    .wait()\n            )\n\n            var maybeChannel1: Channel? = nil\n            // Try 2: Connect to \"localhost\", this will do Happy Eyeballs.\n            var localhost = \"localhost\"\n            // Some platforms don't define \"localhost\" for IPv6, so check that\n            // and use \"ip6-localhost\" instead.\n            if !isIPv4 {\n                let hostResolver = GetaddrinfoResolver(loop: self.group.next(), aiSocktype: .stream, aiProtocol: .tcp)\n                let hostv6 = try! hostResolver.initiateAAAAQuery(host: \"localhost\", port: 8088).wait()\n                if hostv6.isEmpty {\n                    localhost = \"ip6-localhost\"\n                }\n            }\n\n            XCTAssertNoThrow(\n                maybeChannel1 = try ClientBootstrap(group: self.group)\n                    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .bind(to: clientLocalAddressWholeInterface)\n                    .connect(host: localhost, port: server1LocalAddress.port!)\n                    .wait()\n            )\n            guard let myChannel1 = maybeChannel1, let myChannel1Address = myChannel1.localAddress else {\n                XCTFail(\"can't connect channel 1\")\n                return\n            }\n            XCTAssertEqual(localIP, myChannel1Address.ipAddress)\n            // Try 3: Bind the client to the same address/port as in try 2 but to server 2.\n            XCTAssertNoThrow(\n                try ClientBootstrap(group: self.group)\n                    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .connectTimeout(.hours(2))\n                    .bind(to: myChannel1Address)\n                    .connect(to: server2LocalAddress)\n                    .map { channel -> Channel in\n                        XCTAssertEqual(myChannel1Address, channel.localAddress)\n                        return channel\n                    }\n                    .wait()\n                    .close()\n                    .wait()\n            )\n        }\n    }\n\n    // There was a bug where file handle ownership was not released when creating pipe channels failed.\n    func testReleaseFileHandleOnOwningFailure() {\n        struct NIOPipeBootstrapHooksChannelFail: NIOPipeBootstrapHooks {\n            func makePipeChannel(\n                eventLoop: NIOPosix.SelectableEventLoop,\n                input: SelectablePipeHandle?,\n                output: SelectablePipeHandle?\n            ) throws -> PipeChannel {\n                throw IOError(errnoCode: EBADF, reason: \"testing\")\n            }\n        }\n\n        let sock = socket(NIOBSDSocket.ProtocolFamily.local.rawValue, NIOBSDSocket.SocketType.stream.rawValue, 0)\n        defer {\n            close(sock)\n        }\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n\n        let bootstrap = NIOPipeBootstrap(validatingGroup: elg, hooks: NIOPipeBootstrapHooksChannelFail())\n        XCTAssertNotNil(bootstrap)\n\n        let channelFuture = bootstrap?.takingOwnershipOfDescriptor(inputOutput: sock)\n        XCTAssertThrowsError(try channelFuture?.wait())\n    }\n\n    private func doTestNoDoubleAddOnPipeBootstrapTakingOwnership(\n        _ method: (NIOPipeBootstrap, CInt) -> EventLoopFuture<Channel>\n    ) throws {\n        var socketPair: [CInt] = [-1, -1]\n        XCTAssertNoThrow(\n            try socketPair.withUnsafeMutableBufferPointer { socketPairPtr in\n                precondition(socketPairPtr.count == 2)\n                try Posix.socketpair(\n                    domain: .local,\n                    type: .stream,\n                    protocolSubtype: .default,\n                    socketVector: socketPairPtr.baseAddress\n                )\n            }\n        )\n        defer {\n            XCTAssertNoThrow(try socketPair.filter { $0 > 0 }.forEach(Posix.close(descriptor:)))\n        }\n\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n\n        let handler = AddOnceHandler()\n        let bootstrap = NIOPipeBootstrap(group: elg)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(handler)\n                }\n            }\n\n        let channel = try method(bootstrap, dup(socketPair[0])).wait()\n\n        defer {\n            try! channel.close().wait()\n        }\n\n        XCTAssertEqual(handler.added.withLockedValue { $0 }, 1)\n    }\n\n    func testNoDoubleAddOnPipeBootstrapTakingOwnership_inputOutput() throws {\n        try self.doTestNoDoubleAddOnPipeBootstrapTakingOwnership {\n            $0.takingOwnershipOfDescriptor(inputOutput: $1)\n        }\n    }\n\n    func testNoDoubleAddOnPipeBootstrapTakingOwnership_input() throws {\n        try self.doTestNoDoubleAddOnPipeBootstrapTakingOwnership {\n            $0.takingOwnershipOfDescriptor(input: $1)\n        }\n    }\n\n    func testNoDoubleAddOnPipeBootstrapTakingOwnership_output() throws {\n        try self.doTestNoDoubleAddOnPipeBootstrapTakingOwnership {\n            $0.takingOwnershipOfDescriptor(output: $1)\n        }\n    }\n\n    func testNoDoubleAddOnPipeBootstrapTakingOwnership_inputOutputSeparate() throws {\n        try self.doTestNoDoubleAddOnPipeBootstrapTakingOwnership {\n            $0.takingOwnershipOfDescriptors(input: $1, output: dup($1))\n        }\n    }\n}\n\nprivate final class AddOnceHandler: ChannelInboundHandler, Sendable {\n    typealias InboundIn = Any\n\n    let added = NIOLockedValueBox(0)\n\n    init() {}\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        self.added.withLockedValue { $0 += 1 }\n    }\n}\n\nprivate final class WriteStringOnChannelActive: ChannelInboundHandler {\n    typealias InboundIn = Never\n    typealias OutboundOut = ByteBuffer\n\n    let string: String\n\n    init(_ string: String) {\n        self.string = string\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        var buffer = context.channel.allocator.buffer(capacity: self.string.utf8.count)\n        buffer.writeString(string)\n        context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n    }\n}\n\nprivate final class MakeSureAutoReadIsOffInChannelInitializer: ChannelInboundHandler, Sendable {\n    typealias InboundIn = Channel\n\n    func channelActive(context: ChannelHandlerContext) {\n        context.channel.getOption(.autoRead).whenComplete { result in\n            func workaround() {\n                XCTAssertNoThrow(XCTAssertFalse(try result.get()))\n            }\n            workaround()\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/ChannelNotificationTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass ChannelNotificationTest: XCTestCase {\n\n    private static func assertFulfilled(\n        promise: EventLoopPromise<Void>?,\n        promiseName: String,\n        trigger: String,\n        setter: String,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) {\n        if let promise = promise {\n            XCTAssertTrue(\n                promise.futureResult.isFulfilled,\n                \"\\(promiseName) not fulfilled before \\(trigger) was called\",\n                file: (file),\n                line: line\n            )\n        } else {\n            XCTFail(\"\\(setter) not called before \\(trigger)\", file: (file), line: line)\n        }\n    }\n\n    // Handler that verifies the notification order of the different promises + the inbound events that are fired.\n    class SocketChannelLifecycleVerificationHandler: ChannelDuplexHandler {\n        typealias InboundIn = Any\n        typealias OutboundIn = Any\n\n        private var registerPromise: EventLoopPromise<Void>?\n        private var connectPromise: EventLoopPromise<Void>?\n        private var closePromise: EventLoopPromise<Void>?\n\n        public func channelActive(context: ChannelHandlerContext) {\n            XCTAssertTrue(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelActive\",\n                setter: \"register\"\n            )\n            assertFulfilled(\n                promise: self.connectPromise,\n                promiseName: \"connectPromise\",\n                trigger: \"channelActive\",\n                setter: \"connect\"\n            )\n\n            XCTAssertNil(self.closePromise)\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelInactive\",\n                setter: \"register\"\n            )\n            assertFulfilled(\n                promise: self.connectPromise,\n                promiseName: \"connectPromise\",\n                trigger: \"channelInactive\",\n                setter: \"connect\"\n            )\n            assertFulfilled(\n                promise: self.closePromise,\n                promiseName: \"closePromise\",\n                trigger: \"channelInactive\",\n                setter: \"close\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelRegistered(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n            XCTAssertNil(self.connectPromise)\n            XCTAssertNil(self.closePromise)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelRegistered\",\n                setter: \"register\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelUnregistered(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelInactive\",\n                setter: \"register\"\n            )\n            assertFulfilled(\n                promise: self.connectPromise,\n                promiseName: \"connectPromise\",\n                trigger: \"channelInactive\",\n                setter: \"connect\"\n            )\n            assertFulfilled(\n                promise: self.closePromise,\n                promiseName: \"closePromise\",\n                trigger: \"channelInactive\",\n                setter: \"close\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n            XCTAssertNil(self.registerPromise)\n            XCTAssertNil(self.connectPromise)\n            XCTAssertNil(self.closePromise)\n\n            promise!.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertFalse(channel.isActive)\n            }\n\n            self.registerPromise = promise\n            context.register(promise: promise)\n        }\n\n        public func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n            XCTFail(\"bind(...) should not be called\")\n            context.bind(to: address, promise: promise)\n        }\n\n        public func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?)\n        {\n            XCTAssertNotNil(self.registerPromise)\n            XCTAssertNil(self.connectPromise)\n            XCTAssertNil(self.closePromise)\n\n            promise!.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertTrue(channel.isActive)\n            }\n\n            self.connectPromise = promise\n            context.connect(to: address, promise: promise)\n        }\n\n        public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n            XCTAssertNotNil(self.registerPromise)\n            XCTAssertNotNil(self.connectPromise)\n            XCTAssertNil(self.closePromise)\n\n            promise!.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertFalse(channel.isActive)\n            }\n\n            self.closePromise = promise\n            context.close(mode: mode, promise: promise)\n        }\n    }\n\n    class AcceptedSocketChannelLifecycleVerificationHandler: ChannelDuplexHandler {\n        typealias InboundIn = Any\n        typealias OutboundIn = Any\n\n        private var registerPromise: EventLoopPromise<Void>?\n        private let activeChannelPromise: EventLoopPromise<Channel>\n\n        init(_ activeChannelPromise: EventLoopPromise<Channel>) {\n            self.activeChannelPromise = activeChannelPromise\n        }\n\n        public func channelActive(context: ChannelHandlerContext) {\n            XCTAssertTrue(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelActive\",\n                setter: \"register\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n            XCTAssertFalse(self.activeChannelPromise.futureResult.isFulfilled)\n            self.activeChannelPromise.succeed(context.channel)\n        }\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelInactive\",\n                setter: \"register\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelRegistered(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelRegistered\",\n                setter: \"register\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelUnregistered(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelUnregistered\",\n                setter: \"register\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n            XCTAssertNil(self.registerPromise)\n\n            let p = promise ?? context.eventLoop.makePromise()\n            p.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertFalse(channel.isActive)\n            }\n\n            self.registerPromise = p\n            context.register(promise: p)\n        }\n\n        public func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?)\n        {\n            XCTFail(\"connect(...) should not be called\")\n            context.connect(to: address, promise: promise)\n        }\n\n        public func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n            XCTFail(\"bind(...) should not be called\")\n            context.bind(to: address, promise: promise)\n        }\n\n        public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n            XCTFail(\"close(...) should not be called\")\n            context.close(mode: mode, promise: promise)\n        }\n    }\n\n    class ServerSocketChannelLifecycleVerificationHandler: ChannelDuplexHandler {\n        typealias InboundIn = Any\n        typealias OutboundIn = Any\n\n        private var registerPromise: EventLoopPromise<Void>?\n        private var bindPromise: EventLoopPromise<Void>?\n\n        private var closePromise: EventLoopPromise<Void>?\n\n        public func channelActive(context: ChannelHandlerContext) {\n            XCTAssertTrue(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelActive\",\n                setter: \"register\"\n            )\n\n            XCTAssertNil(self.closePromise)\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelInactive\",\n                setter: \"register\"\n            )\n            assertFulfilled(\n                promise: self.closePromise,\n                promiseName: \"closePromise\",\n                trigger: \"channelInactive\",\n                setter: \"close\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelRegistered(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n            XCTAssertNil(closePromise)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelRegistered\",\n                setter: \"register\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func channelUnregistered(context: ChannelHandlerContext) {\n            XCTAssertFalse(context.channel.isActive)\n\n            assertFulfilled(\n                promise: self.registerPromise,\n                promiseName: \"registerPromise\",\n                trigger: \"channelUnregistered\",\n                setter: \"register\"\n            )\n            assertFulfilled(\n                promise: self.closePromise,\n                promiseName: \"closePromise\",\n                trigger: \"channelInactive\",\n                setter: \"close\"\n            )\n\n            XCTAssertFalse(context.channel.closeFuture.isFulfilled)\n        }\n\n        public func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n            XCTAssertNil(self.registerPromise)\n            XCTAssertNil(self.bindPromise)\n            XCTAssertNil(self.closePromise)\n\n            let p = promise ?? context.eventLoop.makePromise()\n            p.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertFalse(channel.isActive)\n            }\n\n            self.registerPromise = p\n            context.register(promise: p)\n        }\n\n        public func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?)\n        {\n            XCTFail(\"connect(...) should not be called\")\n            context.connect(to: address, promise: promise)\n        }\n\n        public func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n            XCTAssertNotNil(self.registerPromise)\n            XCTAssertNil(self.bindPromise)\n            XCTAssertNil(self.closePromise)\n\n            promise?.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertTrue(channel.isActive)\n            }\n\n            self.bindPromise = promise\n            context.bind(to: address, promise: promise)\n        }\n\n        public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n            XCTAssertNotNil(self.registerPromise)\n            XCTAssertNotNil(self.bindPromise)\n            XCTAssertNil(self.closePromise)\n\n            let p = promise ?? context.eventLoop.makePromise()\n            p.futureResult.whenSuccess { [channel = context.channel] in\n                XCTAssertFalse(channel.isActive)\n            }\n\n            self.closePromise = p\n            context.close(mode: mode, promise: p)\n        }\n    }\n\n    func testNotificationOrder() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let acceptedChannelPromise = group.next().makePromise(of: Channel.self)\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .serverChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ServerSocketChannelLifecycleVerificationHandler()\n                        )\n                    }\n                }\n                .childChannelOption(.autoRead, value: false)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            AcceptedSocketChannelLifecycleVerificationHandler(acceptedChannelPromise)\n                        )\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            SocketChannelLifecycleVerificationHandler()\n                        )\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        XCTAssertNoThrow(try clientChannel.close().wait())\n        XCTAssertNoThrow(try clientChannel.closeFuture.wait())\n\n        let channel = try acceptedChannelPromise.futureResult.wait()\n        var buffer = channel.allocator.buffer(capacity: 8)\n        buffer.writeString(\"test\")\n\n        while (try? channel.writeAndFlush(buffer).wait()) != nil {\n            // Just write in a loop until it fails to ensure we detect the closed connection in a timely manner.\n        }\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n\n        XCTAssertNoThrow(try serverChannel.close().wait())\n        XCTAssertNoThrow(try serverChannel.closeFuture.wait())\n    }\n\n    func testActiveBeforeChannelRead() throws {\n        // Use two EventLoops to ensure the ServerSocketChannel and the SocketChannel are on different threads.\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class OrderVerificationHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private enum State {\n                case `init`\n                case active\n                case read\n                case readComplete\n                case inactive\n            }\n\n            private var state = State.`init`\n            private let promise: EventLoopPromise<Void>\n\n            init(_ promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            public func channelActive(context: ChannelHandlerContext) {\n                XCTAssertEqual(.`init`, state)\n                state = .active\n            }\n\n            public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTAssertEqual(.active, state)\n                state = .read\n            }\n\n            public func channelReadComplete(context: ChannelHandlerContext) {\n                XCTAssertTrue(\n                    .read == state || .readComplete == state,\n                    \"State should either be .read or .readComplete but was \\(state)\"\n                )\n                state = .readComplete\n            }\n\n            public func channelInactive(context: ChannelHandlerContext) {\n                XCTAssertEqual(.readComplete, state)\n                state = .inactive\n\n                promise.succeed(())\n            }\n        }\n\n        let promise = group.next().makePromise(of: Void.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelOption(.autoRead, value: true)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(OrderVerificationHandler(promise))\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        var buffer = clientChannel.allocator.buffer(capacity: 2)\n        buffer.writeString(\"X\")\n        XCTAssertNoThrow(\n            try clientChannel.writeAndFlush(buffer).flatMap {\n                clientChannel.close()\n            }.wait()\n        )\n        XCTAssertNoThrow(try promise.futureResult.wait())\n\n        XCTAssertNoThrow(try clientChannel.closeFuture.wait())\n        XCTAssertNoThrow(try serverChannel.close().wait())\n        XCTAssertNoThrow(try serverChannel.closeFuture.wait())\n    }\n\n    func testNoActiveInactiveNotificationsWhenDirectlyClosed() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class OrderVerificationHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            init() {\n                // nop\n            }\n\n            public func channelActive(context: ChannelHandlerContext) {\n                XCTFail(\"There should be no events when the channel is closed directly.\")\n            }\n\n            public func channelInactive(context: ChannelHandlerContext) {\n                XCTFail(\"There should be no events when the channel is closed directly.\")\n            }\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let connectFuture = ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(OrderVerificationHandler())\n                }\n            }\n            .connect(to: serverChannel.localAddress!)\n\n        // Close immediately in the promise callback. The channel must still become active before it becomes inactive!\n        let closeFuture = connectFuture.flatMap { channel in\n            channel.close()\n        }\n\n        XCTAssertNoThrow(try closeFuture.wait())\n\n        XCTAssertNoThrow(try serverChannel.close().wait())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/ChannelPipelineTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport NIOPosix\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOCore\n\nprivate final class IndexWritingHandler: ChannelDuplexHandler {\n    typealias InboundIn = ByteBuffer\n    typealias InboundOut = ByteBuffer\n    typealias OutboundIn = ByteBuffer\n    typealias OutboundOut = ByteBuffer\n\n    private let index: Int\n\n    init(_ index: Int) {\n        self.index = index\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var buf = Self.unwrapInboundIn(data)\n        buf.writeInteger(UInt8(self.index))\n        context.fireChannelRead(Self.wrapInboundOut(buf))\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        var buf = Self.unwrapOutboundIn(data)\n        buf.writeInteger(UInt8(self.index))\n        context.write(Self.wrapOutboundOut(buf), promise: promise)\n    }\n}\n\nextension EmbeddedChannel {\n    fileprivate func assertReadIndexOrder(_ order: [UInt8]) {\n        XCTAssertTrue(try self.writeInbound(self.allocator.buffer(capacity: 32)).isFull)\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                order,\n                try self.readInbound(as: ByteBuffer.self).flatMap { buffer in\n                    var buffer = buffer\n                    return buffer.readBytes(length: buffer.readableBytes)\n                }\n            )\n        )\n    }\n\n    fileprivate func assertWriteIndexOrder(_ order: [UInt8]) {\n        XCTAssertTrue(try self.writeOutbound(self.allocator.buffer(capacity: 32)).isFull)\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                order,\n                try self.readOutbound(as: ByteBuffer.self).flatMap { buffer in\n                    var buffer = buffer\n                    return buffer.readBytes(length: buffer.readableBytes)\n                }\n            )\n        )\n    }\n}\n\nclass ChannelPipelineTest: XCTestCase {\n\n    final class SimpleTypedHandler1: ChannelInboundHandler, Sendable {\n        typealias InboundIn = NIOAny\n    }\n    final class SimpleTypedHandler2: ChannelInboundHandler, Sendable {\n        typealias InboundIn = NIOAny\n    }\n    final class SimpleTypedHandler3: ChannelInboundHandler, Sendable {\n        typealias InboundIn = NIOAny\n    }\n\n    func testGetHandler() throws {\n        let handler1 = SimpleTypedHandler1()\n        let handler2 = SimpleTypedHandler2()\n        let handler3 = SimpleTypedHandler3()\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        try channel.pipeline.addHandlers([\n            handler1,\n            handler2,\n            handler3,\n        ]).wait()\n\n        let result1 = try channel.pipeline.handler(type: SimpleTypedHandler1.self).wait()\n        XCTAssertTrue(result1 === handler1)\n\n        let result2 = try channel.pipeline.handler(type: SimpleTypedHandler2.self).wait()\n        XCTAssertTrue(result2 === handler2)\n\n        let result3 = try channel.pipeline.handler(type: SimpleTypedHandler3.self).wait()\n        XCTAssertTrue(result3 === handler3)\n    }\n\n    func testContainsHandler() throws {\n        let handler1 = SimpleTypedHandler1()\n        let handler2 = SimpleTypedHandler2()\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        try channel.pipeline.syncOperations.addHandler(handler1)\n        try channel.pipeline.syncOperations.addHandler(handler2, name: \"Handler2\")\n\n        try channel.pipeline.containsHandler(type: SimpleTypedHandler1.self).wait()\n        try channel.pipeline.containsHandler(name: \"Handler2\").wait()\n    }\n\n    func testGetFirstHandler() throws {\n        let sameTypeHandler1 = SimpleTypedHandler1()\n        let sameTypeHandler2 = SimpleTypedHandler1()\n        let otherHandler = SimpleTypedHandler2()\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        try channel.pipeline.addHandlers([\n            sameTypeHandler1,\n            sameTypeHandler2,\n            otherHandler,\n        ]).wait()\n\n        let result = try channel.pipeline.handler(type: SimpleTypedHandler1.self).wait()\n        XCTAssertTrue(result === sameTypeHandler1)\n    }\n\n    func testGetNotAddedHandler() throws {\n        let handler1 = SimpleTypedHandler1()\n        let handler2 = SimpleTypedHandler2()\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        try channel.pipeline.addHandlers([\n            handler1,\n            handler2,\n        ]).wait()\n\n        XCTAssertThrowsError(try channel.pipeline.handler(type: SimpleTypedHandler3.self).wait()) {\n            XCTAssertTrue($0 is ChannelPipelineError)\n        }\n    }\n\n    func testAddAfterClose() throws {\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish(acceptAlreadyClosed: true))\n        }\n        XCTAssertNoThrow(try channel.close().wait())\n\n        channel.pipeline.removeHandlers()\n\n        let handler = DummyHandler()\n        defer {\n            XCTAssertFalse(handler.handlerAddedCalled.load(ordering: .relaxed))\n            XCTAssertFalse(handler.handlerRemovedCalled.load(ordering: .relaxed))\n        }\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.addHandler(handler)) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n    }\n\n    private final class DummyHandler: ChannelHandler {\n        let handlerAddedCalled = ManagedAtomic(false)\n        let handlerRemovedCalled = ManagedAtomic(false)\n\n        public func handlerAdded(context: ChannelHandlerContext) {\n            handlerAddedCalled.store(true, ordering: .relaxed)\n        }\n\n        public func handlerRemoved(context: ChannelHandlerContext) {\n            handlerRemovedCalled.store(true, ordering: .relaxed)\n        }\n    }\n\n    func testOutboundOrdering() throws {\n\n        let channel = EmbeddedChannel()\n\n        var buf = channel.allocator.buffer(capacity: 1024)\n        buf.writeString(\"hello\")\n\n        try channel.pipeline.syncOperations.addHandler(\n            TestChannelOutboundHandler<Int, ByteBuffer> { data in\n                XCTAssertEqual(1, data)\n                return buf\n            }\n        )\n\n        try channel.pipeline.syncOperations.addHandler(\n            TestChannelOutboundHandler<String, Int> { data in\n                XCTAssertEqual(\"msg\", data)\n                return 1\n            }\n        )\n\n        XCTAssertNoThrow(try channel.writeAndFlush(\"msg\").wait() as Void)\n        if let data = try channel.readOutbound(as: ByteBuffer.self) {\n            XCTAssertEqual(buf, data)\n        } else {\n            XCTFail(\"couldn't read from channel\")\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testConnectingDoesntCallBind() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n        var ipv4SocketAddress = sockaddr_in()\n        ipv4SocketAddress.sin_port = (12345 as in_port_t).bigEndian\n        let sa = SocketAddress(ipv4SocketAddress, host: \"foobar.com\")\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(NoBindAllowed()))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                TestChannelOutboundHandler<ByteBuffer, ByteBuffer> { data in\n                    data\n                }\n            )\n        )\n\n        XCTAssertNoThrow(try channel.connect(to: sa).wait())\n    }\n\n    private final class TestChannelOutboundHandler<In, Out>: ChannelOutboundHandler {\n        typealias OutboundIn = In\n        typealias OutboundOut = Out\n\n        private let body: (OutboundIn) throws -> OutboundOut\n\n        init(_ body: @escaping (OutboundIn) throws -> OutboundOut) {\n            self.body = body\n        }\n\n        public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n            do {\n                context.write(Self.wrapOutboundOut(try body(Self.unwrapOutboundIn(data))), promise: promise)\n            } catch let err {\n                promise!.fail(err)\n            }\n        }\n    }\n\n    private final class NoBindAllowed: ChannelOutboundHandler {\n        typealias OutboundIn = ByteBuffer\n        typealias OutboundOut = ByteBuffer\n\n        enum TestFailureError: Error {\n            case CalledBind\n        }\n\n        public func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n            promise!.fail(TestFailureError.CalledBind)\n        }\n    }\n\n    private final class FireChannelReadOnRemoveHandler: ChannelInboundHandler, RemovableChannelHandler {\n        typealias InboundIn = Never\n        typealias InboundOut = Int\n\n        public func handlerRemoved(context: ChannelHandlerContext) {\n            context.fireChannelRead(Self.wrapInboundOut(1))\n        }\n    }\n\n    func testFiringChannelReadsInHandlerRemovedWorks() throws {\n        let channel = EmbeddedChannel()\n\n        let h = FireChannelReadOnRemoveHandler()\n        try channel.pipeline.syncOperations.addHandler(h)\n        try channel.pipeline.syncOperations.removeHandler(h).wait()\n\n        XCTAssertNoThrow(XCTAssertEqual(Optional<Int>.some(1), try channel.readInbound()))\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testEmptyPipelineWorks() throws {\n        let channel = EmbeddedChannel()\n        XCTAssertTrue(try assertNoThrowWithValue(channel.writeInbound(2)).isFull)\n        XCTAssertNoThrow(XCTAssertEqual(Optional<Int>.some(2), try channel.readInbound()))\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testWriteAfterClose() throws {\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish(acceptAlreadyClosed: true).isClean))\n        }\n        XCTAssertNoThrow(try channel.close().wait())\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        loop.run()\n\n        XCTAssertTrue(loop.inEventLoop)\n        do {\n            let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            let fr = FileRegion(fileHandle: handle, readerIndex: 0, endIndex: 0)\n            defer {\n                // fake descriptor, so shouldn't be closed.\n                XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n            }\n            try channel.writeOutbound(fr)\n            loop.run()\n            XCTFail(\"we ran but an error should have been thrown\")\n        } catch let err as ChannelError {\n            XCTAssertEqual(err, .ioOnClosedChannel)\n        }\n    }\n\n    func testOutboundNextForInboundOnlyIsCorrect() throws {\n        /// This handler always add its number to the inbound `[Int]` array\n        final class MarkingInboundHandler: ChannelInboundHandler {\n            typealias InboundIn = [Int]\n            typealias InboundOut = [Int]\n\n            private let no: Int\n\n            init(number: Int) {\n                self.no = number\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let data = Self.unwrapInboundIn(data)\n                context.fireChannelRead(Self.wrapInboundOut(data + [self.no]))\n            }\n        }\n\n        /// This handler always add its number to the outbound `[Int]` array\n        final class MarkingOutboundHandler: ChannelOutboundHandler {\n            typealias OutboundIn = [Int]\n            typealias OutboundOut = [Int]\n\n            private let no: Int\n\n            init(number: Int) {\n                self.no = number\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                let data = Self.unwrapOutboundIn(data)\n                context.write(Self.wrapOutboundOut(data + [self.no]), promise: promise)\n            }\n        }\n\n        /// This handler multiplies the inbound `[Int]` it receives by `-1` and writes it to the next outbound handler.\n        final class WriteOnReadHandler: ChannelInboundHandler {\n            typealias InboundIn = [Int]\n            typealias InboundOut = [Int]\n            typealias OutboundOut = [Int]\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let data = Self.unwrapInboundIn(data)\n                context.writeAndFlush(Self.wrapOutboundOut(data.map { $0 * -1 }), promise: nil)\n                context.fireChannelRead(Self.wrapInboundOut(data))\n            }\n        }\n\n        /// This handler just prints out the outbound received `[Int]` as a `ByteBuffer`.\n        final class PrintOutboundAsByteBufferHandler: ChannelOutboundHandler {\n            typealias OutboundIn = [Int]\n            typealias OutboundOut = ByteBuffer\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                let data = Self.unwrapOutboundIn(data)\n                var buf = context.channel.allocator.buffer(capacity: 123)\n                buf.writeString(String(describing: data))\n                context.write(Self.wrapOutboundOut(buf), promise: promise)\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        let loop = channel.embeddedEventLoop\n        loop.run()\n\n        try channel.pipeline.syncOperations.addHandler(PrintOutboundAsByteBufferHandler())\n        try channel.pipeline.syncOperations.addHandler(MarkingInboundHandler(number: 2))\n        try channel.pipeline.syncOperations.addHandler(WriteOnReadHandler())\n        try channel.pipeline.syncOperations.addHandler(MarkingOutboundHandler(number: 4))\n        try channel.pipeline.syncOperations.addHandler(WriteOnReadHandler())\n        try channel.pipeline.syncOperations.addHandler(MarkingInboundHandler(number: 6))\n        try channel.pipeline.syncOperations.addHandler(WriteOnReadHandler())\n\n        try channel.writeInbound([Int]())\n        loop.run()\n        XCTAssertNoThrow(XCTAssertEqual([2, 6], try channel.readInbound()!))\n\n        // the first thing, we should receive is `[-2]` as it shouldn't hit any `MarkingOutboundHandler`s (`4`)\n        var outbound = try channel.readOutbound(as: ByteBuffer.self)\n        if var buf = outbound {\n            XCTAssertEqual(\"[-2]\", buf.readString(length: buf.readableBytes))\n        } else {\n            XCTFail(\"wrong contents: \\(outbound.debugDescription)\")\n        }\n\n        // the next thing we should receive is `[-2, 4]` as the first `WriteOnReadHandler` (receiving `[2]`) is behind the `MarkingOutboundHandler` (`4`)\n        outbound = try channel.readOutbound()\n        if var buf = outbound {\n            XCTAssertEqual(\"[-2, 4]\", buf.readString(length: buf.readableBytes))\n        } else {\n            XCTFail(\"wrong contents: \\(outbound.debugDescription)\")\n        }\n\n        // and finally, we're waiting for `[-2, -6, 4]` as the second `WriteOnReadHandler`s (receiving `[2, 4]`) is behind the `MarkingOutboundHandler` (`4`)\n        outbound = try channel.readOutbound()\n        if var buf = outbound {\n            XCTAssertEqual(\"[-2, -6, 4]\", buf.readString(length: buf.readableBytes))\n        } else {\n            XCTFail(\"wrong contents: \\(outbound.debugDescription)\")\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testChannelInfrastructureIsNotLeaked() throws {\n        class SomeHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n\n            let body: (ChannelHandlerContext) -> Void\n\n            init(_ body: @escaping (ChannelHandlerContext) -> Void) {\n                self.body = body\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                self.body(context)\n            }\n        }\n        try {\n            let channel = EmbeddedChannel()\n            let loop = channel.eventLoop as! EmbeddedEventLoop\n\n            weak var weakHandler1: RemovableChannelHandler?\n            weak var weakHandler2: ChannelHandler?\n            weak var weakHandlerContext1: ChannelHandlerContext?\n            weak var weakHandlerContext2: ChannelHandlerContext?\n\n            ()  // needed because Swift's grammar is so ambiguous that you can't remove this :\\\n\n            try {\n                let handler1 = SomeHandler { context in\n                    weakHandlerContext1 = context\n                }\n                weakHandler1 = handler1\n                let handler2 = SomeHandler { context in\n                    weakHandlerContext2 = context\n                }\n                weakHandler2 = handler2\n                XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler1))\n                XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler2))\n            }()\n\n            XCTAssertNotNil(weakHandler1)\n            XCTAssertNotNil(weakHandler2)\n            XCTAssertNotNil(weakHandlerContext1)\n            XCTAssertNotNil(weakHandlerContext2)\n\n            XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(weakHandler1!).wait())\n\n            XCTAssertNil(weakHandler1)\n            XCTAssertNotNil(weakHandler2)\n            XCTAssertNil(weakHandlerContext1)\n            XCTAssertNotNil(weakHandlerContext2)\n\n            XCTAssertTrue(try channel.finish().isClean)\n\n            XCTAssertNil(weakHandler1)\n            XCTAssertNil(weakHandler2)\n            XCTAssertNil(weakHandlerContext1)\n            XCTAssertNil(weakHandlerContext2)\n\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }()\n    }\n\n    func testAddingHandlersFirstWorks() throws {\n        final class ReceiveIntHandler: ChannelInboundHandler {\n            typealias InboundIn = Int\n\n            var intReadCount = 0\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if data.tryAs(type: Int.self) != nil {\n                    self.intReadCount += 1\n                }\n            }\n        }\n\n        final class TransformStringToIntHandler: ChannelInboundHandler {\n            typealias InboundIn = String\n            typealias InboundOut = Int\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if let dataString = data.tryAs(type: String.self) {\n                    context.fireChannelRead(Self.wrapInboundOut(dataString.count))\n                }\n            }\n        }\n\n        final class TransformByteBufferToStringHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = String\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if var buffer = data.tryAs(type: ByteBuffer.self) {\n                    context.fireChannelRead(Self.wrapInboundOut(buffer.readString(length: buffer.readableBytes)!))\n                }\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let countHandler = ReceiveIntHandler()\n        var buffer = channel.allocator.buffer(capacity: 12)\n        buffer.writeStaticString(\"hello, world\")\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(countHandler))\n        XCTAssertTrue(try channel.writeInbound(buffer).isEmpty)\n        XCTAssertEqual(countHandler.intReadCount, 0)\n\n        try channel.pipeline.syncOperations.addHandlers(\n            TransformByteBufferToStringHandler(),\n            TransformStringToIntHandler(),\n            position: .first\n        )\n        XCTAssertTrue(try channel.writeInbound(buffer).isEmpty)\n        XCTAssertEqual(countHandler.intReadCount, 1)\n    }\n\n    func testAddAfter() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let firstHandler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(firstHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(2)))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .after(firstHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([1, 3, 2])\n        channel.assertWriteIndexOrder([2, 3, 1])\n    }\n\n    func testAddBefore() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let secondHandler = IndexWritingHandler(2)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(1)))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(secondHandler))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .before(secondHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([1, 3, 2])\n        channel.assertWriteIndexOrder([2, 3, 1])\n    }\n\n    func testAddAfterLast() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let secondHandler = IndexWritingHandler(2)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(1)))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(secondHandler))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .after(secondHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([1, 2, 3])\n        channel.assertWriteIndexOrder([3, 2, 1])\n    }\n\n    func testAddBeforeFirst() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let firstHandler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(firstHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(2)))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .before(firstHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([3, 1, 2])\n        channel.assertWriteIndexOrder([2, 1, 3])\n    }\n\n    func testAddAfterWhileClosed() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertThrowsError(try channel.finish()) { error in\n                XCTAssertEqual(.alreadyClosed, error as? ChannelError)\n            }\n        }\n\n        let handler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n        XCTAssertNoThrow(try channel.close().wait())\n        channel.embeddedEventLoop.run()\n\n        XCTAssertThrowsError(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(2),\n                position: .after(handler)\n            )\n        ) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n    }\n\n    func testAddBeforeWhileClosed() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertThrowsError(try channel.finish()) { error in\n                XCTAssertEqual(.alreadyClosed, error as? ChannelError)\n            }\n        }\n\n        let handler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n        XCTAssertNoThrow(try channel.close().wait())\n        channel.embeddedEventLoop.run()\n\n        XCTAssertThrowsError(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(2),\n                position: .before(handler)\n            )\n        ) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n    }\n\n    func testFindHandlerByType() {\n        class TypeAHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n        }\n\n        class TypeBHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n        }\n\n        class TypeCHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let h1 = TypeAHandler()\n        let h2 = TypeBHandler()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(h1))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(h2))\n\n        XCTAssertTrue(try h1 === channel.pipeline.syncOperations.context(handlerType: TypeAHandler.self).handler)\n        XCTAssertTrue(try h2 === channel.pipeline.syncOperations.context(handlerType: TypeBHandler.self).handler)\n\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.context(handlerType: TypeCHandler.self)) { error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n    }\n\n    func testFindHandlerByTypeReturnsTheFirstOfItsType() {\n        class TestHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let h1 = TestHandler()\n        let h2 = TestHandler()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(h1))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(h2))\n\n        XCTAssertTrue(try h1 === channel.pipeline.syncOperations.context(handlerType: TestHandler.self).handler)\n        XCTAssertFalse(try h2 === channel.pipeline.syncOperations.context(handlerType: TestHandler.self).handler)\n    }\n\n    func testContextForHeadOrTail() throws {\n        let channel = EmbeddedChannel()\n\n        defer {\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.context(name: HeadChannelHandler.name)) { error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.context(handlerType: HeadChannelHandler.self)) {\n            error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.context(name: TailChannelHandler.name)) { error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.context(handlerType: TailChannelHandler.self)) {\n            error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n    }\n\n    func testRemoveHeadOrTail() throws {\n        let channel = EmbeddedChannel()\n\n        defer {\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        XCTAssertThrowsError(try channel.pipeline.removeHandler(name: HeadChannelHandler.name).wait()) { error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n        XCTAssertThrowsError(try channel.pipeline.removeHandler(name: TailChannelHandler.name).wait()) { error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n    }\n\n    func testRemovingByContextWithPromiseStillInChannel() throws {\n        class NoOpHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n        }\n        struct DummyError: Error {}\n\n        let channel = EmbeddedChannel()\n        defer {\n            // This will definitely throw.\n            _ = try? channel.finish()\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(NoOpHandler()))\n\n        let context = try assertNoThrowWithValue(channel.pipeline.syncOperations.context(handlerType: NoOpHandler.self))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"Hello, world!\")\n\n        let removalPromise = channel.eventLoop.makePromise(of: Void.self)\n        let loopBoundContext = context.loopBound\n        removalPromise.futureResult.assumeIsolated().whenSuccess {\n            let context = loopBoundContext.value\n            context.writeAndFlush(NIOAny(buffer), promise: nil)\n            context.fireErrorCaught(DummyError())\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        channel.pipeline.syncOperations.removeHandler(context: context, promise: removalPromise)\n\n        XCTAssertNoThrow(try removalPromise.futureResult.wait())\n        guard case .some(.byteBuffer(let receivedBuffer)) = try channel.readOutbound(as: IOData.self) else {\n            XCTFail(\"No buffer\")\n            return\n        }\n        XCTAssertEqual(receivedBuffer, buffer)\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertNotNil(error as? DummyError)\n        }\n    }\n\n    func testRemovingByContextWithFutureNotInChannel() throws {\n        final class NoOpHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n        }\n        struct DummyError: Error {}\n\n        let channel = EmbeddedChannel()\n        defer {\n            // This will definitely throw.\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.addHandler(NoOpHandler()).wait())\n\n        let context = try assertNoThrowWithValue(channel.pipeline.syncOperations.context(handlerType: NoOpHandler.self))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"Hello, world!\")\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        let loopBoundContext = context.loopBound\n        channel.pipeline.syncOperations.removeHandler(context: context).assumeIsolated().whenSuccess {\n            let context = loopBoundContext.value\n            context.writeAndFlush(NIOAny(buffer), promise: nil)\n            context.fireErrorCaught(DummyError())\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n    }\n\n    func testRemovingByNameWithPromiseStillInChannel() throws {\n        class NoOpHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n        }\n        struct DummyError: Error {}\n\n        let channel = EmbeddedChannel()\n        defer {\n            // This will definitely throw.\n            _ = try? channel.finish()\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(NoOpHandler(), name: \"TestHandler\"))\n\n        let context = try assertNoThrowWithValue(channel.pipeline.syncOperations.context(handlerType: NoOpHandler.self))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"Hello, world!\")\n\n        let removalPromise = channel.eventLoop.makePromise(of: Void.self)\n        let loopBoundContext = context.loopBound\n        removalPromise.futureResult.assumeIsolated().map {\n            let context = loopBoundContext._value\n            context.writeAndFlush(NIOAny(buffer), promise: nil)\n            context.fireErrorCaught(DummyError())\n        }.whenFailure {\n            XCTFail(\"unexpected error: \\($0)\")\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        channel.pipeline.removeHandler(name: \"TestHandler\", promise: removalPromise)\n\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readOutbound(), buffer))\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertNotNil(error as? DummyError)\n        }\n    }\n\n    func testRemovingByNameWithFutureNotInChannel() throws {\n        class NoOpHandler: ChannelInboundHandler {\n            typealias InboundIn = Never\n        }\n        struct DummyError: Error {}\n\n        let channel = EmbeddedChannel()\n        defer {\n            // This will definitely throw.\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(NoOpHandler(), name: \"TestHandler\"))\n\n        let context = try assertNoThrowWithValue(channel.pipeline.syncOperations.context(handlerType: NoOpHandler.self))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"Hello, world!\")\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        let loopBoundContext = context.loopBound\n        channel.pipeline.removeHandler(name: \"TestHandler\").assumeIsolated().whenSuccess {\n            let context = loopBoundContext.value\n            context.writeAndFlush(NIOAny(buffer), promise: nil)\n            context.fireErrorCaught(DummyError())\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n    }\n\n    func testRemovingByReferenceWithPromiseStillInChannel() throws {\n        class NoOpHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n        }\n        struct DummyError: Error {}\n\n        let channel = EmbeddedChannel()\n        defer {\n            // This will definitely throw.\n            _ = try? channel.finish()\n        }\n\n        let handler = NoOpHandler()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        let context = try assertNoThrowWithValue(channel.pipeline.syncOperations.context(handlerType: NoOpHandler.self))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"Hello, world!\")\n\n        let removalPromise = channel.eventLoop.makePromise(of: Void.self)\n        let loopBoundContext = context.loopBound\n        removalPromise.futureResult.assumeIsolated().whenSuccess {\n            let context = loopBoundContext.value\n            context.writeAndFlush(NIOAny(buffer), promise: nil)\n            context.fireErrorCaught(DummyError())\n        }\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        channel.pipeline.syncOperations.removeHandler(handler, promise: removalPromise)\n\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readOutbound(), buffer))\n\n        XCTAssertThrowsError(try channel.throwIfErrorCaught()) { error in\n            XCTAssertNotNil(error as? DummyError)\n        }\n    }\n\n    func testRemovingByReferenceWithFutureNotInChannel() throws {\n        class NoOpHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n        }\n        struct DummyError: Error {}\n\n        let channel = EmbeddedChannel()\n        defer {\n            // This will definitely throw.\n            XCTAssertTrue(try channel.finish().isClean)\n        }\n\n        let handler = NoOpHandler()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n\n        let context = try assertNoThrowWithValue(channel.pipeline.syncOperations.context(handlerType: NoOpHandler.self))\n\n        var buffer = channel.allocator.buffer(capacity: 1024)\n        buffer.writeStaticString(\"Hello, world!\")\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n        let loopBoundContext = context.loopBound\n        channel.pipeline.syncOperations.removeHandler(handler).assumeIsolated().whenSuccess {\n            let context = loopBoundContext.value\n            context.writeAndFlush(NIOAny(buffer), promise: nil)\n            context.fireErrorCaught(DummyError())\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(try channel.throwIfErrorCaught())\n    }\n\n    func testFireChannelReadInInactiveChannelDoesNotCrash() throws {\n        final class FireWhenInactiveHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ()\n            typealias InboundOut = ()\n\n            func channelInactive(context: ChannelHandlerContext) {\n                context.fireChannelRead(Self.wrapInboundOut(()))\n            }\n        }\n        let handler = FireWhenInactiveHandler()\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let server = try assertNoThrowWithValue(ServerBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).wait())\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n        let client = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHandler(handler)\n                }\n                .connect(to: server.localAddress!)\n                .wait()\n        )\n        XCTAssertNoThrow(try client.close().wait())\n    }\n\n    func testTeardownDuringFormalRemovalProcess() {\n        class NeverCompleteRemovalHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n\n            private let removalTokenPromise: EventLoopPromise<ChannelHandlerContext.RemovalToken>\n            private let handlerRemovedPromise: EventLoopPromise<Void>\n\n            init(\n                removalTokenPromise: EventLoopPromise<ChannelHandlerContext.RemovalToken>,\n                handlerRemovedPromise: EventLoopPromise<Void>\n            ) {\n                self.removalTokenPromise = removalTokenPromise\n                self.handlerRemovedPromise = handlerRemovedPromise\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                self.handlerRemovedPromise.succeed(())\n            }\n\n            func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n                self.removalTokenPromise.succeed(removalToken)\n            }\n        }\n\n        let eventLoop = EmbeddedEventLoop()\n        let removalTokenPromise = eventLoop.makePromise(of: ChannelHandlerContext.RemovalToken.self)\n        let handlerRemovedPromise = eventLoop.makePromise(of: Void.self)\n\n        let channel = EmbeddedChannel(\n            handler: NeverCompleteRemovalHandler(\n                removalTokenPromise: removalTokenPromise,\n                handlerRemovedPromise: handlerRemovedPromise\n            ),\n            loop: eventLoop\n        )\n\n        // pretend we're real and connect\n        XCTAssertNoThrow(try channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5)).wait())\n\n        // let's trigger the removal process\n        XCTAssertNoThrow(\n            try channel.pipeline.context(handlerType: NeverCompleteRemovalHandler.self).map { handler in\n                channel.pipeline.syncOperations.removeHandler(context: handler, promise: nil)\n            }.wait()\n        )\n\n        XCTAssertNoThrow(\n            try removalTokenPromise.futureResult.map { removalToken in\n                // we know that the removal process has been started, so let's tear down the pipeline\n                func workaroundSR9815withAUselessFunction() {\n                    XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n                }\n                workaroundSR9815withAUselessFunction()\n            }.wait()\n        )\n\n        // verify that the handler has now been removed, despite the fact it should be mid-removal\n        XCTAssertNoThrow(try handlerRemovedPromise.futureResult.wait())\n    }\n\n    func testVariousChannelRemovalAPIsGoThroughRemovableChannelHandler() {\n        class Handler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n\n            var removeHandlerCalled = false\n            var withinRemoveHandler = false\n\n            func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n                self.removeHandlerCalled = true\n                self.withinRemoveHandler = true\n                defer {\n                    self.withinRemoveHandler = false\n                }\n                context.leavePipeline(removalToken: removalToken)\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertTrue(self.removeHandlerCalled)\n                XCTAssertTrue(self.withinRemoveHandler)\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n        let allHandlers = [Handler(), Handler(), Handler()]\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(allHandlers[0], name: \"the first one to remove\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(allHandlers[1]))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(allHandlers[2], name: \"the last one to remove\"))\n\n        let lastContext = try! channel.pipeline.syncOperations.context(name: \"the last one to remove\")\n\n        XCTAssertNoThrow(try channel.pipeline.removeHandler(name: \"the first one to remove\").wait())\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(allHandlers[1]).wait())\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(context: lastContext).wait())\n\n        for handler in allHandlers {\n            XCTAssertTrue(handler.removeHandlerCalled)\n            XCTAssertFalse(handler.withinRemoveHandler)\n        }\n    }\n\n    func testRemovingByContexSync() throws {\n        class Handler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n\n            var removeHandlerCalled = false\n            var withinRemoveHandler = false\n\n            func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n                self.removeHandlerCalled = true\n                self.withinRemoveHandler = true\n                defer {\n                    self.withinRemoveHandler = false\n                }\n                context.leavePipeline(removalToken: removalToken)\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertTrue(self.removeHandlerCalled)\n                XCTAssertTrue(self.withinRemoveHandler)\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n        let allHandlers = [Handler(), Handler(), Handler()]\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(allHandlers[0], name: \"the first one to remove\")\n        )\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(allHandlers[1], name: \"the second one to remove\")\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(allHandlers[2], name: \"the last one to remove\"))\n\n        let firstContext = try! channel.pipeline.syncOperations.context(name: \"the first one to remove\")\n        let secondContext = try! channel.pipeline.syncOperations.context(name: \"the second one to remove\")\n        let lastContext = try! channel.pipeline.syncOperations.context(name: \"the last one to remove\")\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(context: firstContext).wait())\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(context: secondContext).wait())\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.removeHandler(context: lastContext).wait())\n\n        for handler in allHandlers {\n            XCTAssertTrue(handler.removeHandlerCalled)\n            XCTAssertFalse(handler.withinRemoveHandler)\n        }\n    }\n\n    func testNonRemovableChannelHandlerIsNotRemovable() {\n        class NonRemovableHandler: ChannelInboundHandler {\n            typealias InboundIn = Never\n        }\n\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        let allHandlers = [NonRemovableHandler(), NonRemovableHandler(), NonRemovableHandler()]\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(allHandlers[0], name: \"1\"))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(allHandlers[1], name: \"2\"))\n\n        let lastContext = try! channel.pipeline.syncOperations.context(name: \"1\")\n\n        XCTAssertThrowsError(try channel.pipeline.removeHandler(name: \"2\").wait()) { error in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.unremovableHandler, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.removeHandler(context: lastContext).wait()) { error in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.unremovableHandler, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testAddMultipleHandlers() {\n        typealias Handler = TestAddMultipleHandlersHandlerWorkingAroundSR9956\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n        let a = Handler()\n        let b = Handler()\n        let c = Handler()\n        let d = Handler()\n        let e = Handler()\n        let f = Handler()\n        let g = Handler()\n        let h = Handler()\n        let i = Handler()\n        let j = Handler()\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(c))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(h))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandlers([d, e], position: .after(c)))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandlers([f, g], position: .before(h)))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandlers([a, b], position: .first))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandlers([i, j], position: .last))\n\n        Handler.allHandlers = []\n        channel.pipeline.fireUserInboundEventTriggered(())\n\n        XCTAssertEqual([a, b, c, d, e, f, g, h, i, j], Handler.allHandlers)\n    }\n\n    func testPipelineDebugDescription() {\n        final class HTTPRequestParser: ChannelInboundHandler {\n            typealias InboundIn = Never\n        }\n        final class HTTPResponseSerializer: ChannelOutboundHandler {\n            typealias OutboundIn = Never\n        }\n        final class HTTPHandler: ChannelDuplexHandler {\n            typealias InboundIn = Never\n            typealias OutboundIn = Never\n        }\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n        let parser = HTTPRequestParser()\n        let serializer = HTTPResponseSerializer()\n        let handler = HTTPHandler()\n        XCTAssertEqual(\n            channel.pipeline.debugDescription,\n            \"\"\"\n            ChannelPipeline[\\(ObjectIdentifier(channel.pipeline))]:\n             <no handlers>\n            \"\"\"\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandlers([parser, serializer, handler]))\n        XCTAssertEqual(\n            channel.pipeline.debugDescription,\n            \"\"\"\n            ChannelPipeline[\\(ObjectIdentifier(channel.pipeline))]:\n                           [I] ↓↑ [O]\n             HTTPRequestParser ↓↑                        [handler0]\n                               ↓↑ HTTPResponseSerializer [handler1]\n                   HTTPHandler ↓↑ HTTPHandler            [handler2]\n            \"\"\"\n        )\n    }\n\n    func testWeDontCallHandlerRemovedTwiceIfAHandlerCompletesRemovalOnlyAfterChannelTeardown() {\n        enum State: Int {\n            // When we start the test,\n            case testStarted = 0\n            // we send a trigger event,\n            case triggerEventRead = 1\n            // when receiving the trigger event, we start the manual removal (which won't complete).\n            case manualRemovalStarted = 2\n            // Instead, we now close the channel to force a pipeline teardown,\n            case pipelineTeardown = 3\n            // which will make `handlerRemoved` called, from where\n            case handlerRemovedCalled = 4\n            // we also complete the manual removal.\n            case manualRemovalCompleted = 5\n            // And hopefully we never reach the error state.\n            case error = 999\n\n            mutating func next() {\n                if let newState = State(rawValue: self.rawValue + 1) {\n                    self = newState\n                } else {\n                    XCTFail(\"there's no next state starting from \\(self)\")\n                    self = .error\n                }\n            }\n        }\n        class Handler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = State\n            typealias InboundOut = State\n\n            private(set) var state: State = .testStarted\n            private var removalToken: ChannelHandlerContext.RemovalToken? = nil\n            private let allDonePromise: EventLoopPromise<Void>\n\n            init(allDonePromise: EventLoopPromise<Void>) {\n                self.allDonePromise = allDonePromise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let step = Self.unwrapInboundIn(data)\n                self.state.next()\n                XCTAssertEqual(self.state, step)\n\n                // just to communicate to the outside where we are in our state machine\n                context.fireChannelRead(Self.wrapInboundOut(self.state))\n\n                switch step {\n                case .triggerEventRead:\n                    // Step 1: Okay, let's kick off the manual removal (it won't complete)\n                    context.pipeline.syncOperations.removeHandler(self).assumeIsolated().map {\n                        // When the manual removal completes, we advance the state.\n                        self.state.next()\n                    }.nonisolated().cascade(to: self.allDonePromise)\n                default:\n                    XCTFail(\"channelRead called in state \\(self.state)\")\n                }\n            }\n\n            func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n                self.state.next()\n                XCTAssertEqual(.manualRemovalStarted, self.state)\n\n                // Step 2: Save the removal token that we got from kicking off the manual removal (in step 1)\n                self.removalToken = removalToken\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                self.state.next()\n                XCTAssertEqual(.pipelineTeardown, self.state)\n\n                // Step 3: We'll call our own channelRead which will advance the state.\n                self.completeTheManualRemoval(context: context)\n            }\n\n            func completeTheManualRemoval(context: ChannelHandlerContext) {\n                self.state.next()\n                XCTAssertEqual(.handlerRemovedCalled, self.state)\n\n                // just to communicate to the outside where we are in our state machine\n                context.fireChannelRead(Self.wrapInboundOut(self.state))\n\n                // Step 4: This happens when the pipeline is being torn down, so let's now also finish the manual\n                // removal process.\n                self.removalToken.map(context.leavePipeline(removalToken:))\n            }\n        }\n\n        let eventLoop = EmbeddedEventLoop()\n        let allDonePromise = eventLoop.makePromise(of: Void.self)\n        let handler = Handler(allDonePromise: allDonePromise)\n        let channel = EmbeddedChannel(handler: handler, loop: eventLoop)\n        XCTAssertNoThrow(try channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5)).wait())\n\n        XCTAssertEqual(.testStarted, handler.state)\n        XCTAssertNoThrow(try channel.writeInbound(State.triggerEventRead))\n        XCTAssertNoThrow(XCTAssertEqual(State.triggerEventRead, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertNoThrow(\n            try {\n                // we'll get a left-over event on close which triggers the pipeline teardown and therefore continues the\n                // process.\n                switch try channel.finish() {\n                case .clean:\n                    XCTFail(\"expected output\")\n                case .leftOvers(let inbound, let outbound, let pendingOutbound):\n                    XCTAssertEqual(0, outbound.count)\n                    XCTAssertEqual(0, pendingOutbound.count)\n                    XCTAssertEqual(1, inbound.count)\n                    XCTAssertEqual(.handlerRemovedCalled, inbound.first?.tryAs(type: State.self))\n                }\n            }()\n        )\n\n        XCTAssertEqual(.manualRemovalCompleted, handler.state)\n\n        XCTAssertNoThrow(try allDonePromise.futureResult.wait())\n    }\n\n    func testWeFailTheSecondRemoval() {\n        final class Handler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = Never\n\n            private let removalTriggeredPromise: EventLoopPromise<Void>\n            private let continueRemovalFuture: EventLoopFuture<Void>\n            private var removeHandlerCalls = 0\n\n            init(\n                removalTriggeredPromise: EventLoopPromise<Void>,\n                continueRemovalFuture: EventLoopFuture<Void>\n            ) {\n                self.removalTriggeredPromise = removalTriggeredPromise\n                self.continueRemovalFuture = continueRemovalFuture\n            }\n\n            func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) {\n                self.removeHandlerCalls += 1\n                XCTAssertEqual(1, self.removeHandlerCalls)\n                self.removalTriggeredPromise.succeed(())\n                let loopBoundContext = context.loopBound\n                self.continueRemovalFuture.whenSuccess {\n                    let context = loopBoundContext.value\n                    context.leavePipeline(removalToken: removalToken)\n                }\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        let removalTriggeredPromise: EventLoopPromise<Void> = channel.eventLoop.makePromise()\n        let continueRemovalPromise: EventLoopPromise<Void> = channel.eventLoop.makePromise()\n\n        let handler = Handler(\n            removalTriggeredPromise: removalTriggeredPromise,\n            continueRemovalFuture: continueRemovalPromise.futureResult\n        )\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n        let removal1Future = channel.pipeline.syncOperations.removeHandler(handler)\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.removeHandler(handler).wait()) { error in\n            XCTAssert(\n                error is NIOAttemptedToRemoveHandlerMultipleTimesError,\n                \"unexpected error: \\(error)\"\n            )\n        }\n        continueRemovalPromise.succeed(())\n        XCTAssertThrowsError(try channel.pipeline.syncOperations.removeHandler(handler).wait()) { error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError, \"unexpected error: \\(error)\")\n        }\n        XCTAssertNoThrow(try removal1Future.wait())\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testSynchronousViewAddHandler() throws {\n        let channel = EmbeddedChannel()\n        let operations = channel.pipeline.syncOperations\n\n        // Add some handlers.\n        let handler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try operations.addHandler(IndexWritingHandler(2)))\n        XCTAssertNoThrow(try operations.addHandler(handler, position: .first))\n        XCTAssertNoThrow(try operations.addHandler(IndexWritingHandler(3), position: .after(handler)))\n        XCTAssertNoThrow(try operations.addHandler(IndexWritingHandler(4), position: .before(handler)))\n\n        channel.assertReadIndexOrder([4, 1, 3, 2])\n        channel.assertWriteIndexOrder([2, 3, 1, 4])\n    }\n\n    func testSynchronousViewAddHandlerAfterDestroyed() throws {\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.finish())\n\n        let operations = channel.pipeline.syncOperations\n\n        XCTAssertThrowsError(try operations.addHandler(SimpleTypedHandler1())) { error in\n            XCTAssertEqual(error as? ChannelError, .ioOnClosedChannel)\n        }\n\n        // The same for 'addHandlers'.\n        XCTAssertThrowsError(try operations.addHandlers([SimpleTypedHandler1()])) { error in\n            XCTAssertEqual(error as? ChannelError, .ioOnClosedChannel)\n        }\n    }\n\n    func testSynchronousViewAddHandlers() throws {\n        let channel = EmbeddedChannel()\n        let operations = channel.pipeline.syncOperations\n\n        // Add some handlers.\n        let firstHandler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try operations.addHandler(firstHandler))\n        XCTAssertNoThrow(try operations.addHandlers(IndexWritingHandler(2), IndexWritingHandler(3)))\n        XCTAssertNoThrow(\n            try operations.addHandlers(\n                [IndexWritingHandler(4), IndexWritingHandler(5)],\n                position: .before(firstHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([4, 5, 1, 2, 3])\n        channel.assertWriteIndexOrder([3, 2, 1, 5, 4])\n    }\n\n    func testSynchronousViewContext() throws {\n        let channel = EmbeddedChannel()\n        let operations = channel.pipeline.syncOperations\n\n        let simpleTypedHandler1 = SimpleTypedHandler1()\n        // Add some handlers.\n        XCTAssertNoThrow(try operations.addHandler(simpleTypedHandler1))\n        XCTAssertNoThrow(try operations.addHandler(SimpleTypedHandler2(), name: \"simple-2\"))\n        XCTAssertNoThrow(try operations.addHandler(SimpleTypedHandler3()))\n\n        // Get contexts using different predicates.\n\n        // By identity.\n        let simpleTypedHandler1Context = try assertNoThrowWithValue(operations.context(handler: simpleTypedHandler1))\n        XCTAssertTrue(simpleTypedHandler1Context.handler === simpleTypedHandler1)\n\n        // By name.\n        let simpleTypedHandler2Context = try assertNoThrowWithValue(operations.context(name: \"simple-2\"))\n        XCTAssertTrue(simpleTypedHandler2Context.handler is SimpleTypedHandler2)\n\n        // By type.\n        let simpleTypedHandler3Context = try assertNoThrowWithValue(\n            operations.context(handlerType: SimpleTypedHandler3.self)\n        )\n        XCTAssertTrue(simpleTypedHandler3Context.handler is SimpleTypedHandler3)\n    }\n\n    func testSynchronousViewGetTypedHandler() throws {\n        let channel = EmbeddedChannel()\n        let operations = channel.pipeline.syncOperations\n\n        let simpleTypedHandler1 = SimpleTypedHandler1()\n        let simpleTypedHandler2 = SimpleTypedHandler2()\n        // Add some handlers.\n        XCTAssertNoThrow(try operations.addHandler(simpleTypedHandler1))\n        XCTAssertNoThrow(try operations.addHandler(simpleTypedHandler2))\n\n        let handler1 = try assertNoThrowWithValue(try operations.handler(type: SimpleTypedHandler1.self))\n        XCTAssertTrue(handler1 === simpleTypedHandler1)\n\n        let handler2 = try assertNoThrowWithValue(try operations.handler(type: SimpleTypedHandler2.self))\n        XCTAssertTrue(handler2 === simpleTypedHandler2)\n    }\n\n    func testSynchronousViewPerformOperations() throws {\n        struct MyError: Error {}\n\n        let eventCounter = EventCounterHandler()\n        let channel = EmbeddedChannel(handler: eventCounter)\n\n        let operations = channel.pipeline.syncOperations\n        XCTAssertEqual(eventCounter.allTriggeredEvents(), [\"register\", \"channelRegistered\"])\n\n        // First do all the outbounds except close().\n        operations.register(promise: nil)\n        operations.bind(to: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 80), promise: nil)\n        operations.connect(to: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 80), promise: nil)\n        operations.triggerUserOutboundEvent(\"event\", promise: nil)\n        operations.write(NIOAny(ByteBuffer()), promise: nil)\n        operations.flush()\n        operations.writeAndFlush(NIOAny(ByteBuffer()), promise: nil)\n        operations.read()\n\n        XCTAssertEqual(eventCounter.bindCalls, 1)\n        XCTAssertEqual(eventCounter.channelActiveCalls, 1)\n        XCTAssertEqual(eventCounter.channelInactiveCalls, 0)\n        XCTAssertEqual(eventCounter.channelReadCalls, 0)\n        XCTAssertEqual(eventCounter.channelReadCompleteCalls, 0)\n        XCTAssertEqual(eventCounter.channelRegisteredCalls, 2)  // EmbeddedChannel itself does one, we did the other.\n        XCTAssertEqual(eventCounter.channelUnregisteredCalls, 0)\n        XCTAssertEqual(eventCounter.channelWritabilityChangedCalls, 0)\n        XCTAssertEqual(eventCounter.closeCalls, 0)\n        XCTAssertEqual(eventCounter.connectCalls, 1)\n        XCTAssertEqual(eventCounter.errorCaughtCalls, 0)\n        XCTAssertEqual(eventCounter.flushCalls, 2)  // flush, and writeAndFlush\n        XCTAssertEqual(eventCounter.readCalls, 1)\n        XCTAssertEqual(eventCounter.registerCalls, 2)  // EmbeddedChannel itself does one, we did the other.\n        XCTAssertEqual(eventCounter.triggerUserOutboundEventCalls, 1)\n        XCTAssertEqual(eventCounter.userInboundEventTriggeredCalls, 0)\n        XCTAssertEqual(eventCounter.writeCalls, 2)  // write, and writeAndFlush\n\n        // Now the inbound methods.\n        operations.fireChannelRegistered()\n        operations.fireChannelUnregistered()\n        operations.fireUserInboundEventTriggered(\"event\")\n        operations.fireChannelActive()\n        operations.fireChannelInactive()\n        operations.fireChannelRead(NIOAny(ByteBuffer()))\n        operations.fireChannelReadComplete()\n        operations.fireChannelWritabilityChanged()\n        operations.fireErrorCaught(MyError())\n\n        // And now close\n        operations.close(promise: nil)\n\n        // EmbeddedChannel itself does one, we did the other.\n        XCTAssertEqual(eventCounter.bindCalls, 1)\n        XCTAssertEqual(eventCounter.channelActiveCalls, 2)\n        XCTAssertEqual(eventCounter.channelInactiveCalls, 2)\n        XCTAssertEqual(eventCounter.channelReadCalls, 1)\n        XCTAssertEqual(eventCounter.channelReadCompleteCalls, 1)\n        // EmbeddedChannel itself does one, we did the other two.\n        XCTAssertEqual(eventCounter.channelRegisteredCalls, 3)\n        // EmbeddedChannel itself does one, we did the other.\n        XCTAssertEqual(eventCounter.channelUnregisteredCalls, 2)\n        XCTAssertEqual(eventCounter.channelWritabilityChangedCalls, 1)\n        XCTAssertEqual(eventCounter.closeCalls, 1)\n        XCTAssertEqual(eventCounter.connectCalls, 1)\n        XCTAssertEqual(eventCounter.errorCaughtCalls, 1)\n        XCTAssertEqual(eventCounter.flushCalls, 2)  // flush, and writeAndFlush\n        XCTAssertEqual(eventCounter.readCalls, 1)\n        // EmbeddedChannel itself does one, we did the other.\n        XCTAssertEqual(eventCounter.registerCalls, 2)\n        XCTAssertEqual(eventCounter.triggerUserOutboundEventCalls, 1)\n        XCTAssertEqual(eventCounter.userInboundEventTriggeredCalls, 1)\n        XCTAssertEqual(eventCounter.writeCalls, 2)  // write, and writeAndFlush\n    }\n\n    func testRetrieveInboundBufferedBytesFromChannelWithZeroHandler() throws {\n        let channel = EmbeddedChannel()\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeInbound(data)\n            let bufferedBytes = try channel.pipeline.inboundBufferedBytes().wait()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveOutboundBufferedBytesFromChannelWithZeroHandler() throws {\n        let channel = EmbeddedChannel()\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeOutbound(data)\n            let bufferedBytes = try channel.pipeline.outboundBufferedBytes().wait()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveInboundBufferedBytesFromChannelWithOneHandler() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                buffer.writeImmutableBuffer(self.unwrapInboundIn(data))\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([InboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for cnt in 1...5 {\n            try channel.writeInbound(data)\n            let bufferedBytes = try channel.pipeline.inboundBufferedBytes().wait()\n            XCTAssertEqual(bufferedBytes, cnt * data.readableBytes)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveOutboundBufferedBytesFromChannelWithOneHandler() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                buffer.writeImmutableBuffer(self.unwrapOutboundIn(data))\n                promise?.succeed()\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([OutboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for cnt in 1...5 {\n            try channel.writeOutbound(data)\n            let bufferedBytes = try channel.pipeline.outboundBufferedBytes().wait()\n            XCTAssertEqual(bufferedBytes, cnt * data.readableBytes)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveInboundBufferedBytesFromChannelWithEmptyBuffer() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.fireChannelRead(data)\n            }\n\n            var inboundBufferedBytes: Int { 0 }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([InboundBufferHandler(), InboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeInbound(data)\n            let bufferedBytes = try channel.pipeline.inboundBufferedBytes().wait()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveOutboundBufferedBytesFromChannelWithEmptyBuffer() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                context.write(data, promise: promise)\n            }\n\n            var outboundBufferedBytes: Int { 0 }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([OutboundBufferHandler(), OutboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeOutbound(data)\n            let bufferedBytes = try channel.pipeline.outboundBufferedBytes().wait()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveInboundBufferedBytesFromChannelWithMultipleHandlers() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            private let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buf = self.unwrapInboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readSlice(length: readSize) {\n                    buffer.writeImmutableBuffer(b)\n                }\n                context.fireChannelRead(self.wrapInboundOut(buf))\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { InboundBufferHandler(expectedBufferCount: $0) }\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers(handlers)\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeInbound(data)\n        let bufferedBytes = try channel.pipeline.inboundBufferedBytes().wait()\n        XCTAssertEqual(bufferedBytes, data.readableBytes)\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveOutboundBufferedBytesFromChannelWithMultipleHandlers() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            private let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                var buf = self.unwrapOutboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readSlice(length: readSize) {\n                    buffer.writeImmutableBuffer(b)\n                }\n\n                context.write(self.wrapOutboundOut(buf), promise: promise)\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { OutboundBufferHandler(expectedBufferCount: $0) }\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers(handlers)\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeOutbound(data)\n        let bufferedBytes = try channel.pipeline.outboundBufferedBytes().wait()\n        XCTAssertEqual(bufferedBytes, data.readableBytes)\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveInboundBufferedBytesFromChannelWithHandlersRemoved() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler,\n            RemovableChannelHandler\n        {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buf = self.unwrapInboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readBytes(length: readSize) {\n                    buffer.writeBytes(b)\n                    context.fireChannelRead(self.wrapInboundOut(buf))\n                }\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { InboundBufferHandler(expectedBufferCount: $0) }\n\n        let channel = EmbeddedChannel()\n        for handler in handlers {\n            try channel.pipeline.syncOperations.addHandler(handler, position: .last)\n        }\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeInbound(data)\n        var total = try channel.pipeline.inboundBufferedBytes().wait()\n        XCTAssertEqual(total, data.readableBytes)\n        let expectedBufferedBytes = handlers.map { $0.inboundBufferedBytes }\n        print(expectedBufferedBytes)\n\n        for (expectedBufferedByte, handler) in zip(expectedBufferedBytes, handlers) {\n            let expectedRemaining = total - expectedBufferedByte\n            channel.pipeline.syncOperations.removeHandler(handler).flatMap { _ in\n                channel.pipeline.inboundBufferedBytes()\n            }.and(value: expectedRemaining).whenSuccess { (remaining, expectedRemaining) in\n                XCTAssertEqual(remaining, expectedRemaining)\n            }\n            total -= expectedBufferedByte\n        }\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveOutboundBufferedBytesFromChannelWithHandlersRemoved() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler,\n            RemovableChannelHandler\n        {\n\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                var buf = self.unwrapOutboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readBytes(length: readSize) {\n                    buffer.writeBytes(b)\n                    context.write(self.wrapOutboundOut(buf), promise: promise)\n                }\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { OutboundBufferHandler(expectedBufferCount: $0) }\n\n        let channel = EmbeddedChannel()\n        for handler in handlers {\n            try channel.pipeline.syncOperations.addHandler(handler, position: .first)\n        }\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeOutbound(data)\n        var total = try channel.pipeline.outboundBufferedBytes().wait()\n        XCTAssertEqual(total, data.readableBytes)\n        let expectedBufferedBytes = handlers.map { $0.outboundBufferedBytes }\n\n        for (expectedBufferedByte, handler) in zip(expectedBufferedBytes, handlers) {\n            let expectedRemaining = total - expectedBufferedByte\n            channel.pipeline.syncOperations.removeHandler(handler).flatMap { _ in\n                channel.pipeline.outboundBufferedBytes()\n            }.and(value: expectedRemaining).whenSuccess { (remaining, expectedRemaining) in\n                XCTAssertEqual(remaining, expectedRemaining)\n            }\n            total -= expectedBufferedByte\n        }\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testRetrieveBufferedBytesFromChannelWithMixedHandlers() throws {\n        // A inbound channel handler that buffers incoming byte buffer when the total number of\n        // calls to the channelRead() is even.\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n            var count: Int\n            var bb: ByteBuffer\n\n            init() {\n                self.count = 0\n                self.bb = ByteBuffer()\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var d = unwrapInboundIn(data)\n                self.bb.writeBuffer(&d)\n\n                if count % 2 == 1 {\n                    context.fireChannelRead(self.wrapInboundOut(self.bb))\n                    self.bb.moveReaderIndex(forwardBy: self.bb.readableBytes)\n                }\n\n                count += 1\n            }\n\n            var inboundBufferedBytes: Int {\n                bb.readableBytes\n            }\n        }\n\n        // A outbound channel handler that buffers incoming byte buffer when the total number of\n        // calls to the write() is odd.\n        class OutboundBufferedHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n            var count: Int\n            var bb: ByteBuffer\n\n            init() {\n                self.count = 0\n                self.bb = ByteBuffer()\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                var d = unwrapOutboundIn(data)\n                self.bb.writeBuffer(&d)\n                if count % 2 == 0 {\n                    promise?.succeed()\n                } else {\n                    context.write(self.wrapOutboundOut(self.bb), promise: promise)\n                    self.bb.moveWriterIndex(forwardBy: self.bb.writableBytes)\n                }\n                count += 1\n            }\n\n            var outboundBufferedBytes: Int {\n                bb.writableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel(handlers: [InboundBufferHandler(), OutboundBufferedHandler()])\n\n        let data = ByteBuffer(string: \"123\")\n        try channel.writeAndFlush(data).wait()\n\n        channel.pipeline.outboundBufferedBytes().whenSuccess { result in\n            XCTAssertEqual(result, data.writableBytes)\n        }\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n\n        try channel.writeAndFlush(data).wait()\n\n        channel.pipeline.outboundBufferedBytes().whenSuccess { result in\n            XCTAssertEqual(result, 0)\n        }\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n\n        try channel.writeInbound(data)\n\n        channel.pipeline.inboundBufferedBytes().whenSuccess { result in\n            XCTAssertEqual(result, data.readableBytes)\n        }\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n\n        try channel.writeInbound(data)\n\n        channel.pipeline.inboundBufferedBytes().whenSuccess { result in\n            XCTAssertEqual(result, 0)\n        }\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesWhenChannelHandlerNotConformToProtocol() throws {\n        class InboundBufferHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.fireChannelRead(data)\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        let inboundChannelHandlerName = \"InboundBufferHandler\"\n        try channel.pipeline.syncOperations.addHandler(InboundBufferHandler(), name: inboundChannelHandlerName)\n        let context = try channel.pipeline.syncOperations.context(name: inboundChannelHandlerName)\n        let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes(in: context)\n\n        XCTAssertNil(bufferedBytes)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesWhenChannelHandlerNotConformToProtocol() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                context.write(data, promise: promise)\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        let outboundChannelHandlerName = \"outboundBufferHandler\"\n        try channel.pipeline.syncOperations.addHandler(OutboundBufferHandler(), name: outboundChannelHandlerName)\n        let context = try channel.pipeline.syncOperations.context(name: outboundChannelHandlerName)\n        let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes(in: context)\n\n        XCTAssertNil(bufferedBytes)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesFromOneHandler() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                buffer.writeImmutableBuffer(self.unwrapInboundIn(data))\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        let inboundChannelHandlerName = \"InboundBufferHandler\"\n        try channel.pipeline.syncOperations.addHandler(InboundBufferHandler(), name: inboundChannelHandlerName)\n\n        let data = ByteBuffer(string: \"1234\")\n        for cnt in 1...5 {\n            try channel.writeInbound(data)\n            let context = try channel.pipeline.syncOperations.context(name: inboundChannelHandlerName)\n            let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes(in: context)\n            XCTAssertNotNil(bufferedBytes)\n            XCTAssertEqual(bufferedBytes, data.readableBytes * cnt)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesFromOneHandler() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                buffer.writeImmutableBuffer(self.unwrapOutboundIn(data))\n                promise?.succeed()\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        let outboundChannelHandlerName = \"outboundBufferHandler\"\n        try channel.pipeline.syncOperations.addHandler(OutboundBufferHandler(), name: outboundChannelHandlerName)\n\n        let data = ByteBuffer(string: \"1234\")\n        for cnt in 1...5 {\n            try channel.writeOutbound(data)\n            let context = try channel.pipeline.syncOperations.context(name: outboundChannelHandlerName)\n            let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes(in: context)\n\n            XCTAssertNotNil(bufferedBytes)\n            XCTAssertEqual(bufferedBytes, data.readableBytes * cnt)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveEmptyInboundBufferedBytes() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.fireChannelRead(data)\n            }\n\n            var inboundBufferedBytes: Int { 0 }\n        }\n\n        let channel = EmbeddedChannel()\n        let inboundChannelHandlerName = \"InboundBufferHandler\"\n        try channel.pipeline.syncOperations.addHandler(InboundBufferHandler(), name: inboundChannelHandlerName)\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeInbound(data)\n            let context = try channel.pipeline.syncOperations.context(name: inboundChannelHandlerName)\n            let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes(in: context)\n\n            XCTAssertNotNil(bufferedBytes)\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveEmptyOutboundBufferedBytes() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                context.write(data, promise: promise)\n            }\n\n            var outboundBufferedBytes: Int { 0 }\n        }\n\n        let channel = EmbeddedChannel()\n        let outboundChannelHandlerName = \"outboundBufferHandler\"\n        try channel.pipeline.syncOperations.addHandler(OutboundBufferHandler(), name: outboundChannelHandlerName)\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeOutbound(data)\n            let context = try channel.pipeline.syncOperations.context(name: outboundChannelHandlerName)\n            let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes(in: context)\n\n            XCTAssertNotNil(bufferedBytes)\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesFromChannelWithZeroHandler() throws {\n        let channel = EmbeddedChannel()\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeInbound(data)\n            let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesFromChannelWithZeroHandler() throws {\n        let channel = EmbeddedChannel()\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeOutbound(data)\n            let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesFromChannelWithOneHandler() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                buffer.writeImmutableBuffer(self.unwrapInboundIn(data))\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([InboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for cnt in 1...5 {\n            try channel.writeInbound(data)\n            let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes()\n            XCTAssertEqual(bufferedBytes, cnt * data.readableBytes)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesFromChannelWithOneHandler() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                buffer.writeImmutableBuffer(self.unwrapOutboundIn(data))\n                promise?.succeed()\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([OutboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for cnt in 1...5 {\n            try channel.writeOutbound(data)\n            let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes()\n            XCTAssertEqual(bufferedBytes, cnt * data.readableBytes)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesFromChannelWithEmptyBuffer() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.fireChannelRead(data)\n            }\n\n            var inboundBufferedBytes: Int { 0 }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([InboundBufferHandler(), InboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeInbound(data)\n            let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readInbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesFromChannelWithEmptyBuffer() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                context.write(data, promise: promise)\n            }\n\n            var outboundBufferedBytes: Int { 0 }\n        }\n\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers([OutboundBufferHandler(), OutboundBufferHandler()])\n\n        let data = ByteBuffer(string: \"1234\")\n        for _ in 1...5 {\n            try channel.writeOutbound(data)\n            let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes()\n            XCTAssertEqual(bufferedBytes, 0)\n        }\n\n        for _ in 1...5 {\n            _ = try channel.readOutbound(as: ByteBuffer.self)\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesFromChannelWithMultipleHandlers() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            private let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buf = self.unwrapInboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readSlice(length: readSize) {\n                    buffer.writeImmutableBuffer(b)\n                }\n                context.fireChannelRead(self.wrapInboundOut(buf))\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { InboundBufferHandler(expectedBufferCount: $0) }\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers(handlers)\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeInbound(data)\n        let bufferedBytes = channel.pipeline.syncOperations.inboundBufferedBytes()\n        XCTAssertEqual(bufferedBytes, data.readableBytes)\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesFromChannelWithMultipleHandlers() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            private let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                var buf = self.unwrapOutboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readSlice(length: readSize) {\n                    buffer.writeImmutableBuffer(b)\n                }\n\n                context.write(self.wrapOutboundOut(buf), promise: promise)\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { OutboundBufferHandler(expectedBufferCount: $0) }\n        let channel = EmbeddedChannel()\n        try channel.pipeline.syncOperations.addHandlers(handlers)\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeOutbound(data)\n        let bufferedBytes = channel.pipeline.syncOperations.outboundBufferedBytes()\n        XCTAssertEqual(bufferedBytes, data.readableBytes)\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveInboundBufferedBytesFromChannelWithHandlersRemoved() throws {\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler,\n            RemovableChannelHandler\n        {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var buf = self.unwrapInboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readBytes(length: readSize) {\n                    buffer.writeBytes(b)\n                    context.fireChannelRead(self.wrapInboundOut(buf))\n                }\n            }\n\n            var inboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { InboundBufferHandler(expectedBufferCount: $0) }\n\n        let channel = EmbeddedChannel()\n        for handler in handlers {\n            try channel.pipeline.syncOperations.addHandler(handler, position: .last)\n        }\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeInbound(data)\n        var total = channel.pipeline.syncOperations.inboundBufferedBytes()\n        XCTAssertEqual(total, data.readableBytes)\n        let expectedBufferedBytes = handlers.map { $0.inboundBufferedBytes }\n        print(expectedBufferedBytes)\n\n        for (expectedBufferedByte, handler) in zip(expectedBufferedBytes, handlers) {\n            let expectedRemaining = total - expectedBufferedByte\n            channel.pipeline.syncOperations\n                .removeHandler(handler)\n                .and(value: expectedRemaining)\n                .whenSuccess { (_, expectedRemaining) in\n                    let remaining = channel.pipeline.syncOperations.inboundBufferedBytes()\n                    XCTAssertEqual(remaining, expectedRemaining)\n                }\n            total -= expectedBufferedByte\n        }\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveOutboundBufferedBytesFromChannelWithHandlersRemoved() throws {\n        class OutboundBufferHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler,\n            RemovableChannelHandler\n        {\n\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var buffer = ByteBuffer()\n            let expectedBufferCount: Int\n\n            init(expectedBufferCount: Int) {\n                self.expectedBufferCount = expectedBufferCount\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                var buf = self.unwrapOutboundIn(data)\n                let readSize = min(expectedBufferCount, buf.readableBytes)\n                if let b = buf.readBytes(length: readSize) {\n                    buffer.writeBytes(b)\n                    context.write(self.wrapOutboundOut(buf), promise: promise)\n                }\n            }\n\n            var outboundBufferedBytes: Int {\n                self.buffer.readableBytes\n            }\n        }\n\n        let handlers = (0..<5).map { OutboundBufferHandler(expectedBufferCount: $0) }\n\n        let channel = EmbeddedChannel()\n        for handler in handlers {\n            try channel.pipeline.syncOperations.addHandler(handler, position: .first)\n        }\n\n        let data = ByteBuffer(string: \"1234\")\n        try channel.writeOutbound(data)\n        var total = channel.pipeline.syncOperations.outboundBufferedBytes()\n        XCTAssertEqual(total, data.readableBytes)\n        let expectedBufferedBytes = handlers.map { $0.outboundBufferedBytes }\n\n        for (expectedBufferedByte, handler) in zip(expectedBufferedBytes, handlers) {\n            let expectedRemaining = total - expectedBufferedByte\n            channel.pipeline.syncOperations\n                .removeHandler(handler)\n                .and(value: expectedRemaining)\n                .whenSuccess { (_, expectedRemaining) in\n                    let remaining = channel.pipeline.syncOperations.outboundBufferedBytes()\n                    XCTAssertEqual(remaining, expectedRemaining)\n                }\n            total -= expectedBufferedByte\n        }\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testSynchronouslyRetrieveBufferedBytesFromChannelWithMixedHandlers() throws {\n        // A inbound channel handler that buffers incoming byte buffer when the total number of\n        // calls to the channelRead() is even.\n        class InboundBufferHandler: ChannelInboundHandler, NIOInboundByteBufferingChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n            var count: Int\n            var bb: ByteBuffer\n\n            init() {\n                self.count = 0\n                self.bb = ByteBuffer()\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                var d = unwrapInboundIn(data)\n                self.bb.writeBuffer(&d)\n\n                if count % 2 == 1 {\n                    context.fireChannelRead(self.wrapInboundOut(self.bb))\n                    self.bb.moveReaderIndex(forwardBy: self.bb.readableBytes)\n                }\n\n                count += 1\n            }\n\n            var inboundBufferedBytes: Int {\n                bb.readableBytes\n            }\n        }\n\n        // A outbound channel handler that buffers incoming byte buffer when the total number of\n        // calls to the write() is odd.\n        class OutboundBufferedHandler: ChannelOutboundHandler, NIOOutboundByteBufferingChannelHandler {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n            var count: Int\n            var bb: ByteBuffer\n\n            init() {\n                self.count = 0\n                self.bb = ByteBuffer()\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                var d = unwrapOutboundIn(data)\n                self.bb.writeBuffer(&d)\n                if count % 2 == 0 {\n                    promise?.succeed()\n                } else {\n                    context.write(self.wrapOutboundOut(self.bb), promise: promise)\n                    self.bb.moveWriterIndex(forwardBy: self.bb.writableBytes)\n                }\n                count += 1\n            }\n\n            var outboundBufferedBytes: Int {\n                bb.writableBytes\n            }\n        }\n\n        let channel = EmbeddedChannel(handlers: [InboundBufferHandler(), OutboundBufferedHandler()])\n\n        let data = ByteBuffer(string: \"123\")\n        try channel.writeAndFlush(data).wait()\n\n        var result = channel.pipeline.syncOperations.outboundBufferedBytes()\n        XCTAssertEqual(result, data.writableBytes)\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n\n        try channel.writeAndFlush(data).wait()\n\n        result = channel.pipeline.syncOperations.outboundBufferedBytes()\n        XCTAssertEqual(result, 0)\n\n        _ = try channel.readOutbound(as: ByteBuffer.self)\n\n        try channel.writeInbound(data)\n\n        result = channel.pipeline.syncOperations.inboundBufferedBytes()\n        XCTAssertEqual(result, data.readableBytes)\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n\n        try channel.writeInbound(data)\n\n        result = channel.pipeline.syncOperations.inboundBufferedBytes()\n        XCTAssertEqual(result, 0)\n\n        _ = try channel.readInbound(as: ByteBuffer.self)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testAddAfterForSynchronousPosition() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let firstHandler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(firstHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(2)))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .after(firstHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([1, 3, 2])\n        channel.assertWriteIndexOrder([2, 3, 1])\n    }\n\n    func testAddBeforeForSynchronousPosition() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let secondHandler = IndexWritingHandler(2)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(1)))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(secondHandler))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .before(secondHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([1, 3, 2])\n        channel.assertWriteIndexOrder([2, 3, 1])\n    }\n\n    func testAddAfterLastForSynchronousPosition() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let secondHandler = IndexWritingHandler(2)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(1)))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(secondHandler))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .after(secondHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([1, 2, 3])\n        channel.assertWriteIndexOrder([3, 2, 1])\n    }\n\n    func testAddBeforeFirstForSynchronousPosition() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        let firstHandler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(firstHandler))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IndexWritingHandler(2)))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(3),\n                position: .before(firstHandler)\n            )\n        )\n\n        channel.assertReadIndexOrder([3, 1, 2])\n        channel.assertWriteIndexOrder([2, 1, 3])\n    }\n\n    func testAddAfterWhileClosedForSynchronousPosition() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertThrowsError(try channel.finish()) { error in\n                XCTAssertEqual(.alreadyClosed, error as? ChannelError)\n            }\n        }\n\n        let handler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n        XCTAssertNoThrow(try channel.close().wait())\n        channel.embeddedEventLoop.run()\n\n        XCTAssertThrowsError(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(2),\n                position: .after(handler)\n            )\n        ) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n    }\n\n    func testAddBeforeWhileClosedForSynchronousPosition() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertThrowsError(try channel.finish()) { error in\n                XCTAssertEqual(.alreadyClosed, error as? ChannelError)\n            }\n        }\n\n        let handler = IndexWritingHandler(1)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(handler))\n        XCTAssertNoThrow(try channel.close().wait())\n        channel.embeddedEventLoop.run()\n\n        XCTAssertThrowsError(\n            try channel.pipeline.syncOperations.addHandler(\n                IndexWritingHandler(2),\n                position: .before(handler)\n            )\n        ) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n    }\n}\n\n// this should be within `testAddMultipleHandlers` but https://bugs.swift.org/browse/SR-9956\nfinal class TestAddMultipleHandlersHandlerWorkingAroundSR9956: ChannelDuplexHandler, Equatable, Sendable {\n    typealias InboundIn = Never\n    typealias OutboundIn = Never\n\n    static let _allHandlers = NIOLockedValueBox<[TestAddMultipleHandlersHandlerWorkingAroundSR9956]>([])\n\n    static var allHandlers: [TestAddMultipleHandlersHandlerWorkingAroundSR9956] {\n        get {\n            Self._allHandlers.withLockedValue { $0 }\n        }\n        set {\n            Self._allHandlers.withLockedValue { $0 = newValue }\n        }\n    }\n\n    init() {}\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        Self.allHandlers.append(self)\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    public static func == (\n        lhs: TestAddMultipleHandlersHandlerWorkingAroundSR9956,\n        rhs: TestAddMultipleHandlersHandlerWorkingAroundSR9956\n    ) -> Bool {\n        lhs === rhs\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/ChannelTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOConcurrencyHelpers\n@_spi(CustomByteBufferAllocator) @testable import NIOCore\nimport NIOEmbedded\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOPosix\n\n#if os(Linux)\nimport CNIOLinux\n#endif\n\nclass ChannelLifecycleHandler: ChannelInboundHandler {\n    public typealias InboundIn = Any\n\n    public enum ChannelState {\n        case unregistered\n        case registered\n        case inactive\n        case active\n    }\n\n    public var currentState: ChannelState\n    public var stateHistory: [ChannelState]\n\n    public init() {\n        currentState = .unregistered\n        stateHistory = [.unregistered]\n    }\n\n    private func updateState(_ state: ChannelState) {\n        currentState = state\n        stateHistory.append(state)\n    }\n\n    public func channelRegistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .unregistered)\n        XCTAssertFalse(context.channel.isActive)\n        updateState(.registered)\n        context.fireChannelRegistered()\n    }\n\n    public func channelActive(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .registered)\n        XCTAssertTrue(context.channel.isActive)\n        updateState(.active)\n        context.fireChannelActive()\n    }\n\n    public func channelInactive(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .active)\n        XCTAssertFalse(context.channel.isActive)\n        updateState(.inactive)\n        context.fireChannelInactive()\n    }\n\n    public func channelUnregistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(currentState, .inactive)\n        XCTAssertFalse(context.channel.isActive)\n        updateState(.unregistered)\n        context.fireChannelUnregistered()\n    }\n}\n\nfinal class ChannelTests: XCTestCase {\n    func testBasicLifecycle() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverAcceptedChannelPromise = loop.makePromise(of: Channel.self)\n        let serverLifecycleHandler = try loop.submit {\n            NIOLoopBound(ChannelLifecycleHandler(), eventLoop: loop)\n        }.wait()\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: loop)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    serverAcceptedChannelPromise.succeed(channel)\n                    return channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(serverLifecycleHandler.value)\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientLifecycleHandler = try loop.submit {\n            NIOLoopBound(ChannelLifecycleHandler(), eventLoop: loop)\n        }.wait()\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: loop)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(clientLifecycleHandler.value)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        var buffer = clientChannel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"a\")\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        let serverAcceptedChannel = try serverAcceptedChannelPromise.futureResult.wait()\n\n        // Start shutting stuff down.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        // Wait for the close promises. These fire last.\n        XCTAssertNoThrow(\n            try EventLoopFuture.andAllSucceed(\n                [\n                    clientChannel.closeFuture,\n                    serverAcceptedChannel.closeFuture,\n                ],\n                on: loop\n            ).map {\n                XCTAssertEqual(clientLifecycleHandler.value.currentState, .unregistered)\n                XCTAssertEqual(serverLifecycleHandler.value.currentState, .unregistered)\n                XCTAssertEqual(\n                    clientLifecycleHandler.value.stateHistory,\n                    [.unregistered, .registered, .active, .inactive, .unregistered]\n                )\n                XCTAssertEqual(\n                    serverLifecycleHandler.value.stateHistory,\n                    [.unregistered, .registered, .active, .inactive, .unregistered]\n                )\n            }.wait()\n        )\n    }\n\n    func testManyManyWrites() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        // We're going to try to write loads, and loads, and loads of data. In this case, one more\n        // write than the iovecs max.\n        var buffer = clientChannel.allocator.buffer(capacity: 1)\n        for _ in 0..<Socket.writevLimitIOVectors {\n            buffer.clear()\n            buffer.writeString(\"a\")\n            clientChannel.write(buffer, promise: nil)\n        }\n        buffer.clear()\n        buffer.writeString(\"a\")\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        // Start shutting stuff down.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    func testWritevLotsOfData() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        let bufferSize = 1024 * 1024 * 2\n        var buffer = clientChannel.allocator.buffer(capacity: bufferSize)\n        for _ in 0..<bufferSize {\n            buffer.writeStaticString(\"a\")\n        }\n\n        let lotsOfData = Int(Int32.max)\n        var written: Int64 = 0\n        while written <= lotsOfData {\n            clientChannel.write(buffer, promise: nil)\n            written += Int64(bufferSize)\n        }\n\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n\n        // Start shutting stuff down.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    func testParentsOfSocketChannels() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let childChannelPromise = group.next().makePromise(of: Channel.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    childChannelPromise.succeed(channel)\n                    return channel.eventLoop.makeSucceededFuture(())\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        // Check the child channel has a parent, and that that parent is the server channel.\n        childChannelPromise.futureResult.map { chan in\n            XCTAssertTrue(chan.parent === serverChannel)\n        }.whenFailure { err in\n            XCTFail(\"Unexpected error \\(err)\")\n        }\n        _ = try childChannelPromise.futureResult.wait()\n\n        // Neither the server nor client channels have parents.\n        XCTAssertNil(serverChannel.parent)\n        XCTAssertNil(clientChannel.parent)\n\n        // Start shutting stuff down.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    private func withPendingStreamWritesManager(_ body: (PendingStreamWritesManager) throws -> Void) rethrows {\n        let bufferPool = Pool<PooledBuffer>(maxSize: 16)\n        let pwm = NIOPosix.PendingStreamWritesManager(bufferPool: bufferPool)\n\n        XCTAssertTrue(pwm.isEmpty)\n        XCTAssertTrue(pwm.isOpen)\n        XCTAssertFalse(pwm.isFlushPending)\n        XCTAssertTrue(pwm.isWritable)\n\n        try body(pwm)\n\n        XCTAssertTrue(pwm.isEmpty)\n        XCTAssertFalse(pwm.isFlushPending)\n    }\n\n    /// A frankenstein testing monster. It asserts that for `PendingStreamWritesManager` `pwm` and `EventLoopPromises` `promises`\n    /// the following conditions hold:\n    ///  - The 'single write operation' is called `exepectedSingleWritabilities.count` number of times with the respective buffer lengths in the array.\n    ///  - The 'vector write operation' is called `exepectedVectorWritabilities.count` number of times with the respective buffer lengths in the array.\n    ///  - after calling the write operations, the promises have the states in `promiseStates`\n    ///\n    /// The write operations will all be faked and return the return values provided in `returns`.\n    ///\n    /// - Parameters:\n    ///   - pwm: The `PendingStreamWritesManager` to test.\n    ///   - promises: The promises for the writes issued.\n    ///   - expectedSingleWritabilities: The expected buffer lengths for the calls to the single write operation.\n    ///   - expectedVectorWritabilities: The expected buffer lengths for the calls to the vector write operation.\n    ///   - returns: The return values of the fakes write operations (both single and vector).\n    ///   - promiseStates: The states of the promises _after_ the write operations are done.\n    func assertExpectedWritability(\n        pendingWritesManager pwm: PendingStreamWritesManager,\n        promises: [EventLoopPromise<Void>],\n        expectedSingleWritabilities: [Int]?,\n        expectedVectorWritabilities: [[Int]]?,\n        expectedFileWritabilities: [(Int, Int)]?,\n        returns: [NIOPosix.IOResult<Int>],\n        promiseStates: [[Bool]],\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> OverallWriteResult {\n        var everythingState = 0\n        var singleState = 0\n        var multiState = 0\n        var fileState = 0\n        let result = try pwm.triggerAppropriateWriteOperations(\n            scalarBufferWriteOperation: { buf in\n                defer {\n                    singleState += 1\n                    everythingState += 1\n                }\n                if let expected = expectedSingleWritabilities {\n                    if expected.count > singleState {\n                        XCTAssertGreaterThan(returns.count, everythingState)\n                        XCTAssertEqual(\n                            expected[singleState],\n                            buf.count,\n                            \"in single write \\(singleState) (overall \\(everythingState)), \\(expected[singleState]) bytes expected but \\(buf.count) actual\"\n                        )\n                        return returns[everythingState]\n                    } else {\n                        XCTFail(\n                            \"single write call \\(singleState) but less than \\(expected.count) expected\",\n                            file: (file),\n                            line: line\n                        )\n                        return IOResult.wouldBlock(-1 * (everythingState + 1))\n                    }\n                } else {\n                    XCTFail(\"single write called on \\(buf) but no single writes expected\", file: (file), line: line)\n                    return IOResult.wouldBlock(-1 * (everythingState + 1))\n                }\n            },\n            vectorBufferWriteOperation: { ptrs in\n                defer {\n                    multiState += 1\n                    everythingState += 1\n                }\n                if let expected = expectedVectorWritabilities {\n                    if expected.count > multiState {\n                        XCTAssertGreaterThan(returns.count, everythingState)\n                        XCTAssertEqual(\n                            expected[multiState],\n                            ptrs.map { numericCast($0.iov_len) },\n                            \"in vector write \\(multiState) (overall \\(everythingState)), \\(expected[multiState]) byte counts expected but \\(ptrs.map { $0.iov_len }) actual\",\n                            file: (file),\n                            line: line\n                        )\n                        return returns[everythingState]\n                    } else {\n                        XCTFail(\n                            \"vector write call \\(multiState) but less than \\(expected.count) expected\",\n                            file: (file),\n                            line: line\n                        )\n                        return IOResult.wouldBlock(-1 * (everythingState + 1))\n                    }\n                } else {\n                    XCTFail(\n                        \"vector write called on \\(ptrs) but no vector writes expected\",\n                        file: (file),\n                        line: line\n                    )\n                    return IOResult.wouldBlock(-1 * (everythingState + 1))\n                }\n            },\n            scalarFileWriteOperation: { _, start, end in\n                defer {\n                    fileState += 1\n                    everythingState += 1\n                }\n                guard let expected = expectedFileWritabilities else {\n                    XCTFail(\n                        \"file write (\\(start), \\(end)) but no file writes expected\",\n                        file: (file),\n                        line: line\n                    )\n                    return IOResult.wouldBlock(-1 * (everythingState + 1))\n                }\n\n                if expected.count > fileState {\n                    XCTAssertGreaterThan(returns.count, everythingState)\n                    XCTAssertEqual(\n                        expected[fileState].0,\n                        start,\n                        \"in file write \\(fileState) (overall \\(everythingState)), \\(expected[fileState].0) expected as start index but \\(start) actual\",\n                        file: (file),\n                        line: line\n                    )\n                    XCTAssertEqual(\n                        expected[fileState].1,\n                        end,\n                        \"in file write \\(fileState) (overall \\(everythingState)), \\(expected[fileState].1) expected as end index but \\(end) actual\",\n                        file: (file),\n                        line: line\n                    )\n                    return returns[everythingState]\n                } else {\n                    XCTFail(\n                        \"file write call \\(fileState) but less than \\(expected.count) expected\",\n                        file: (file),\n                        line: line\n                    )\n                    return IOResult.wouldBlock(-1 * (everythingState + 1))\n                }\n            }\n        )\n        if everythingState > 0 {\n            XCTAssertEqual(\n                promises.count,\n                promiseStates[everythingState - 1].count,\n                \"number of promises (\\(promises.count)) != number of promise states (\\(promiseStates[everythingState - 1].count))\",\n                file: (file),\n                line: line\n            )\n            _ = zip(promises, promiseStates[everythingState - 1]).map { p, pState in\n                XCTAssertEqual(\n                    p.futureResult.isFulfilled,\n                    pState,\n                    \"promise states incorrect (\\(everythingState) callbacks)\",\n                    file: (file),\n                    line: line\n                )\n            }\n\n            XCTAssertEqual(\n                everythingState,\n                singleState + multiState + fileState,\n                \"odd, calls the single/vector/file writes: \\(singleState)/\\(multiState)/\\(fileState) but overall \\(everythingState+1)\",\n                file: (file),\n                line: line\n            )\n\n            if singleState == 0 {\n                XCTAssertNil(expectedSingleWritabilities, \"no single writes have been done but we expected some\")\n            } else {\n                XCTAssertEqual(\n                    singleState,\n                    (expectedSingleWritabilities?.count ?? Int.min),\n                    \"different number of single writes than expected\",\n                    file: (file),\n                    line: line\n                )\n            }\n            if multiState == 0 {\n                XCTAssertNil(expectedVectorWritabilities, \"no vector writes have been done but we expected some\")\n            } else {\n                XCTAssertEqual(\n                    multiState,\n                    (expectedVectorWritabilities?.count ?? Int.min),\n                    \"different number of vector writes than expected\",\n                    file: (file),\n                    line: line\n                )\n            }\n            if fileState == 0 {\n                XCTAssertNil(expectedFileWritabilities, \"no file writes have been done but we expected some\")\n            } else {\n                XCTAssertEqual(\n                    fileState,\n                    (expectedFileWritabilities?.count ?? Int.min),\n                    \"different number of file writes than expected\",\n                    file: (file),\n                    line: line\n                )\n            }\n        } else {\n            XCTAssertEqual(\n                0,\n                returns.count,\n                \"no callbacks called but apparently \\(returns.count) expected\",\n                file: (file),\n                line: line\n            )\n            XCTAssertNil(\n                expectedSingleWritabilities,\n                \"no callbacks called but apparently some single writes expected\",\n                file: (file),\n                line: line\n            )\n            XCTAssertNil(\n                expectedVectorWritabilities,\n                \"no callbacks calles but apparently some vector writes expected\",\n                file: (file),\n                line: line\n            )\n            XCTAssertNil(\n                expectedFileWritabilities,\n                \"no callbacks calles but apparently some file writes expected\",\n                file: (file),\n                line: line\n            )\n\n            _ = zip(promises, promiseStates[0]).map { p, pState in\n                XCTAssertEqual(\n                    p.futureResult.isFulfilled,\n                    pState,\n                    \"promise states incorrect (no callbacks)\",\n                    file: (file),\n                    line: line\n                )\n            }\n        }\n        return result\n    }\n\n    /// Tests that writes of empty buffers work correctly and that we don't accidentally write buffers that haven't been flushed.\n    func testPendingWritesEmptyWritesWorkAndWeDontWriteUnflushedThings() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n\n        try withPendingStreamWritesManager { pwm in\n            buffer.clear()\n            let ps: [EventLoopPromise<Void>] = (0..<2).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n\n            XCTAssertFalse(pwm.isEmpty)\n            XCTAssertFalse(pwm.isFlushPending)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            XCTAssertFalse(pwm.isEmpty)\n            XCTAssertTrue(pwm.isFlushPending)\n\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [0],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(0)],\n                promiseStates: [[true, false]]\n            )\n\n            XCTAssertFalse(pwm.isEmpty)\n            XCTAssertFalse(pwm.isFlushPending)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [],\n                promiseStates: [[true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [0],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(0)],\n                promiseStates: [[true, true]]\n            )\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    /// This tests that we do use the vector write operation if we have more than one flushed and still doesn't write unflushed buffers\n    func testPendingWritesUsesVectorWriteOperationAndDoesntWriteTooMuch() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        let emptyBuffer = buffer\n        _ = buffer.writeString(\"1234\")\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(Int64(2 * buffer.readableBytes), pwm.bufferedBytes)\n            _ = pwm.add(data: .byteBuffer(emptyBuffer), promise: ps[2])\n            XCTAssertEqual(Int64(2 * buffer.readableBytes), pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[4, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(8)],\n                promiseStates: [[true, true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [0],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(0)],\n                promiseStates: [[true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Tests that we can handle partial writes correctly.\n    func testPendingWritesWorkWithPartialWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        _ = buffer.writeString(\"1234\")\n        let totalBytes = Int64(4 * buffer.readableBytes)\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<4).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[2])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[3])\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[4, 4, 4, 4], [3, 4, 4, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(1), .wouldBlock(0)],\n                promiseStates: [[false, false, false, false], [false, false, false, false]]\n            )\n\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(totalBytes - 1, pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[3, 4, 4, 4], [4, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(7), .wouldBlock(0)],\n                promiseStates: [[true, true, false, false], [true, true, false, false]]\n\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(totalBytes - 1 - 7, pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[4, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(8)],\n                promiseStates: [[true, true, true, true], [true, true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(totalBytes - 1 - 7 - 8, pwm.bufferedBytes)\n        }\n    }\n\n    /// Tests that the spin count works for one long buffer if small bits are written one by one.\n    func testPendingWritesSpinCountWorksForSingleWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n\n        try withPendingStreamWritesManager { pwm in\n            let numberOfBytes = Int(\n                1  // first write\n                    + pwm.writeSpinCount  // the spins\n                    + 1  // so one byte remains at the end\n            )\n            buffer.clear()\n            buffer.writeBytes([UInt8](repeating: 0xff, count: numberOfBytes))\n            let ps: [EventLoopPromise<Void>] = (0..<1).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(Int64(numberOfBytes), pwm.bufferedBytes)\n\n            // below, we'll write 1 byte at a time. So the number of bytes offered should decrease by one.\n            // The write operation should be repeated until we did it 1 + spin count times and then return `.writtenPartially`.\n            // After that, one byte will remain\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: Array((2...numberOfBytes).reversed()),\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: Array(repeating: .processed(1), count: numberOfBytes),\n                promiseStates: Array(repeating: [false], count: numberOfBytes)\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(1, pwm.bufferedBytes)\n\n            // we'll now write the one last byte and assert that all the writes are complete\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [1],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(1)],\n                promiseStates: [[true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Tests that the spin count works if we have many small buffers, which'll be written with the vector write op.\n    func testPendingWritesSpinCountWorksForVectorWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n\n        try withPendingStreamWritesManager { pwm in\n            let numberOfBytes = Int(\n                1  // first write\n                    + pwm.writeSpinCount  // the spins\n                    + 1  // so one byte remains at the end\n            )\n            buffer.clear()\n            buffer.writeBytes([0xff] as [UInt8])\n            let ps: [EventLoopPromise<Void>] = (0..<numberOfBytes).map { (_: Int) in\n                let p = el.makePromise(of: Void.self)\n                _ = pwm.add(data: .byteBuffer(buffer), promise: p)\n                return p\n            }\n            XCTAssertEqual(Int64(numberOfBytes * buffer.readableBytes), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            // this will create an `Array` like this (for `numberOfBytes == 4`)\n            // `[[1, 1, 1, 1], [1, 1, 1], [1, 1], [1]]`\n            let expectedVectorWrites = Array((2...numberOfBytes).reversed()).map { n in\n                Array(repeating: 1, count: n)\n            }\n\n            // this will create an `Array` like this (for `numberOfBytes == 4`)\n            // `[[true, false, false, false], [true, true, false, false], [true, true, true, false]`\n            let expectedPromiseStates = Array((2...numberOfBytes).reversed()).map { n in\n                Array(repeating: true, count: numberOfBytes - n + 1) + Array(repeating: false, count: n - 1)\n            }\n\n            // below, we'll write 1 byte at a time. So the number of bytes offered should decrease by one.\n            // The write operation should be repeated until we did it 1 + spin count times and then return `.writtenPartially`.\n            // After that, one byte will remain */\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: expectedVectorWrites,\n                expectedFileWritabilities: nil,\n                returns: Array(repeating: .processed(1), count: numberOfBytes),\n                promiseStates: expectedPromiseStates\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n\n            // we'll now write the one last byte and assert that all the writes are complete\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [1],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(1)],\n                promiseStates: [Array(repeating: true, count: numberOfBytes)]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Tests that the spin count works for one long buffer if small bits are written one by one.\n    func testPendingWritesCompleteWritesDontConsumeWriteSpinCount() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n\n        try withPendingStreamWritesManager { pwm in\n            let numberOfWrites = Int(\n                1  // first write\n                    + pwm.writeSpinCount  // the spins\n                    + 1  // so one byte remains at the end\n            )\n            buffer.clear()\n            buffer.writeBytes([UInt8](repeating: 0xff, count: 1))\n            let handle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            defer {\n                // fake file handle, so don't actually close\n                XCTAssertNoThrow(try handle.takeDescriptorOwnership())\n            }\n            let fileRegion = FileRegion(fileHandle: handle, readerIndex: 0, endIndex: 1)\n            let ps: [EventLoopPromise<Void>] = (0..<numberOfWrites).map { _ in el.makePromise() }\n            for i in (0..<numberOfWrites) {\n                _ = pwm.add(data: i % 2 == 0 ? .byteBuffer(buffer) : .fileRegion(fileRegion), promise: ps[i])\n            }\n            let totalBytes = (0..<numberOfWrites).map { $0 % 2 == 0 ? buffer.readableBytes : fileRegion.readableBytes }\n                .reduce(0, +)\n            XCTAssertEqual(Int64(totalBytes), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            let expectedPromiseStates = Array((1...numberOfWrites).reversed()).map { n in\n                Array(repeating: true, count: numberOfWrites - n + 1) + Array(repeating: false, count: n - 1)\n            }\n            // below, we'll write 1 byte at a time. So the number of bytes offered should decrease by one.\n            // The write operation should be repeated until we did it 1 + spin count times and then return `.writtenPartially`.\n            // After that, one byte will remain\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: Array(repeating: 1, count: numberOfWrites / 2),\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: Array(repeating: (0, 1), count: numberOfWrites / 2),\n                returns: Array(repeating: .processed(1), count: numberOfWrites),\n                promiseStates: expectedPromiseStates\n            )\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    /// Test that cancellation of the Channel writes works correctly.\n    func testPendingWritesCancellationWorksCorrectly() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        let emptyBuffer = buffer\n        _ = buffer.writeString(\"1234\")\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            let totalBytes = Int64(buffer.readableBytes * 2)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(data: .byteBuffer(emptyBuffer), promise: ps[2])\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[4, 4], [2, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(2), .wouldBlock(0)],\n                promiseStates: [[false, false, false], [false, false, false]]\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(totalBytes - 2, pwm.bufferedBytes)\n\n            _ = pwm.failAll(error: ChannelError.operationUnsupported)\n\n            XCTAssertTrue(ps.map { $0.futureResult.isFulfilled }.allSatisfy { $0 })\n        }\n    }\n\n    /// Test that with a few massive buffers, we don't offer more than we should to `writev` if the individual chunks fit.\n    func testPendingWritesNoMoreThanWritevLimitIsWritten() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator(\n            allocate: { _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            reallocate: { _, _, _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            deallocate: { _ in },\n            copy: { _, _, _ in }\n        )\n        // each buffer is half the writev limit\n        let halfTheWriteVLimit = Socket.writevLimitBytes / 2\n        var buffer = alloc.buffer(capacity: halfTheWriteVLimit)\n        buffer.moveReaderIndex(to: 0)\n        buffer.moveWriterIndex(to: halfTheWriteVLimit)\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            // add 1.5x the writev limit\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[2])\n            XCTAssertEqual(Int64(buffer.readableBytes * 3), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [halfTheWriteVLimit],\n                expectedVectorWritabilities: [[halfTheWriteVLimit, halfTheWriteVLimit]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(2 * halfTheWriteVLimit), .processed(halfTheWriteVLimit)],\n                promiseStates: [[true, true, false], [true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Test that with a massive buffers (bigger than writev size), we don't offer more than we should to `writev`.\n    func testPendingWritesNoMoreThanWritevLimitIsWrittenInOneMassiveChunk() throws {\n        if MemoryLayout<Int>.size == MemoryLayout<Int32>.size {  // skip this test on 32bit system\n            return\n        }\n\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator(\n            allocate: { _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            reallocate: { _, _, _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            deallocate: { _ in },\n            copy: { _, _, _ in }\n        )\n\n        let biggerThanWriteV = Socket.writevLimitBytes + 23\n        var buffer = alloc.buffer(capacity: biggerThanWriteV)\n        buffer.moveReaderIndex(to: 0)\n        buffer.moveWriterIndex(to: biggerThanWriteV)\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            var totalBytes: Int64 = 0\n\n            // add 1.5x the writev limit\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            totalBytes += Int64(buffer.readableBytes * 2)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            buffer.moveWriterIndex(to: 100)\n            totalBytes += Int64(buffer.readableBytes)\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[2])\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [\n                    [Socket.writevLimitBytes],\n                    [23],\n                    [Socket.writevLimitBytes],\n                    [23, 100],\n                ],\n                expectedFileWritabilities: nil,\n                returns: [\n                    .processed(Socket.writevLimitBytes),\n                    // Xcode\n                    .processed(23),\n                    // needs\n                    .processed(Socket.writevLimitBytes),\n                    // help\n                    .processed(23 + 100),\n                ],\n                promiseStates: [\n                    [false, false, false],\n                    // Xcode\n                    [true, false, false],\n                    // needs\n                    [true, false, false],\n                    // help\n                    [true, true, true],\n                ]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n        }\n    }\n\n    func testPendingWritesFileRegion() throws {\n        let el = EmbeddedEventLoop()\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<2).map { (_: Int) in el.makePromise() }\n\n            let fh1 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            let fh2 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -2)\n            let fr1 = FileRegion(fileHandle: fh1, readerIndex: 12, endIndex: 14)\n            let fr2 = FileRegion(fileHandle: fh2, readerIndex: 0, endIndex: 2)\n            defer {\n                // fake descriptors, so shouldn't be closed.\n                XCTAssertNoThrow(try fh1.takeDescriptorOwnership())\n                XCTAssertNoThrow(try fh2.takeDescriptorOwnership())\n            }\n            var totalBytes: Int64 = 0\n            _ = pwm.add(data: .fileRegion(fr1), promise: ps[0])\n            totalBytes += Int64(fr1.readableBytes)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(data: .fileRegion(fr2), promise: ps[1])\n            totalBytes += Int64(fr2.readableBytes)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: [(12, 14)],\n                returns: [.processed(2)],\n                promiseStates: [[true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            totalBytes -= Int64(fr1.readableBytes)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [],\n                promiseStates: [[true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: [(0, 2), (1, 2)],\n                returns: [.processed(1), .processed(1)],\n                promiseStates: [[true, false], [true, true]]\n            )\n\n            totalBytes -= Int64(fr2.readableBytes)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testPendingWritesEmptyFileRegion() throws {\n        let el = EmbeddedEventLoop()\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<1).map { (_: Int) in el.makePromise() }\n\n            let fh = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            let fr = FileRegion(fileHandle: fh, readerIndex: 99, endIndex: 99)\n            defer {\n                // fake descriptor, so shouldn't be closed.\n                XCTAssertNoThrow(try fh.takeDescriptorOwnership())\n            }\n            _ = pwm.add(data: .fileRegion(fr), promise: ps[0])\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: [(99, 99)],\n                returns: [.processed(0)],\n                promiseStates: [[true]]\n            )\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testPendingWritesInterleavedBuffersAndFiles() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        _ = buffer.writeString(\"1234\")\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<5).map { (_: Int) in el.makePromise() }\n\n            let fh1 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            let fh2 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            let fr1 = FileRegion(fileHandle: fh1, readerIndex: 99, endIndex: 99)\n            let fr2 = FileRegion(fileHandle: fh1, readerIndex: 0, endIndex: 10)\n            defer {\n                // fake descriptors, so shouldn't be closed.\n                XCTAssertNoThrow(try fh1.takeDescriptorOwnership())\n                XCTAssertNoThrow(try fh2.takeDescriptorOwnership())\n            }\n\n            var totalBytes: Int64 = 0\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            _ = pwm.add(data: .fileRegion(fr1), promise: ps[2])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[3])\n            _ = pwm.add(data: .fileRegion(fr2), promise: ps[4])\n            totalBytes += Int64(\n                buffer.readableBytes + buffer.readableBytes + fr1.readableBytes + buffer.readableBytes\n                    + fr2.readableBytes\n            )\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [4, 3, 2, 1],\n                expectedVectorWritabilities: [[4, 4]],\n                expectedFileWritabilities: [(99, 99), (0, 10), (3, 10), (6, 10)],\n                returns: [\n                    .processed(8), .processed(0), .processed(1), .processed(1), .processed(1), .processed(1),\n                    .wouldBlock(3), .processed(3), .wouldBlock(0),\n                ],\n                promiseStates: [\n                    [true, true, false, false, false],\n                    [true, true, true, false, false],\n                    [true, true, true, false, false],\n                    [true, true, true, false, false],\n                    [true, true, true, false, false],\n                    [true, true, true, true, false],\n                    [true, true, true, true, false],\n                    [true, true, true, true, false],\n                    [true, true, true, true, false],\n                ]\n            )\n\n            totalBytes -= (4 + 4 + 0 + 4 + 6)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: [(6, 10)],\n                returns: [.processed(4)],\n                promiseStates: [[true, true, true, true, true]]\n            )\n\n            totalBytes -= 4\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testTwoFlushedNonEmptyWritesFollowedByUnflushedEmpty() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        let emptyBuffer = buffer\n        _ = buffer.writeString(\"1234\")\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            // let's start with no writes and just a flush\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [],\n                promiseStates: [[false, false, false]]\n            )\n\n            // let's add a few writes but still without any promises\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            XCTAssertEqual(Int64(buffer.readableBytes * 2), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            _ = pwm.add(data: .byteBuffer(emptyBuffer), promise: ps[2])\n            XCTAssertEqual(Int64(buffer.readableBytes * 2), pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[4, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(8)],\n                promiseStates: [[true, true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [0],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(0)],\n                promiseStates: [[true, true, true]]\n            )\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testPendingWritesWorksWithManyEmptyWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let emptyBuffer = alloc.buffer(capacity: 12)\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(emptyBuffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(emptyBuffer), promise: ps[1])\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(data: .byteBuffer(emptyBuffer), promise: ps[2])\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[0, 0]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(0)],\n                promiseStates: [[true, true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [0],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(0)],\n                promiseStates: [[true, true, true]]\n            )\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testPendingWritesCloseDuringVectorWrite() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[0])\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[1])\n            XCTAssertEqual(Int64(buffer.readableBytes * 2), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(data: .byteBuffer(buffer), promise: ps[2])\n            XCTAssertEqual(Int64(buffer.readableBytes * 3), pwm.bufferedBytes)\n\n            ps[0].futureResult.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                _ = pwm.failAll(error: ChannelError.inputClosed)\n            }\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[4, 4]],\n                expectedFileWritabilities: nil,\n                returns: [.processed(4)],\n                promiseStates: [[true, true, true]]\n            )\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.closed(nil)), result.writeResult)\n            XCTAssertNoThrow(try ps[0].futureResult.wait())\n            XCTAssertThrowsError(try ps[1].futureResult.wait())\n            XCTAssertThrowsError(try ps[2].futureResult.wait())\n        }\n    }\n\n    func testPendingWritesMoreThanWritevIOVectorLimit() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try withPendingStreamWritesManager { pwm in\n            var totalBytes: Int64 = 0\n            let ps: [EventLoopPromise<Void>] = (0...Socket.writevLimitIOVectors).map { (_: Int) in el.makePromise() }\n            for p in ps {\n                _ = pwm.add(data: .byteBuffer(buffer), promise: p)\n                totalBytes += Int64(buffer.readableBytes)\n                XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            }\n            pwm.markFlushCheckpoint()\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [4],\n                expectedVectorWritabilities: [Array(repeating: 4, count: Socket.writevLimitIOVectors)],\n                expectedFileWritabilities: nil,\n                returns: [.processed(4 * Socket.writevLimitIOVectors), .wouldBlock(0)],\n                promiseStates: [\n                    Array(repeating: true, count: Socket.writevLimitIOVectors) + [false],\n                    Array(repeating: true, count: Socket.writevLimitIOVectors) + [false],\n                ]\n            )\n            totalBytes -= Int64(buffer.readableBytes * Socket.writevLimitIOVectors)\n            XCTAssertEqual(totalBytes, pwm.bufferedBytes)\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [4],\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: nil,\n                returns: [.processed(4)],\n                promiseStates: [Array(repeating: true, count: Socket.writevLimitIOVectors + 1)]\n            )\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testPendingWritesIsHappyWhenSendfileReturnsWouldBlockButWroteFully() throws {\n        let el = EmbeddedEventLoop()\n        try withPendingStreamWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<1).map { (_: Int) in el.makePromise() }\n\n            let fh = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: -1)\n            let fr = FileRegion(fileHandle: fh, readerIndex: 0, endIndex: 8192)\n            defer {\n                // fake descriptor, so shouldn't be closed.\n                XCTAssertNoThrow(try fh.takeDescriptorOwnership())\n            }\n\n            _ = pwm.add(data: .fileRegion(fr), promise: ps[0])\n            XCTAssertEqual(Int64(fr.readableBytes), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                expectedFileWritabilities: [(0, 8192)],\n                returns: [.wouldBlock(8192)],\n                promiseStates: [[true]]\n            )\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n        }\n    }\n\n    func testSpecificConnectTimeout() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        do {\n            // This must throw as 198.51.100.254 is reserved for documentation only\n            _ = try ClientBootstrap(group: group)\n                .channelOption(.connectTimeout, value: .milliseconds(10))\n                .connect(to: SocketAddress.makeAddressResolvingHost(\"198.51.100.254\", port: 65535)).wait()\n            XCTFail()\n        } catch let err as ChannelError {\n            if case .connectTimeout(_) = err {\n                // expected, sadly there is no \"if not case\"\n            } else {\n                XCTFail()\n            }\n        } catch let err as IOError\n            where err.errnoCode == ENETDOWN || err.errnoCode == ENETUNREACH || err.errnoCode == ECONNREFUSED\n        {\n            // we need to accept those too unfortunately\n            print(\"WARNING: \\(#function) did not meaningfully test anything, received \\(err)\")\n        } catch {\n            XCTFail(\"unexpected error \\(error)\")\n        }\n    }\n\n    func testGeneralConnectTimeout() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        do {\n            // This must throw as 198.51.100.254 is reserved for documentation only\n            _ = try ClientBootstrap(group: group)\n                .connectTimeout(.milliseconds(10))\n                .connect(to: SocketAddress.makeAddressResolvingHost(\"198.51.100.254\", port: 65535)).wait()\n            XCTFail()\n        } catch let err as ChannelError {\n            if case .connectTimeout(_) = err {\n                // expected, sadly there is no \"if not case\"\n            } else {\n                XCTFail()\n            }\n        } catch let err as IOError\n            where err.errnoCode == ENETDOWN || err.errnoCode == ENETUNREACH || err.errnoCode == ECONNREFUSED\n        {\n            // we need to accept those too unfortunately\n            print(\"WARNING: \\(#function) did not meaningfully test anything, received \\(err)\")\n        } catch {\n            XCTFail(\"unexpected error \\(error)\")\n        }\n    }\n\n    func testCloseOutput() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let server = try assertNoThrowWithValue(ServerSocket(protocolFamily: .inet))\n        defer {\n            XCTAssertNoThrow(try server.close())\n        }\n        try server.bind(to: SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0))\n        try server.listen()\n\n        let shutdownPromise = group.next().makePromise(of: Void.self)\n        let receivedPromise = group.next().makePromise(of: ByteBuffer.self)\n        let future = ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let verificationHandler = ShutdownVerificationHandler(\n                        shutdownEvent: .output,\n                        promise: shutdownPromise\n                    )\n                    try channel.pipeline.syncOperations.addHandler(verificationHandler)\n\n                    let byteCountingHandler = ByteCountingHandler(numBytes: 4, promise: receivedPromise)\n                    try channel.pipeline.syncOperations.addHandler(byteCountingHandler)\n                }\n            }\n            .connect(to: try! server.localAddress())\n        let accepted = try server.accept()!\n        defer {\n            XCTAssertNoThrow(try accepted.close())\n        }\n\n        let channel = try future.wait()\n        defer {\n            XCTAssertNoThrow(try channel.close(mode: .all).wait())\n        }\n\n        var buffer = channel.allocator.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try channel.writeAndFlush(buffer).wait()\n        try channel.close(mode: .output).wait()\n\n        try shutdownPromise.futureResult.wait()\n        XCTAssertThrowsError(try channel.writeAndFlush(buffer).wait()) { error in\n            XCTAssertEqual(.outputClosed, error as? ChannelError)\n        }\n        let written = try buffer.withUnsafeReadableBytes { p in\n            try accepted.write(pointer: UnsafeRawBufferPointer(rebasing: p.prefix(4)))\n        }\n        if case .processed(let numBytes) = written {\n            XCTAssertEqual(4, numBytes)\n        } else {\n            XCTFail()\n        }\n\n        let received = try receivedPromise.futureResult.wait()\n        XCTAssertEqual(received, buffer)\n    }\n\n    func testCloseInput() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let server = try assertNoThrowWithValue(ServerSocket(protocolFamily: .inet))\n        defer {\n            XCTAssertNoThrow(try server.close())\n        }\n        try server.bind(to: SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0))\n        try server.listen()\n\n        final class VerifyNoReadHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n\n            public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTFail(\"Received data: \\(data)\")\n            }\n        }\n\n        let promise = group.next().makePromise(of: Void.self)\n        let future = ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.pipeline.addHandler(VerifyNoReadHandler()).flatMapThrowing {\n                    let verificationHandler = ShutdownVerificationHandler(\n                        shutdownEvent: .input,\n                        promise: promise\n                    )\n                    return try channel.pipeline.syncOperations.addHandler(verificationHandler)\n                }\n            }\n            .channelOption(.allowRemoteHalfClosure, value: true)\n            .connect(to: try! server.localAddress())\n        let accepted = try server.accept()!\n        defer {\n            XCTAssertNoThrow(try accepted.close())\n        }\n\n        let channel = try future.wait()\n        defer {\n            XCTAssertNoThrow(try channel.close(mode: .all).wait())\n        }\n\n        try channel.close(mode: .input).wait()\n\n        try promise.futureResult.wait()\n\n        var buffer = channel.allocator.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        let written = try buffer.withUnsafeReadableBytes { p in\n            try accepted.write(pointer: UnsafeRawBufferPointer(rebasing: p.prefix(4)))\n        }\n\n        switch written {\n        case .processed(let numBytes):\n            XCTAssertEqual(4, numBytes)\n        default:\n            XCTFail()\n        }\n\n        try channel.eventLoop.submit {\n            // Dummy task execution to give some time for an actual read to open (which should not happen as we closed the input).\n        }.wait()\n    }\n\n    func testHalfClosure() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let server = try assertNoThrowWithValue(ServerSocket(protocolFamily: .inet))\n        defer {\n            XCTAssertNoThrow(try server.close())\n        }\n        try server.bind(to: SocketAddress.makeAddressResolvingHost(\"127.0.0.1\", port: 0))\n        try server.listen()\n\n        let shutdownPromise = group.next().makePromise(of: Void.self)\n        let future = ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let verificationHandler = ShutdownVerificationHandler(\n                        shutdownEvent: .input,\n                        promise: shutdownPromise\n                    )\n                    try channel.pipeline.syncOperations.addHandler(verificationHandler)\n                }\n            }\n            .channelOption(.allowRemoteHalfClosure, value: true)\n            .connect(to: try! server.localAddress())\n        let accepted = try server.accept()!\n        defer {\n            XCTAssertNoThrow(try accepted.close())\n        }\n\n        let channel = try future.wait()\n        defer {\n            XCTAssertNoThrow(try channel.close(mode: .all).wait())\n        }\n\n        try accepted.shutdown(how: .WR)\n\n        try shutdownPromise.futureResult.wait()\n\n        var buffer = channel.allocator.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try channel.writeAndFlush(buffer).wait()\n    }\n\n    func testInputAndOutputClosedResultsInFullClosure() throws {\n        final class PromiseOnChildChannelInitHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n            private let promise: EventLoopPromise<Channel>\n\n            init(promise: EventLoopPromise<Channel>) {\n                self.promise = promise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                self.promise.succeed(context.channel)\n                context.fireChannelActive()\n            }\n        }\n\n        final class ChannelInactiveHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n            private let promise: EventLoopPromise<Void>\n\n            init(promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                self.promise.succeed()\n                context.fireChannelActive()\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChildChannelInitPromise: EventLoopPromise<Channel> = group.next().makePromise()\n        let serverChildChannelInactivePromise: EventLoopPromise<Void> = group.next().makePromise()\n        let serverChannel: Channel = try ServerBootstrap(group: group)\n            .childChannelOption(.allowRemoteHalfClosure, value: true)  // Important!\n            .childChannelInitializer { channel in\n                channel.pipeline.addHandlers(\n                    PromiseOnChildChannelInitHandler(promise: serverChildChannelInitPromise),\n                    ChannelInactiveHandler(promise: serverChildChannelInactivePromise)\n                )\n            }\n            .bind(host: \"127.0.0.1\", port: 0)\n            .wait()\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannelInactivePromise: EventLoopPromise<Void> = group.next().makePromise()\n        let clientChannel = try ClientBootstrap(group: group)\n            .channelInitializer { channel in\n                channel.pipeline.addHandler(ChannelInactiveHandler(promise: clientChannelInactivePromise))\n            }\n            .connect(to: serverChannel.localAddress!)\n            .wait()\n\n        XCTAssertNoThrow(try clientChannel.setOption(.allowRemoteHalfClosure, value: true).wait())\n\n        // Ok, the connection is definitely up.\n        // Now retrieve the client channel that our server opened for the connection to our client.\n        let serverConnectionChildChannel = try serverChildChannelInitPromise.futureResult.wait()\n\n        // First we close the output of the connection channel on the server.\n        // This results in the input of the clientChannel being closed.\n        XCTAssertNoThrow(try serverConnectionChildChannel.close(mode: .output).wait())\n        // Now we close the output of the clientChannel.\n        // Given that the the input of the clientChannel is already closed,\n        // this should escalate to a full closure of the clientChannel.\n        XCTAssertNoThrow(try clientChannel.close(mode: .output).wait())\n\n        // Assert that full closure of client channel occurred by verifying\n        // that channelInactive was invoked on the channel.\n        XCTAssertNoThrow(try clientChannelInactivePromise.futureResult.wait())\n\n        // Assert that the server child channel becomes inactive now that the\n        // client channel has been closed completely.\n        XCTAssertNoThrow(try serverChildChannelInactivePromise.futureResult.wait())\n\n        // Additional assertion: trying to close the clientChannel manually\n        // should fail as it is closed already.\n        XCTAssertThrowsError(try clientChannel.close().wait()) { error in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.alreadyClosed, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    enum ShutDownEvent {\n        case input\n        case output\n    }\n    private class ShutdownVerificationHandler: ChannelInboundHandler {\n        typealias InboundIn = ByteBuffer\n\n        private var inputShutdownEventReceived = false\n        private var outputShutdownEventReceived = false\n\n        private let promise: EventLoopPromise<Void>\n        private let shutdownEvent: ShutDownEvent\n\n        init(shutdownEvent: ShutDownEvent, promise: EventLoopPromise<Void>) {\n            self.promise = promise\n            self.shutdownEvent = shutdownEvent\n        }\n\n        public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n            switch event {\n            case let ev as ChannelEvent:\n                switch ev {\n                case .inputClosed:\n                    XCTAssertFalse(inputShutdownEventReceived)\n                    inputShutdownEventReceived = true\n\n                    if shutdownEvent == .input {\n                        promise.succeed(())\n                    }\n                case .outputClosed:\n                    XCTAssertFalse(outputShutdownEventReceived)\n                    outputShutdownEventReceived = true\n\n                    if shutdownEvent == .output {\n                        promise.succeed(())\n                    }\n                }\n\n                fallthrough\n            default:\n                context.fireUserInboundEventTriggered(event)\n            }\n        }\n\n        public func waitForEvent() {\n            // We always notify it with a success so just force it with !\n            try! promise.futureResult.wait()\n        }\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            switch shutdownEvent {\n            case .input:\n                XCTAssertTrue(inputShutdownEventReceived)\n                XCTAssertFalse(outputShutdownEventReceived)\n            case .output:\n                XCTAssertFalse(inputShutdownEventReceived)\n                XCTAssertTrue(outputShutdownEventReceived)\n            }\n\n            promise.succeed(())\n        }\n    }\n\n    func testWeDontCrashIfChannelReleasesBeforePipeline() throws {\n        final class StuffHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n\n            let promise: EventLoopPromise<ChannelPipeline>\n\n            init(promise: EventLoopPromise<ChannelPipeline>) {\n                self.promise = promise\n            }\n\n            func channelRegistered(context: ChannelHandlerContext) {\n                self.promise.succeed(context.channel.pipeline)\n            }\n        }\n        weak var weakClientChannel: Channel? = nil\n        weak var weakServerChannel: Channel? = nil\n        weak var weakServerChildChannel: Channel? = nil\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let promise = group.next().makePromise(of: ChannelPipeline.self)\n\n        try {\n            let serverChildChannelPromise = group.next().makePromise(of: Channel.self)\n            let serverChannel = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .childChannelInitializer { channel in\n                        serverChildChannelPromise.succeed(channel)\n                        channel.close(promise: nil)\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }\n                    .bind(host: \"127.0.0.1\", port: 0).wait()\n            )\n\n            let clientChannel = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .channelInitializer {\n                        $0.pipeline.addHandler(StuffHandler(promise: promise))\n                    }\n                    .connect(to: serverChannel.localAddress!).wait()\n            )\n            weakClientChannel = clientChannel\n            weakServerChannel = serverChannel\n            weakServerChildChannel = try serverChildChannelPromise.futureResult.wait()\n            clientChannel.close().whenFailure {\n                if case let error = $0 as? ChannelError, error != ChannelError.alreadyClosed {\n                    XCTFail(\"unexpected error \\($0)\")\n                }\n            }\n            serverChannel.close().whenFailure {\n                XCTFail(\"unexpected error \\($0)\")\n            }\n\n            // We need to wait for the close futures to fire before we move on. Before the\n            // close promises are hit, the channel can keep a reference to itself alive because it's running\n            // background code on the event loop. Completing the close promise should be the last thing the\n            // channel will ever do, assuming there is no work holding a ref to it anywhere.\n            XCTAssertNoThrow(try clientChannel.closeFuture.wait())\n            XCTAssertNoThrow(try serverChannel.closeFuture.wait())\n        }()\n        let pipeline = try promise.futureResult.wait()\n        XCTAssertThrowsError(\n            try pipeline.eventLoop.submit { () -> Channel in\n                XCTAssertTrue(pipeline.channel is DeadChannel)\n                return pipeline.channel\n            }.wait().writeAndFlush(()).wait()\n        ) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n\n        // Annoyingly it's totally possible to get to this stage and have the channels\n        // not yet be entirely freed on the background thread. There is no way we can guarantee\n        // that this hasn't happened, so we wait for up to a second to let this happen. If it hasn't\n        // happened in one second, we assume it never will.\n        assert(weakClientChannel == nil, within: .seconds(1), \"weakClientChannel not nil, looks like we leaked it!\")\n        assert(weakServerChannel == nil, within: .seconds(1), \"weakServerChannel not nil, looks like we leaked it!\")\n        assert(\n            weakServerChildChannel == nil,\n            within: .seconds(1),\n            \"weakServerChildChannel not nil, looks like we leaked it!\"\n        )\n    }\n\n    func testAskForLocalAndRemoteAddressesAfterChannelIsClosed() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        // Start shutting stuff down.\n        XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n\n        XCTAssertNoThrow(try serverChannel.closeFuture.wait())\n        XCTAssertNoThrow(try clientChannel.closeFuture.wait())\n\n        // Schedule on the EventLoop to ensure we scheduled the cleanup of the cached addresses before.\n        XCTAssertNoThrow(\n            try group.next().submit {\n                for f in [\n                    serverChannel.remoteAddress, serverChannel.localAddress, clientChannel.remoteAddress,\n                    clientChannel.localAddress,\n                ] {\n                    XCTAssertNil(f)\n                }\n            }.wait()\n        )\n\n    }\n\n    func testReceiveAddressAfterAccept() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        final class AddressVerificationHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n\n            public func channelActive(context: ChannelHandlerContext) {\n                XCTAssertNotNil(context.channel.localAddress)\n                XCTAssertNotNil(context.channel.remoteAddress)\n                context.channel.close(promise: nil)\n            }\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { ch in\n                    ch.pipeline.addHandler(AddressVerificationHandler())\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        XCTAssertNoThrow(try clientChannel.closeFuture.wait())\n        XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    func testWeDontJamSocketsInANoIOState() throws {\n        final class ReadDelayer: ChannelDuplexHandler {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n            typealias OutboundIn = Any\n            typealias OutboundOut = Any\n\n            public var reads = 0\n            private var context: ChannelHandlerContext!\n            private var readCountPromise: EventLoopPromise<Void>!\n            private var waitingForReadPromise: EventLoopPromise<Void>?\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                self.context = context\n                self.readCountPromise = context.eventLoop.makePromise()\n            }\n\n            func expectRead(loop: EventLoop) -> EventLoopFuture<Void> {\n                loop.assumeIsolated().submit {\n                    self.waitingForReadPromise = loop.makePromise()\n                }.assumeIsolated().flatMap {\n                    self.waitingForReadPromise!.futureResult\n                }.nonisolated()\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                self.waitingForReadPromise?.succeed(())\n                self.waitingForReadPromise = nil\n            }\n\n            func read(context: ChannelHandlerContext) {\n                self.reads += 1\n\n                // Allow the first read through.\n                if self.reads == 1 {\n                    self.context.read()\n                }\n            }\n\n            func issueDelayedRead() {\n                self.context.read()\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let loopBoundDelayer = try loop.next().submit { NIOLoopBound(ReadDelayer(), eventLoop: loop) }.wait()\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandlers(loopBoundDelayer.value)\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        // We send a first write and expect it to arrive.\n        var buffer = clientChannel.allocator.buffer(capacity: 12)\n        let firstReadFuture = try loop.submit {\n            loopBoundDelayer.value.expectRead(loop: loop)\n        }.wait()\n        buffer.writeStaticString(\"hello, world\")\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n        XCTAssertNoThrow(try firstReadFuture.wait())\n\n        // We send a second write. This won't arrive immediately.\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n        let readFuture = try loop.submit {\n            loopBoundDelayer.value.expectRead(loop: loop)\n        }.wait()\n        try serverChannel.eventLoop.scheduleTask(in: .milliseconds(100)) {\n            XCTAssertFalse(readFuture.isFulfilled)\n        }.futureResult.wait()\n\n        // Ok, now let it proceed.\n        XCTAssertNoThrow(\n            try loop.submit {\n                XCTAssertEqual(loopBoundDelayer.value.reads, 2)\n                loopBoundDelayer.value.issueDelayedRead()\n            }.wait()\n        )\n\n        // The read should go through.\n        XCTAssertNoThrow(try readFuture.wait())\n    }\n\n    func testNoChannelReadBeforeEOFIfNoAutoRead() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = group.next()\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        final class VerifyNoReadBeforeEOFHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            var expectingData: Bool = false\n\n            public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if !self.expectingData {\n                    XCTFail(\"Received data before we expected it.\")\n                } else {\n                    let data = Self.unwrapInboundIn(data)\n                    XCTAssertEqual(data.getString(at: data.readerIndex, length: data.readableBytes), \"test\")\n                }\n            }\n        }\n\n        let loopBoundVerifyHandler = try loop.submit {\n            NIOLoopBound(VerifyNoReadBeforeEOFHandler(), eventLoop: loop)\n        }.wait()\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelOption(.autoRead, value: false)\n                .childChannelInitializer { ch in\n                    ch.eventLoop.makeCompletedFuture {\n                        try ch.pipeline.syncOperations.addHandler(loopBoundVerifyHandler.value)\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        var buffer = clientChannel.allocator.buffer(capacity: 8)\n        buffer.writeString(\"test\")\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        // Wait for 100 ms. No data should be delivered.\n        usleep(100 * 1000)\n\n        // Now we send close. This should deliver data.\n        try loop.flatSubmit {\n            loopBoundVerifyHandler.value.expectingData = true\n            return clientChannel.close()\n        }.wait()\n        try serverChannel.close().wait()\n    }\n\n    func testCloseInEOFdChannelReadBehavesCorrectly() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        final class VerifyEOFReadOrderingAndCloseInChannelReadHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private var seenEOF: Bool = false\n            private var numberOfChannelReads: Int = 0\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                if case .some(ChannelEvent.inputClosed) = event as? ChannelEvent {\n                    self.seenEOF = true\n                }\n                context.fireUserInboundEventTriggered(event)\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if self.seenEOF {\n                    XCTFail(\n                        \"Should not be called before seeing the EOF as autoRead is false and we did not call read(), but received \\(self.unwrapInboundIn(data))\"\n                    )\n                }\n                self.numberOfChannelReads += 1\n                let buffer = Self.unwrapInboundIn(data)\n                XCTAssertLessThanOrEqual(buffer.readableBytes, 8)\n                XCTAssertEqual(1, self.numberOfChannelReads)\n                context.close(mode: .all, promise: nil)\n            }\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelOption(.autoRead, value: false)\n                .childChannelInitializer { ch in\n                    ch.eventLoop.makeCompletedFuture {\n                        try ch.pipeline.syncOperations.addHandler(VerifyEOFReadOrderingAndCloseInChannelReadHandler())\n                    }\n                }\n                .childChannelOption(.maxMessagesPerRead, value: 1)\n                .childChannelOption(.recvAllocator, value: FixedSizeRecvByteBufferAllocator(capacity: 8))\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        var buffer = clientChannel.allocator.buffer(capacity: 8)\n        buffer.writeString(\"01234567\")\n        for _ in 0..<20 {\n            XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n        }\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        // Wait for 100 ms.\n        usleep(100 * 1000)\n        XCTAssertNoThrow(try serverChannel.close().wait())\n    }\n\n    func testCloseInSameReadThatEOFGetsDelivered() throws {\n        guard isEarlyEOFDeliveryWorkingOnThisOS else {\n            #if os(Linux) || os(Android)\n            preconditionFailure(\"this should only ever be entered on Darwin.\")\n            #else\n            return\n            #endif\n        }\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class CloseWhenWeGetEOFHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            private var didRead: Bool = false\n            private let allDone: EventLoopPromise<Void>\n\n            init(allDone: EventLoopPromise<Void>) {\n                self.allDone = allDone\n            }\n\n            public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                if !self.didRead {\n                    self.didRead = true\n                    // closing this here causes an interesting situation:\n                    // in readFromSocket we will spin one more iteration until we see the EOF but when we then return\n                    // to `BaseSocketChannel.readable0`, we deliver EOF with the channel already deactivated.\n                    context.close(mode: .all, promise: self.allDone)\n                }\n            }\n        }\n\n        let allDone = group.next().makePromise(of: Void.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelOption(.autoRead, value: false)\n                .childChannelInitializer { ch in\n                    ch.eventLoop.makeCompletedFuture {\n                        try ch.pipeline.syncOperations.addHandler(CloseWhenWeGetEOFHandler(allDone: allDone))\n                    }\n                }\n                // maxMessagesPerRead is large so that we definitely spin and seen the EOF\n                .childChannelOption(.maxMessagesPerRead, value: 10)\n                .childChannelOption(.allowRemoteHalfClosure, value: true)\n                // that fits the message we prepared\n                .childChannelOption(.recvAllocator, value: FixedSizeRecvByteBufferAllocator(capacity: 8))\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        var buf = clientChannel.allocator.buffer(capacity: 16)\n        buf.writeStaticString(\"012345678\")\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(buf).wait())\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(buf).wait())\n        XCTAssertNoThrow(try clientChannel.close().wait())  // autoRead=off so this EOF will trigger the channelRead\n        XCTAssertNoThrow(try allDone.futureResult.wait())\n\n        XCTAssertNoThrow(try serverChannel.close().wait())\n    }\n\n    func testEOFReceivedWithoutReadRequests() throws {\n        guard isEarlyEOFDeliveryWorkingOnThisOS else {\n            #if os(Linux) || os(Android)\n            preconditionFailure(\"this should only ever be entered on Darwin.\")\n            #else\n            return\n            #endif\n        }\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        final class ChannelInactiveVerificationHandler: ChannelDuplexHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundIn = ByteBuffer\n\n            private let promise: EventLoopPromise<Void>\n\n            init(_ promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            public func read(context: ChannelHandlerContext) {\n                XCTFail(\"shouldn't read\")\n            }\n\n            public func channelInactive(context: ChannelHandlerContext) {\n                promise.succeed(())\n            }\n        }\n\n        let promise = group.next().makePromise(of: Void.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelOption(.autoRead, value: false)\n                .childChannelInitializer { ch in\n                    ch.pipeline.addHandler(ChannelInactiveVerificationHandler(promise))\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        var buffer = clientChannel.allocator.buffer(capacity: 8)\n        buffer.writeString(\"test\")\n        try clientChannel.writeAndFlush(buffer).wait()\n        try clientChannel.close().wait()\n        try promise.futureResult.wait()\n\n        try serverChannel.close().wait()\n    }\n\n    func testAcceptsAfterCloseDontCauseIssues() throws {\n        final class ChannelCollector: Sendable {\n            private let channels: NIOLockedValueBox<[ObjectIdentifier: Channel]> = NIOLockedValueBox([:])\n\n            deinit {\n                XCTAssertTrue(self.channels.withLockedValue { $0.isEmpty })\n            }\n\n            func add(_ channel: Channel) {\n                let key = ObjectIdentifier(channel)\n                let old = self.channels.withLockedValue { $0.updateValue(channel, forKey: key) }\n                assert(old == nil)\n            }\n\n            func remove(_ channel: Channel) {\n                let removed = self.channels.withLockedValue {\n                    $0.removeValue(forKey: ObjectIdentifier(channel))\n                }\n                XCTAssertTrue(removed != nil)\n            }\n\n            func closeAll() -> [EventLoopFuture<Void>] {\n                let channels = self.channels.withLockedValue { $0.values }\n                return channels.map { channel in\n                    channel.close()\n                }\n            }\n        }\n\n        class CheckActiveHandler: ChannelInboundHandler {\n            public typealias InboundIn = Any\n            public typealias OutboundOut = Any\n\n            private var isActive = false\n            private let channelCollector: ChannelCollector\n\n            init(channelCollector: ChannelCollector) {\n                self.channelCollector = channelCollector\n            }\n\n            deinit {\n                XCTAssertFalse(self.isActive)\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                XCTAssertFalse(self.isActive)\n                self.isActive = true\n                self.channelCollector.add(context.channel)\n                context.fireChannelActive()\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                XCTAssertTrue(self.isActive)\n                self.isActive = false\n                self.channelCollector.remove(context.channel)\n                context.fireChannelInactive()\n            }\n        }\n\n        func runTest() throws {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\n            defer {\n                XCTAssertNoThrow(try group.syncShutdownGracefully())\n            }\n            let collector = ChannelCollector()\n            let serverBoot = ServerBootstrap(group: group)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            CheckActiveHandler(channelCollector: collector)\n                        )\n                    }\n                }\n            let listeningChannel = try serverBoot.bind(host: \"127.0.0.1\", port: 0).wait()\n            let clientBoot = ClientBootstrap(group: group)\n            XCTAssertNoThrow(try clientBoot.connect(to: listeningChannel.localAddress!).wait().close().wait())\n            let closeFutures = collector.closeAll()\n            // a stray client\n            XCTAssertNoThrow(try clientBoot.connect(to: listeningChannel.localAddress!).wait().close().wait())\n            XCTAssertNoThrow(try listeningChannel.close().wait())\n            for future in closeFutures {\n                do {\n                    try future.wait()\n                    // No error is okay,\n                } catch ChannelError.alreadyClosed {\n                    // as well as already closed.\n                } catch {\n                    XCTFail(\"unexpected error \\(error) received\")\n                }\n            }\n        }\n\n        for _ in 0..<20 {\n            XCTAssertNoThrow(try runTest())\n        }\n    }\n\n    func testChannelReadsDoesNotHappenAfterRegistration() throws {\n        class SocketThatSucceedsOnSecondConnectForPort123: Socket {\n            init(protocolFamily: NIOBSDSocket.ProtocolFamily) throws {\n                try super.init(protocolFamily: protocolFamily, type: .stream, setNonBlocking: true)\n            }\n            override func connect(to address: SocketAddress) throws -> Bool {\n                if address.port == 123 {\n                    return true\n                } else {\n                    return try super.connect(to: address)\n                }\n            }\n        }\n        class ReadDoesNotHappen: ChannelInboundHandler {\n            typealias InboundIn = Any\n            private let hasRegisteredPromise: EventLoopPromise<Void>\n            private let hasUnregisteredPromise: EventLoopPromise<Void>\n            private let hasReadPromise: EventLoopPromise<Void>\n            enum State {\n                case start\n                case registered\n                case active\n                case read\n            }\n            private var state: State = .start\n            init(\n                hasRegisteredPromise: EventLoopPromise<Void>,\n                hasUnregisteredPromise: EventLoopPromise<Void>,\n                hasReadPromise: EventLoopPromise<Void>\n            ) {\n                self.hasRegisteredPromise = hasRegisteredPromise\n                self.hasUnregisteredPromise = hasUnregisteredPromise\n                self.hasReadPromise = hasReadPromise\n            }\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTAssertEqual(.active, self.state)\n                self.state = .read\n                self.hasReadPromise.succeed(())\n            }\n            func channelActive(context: ChannelHandlerContext) {\n                XCTAssertEqual(.registered, self.state)\n                self.state = .active\n            }\n            func channelRegistered(context: ChannelHandlerContext) {\n                XCTAssertEqual(.start, self.state)\n                self.state = .registered\n                self.hasRegisteredPromise.succeed(())\n            }\n            func channelUnregistered(context: ChannelHandlerContext) {\n                self.hasUnregisteredPromise.succeed(())\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverEL = group.next()\n        let clientEL = group.next()\n        precondition(serverEL !== clientEL)\n        let sc = try SocketChannel(\n            socket: SocketThatSucceedsOnSecondConnectForPort123(protocolFamily: .inet),\n            eventLoop: clientEL as! SelectableEventLoop\n        )\n\n        final class WriteImmediatelyHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Any\n            typealias OutboundOut = ByteBuffer\n\n            private let writeDonePromise: EventLoopPromise<Void>\n\n            init(writeDonePromise: EventLoopPromise<Void>) {\n                self.writeDonePromise = writeDonePromise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                var buffer = context.channel.allocator.buffer(capacity: 4)\n                buffer.writeString(\"foo\")\n                context.writeAndFlush(NIOAny(buffer), promise: self.writeDonePromise)\n            }\n        }\n\n        let serverWriteHappenedPromise = serverEL.next().makePromise(of: Void.self)\n        let clientHasRegistered = serverEL.next().makePromise(of: Void.self)\n        let clientHasUnregistered = serverEL.next().makePromise(of: Void.self)\n        let clientHasRead = serverEL.next().makePromise(of: Void.self)\n\n        let bootstrap = try assertNoThrowWithValue(\n            ServerBootstrap(group: serverEL)\n                .childChannelInitializer { channel in\n                    channel.pipeline.addHandler(WriteImmediatelyHandler(writeDonePromise: serverWriteHappenedPromise))\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        // This is a bit ugly, we're trying to fabricate a situation that can happen in the real world which is that\n        // a socket is readable straight after becoming registered & connected.\n        // In here what we're doing is that we flip the order around and connect it first, make sure the server\n        // has written something and then on registration something is available to be read. We then 'fake connect'\n        // again which our special `Socket` subclass will let succeed.\n        _ = try sc.socket.connect(to: bootstrap.localAddress!)\n        try serverWriteHappenedPromise.futureResult.wait()\n        try sc.eventLoop.submit {\n            try sc.pipeline.syncOperations.addHandler(\n                ReadDoesNotHappen(\n                    hasRegisteredPromise: clientHasRegistered,\n                    hasUnregisteredPromise: clientHasUnregistered,\n                    hasReadPromise: clientHasRead\n                )\n            )\n        }.flatMap {\n            // this will succeed and should not cause the socket to be read even though there'll be something\n            // available to be read immediately\n            sc.register()\n        }.flatMap {\n            // this would normally fail but our special Socket subclass will let it succeed.\n            sc.connect(to: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 123))\n        }.wait()\n        try clientHasRegistered.futureResult.wait()\n        try clientHasRead.futureResult.wait()\n        try sc.syncCloseAcceptingAlreadyClosed()\n        try clientHasUnregistered.futureResult.wait()\n    }\n\n    func testAppropriateAndInappropriateOperationsForUnregisteredSockets() throws {\n        func checkThatItThrowsInappropriateOperationForState(\n            file: StaticString = #filePath,\n            line: UInt = #line,\n            _ body: () throws -> Void\n        ) {\n            XCTAssertThrowsError(try body(), file: (file), line: line) { error in\n                XCTAssertEqual(.inappropriateOperationForState, error as? ChannelError)\n            }\n        }\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n\n        func withChannel(\n            skipDatagram: Bool = false,\n            skipStream: Bool = false,\n            skipServerSocket: Bool = false,\n            file: StaticString = #filePath,\n            line: UInt = #line,\n            _ body: (Channel) throws -> Void\n        ) {\n            XCTAssertNoThrow(\n                try {\n                    let el = elg.next() as! SelectableEventLoop\n                    let channels: [Channel] =\n                        (skipDatagram\n                            ? []\n                            : [try DatagramChannel(eventLoop: el, protocolFamily: .inet, protocolSubtype: .default)])\n                        // Xcode need help\n                        + (skipStream ? [] : [try SocketChannel(eventLoop: el, protocolFamily: .inet)])\n                        // Xcode need help\n                        + (skipServerSocket\n                            ? [] : [try ServerSocketChannel(eventLoop: el, group: elg, protocolFamily: .inet)])\n                    for channel in channels {\n                        try body(channel)\n                        XCTAssertNoThrow(try channel.close().wait(), file: (file), line: line)\n                    }\n                }(),\n                file: (file),\n                line: line\n            )\n        }\n        withChannel { channel in\n            checkThatItThrowsInappropriateOperationForState {\n                try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 1234)).wait()\n            }\n        }\n        withChannel { channel in\n            XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"foo\").wait()) { error in\n                if let error = error as? ChannelError {\n                    XCTAssertEqual(ChannelError.operationUnsupported, error)\n                } else {\n                    XCTFail(\"wrong error: \\(error)\")\n                }\n            }\n        }\n        withChannel { channel in\n            XCTAssertFalse(channel.isActive)\n        }\n        withChannel(skipServerSocket: true) { channel in\n            // should probably be changed\n            XCTAssertTrue(channel.isWritable)\n        }\n        withChannel(skipDatagram: true, skipStream: true) { channel in\n            // this should probably be the default for all types\n            XCTAssertFalse(channel.isWritable)\n        }\n\n        withChannel(skipStream: true) { channel in\n            checkThatItThrowsInappropriateOperationForState {\n                XCTAssertEqual(0, channel.localAddress?.port ?? 0xffff)\n                XCTAssertNil(channel.remoteAddress)\n                try channel.bind(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0)).wait()\n            }\n        }\n    }\n\n    func testCloseSocketWhenReadErrorWasReceivedAndMakeSureNoReadCompleteArrives() throws {\n        class SocketThatHasTheFirstReadSucceedButFailsTheNextWithECONNRESET: Socket {\n            private var firstReadHappened = false\n            init(protocolFamily: NIOBSDSocket.ProtocolFamily) throws {\n                try super.init(protocolFamily: protocolFamily, type: .stream, setNonBlocking: true)\n            }\n            override func read(pointer: UnsafeMutableRawBufferPointer) throws -> NIOPosix.IOResult<Int> {\n                defer {\n                    self.firstReadHappened = true\n                }\n                XCTAssertGreaterThan(pointer.count, 0)\n                if self.firstReadHappened {\n                    // this is a copy of the exact error that'd come out of the real Socket.read\n                    throw IOError.init(errnoCode: ECONNRESET, reason: \"read(descriptor:pointer:size:)\")\n                } else {\n                    pointer[0] = 0xff\n                    return .processed(1)\n                }\n            }\n        }\n        class VerifyThingsAreRightHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            private let allDone: EventLoopPromise<Void>\n            enum State {\n                case fresh\n                case active\n                case read\n                case error\n                case readComplete\n                case inactive\n            }\n            private var state: State = .fresh\n\n            init(allDone: EventLoopPromise<Void>) {\n                self.allDone = allDone\n            }\n            func channelActive(context: ChannelHandlerContext) {\n                XCTAssertEqual(.fresh, self.state)\n                self.state = .active\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTAssertEqual(.active, self.state)\n                self.state = .read\n                var buffer = Self.unwrapInboundIn(data)\n                XCTAssertEqual(1, buffer.readableBytes)\n                XCTAssertEqual([0xff], buffer.readBytes(length: 1)!)\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                XCTAssertEqual(.read, self.state)\n                self.state = .readComplete\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                XCTAssertEqual(.readComplete, self.state)\n                self.state = .error\n                context.close(promise: nil)\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                XCTAssertEqual(.error, self.state)\n                self.state = .inactive\n                self.allDone.succeed(())\n            }\n        }\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverEL = group.next()\n        let clientEL = group.next()\n        precondition(serverEL !== clientEL)\n        let sc = try SocketChannel(\n            socket: SocketThatHasTheFirstReadSucceedButFailsTheNextWithECONNRESET(protocolFamily: .inet),\n            eventLoop: clientEL as! SelectableEventLoop\n        )\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: serverEL)\n                .childChannelInitializer { channel in\n                    var buffer = channel.allocator.buffer(capacity: 4)\n                    buffer.writeString(\"foo\")\n                    channel.writeAndFlush(buffer, promise: nil)\n                    return channel.eventLoop.makeSucceededVoidFuture()\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let allDone = clientEL.makePromise(of: Void.self)\n\n        XCTAssertNoThrow(\n            try sc.eventLoop.flatSubmit {\n                // this is pretty delicate at the moment:\n                // `bind` must be _synchronously_ follow `register`, otherwise in our current implementation, `epoll` will\n                // send us `EPOLLHUP`. To have it run synchronously, we need to invoke the `flatMap` on the eventloop that the\n                // `register` will succeed.\n\n                sc.register().flatMapThrowing {\n                    try sc.pipeline.syncOperations.addHandler(VerifyThingsAreRightHandler(allDone: allDone))\n                }.flatMap {\n                    sc.connect(to: serverChannel.localAddress!)\n                }\n            }.wait() as Void\n        )\n        XCTAssertNoThrow(try allDone.futureResult.wait())\n        XCTAssertNoThrow(try sc.syncCloseAcceptingAlreadyClosed())\n    }\n\n    func testSocketFailingAsyncCorrectlyTearsTheChannelDownAndDoesntCrash() throws {\n        // regression test for #302\n        enum DummyError: Error { case dummy }\n        class SocketFailingAsyncConnect: Socket {\n            init() throws {\n                try super.init(protocolFamily: .inet, type: .stream, setNonBlocking: true)\n            }\n\n            override func connect(to address: SocketAddress) throws -> Bool {\n                _ = try super.connect(to: address)\n                return false\n            }\n\n            override func finishConnect() throws {\n                throw DummyError.dummy\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let sc = try SocketChannel(socket: SocketFailingAsyncConnect(), eventLoop: group.next() as! SelectableEventLoop)\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group.next())\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let allDone = group.next().makePromise(of: Void.self)\n        let cf = try! sc.eventLoop.submit {\n            try sc.pipeline.syncOperations.addHandler(VerifyConnectionFailureHandler(allDone: allDone))\n            return sc.register().flatMap {\n                sc.connect(to: serverChannel.localAddress!)\n            }\n        }.wait()\n        XCTAssertThrowsError(try cf.wait()) { error in\n            XCTAssertEqual(.dummy, error as? DummyError)\n        }\n        XCTAssertNoThrow(try allDone.futureResult.wait())\n        XCTAssertNoThrow(try sc.syncCloseAcceptingAlreadyClosed())\n    }\n\n    func testSocketErroringSynchronouslyCorrectlyTearsTheChannelDown() throws {\n        // regression test for #322\n        enum DummyError: Error { case dummy }\n        class SocketFailingConnect: Socket {\n            init() throws {\n                try super.init(protocolFamily: .inet, type: .stream, setNonBlocking: true)\n            }\n\n            override func connect(to address: SocketAddress) throws -> Bool {\n                throw DummyError.dummy\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let sc = try SocketChannel(socket: SocketFailingConnect(), eventLoop: group.next() as! SelectableEventLoop)\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group.next())\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let allDone = group.next().makePromise(of: Void.self)\n        try! sc.eventLoop.submit {\n            try sc.pipeline.syncOperations.addHandler(VerifyConnectionFailureHandler(allDone: allDone))\n            let f = sc.register().flatMap {\n                sc.connect(to: serverChannel.localAddress!)\n            }\n            f.whenSuccess {\n                XCTFail(\"Must not succeed\")\n            }\n            f.whenFailure { err in\n                XCTAssertEqual(err as? DummyError, .dummy)\n            }\n            // We can block here because connect must have failed synchronously.\n            XCTAssertTrue(f.isFulfilled)\n        }.wait() as Void\n        XCTAssertNoThrow(try allDone.futureResult.wait())\n\n        XCTAssertNoThrow(try sc.closeFuture.wait())\n        XCTAssertNoThrow(try sc.syncCloseAcceptingAlreadyClosed())\n    }\n\n    func testConnectWithECONNREFUSEDGetsTheRightError() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverSock = try Socket(protocolFamily: .inet, type: .stream)\n        // we deliberately don't set SO_REUSEADDR\n        XCTAssertNoThrow(try serverSock.bind(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0)))\n        let serverSockAddress = try! serverSock.localAddress()\n        XCTAssertNoThrow(try serverSock.close())\n\n        // we're just looping here to get a pretty good chance we're hitting both the synchronous and the asynchronous\n        // connect path.\n        for _ in 0..<64 {\n            XCTAssertThrowsError(try ClientBootstrap(group: group).connect(to: serverSockAddress).wait()) { error in\n                XCTAssertEqual(ECONNREFUSED, (error as? IOError).map { $0.errnoCode })\n            }\n        }\n    }\n\n    func testCloseInUnregister() throws {\n        enum DummyError: Error { case dummy }\n        class SocketFailingClose: Socket {\n            init() throws {\n                try super.init(protocolFamily: .inet, type: .stream, setNonBlocking: true)\n            }\n\n            override func close() throws {\n                _ = try? super.close()\n                throw DummyError.dummy\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let sc = try SocketChannel(socket: SocketFailingClose(), eventLoop: group.next() as! SelectableEventLoop)\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group.next())\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        XCTAssertNoThrow(\n            try sc.eventLoop.flatSubmit {\n                sc.register().flatMap {\n                    sc.connect(to: serverChannel.localAddress!)\n                }\n            }.wait() as Void\n        )\n\n        XCTAssertThrowsError(\n            try sc.eventLoop.flatSubmit { () -> EventLoopFuture<Void> in\n                let p = sc.eventLoop.makePromise(of: Void.self)\n                // this callback must be attached before we call the close\n                let f = p.futureResult.map {\n                    XCTFail(\"shouldn't be reached\")\n                }.flatMapError { err in\n                    XCTAssertNotNil(err as? DummyError)\n                    return sc.close()\n                }\n                sc.close(promise: p)\n                return f\n            }.wait()\n        ) { error in\n            XCTAssertEqual(.alreadyClosed, error as? ChannelError)\n        }\n    }\n\n    func testLazyRegistrationWorksForServerSockets() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let server = try assertNoThrowWithValue(\n            ServerSocketChannel(\n                eventLoop: group.next() as! SelectableEventLoop,\n                group: group,\n                protocolFamily: .inet\n            )\n        )\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n        XCTAssertNoThrow(try server.register().wait())\n        XCTAssertNoThrow(\n            try server.eventLoop.submit {\n                XCTAssertFalse(server.isActive)\n            }.wait()\n        )\n        XCTAssertEqual(0, server.localAddress!.port!)\n        XCTAssertNoThrow(try server.bind(to: SocketAddress(ipAddress: \"0.0.0.0\", port: 0)).wait())\n        XCTAssertNotEqual(0, server.localAddress!.port!)\n    }\n\n    func testLazyRegistrationWorksForClientSockets() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"localhost\", port: 0)\n                .wait()\n        )\n\n        let client = try SocketChannel(\n            eventLoop: group.next() as! SelectableEventLoop,\n            protocolFamily: serverChannel.localAddress!.protocol\n        )\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n        }\n        XCTAssertNoThrow(try client.register().wait())\n        XCTAssertNoThrow(\n            try client.eventLoop.submit {\n                XCTAssertFalse(client.isActive)\n            }.wait()\n        )\n        XCTAssertNoThrow(try client.connect(to: serverChannel.localAddress!).wait())\n        XCTAssertTrue(client.isActive)\n        XCTAssertEqual(serverChannel.localAddress!, client.remoteAddress!)\n    }\n\n    func testFailedRegistrationOfClientSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"localhost\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n        XCTAssertThrowsError(\n            try ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHandler(FailRegistrationAndDelayCloseHandler())\n                }\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        ) { error in\n            XCTAssertEqual(.error, error as? FailRegistrationAndDelayCloseHandler.RegistrationFailedError)\n        }\n    }\n\n    func testFailedRegistrationOfAcceptedSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .childChannelInitializer { channel in\n                    channel.pipeline.addHandler(FailRegistrationAndDelayCloseHandler())\n                }\n                .bind(host: \"localhost\", port: 0).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait(),\n            message:\n                \"resolver debug info: \\(try! resolverDebugInformation(eventLoop: group.next(),host: \"localhost\", previouslyReceivedResult: serverChannel.localAddress!))\"\n        )\n        XCTAssertNoThrow(try clientChannel.closeFuture.wait() as Void)\n    }\n\n    func testFailedRegistrationOfServerSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        XCTAssertThrowsError(\n            try ServerBootstrap(group: group)\n                .serverChannelInitializer { channel in\n                    channel.pipeline.addHandler(FailRegistrationAndDelayCloseHandler())\n                }\n                .bind(host: \"localhost\", port: 0)\n                .wait()\n        ) { error in\n            XCTAssertEqual(.error, error as? FailRegistrationAndDelayCloseHandler.RegistrationFailedError)\n        }\n    }\n\n    func testTryingToBindOnPortThatIsAlreadyBoundFailsButDoesNotCrash() throws {\n        // this is a regression test for #417\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel1 = try! ServerBootstrap(group: group)\n            .bind(host: \"localhost\", port: 0)\n            .wait()\n        defer {\n            XCTAssertNoThrow(try serverChannel1.close().wait())\n        }\n\n        do {\n            let serverChannel2 = try ServerBootstrap(group: group)\n                .bind(to: serverChannel1.localAddress!)\n                .wait()\n            XCTFail(\n                \"shouldn't have succeeded, got two server channels on the same port: \\(serverChannel1) and \\(serverChannel2)\"\n            )\n        } catch let e as IOError where e.errnoCode == EADDRINUSE {\n            // OK\n        } catch {\n            XCTFail(\"unexpected error: \\(error)\")\n        }\n    }\n\n    func testCloseInReadTriggeredByDrainingTheReceiveBufferBecauseOfWriteError() throws {\n        final class WriteWhenActiveHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            let channelAvailablePromise: EventLoopPromise<Channel>\n\n            init(channelAvailablePromise: EventLoopPromise<Channel>) {\n                self.channelAvailablePromise = channelAvailablePromise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let buffer = Self.unwrapInboundIn(data)\n                XCTFail(\"unexpected read: \\(String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\")\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                var buffer = context.channel.allocator.buffer(capacity: 1)\n                buffer.writeStaticString(\"X\")\n                context.channel.writeAndFlush(buffer).map { [channel = context.channel] in\n                    channel\n                }.cascade(\n                    to: self.channelAvailablePromise\n                )\n            }\n        }\n\n        final class WriteAlwaysFailingSocket: Socket {\n            init() throws {\n                try super.init(protocolFamily: .inet, type: .stream, setNonBlocking: true)\n            }\n\n            override func write(pointer: UnsafeRawBufferPointer) throws -> NIOPosix.IOResult<Int> {\n                throw IOError(errnoCode: ETXTBSY, reason: \"WriteAlwaysFailingSocket.write fake error\")\n            }\n\n            override func writev(iovecs: UnsafeBufferPointer<IOVector>) throws -> NIOPosix.IOResult<Int> {\n                throw IOError(errnoCode: ETXTBSY, reason: \"WriteAlwaysFailingSocket.writev fake error\")\n            }\n        }\n\n        final class MakeChannelInactiveInReadCausedByWriteErrorHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            let serverChannel: EventLoopFuture<Channel>\n            let allDonePromise: EventLoopPromise<Void>\n\n            init(\n                serverChannel: EventLoopFuture<Channel>,\n                allDonePromise: EventLoopPromise<Void>\n            ) {\n                self.serverChannel = serverChannel\n                self.allDonePromise = allDonePromise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                XCTAssert(serverChannel.eventLoop === context.eventLoop)\n                let loopBoundContext = context.loopBound\n                self.serverChannel.whenSuccess { [channel = context.channel, allDonePromise] serverChannel in\n                    // all of the following futures need to complete synchronously for this test to test the correct\n                    // thing. Therefore we keep track if we're still on the same stack frame.\n                    var inSameStackFrame = true\n                    defer {\n                        inSameStackFrame = false\n                    }\n\n                    XCTAssertTrue(serverChannel.isActive)\n                    // we allow auto-read again to make sure that the socket buffer is drained on write error\n                    // (cf. https://github.com/apple/swift-nio/issues/593)\n                    channel.setOption(.autoRead, value: true).assumeIsolated().flatMap {\n                        let context = loopBoundContext.value\n                        // let's trigger the write error\n                        var buffer = channel.allocator.buffer(capacity: 16)\n                        buffer.writeStaticString(\"THIS WILL FAIL ANYWAY\")\n\n                        // this needs to be in a function as otherwise the Swift compiler believes this is throwing\n                        func workaroundSR487() {\n                            // this test only tests the correct condition if the bytes sent from the other side have already\n                            // arrived at the time the write fails. So this is a hack that makes sure they do have arrived.\n                            // (https://github.com/apple/swift-nio/issues/657)\n                            XCTAssertNoThrow(\n                                try veryNasty_blockUntilReadBufferIsNonEmpty(channel: channel)\n                            )\n                        }\n                        workaroundSR487()\n\n                        return context.writeAndFlush(Self.wrapOutboundOut(buffer))\n                    }.map {\n                        XCTFail(\"this should have failed\")\n                    }.whenFailure { error in\n                        XCTAssertEqual(\n                            ChannelError.ioOnClosedChannel,\n                            error as? ChannelError,\n                            \"unexpected error: \\(error)\"\n                        )\n                        XCTAssertTrue(inSameStackFrame)\n                        allDonePromise.succeed(())\n                    }\n                }\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let buffer = Self.unwrapInboundIn(data)\n                XCTAssertEqual(\"X\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                context.close(promise: nil)\n            }\n        }\n\n        let singleThreadedELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try singleThreadedELG.syncShutdownGracefully())\n        }\n        let serverChannelAvailablePromise = singleThreadedELG.next().makePromise(of: Channel.self)\n        let allDonePromise = singleThreadedELG.next().makePromise(of: Void.self)\n        let server = try assertNoThrowWithValue(\n            ServerBootstrap(group: singleThreadedELG)\n                .childChannelOption(.allowRemoteHalfClosure, value: true)\n                .childChannelInitializer { channel in\n                    channel.pipeline.addHandler(\n                        WriteWhenActiveHandler(channelAvailablePromise: serverChannelAvailablePromise)\n                    )\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        let c = try assertNoThrowWithValue(\n            SocketChannel(\n                socket: WriteAlwaysFailingSocket(),\n                parent: nil,\n                eventLoop: singleThreadedELG.next() as! SelectableEventLoop\n            )\n        )\n        XCTAssertNoThrow(try c.setOption(.autoRead, value: false).wait())\n        XCTAssertNoThrow(try c.setOption(.allowRemoteHalfClosure, value: true).wait())\n        XCTAssertNoThrow(\n            try c.pipeline.addHandler(\n                MakeChannelInactiveInReadCausedByWriteErrorHandler(\n                    serverChannel: serverChannelAvailablePromise.futureResult,\n                    allDonePromise: allDonePromise\n                )\n            ).wait()\n        )\n        XCTAssertNoThrow(try c.register().wait())\n        XCTAssertNoThrow(try c.connect(to: server.localAddress!).wait())\n\n        XCTAssertNoThrow(try allDonePromise.futureResult.wait())\n        XCTAssertFalse(c.isActive)\n    }\n\n    func testApplyingTwoDistinctSocketOptionsOfSameTypeWorks() throws {\n        let singleThreadedELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try singleThreadedELG.syncShutdownGracefully())\n        }\n\n        let numberOfAcceptedChannel = NIOLockedValueBox(0)\n        let acceptedChannels: [EventLoopPromise<Channel>] = [\n            singleThreadedELG.next().makePromise(),\n            singleThreadedELG.next().makePromise(),\n            singleThreadedELG.next().makePromise(),\n        ]\n        let server = try assertNoThrowWithValue(\n            ServerBootstrap(group: singleThreadedELG)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .serverChannelOption(.socketOption(.so_timestamp), value: 1)\n                .childChannelOption(.socketOption(.so_keepalive), value: 1)\n                .childChannelOption(.tcpOption(.tcp_nodelay), value: 0)\n                .childChannelInitializer { channel in\n                    acceptedChannels[numberOfAcceptedChannel.withLockedValue { $0 }].succeed(channel)\n                    numberOfAcceptedChannel.withLockedValue { $0 += 1 }\n                    return channel.eventLoop.makeSucceededFuture(())\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n        XCTAssertTrue(try getBoolSocketOption(channel: server, level: .socket, name: .so_reuseaddr))\n        XCTAssertTrue(try getBoolSocketOption(channel: server, level: .socket, name: .so_timestamp))\n\n        let client1 = try assertNoThrowWithValue(\n            ClientBootstrap(group: singleThreadedELG)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .channelOption(.tcpOption(.tcp_nodelay), value: 0)\n                .connect(to: server.localAddress!)\n                .wait()\n        )\n        let accepted1 = try assertNoThrowWithValue(acceptedChannels[0].futureResult.wait())\n        defer {\n            XCTAssertNoThrow(try client1.close().wait())\n        }\n        let client2 = try assertNoThrowWithValue(\n            ClientBootstrap(group: singleThreadedELG)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .connect(to: server.localAddress!)\n                .wait()\n        )\n        let accepted2 = try assertNoThrowWithValue(acceptedChannels[0].futureResult.wait())\n        defer {\n            XCTAssertNoThrow(try client2.close().wait())\n        }\n        let client3 = try assertNoThrowWithValue(\n            ClientBootstrap(group: singleThreadedELG)\n                .connect(to: server.localAddress!)\n                .wait()\n        )\n        let accepted3 = try assertNoThrowWithValue(acceptedChannels[0].futureResult.wait())\n        defer {\n            XCTAssertNoThrow(try client3.close().wait())\n        }\n\n        XCTAssertTrue(try getBoolSocketOption(channel: client1, level: .socket, name: .so_reuseaddr))\n\n        XCTAssertFalse(try getBoolSocketOption(channel: client1, level: .tcp, name: .tcp_nodelay))\n\n        XCTAssertTrue(try getBoolSocketOption(channel: accepted1, level: .socket, name: .so_keepalive))\n\n        XCTAssertFalse(try getBoolSocketOption(channel: accepted1, level: .tcp, name: .tcp_nodelay))\n\n        XCTAssertTrue(try getBoolSocketOption(channel: client2, level: .socket, name: .so_reuseaddr))\n\n        XCTAssertTrue(try getBoolSocketOption(channel: client2, level: .tcp, name: .tcp_nodelay))\n\n        XCTAssertTrue(try getBoolSocketOption(channel: accepted2, level: .socket, name: .so_keepalive))\n\n        XCTAssertFalse(try getBoolSocketOption(channel: accepted2, level: .tcp, name: .tcp_nodelay))\n\n        XCTAssertFalse(try getBoolSocketOption(channel: client3, level: .socket, name: .so_reuseaddr))\n\n        XCTAssertTrue(try getBoolSocketOption(channel: client3, level: .tcp, name: .tcp_nodelay))\n\n        XCTAssertTrue(try getBoolSocketOption(channel: accepted3, level: .socket, name: .so_keepalive))\n\n        XCTAssertFalse(try getBoolSocketOption(channel: accepted3, level: .tcp, name: .tcp_nodelay))\n    }\n\n    func testUnprocessedOutboundUserEventFailsOnServerSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let channel = try ServerSocketChannel(\n            eventLoop: group.next() as! SelectableEventLoop,\n            group: group,\n            protocolFamily: .inet\n        )\n        XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"event\").wait()) { (error: Error) in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.operationUnsupported, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testAcceptHandlerDoesNotSwallowCloseErrorsWhenQuiescing() {\n        // AcceptHandler is a `private class` so I can only implicitly get it by creating the real thing\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let counter = EventCounterHandler()\n\n        struct DummyError: Error {}\n        class MakeFirstCloseFailAndDontActuallyCloseHandler: ChannelOutboundHandler {\n            typealias OutboundIn = Any\n\n            var closes = 0\n\n            func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n                self.closes += 1\n                if self.closes == 1 {\n                    promise?.fail(DummyError())\n                } else {\n                    context.close(mode: mode, promise: promise)\n                }\n            }\n        }\n\n        let channel = try! assertNoThrowWithValue(\n            ServerBootstrap(group: group).serverChannelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        MakeFirstCloseFailAndDontActuallyCloseHandler(),\n                        position: .first\n                    )\n                }\n            }.bind(host: \"localhost\", port: 0).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try channel.close().wait())\n        }\n\n        XCTAssertNoThrow(try channel.pipeline.addHandler(counter).wait())\n\n        XCTAssertNoThrow(\n            try channel.eventLoop.submit {\n                // this will trigger a close (which will fail and also not actually close)\n                channel.pipeline.fireUserInboundEventTriggered(ChannelShouldQuiesceEvent())\n            }.wait()\n        )\n        XCTAssertEqual([\"userInboundEventTriggered\", \"close\", \"errorCaught\"], counter.allTriggeredEvents())\n        XCTAssertEqual(1, counter.errorCaughtCalls)\n    }\n\n    func _testTCP_NODELAYDefaultValue(\n        value: Bool,\n        _ socketAddress: SocketAddress,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        let singleThreadedELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try singleThreadedELG.syncShutdownGracefully(), file: file, line: line)\n        }\n        let acceptedChannel = singleThreadedELG.next().makePromise(of: Channel.self)\n        let server = try assertNoThrowWithValue(\n            ServerBootstrap(group: singleThreadedELG)\n                .childChannelInitializer { channel in\n                    acceptedChannel.succeed(channel)\n                    return channel.eventLoop.makeSucceededFuture(())\n                }\n                .bind(to: socketAddress)\n                .wait(),\n            file: file,\n            line: line\n        )\n        defer {\n            XCTAssertNoThrow(try server.close().wait(), file: file, line: line)\n        }\n\n        let client = try assertNoThrowWithValue(\n            ClientBootstrap(group: singleThreadedELG)\n                .connect(to: server.localAddress!)\n                .wait(),\n            file: file,\n            line: line\n        )\n        let accepted = try assertNoThrowWithValue(acceptedChannel.futureResult.wait(), file: file, line: line)\n        defer {\n            XCTAssertNoThrow(try client.close().wait(), file: file, line: line)\n        }\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                try getBoolSocketOption(channel: accepted, level: .tcp, name: .tcp_nodelay),\n                value,\n                file: file,\n                line: line\n            ),\n            file: file,\n            line: line\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                try getBoolSocketOption(channel: client, level: .tcp, name: .tcp_nodelay),\n                value,\n                file: file,\n                line: line\n            ),\n            file: file,\n            line: line\n        )\n    }\n\n    func testTCP_NODELAYisOnByDefaultForInetSockets() throws {\n        try _testTCP_NODELAYDefaultValue(value: true, SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n    }\n\n    func testTCP_NODELAYisOnByDefaultForInet6Sockets() throws {\n        try XCTSkipUnless(System.supportsIPv6)\n        try _testTCP_NODELAYDefaultValue(value: true, SocketAddress(ipAddress: \"::1\", port: 0))\n    }\n\n    func testDescriptionCanBeCalledFromNonEventLoopThreads() {\n        // regression test for https://github.com/apple/swift-nio/issues/1141\n        let q = DispatchQueue(label: \"elsewhere\")\n        XCTAssertNoThrow(\n            try forEachActiveChannelType { channel in\n                let g = DispatchGroup()\n                q.async(group: g) {\n                    // we spin here for a bit and read\n                    for _ in 0..<10_000 {\n                        // this should trigger TSan if there's an issue.\n                        XCTAssert(String(describing: channel).count != 0)\n                    }\n                }\n\n                // We need to write to BaseSocket's `descriptor` which can only be done by closing the channel.\n                XCTAssertNoThrow(try channel.syncCloseAcceptingAlreadyClosed())\n                g.wait()\n            }\n        )\n    }\n\n    func testFixedSizeRecvByteBufferAllocatorSizeIsConstant() {\n        let actualAllocator = ByteBufferAllocator()\n        var allocator = FixedSizeRecvByteBufferAllocator(capacity: 1)\n        let b1 = allocator.buffer(allocator: actualAllocator)\n        XCTAssertFalse(allocator.record(actualReadBytes: 1024))\n        let b2 = allocator.buffer(allocator: actualAllocator)\n        XCTAssertEqual(1, b1.capacity)\n        XCTAssertEqual(1, b2.capacity)\n        XCTAssertEqual(1, allocator.capacity)\n    }\n\n    func testCloseInConnectPromise() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        var maybeServer: Channel? = nil\n        XCTAssertNoThrow(\n            maybeServer = try ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        guard let server = maybeServer else {\n            XCTFail(\"couldn't bootstrap server\")\n            return\n        }\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        for _ in 0..<10 {\n            // 10 times so we get a good chance of an asynchronous connect.\n            XCTAssertNoThrow(\n                try ClientBootstrap(group: group).connect(to: server.localAddress!).flatMap { channel in\n                    channel.close()\n                }.wait()\n            )\n        }\n    }\n\n    func testWritabilityChangeDuringReentrantFlushNow() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let loop = group.next()\n        let becameUnwritable = loop.makePromise(of: Void.self)\n        let becameWritable = loop.makePromise(of: Void.self)\n\n        let serverFuture = ServerBootstrap(group: group)\n            .childChannelOption(.writeBufferWaterMark, value: ReentrantWritabilityChangingHandler.watermark)\n            .childChannelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let handler = ReentrantWritabilityChangingHandler(\n                        becameUnwritable: becameUnwritable,\n                        becameWritable: becameWritable\n                    )\n                    return try channel.pipeline.syncOperations.addHandler(handler)\n                }\n            }\n            .bind(host: \"localhost\", port: 0)\n\n        let server: Channel = try assertNoThrowWithValue(try serverFuture.wait())\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        let clientFuture = ClientBootstrap(group: group)\n            .connect(host: \"localhost\", port: server.localAddress!.port!)\n\n        let client: Channel = try assertNoThrowWithValue(try clientFuture.wait())\n        defer {\n            XCTAssertNoThrow(try client.close().wait())\n        }\n\n        XCTAssertNoThrow(try becameUnwritable.futureResult.wait())\n        XCTAssertNoThrow(try becameWritable.futureResult.wait())\n    }\n\n    func testChannelCanReportWritableBufferedBytes() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let server = try ServerBootstrap(group: group)\n            .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n            .bind(host: \"localhost\", port: 0)\n            .wait()\n\n        let client = try ClientBootstrap(group: group)\n            .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n            .connect(to: server.localAddress!)\n            .wait()\n\n        let buffer = client.allocator.buffer(string: \"abcd\")\n        let writeCount = 3\n\n        let promises = (0..<writeCount).map { _ in client.write(buffer) }\n        let bufferedAmount = try client.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(bufferedAmount, buffer.readableBytes * writeCount)\n        client.flush()\n        XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: client.eventLoop).wait())\n        let bufferedAmountAfterFlush = try client.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(bufferedAmountAfterFlush, 0)\n    }\n\n    func testChannelCanReportWritableBufferedBytesWhenSendBufferWouldBlock() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let server = try ServerBootstrap(group: group)\n            .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n            .bind(host: \"localhost\", port: 0)\n            .wait()\n\n        let client = try ClientBootstrap(group: group)\n            .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)\n            .channelOption(ChannelOptions.socketOption(.so_sndbuf), value: 8)\n            .connect(to: server.localAddress!)\n            .wait()\n\n        let buffer = client.allocator.buffer(string: \"abcd\")\n        let writeCount = 20\n\n        var promises = (0..<writeCount).map { _ in client.writeAndFlush(buffer) }\n        var bufferedAmount = try client.getOption(.bufferedWritableBytes).wait()\n        XCTAssertTrue(bufferedAmount >= 0 && bufferedAmount <= buffer.readableBytes * writeCount)\n        promises.append(client.write(buffer))\n        bufferedAmount = try client.getOption(.bufferedWritableBytes).wait()\n        XCTAssertTrue(\n            bufferedAmount >= buffer.readableBytes && bufferedAmount <= buffer.readableBytes * (writeCount + 1)\n        )\n        client.flush()\n        XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: client.eventLoop).wait())\n        let bufferedAmountAfterFlush = try client.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(bufferedAmountAfterFlush, 0)\n    }\n}\n\nprivate final class FailRegistrationAndDelayCloseHandler: ChannelOutboundHandler, Sendable {\n    enum RegistrationFailedError: Error { case error }\n\n    typealias OutboundIn = Never\n\n    func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        promise!.fail(RegistrationFailedError.error)\n    }\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        let loopBoundContext = context.loopBound\n        // for extra nastiness, let's delay close. This makes sure the ChannelPipeline correctly retains the Channel\n        _ = context.eventLoop.scheduleTask(in: .milliseconds(10)) {\n            let context = loopBoundContext.value\n            context.close(mode: mode, promise: promise)\n        }\n    }\n}\n\nprivate class VerifyConnectionFailureHandler: ChannelInboundHandler {\n    typealias InboundIn = Never\n    private let allDone: EventLoopPromise<Void>\n    enum State {\n        case fresh\n        case registered\n        case unregistered\n    }\n    private var state: State = .fresh\n\n    init(allDone: EventLoopPromise<Void>) {\n        self.allDone = allDone\n    }\n    deinit { XCTAssertEqual(.unregistered, self.state) }\n\n    func channelActive(context: ChannelHandlerContext) { XCTFail(\"should never become active\") }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) { XCTFail(\"should never read\") }\n\n    func channelReadComplete(context: ChannelHandlerContext) { XCTFail(\"should never readComplete\") }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        XCTFail(\"pipeline shouldn't be told about connect error\")\n    }\n\n    func channelRegistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(.fresh, self.state)\n        self.state = .registered\n        context.fireChannelRegistered()\n    }\n\n    func channelUnregistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(.registered, self.state)\n        self.state = .unregistered\n        self.allDone.succeed(())\n        context.fireChannelUnregistered()\n    }\n}\n\nfinal class ReentrantWritabilityChangingHandler: ChannelInboundHandler {\n    typealias InboundIn = ByteBuffer\n    typealias OutboundOut = ByteBuffer\n\n    static let watermark = ChannelOptions.Types.WriteBufferWaterMark(low: 100, high: 200)\n\n    let becameWritable: EventLoopPromise<Void>\n    let becameUnwritable: EventLoopPromise<Void>\n\n    var isWritableCount = 0\n    var isNotWritableCount = 0\n\n    init(becameUnwritable: EventLoopPromise<Void>, becameWritable: EventLoopPromise<Void>) {\n        self.becameUnwritable = becameUnwritable\n        self.becameWritable = becameWritable\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        // We want to enqueue at least two pending writes before flushing. Neither of which\n        // should cause writability to change. However, we'll chain a callback off the first\n        // write which will make the channel unwritable and a writability change to be\n        // emitted. The flush for that write should result in the writability flipping back\n        // again.\n        let b1 = context.channel.allocator.buffer(repeating: 0, count: 50)\n        let loopBoundContext = context.loopBound\n        context.write(Self.wrapOutboundOut(b1)).assumeIsolated().whenSuccess { _ in\n            let context = loopBoundContext.value\n            // We should still be writable.\n            XCTAssertTrue(context.channel.isWritable)\n            XCTAssertEqual(self.isNotWritableCount, 0)\n            XCTAssertEqual(self.isWritableCount, 0)\n\n            // Write again. But now breach high water mark. This should cause us to become\n            // unwritable.\n            let b2 = context.channel.allocator.buffer(repeating: 0, count: 250)\n            context.write(Self.wrapOutboundOut(b2), promise: nil)\n            XCTAssertFalse(context.channel.isWritable)\n            XCTAssertEqual(self.isNotWritableCount, 1)\n            XCTAssertEqual(self.isWritableCount, 0)\n\n            // Now flush. This should lead to us becoming writable again.\n            context.flush()\n        }\n\n        // Queue another write and flush.\n        context.writeAndFlush(Self.wrapOutboundOut(b1), promise: nil)\n    }\n\n    func channelWritabilityChanged(context: ChannelHandlerContext) {\n        if context.channel.isWritable {\n            self.isWritableCount += 1\n            self.becameWritable.succeed(())\n        } else {\n            self.isNotWritableCount += 1\n            self.becameUnwritable.succeed(())\n        }\n    }\n}\n\nprivate func veryNasty_blockUntilReadBufferIsNonEmpty(channel: Channel) throws {\n    struct ThisIsNotASocketChannelError: Error {}\n    guard let channel = channel as? SocketChannel else {\n        throw ThisIsNotASocketChannelError()\n    }\n    try channel.socket.withUnsafeHandle { fd in\n        var pollFd: pollfd = .init(fd: fd, events: Int16(POLLIN), revents: 0)\n        let nfds =\n            try NIOBSDSocket.poll(fds: &pollFd, nfds: 1, timeout: -1)\n        XCTAssertEqual(1, nfds)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/CoWValue.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A Copy on Write (CoW) type that can be used in tests to assert in-place mutation\nstruct CoWValue: @unchecked Sendable {\n    private final class UniquenessIndicator {}\n\n    /// This reference is \"copied\" if not uniquely referenced\n    private var uniquenessIndicator = UniquenessIndicator()\n\n    /// mutates `self` and returns a boolean whether it was mutated in place or not\n    /// - Returns: true if mutation happened in-place, false if Copy on Write (CoW) was triggered\n    mutating func mutateInPlace() -> Bool {\n        guard isKnownUniquelyReferenced(&self.uniquenessIndicator) else {\n            self.uniquenessIndicator = UniquenessIndicator()\n            return false\n        }\n        return true\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/CodecTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\n@_spi(CustomByteBufferAllocator) @testable import NIOCore\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOPosix\n\nprivate let testDecoderIsNotQuadratic_mallocs = NIOLockedValueBox(0)\nprivate let testDecoderIsNotQuadratic_reallocs = NIOLockedValueBox(0)\nprivate func testDecoderIsNotQuadratic_freeHook(_ ptr: UnsafeMutableRawPointer) {\n    free(ptr)\n}\n\nprivate func testDecoderIsNotQuadratic_mallocHook(_ size: Int) -> UnsafeMutableRawPointer? {\n    testDecoderIsNotQuadratic_mallocs.withLockedValue { $0 += 1 }\n    return malloc(size)\n}\n\nprivate func testDecoderIsNotQuadratic_reallocHook(\n    _ ptr: UnsafeMutableRawPointer?,\n    _ oldSize: Int,\n    _ newSize: Int\n) -> UnsafeMutableRawPointer? {\n    testDecoderIsNotQuadratic_reallocs.withLockedValue { $0 += 1 }\n    return realloc(ptr, newSize)\n}\n\nprivate func testDecoderIsNotQuadratic_memcpyHook(_ dst: UnsafeMutableRawPointer, _ src: UnsafeRawPointer, _ count: Int)\n{\n    _ = memcpy(dst, src, count)\n}\n\nprivate final class ChannelInactivePromiser: ChannelInboundHandler {\n    typealias InboundIn = Any\n\n    let channelInactivePromise: EventLoopPromise<Void>\n\n    init(channel: Channel) {\n        channelInactivePromise = channel.eventLoop.makePromise()\n    }\n\n    func channelInactive(context: ChannelHandlerContext) {\n        channelInactivePromise.succeed(())\n    }\n}\n\nfinal class ByteToMessageDecoderTest: XCTestCase {\n    private final class ByteToInt32Decoder: ByteToMessageDecoder {\n        typealias InboundIn = ByteBuffer\n        typealias InboundOut = Int32\n\n        func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) -> DecodingState {\n            guard buffer.readableBytes >= MemoryLayout<Int32>.size else {\n                return .needMoreData\n            }\n            context.fireChannelRead(Self.wrapInboundOut(buffer.readInteger()!))\n            return .continue\n        }\n\n        func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState\n        {\n            XCTAssertTrue(seenEOF)\n            return self.decode(context: context, buffer: &buffer)\n        }\n    }\n\n    private final class ForeverDecoder: ByteToMessageDecoder {\n        typealias InboundIn = ByteBuffer\n        typealias InboundOut = Never\n\n        func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) -> DecodingState {\n            .needMoreData\n        }\n\n        func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState\n        {\n            XCTAssertTrue(seenEOF)\n            return self.decode(context: context, buffer: &buffer)\n        }\n    }\n\n    private final class LargeChunkDecoder: ByteToMessageDecoder {\n        typealias InboundIn = ByteBuffer\n        typealias InboundOut = ByteBuffer\n\n        func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) -> DecodingState {\n            guard case .some(let buffer) = buffer.readSlice(length: 512) else {\n                return .needMoreData\n            }\n\n            context.fireChannelRead(Self.wrapInboundOut(buffer))\n            return .continue\n        }\n\n        func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState\n        {\n            XCTAssertTrue(seenEOF)\n            return self.decode(context: context, buffer: &buffer)\n        }\n    }\n\n    // A special case decoder that decodes only once there is 5,120 bytes in the buffer,\n    // at which point it decodes exactly 2kB of memory.\n    private final class OnceDecoder: ByteToMessageDecoder {\n        typealias InboundIn = ByteBuffer\n        typealias InboundOut = ByteBuffer\n\n        func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) -> DecodingState {\n            guard buffer.readableBytes >= 5120 else {\n                return .needMoreData\n            }\n\n            context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: 2048)!))\n            return .continue\n        }\n\n        func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState\n        {\n            XCTAssertTrue(seenEOF)\n            return self.decode(context: context, buffer: &buffer)\n        }\n    }\n\n    func testDecoder() throws {\n        let channel = EmbeddedChannel()\n\n        _ = try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(ByteToInt32Decoder()))\n\n        var buffer = channel.allocator.buffer(capacity: 32)\n        buffer.writeInteger(Int32(1))\n        let writerIndex = buffer.writerIndex\n        buffer.moveWriterIndex(to: writerIndex - 1)\n\n        channel.pipeline.fireChannelRead(buffer)\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        buffer.moveWriterIndex(to: writerIndex)\n        channel.pipeline.fireChannelRead(buffer.getSlice(at: writerIndex - 1, length: 1)!)\n\n        var buffer2 = channel.allocator.buffer(capacity: 32)\n        buffer2.writeInteger(Int32(2))\n        buffer2.writeInteger(Int32(3))\n        channel.pipeline.fireChannelRead(buffer2)\n\n        XCTAssertNoThrow(try channel.finish())\n\n        XCTAssertNoThrow(XCTAssertEqual(Int32(1), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(Int32(2), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(Int32(3), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testDecoderPropagatesChannelInactive() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n        let inactivePromiser = ChannelInactivePromiser(channel: channel)\n        try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(ByteToInt32Decoder()))\n        try channel.pipeline.syncOperations.addHandler(inactivePromiser)\n\n        var buffer = channel.allocator.buffer(capacity: 32)\n        buffer.writeInteger(Int32(1))\n        channel.pipeline.fireChannelRead(buffer)\n        XCTAssertNoThrow(XCTAssertEqual(Int32(1), try channel.readInbound()))\n\n        XCTAssertFalse(inactivePromiser.channelInactivePromise.futureResult.isFulfilled)\n\n        channel.pipeline.fireChannelInactive()\n        XCTAssertTrue(inactivePromiser.channelInactivePromise.futureResult.isFulfilled)\n    }\n\n    func testDecoderIsNotQuadratic() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        XCTAssertEqual(testDecoderIsNotQuadratic_mallocs.withLockedValue { $0 }, 0)\n        XCTAssertEqual(testDecoderIsNotQuadratic_reallocs.withLockedValue { $0 }, 0)\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(ForeverDecoder())))\n\n        let dummyAllocator = ByteBufferAllocator(\n            allocate: testDecoderIsNotQuadratic_mallocHook,\n            reallocate: testDecoderIsNotQuadratic_reallocHook,\n            deallocate: testDecoderIsNotQuadratic_freeHook,\n            copy: testDecoderIsNotQuadratic_memcpyHook\n        )\n        channel.allocator = dummyAllocator\n        var inputBuffer = dummyAllocator.buffer(capacity: 8)\n        inputBuffer.writeStaticString(\"whatwhat\")\n\n        for _ in 0..<10 {\n            channel.pipeline.fireChannelRead(inputBuffer)\n        }\n\n        // We get one extra malloc the first time around the loop, when we have aliased the buffer. From then on it's\n        // all reallocs of the underlying buffer.\n        XCTAssertEqual(testDecoderIsNotQuadratic_mallocs.withLockedValue { $0 }, 2)\n        XCTAssertEqual(testDecoderIsNotQuadratic_reallocs.withLockedValue { $0 }, 3)\n    }\n\n    func testMemoryIsReclaimedIfMostIsConsumed() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        let decoder = ByteToMessageHandler(LargeChunkDecoder())\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n\n        // We're going to send in 513 bytes. This will cause a chunk to be passed on, and will leave\n        // a 512-byte empty region in a byte buffer with a capacity of 1024 bytes. Since 512 empty\n        // bytes are exactly 50% of the buffers capacity and not one tiny bit more, the empty space\n        // will not be reclaimed.\n        var buffer = channel.allocator.buffer(capacity: 513)\n        buffer.writeBytes(Array(repeating: 0x04, count: 513))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.writeInbound(buffer).isFull))\n        XCTAssertNoThrow(XCTAssertEqual(ByteBuffer(repeating: 0x04, count: 512), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertEqual(decoder.cumulationBuffer!.capacity, 1024)\n        XCTAssertEqual(decoder.cumulationBuffer!.readableBytes, 1)\n        XCTAssertEqual(decoder.cumulationBuffer!.readerIndex, 512)\n\n        // Next we're going to send in another 513 bytes. This will cause another chunk to be passed\n        // into our decoder buffer, which has a capacity of 1024 bytes, before we pass in another\n        // 513 bytes. Since we already have written to 513 bytes, there isn't enough space in the\n        // buffer, which will cause a resize to a new underlying storage with 2048 bytes. Since the\n        // `LargeChunkDecoder` has consumed another 512 bytes, there are now two bytes left to read\n        // (513 + 513) - (512 + 512). The reader index is at 1024. The empty space has not been\n        // reclaimed: While the capacity is more than 1024 bytes (2048 bytes), the reader index is\n        // now at 1024. This means the buffer is exactly 50% consumed and not a tiny bit more, which\n        // means no space will be reclaimed.\n        XCTAssertNoThrow(XCTAssertTrue(try channel.writeInbound(buffer).isFull))\n        XCTAssertNoThrow(XCTAssertEqual(ByteBuffer(repeating: 0x04, count: 512), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertEqual(decoder.cumulationBuffer!.capacity, 2048)\n        XCTAssertEqual(decoder.cumulationBuffer!.readableBytes, 2)\n        XCTAssertEqual(decoder.cumulationBuffer!.readerIndex, 1024)\n\n        // Finally we're going to send in another 513 bytes. This will cause another chunk to be\n        // passed into our decoder buffer, which has a capacity of 2048 bytes. Since the buffer has\n        // enough available space (1022 bytes) there will be no buffer resize before the decoding.\n        // After the decoding of another 512 bytes, the buffer will have 1536 empty bytes\n        // (3 * 512 bytes). This means that 75% of the buffer's capacity can now be reclaimed, which\n        // will lead to a reclaim. The resulting buffer will have a capacity of 2048 bytes (based\n        // on its previous growth), with 3 readable bytes remaining.\n        XCTAssertNoThrow(XCTAssertTrue(try channel.writeInbound(buffer).isFull))\n        XCTAssertNoThrow(XCTAssertEqual(ByteBuffer(repeating: 0x04, count: 512), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertEqual(decoder.cumulationBuffer!.capacity, 2048)\n        XCTAssertEqual(decoder.cumulationBuffer!.readableBytes, 3)\n        XCTAssertEqual(decoder.cumulationBuffer!.readerIndex, 0)\n    }\n\n    func testMemoryIsReclaimedIfLotsIsAvailable() {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        let decoder = ByteToMessageHandler(OnceDecoder())\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(decoder))\n\n        // We're going to send in 5119 bytes. This will be held.\n        var buffer = channel.allocator.buffer(capacity: 5119)\n        buffer.writeBytes(Array(repeating: 0x04, count: 5119))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.writeInbound(buffer).isEmpty))\n\n        XCTAssertEqual(decoder.cumulationBuffer!.readableBytes, 5119)\n        XCTAssertEqual(decoder.cumulationBuffer!.readerIndex, 0)\n\n        // Now we're going to send in one more byte. This will cause a chunk to be passed on,\n        // shrinking the held memory to 3072 bytes. However, memory will be reclaimed.\n        XCTAssertNoThrow(XCTAssertTrue(try channel.writeInbound(buffer.getSlice(at: 0, length: 1)).isFull))\n        XCTAssertNoThrow(XCTAssertEqual(ByteBuffer(repeating: 0x04, count: 2048), try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertEqual(decoder.cumulationBuffer!.readableBytes, 3072)\n        XCTAssertEqual(decoder.cumulationBuffer!.readerIndex, 0)\n    }\n\n    func testWeDoNotCallShouldReclaimMemoryAsLongAsWeContinue() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            var numberOfDecodeCalls = 0\n            var numberOfShouldReclaimCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.numberOfDecodeCalls += 1\n\n                guard\n                    buffer.readSlice(\n                        length: [\n                            2048, 1024, 512, 256,\n                            128, 64, .max,\n                        ][self.numberOfDecodeCalls - 1]\n                    ) != nil\n                else {\n                    return .needMoreData\n                }\n\n                XCTAssertEqual(0, self.numberOfShouldReclaimCalls)\n                return .continue\n            }\n\n            func shouldReclaimBytes(buffer: ByteBuffer) -> Bool {\n                XCTAssertEqual(7, self.numberOfDecodeCalls)\n                XCTAssertEqual(64, buffer.readableBytes)\n                self.numberOfShouldReclaimCalls += 1\n\n                return false\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertEqual(64, buffer.readableBytes)\n                XCTAssertTrue(seenEOF)\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        let buffer = ByteBuffer(repeating: 0, count: 4096)\n        XCTAssertEqual(4096, buffer.storageCapacity)\n\n        // We're sending 4096 bytes. The decoder will do:\n        // 1. read 2048 -> .continue\n        // 2. read 1024 -> .continue\n        // 3. read 512 -> .continue\n        // 4. read 256 -> .continue\n        // 5. read 128 -> .continue\n        // 6. read 64 -> .continue\n        // 7. read Int.max -> .needMoreData\n        //\n        // So we're expecting 7 decode calls but only 1 call to shouldReclaimBytes (at the end).\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertEqual(7, decoder.numberOfDecodeCalls)\n        XCTAssertEqual(1, decoder.numberOfShouldReclaimCalls)\n    }\n\n    func testDecoderReentranceChannelRead() throws {\n        let channel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try channel.finish())\n        }\n\n        class TestDecoder: ByteToMessageDecoder {\n\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            var numberOfDecodeCalls = 0\n            var hasReentranced = false\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.numberOfDecodeCalls += 1\n                var reentrantWriteBuffer = context.channel.allocator.buffer(capacity: 1)\n                if self.numberOfDecodeCalls == 2 {\n                    // this is the first time, let's fireChannelRead\n                    self.hasReentranced = true\n                    reentrantWriteBuffer.clear()\n                    reentrantWriteBuffer.writeStaticString(\"3\")\n                    context.channel.pipeline.syncOperations.fireChannelRead(Self.wrapInboundOut(reentrantWriteBuffer))\n                }\n                context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: 1)!))\n                if self.numberOfDecodeCalls == 2 {\n                    reentrantWriteBuffer.clear()\n                    reentrantWriteBuffer.writeStaticString(\"4\")\n                    context.channel.pipeline.syncOperations.fireChannelRead(Self.wrapInboundOut(reentrantWriteBuffer))\n                }\n                return .continue\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                return .needMoreData\n            }\n        }\n\n        let testDecoder = TestDecoder()\n\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(testDecoder)))\n\n        var inputBuffer = channel.allocator.buffer(capacity: 4)\n        // 1\n        inputBuffer.writeStaticString(\"1\")\n        XCTAssertTrue(try channel.writeInbound(inputBuffer).isFull)\n        inputBuffer.clear()\n\n        // 2\n        inputBuffer.writeStaticString(\"2\")\n        XCTAssertTrue(try channel.writeInbound(inputBuffer).isFull)\n        inputBuffer.clear()\n\n        // 3\n        inputBuffer.writeStaticString(\"5\")\n        XCTAssertTrue(try channel.writeInbound(inputBuffer).isFull)\n        inputBuffer.clear()\n\n        func readOneInboundString() -> String {\n            do {\n                switch try channel.readInbound(as: ByteBuffer.self) {\n                case .some(let buffer):\n                    return String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self)\n                case .none:\n                    XCTFail(\"expected ByteBuffer found nothing\")\n                    return \"no, error from \\(#line)\"\n                }\n            } catch {\n                XCTFail(\"unexpected error: \\(error)\")\n                return \"no, error from \\(#line)\"\n            }\n        }\n\n        channel.embeddedEventLoop.run()\n        XCTAssertEqual(\"1\", readOneInboundString())\n        XCTAssertEqual(\"2\", readOneInboundString())\n        XCTAssertEqual(\"3\", readOneInboundString())\n        XCTAssertEqual(\"4\", readOneInboundString())\n        XCTAssertEqual(\"5\", readOneInboundString())\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound(as: IOData.self)))\n        XCTAssertTrue(testDecoder.hasReentranced)\n    }\n\n    func testTrivialDecoderDoesSensibleStuffWhenCloseInRead() {\n        class HandItThroughDecoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            var decodeLastCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                let originalBuffer = buffer\n                context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: buffer.readableBytes)!))\n                if originalBuffer.readableBytesView.last == \"0\".utf8.last {\n                    context.close().whenFailure { error in\n                        XCTFail(\"unexpected error: \\(error)\")\n                    }\n                }\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                self.decodeLastCalls += 1\n                XCTAssertEqual(1, self.decodeLastCalls)\n                return .needMoreData\n            }\n        }\n\n        let decoder = HandItThroughDecoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        XCTAssertTrue(channel.isActive)\n\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.clear()\n        buffer.writeStaticString(\"1\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"23\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"4567890\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        channel.embeddedEventLoop.run()\n        XCTAssertFalse(channel.isActive)\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"1\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"23\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"4567890\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testLeftOversMakeDecodeLastCalled() {\n        let lastPromise = EmbeddedEventLoop().makePromise(of: ByteBuffer.self)\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(PairOfBytesDecoder(lastPromise: lastPromise)))\n\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.clear()\n        buffer.writeStaticString(\"1\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"23\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"4567890x\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(try channel.close().wait())\n        XCTAssertFalse(channel.isActive)\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"12\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"34\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"56\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"78\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"90\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"x\",\n                String(\n                    decoding: try lastPromise.futureResult.wait().readableBytesView,\n                    as: Unicode.UTF8.self\n                )\n            )\n        )\n    }\n\n    func testRemovingHandlerMakesLeftoversAppearInDecodeLast() {\n        let lastPromise = EmbeddedEventLoop().makePromise(of: ByteBuffer.self)\n        let decoder = PairOfBytesDecoder(lastPromise: lastPromise)\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.clear()\n        buffer.writeStaticString(\"1\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"23\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"4567890x\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        channel.pipeline.context(handlerType: ByteToMessageHandler<PairOfBytesDecoder>.self).flatMap { context in\n            channel.pipeline.syncOperations.removeHandler(context: context)\n        }.whenFailure { error in\n            XCTFail(\"unexpected error: \\(error)\")\n        }\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"12\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"34\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"56\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"78\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"90\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        channel.embeddedEventLoop.run()\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"x\",\n                String(\n                    decoding: try lastPromise.futureResult.wait().readableBytesView,\n                    as: Unicode.UTF8.self\n                )\n            )\n        )\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testStructsWorkAsByteToMessageDecoders() {\n        struct WantsOneThenTwoBytesDecoder: ByteToMessageDecoder {\n            typealias InboundOut = Int\n\n            var state: Int = 1\n\n            mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                if buffer.readSlice(length: self.state) != nil {\n                    defer {\n                        self.state += 1\n                    }\n                    context.fireChannelRead(Self.wrapInboundOut(self.state))\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            mutating func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                context.fireChannelRead(Self.wrapInboundOut(buffer.readableBytes * -1))\n                return .needMoreData\n            }\n        }\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(WantsOneThenTwoBytesDecoder()))\n\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.clear()\n        buffer.writeStaticString(\"1\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"23\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"4567890qwer\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertNoThrow(XCTAssertEqual(1, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(2, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(3, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(4, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertNoThrow(try channel.close().wait())\n        XCTAssertFalse(channel.isActive)\n\n        XCTAssertNoThrow(XCTAssertEqual(-4, try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testReentrantChannelReadWhileWholeBufferIsBeingProcessed() {\n        struct ProcessAndReentrantylyProcessExponentiallyLessStuffDecoder: ByteToMessageDecoder {\n            typealias InboundOut = String\n            var state = 16\n\n            mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTAssertGreaterThan(self.state, 0)\n                if let slice = buffer.readSlice(length: self.state) {\n                    self.state >>= 1\n                    for i in 0..<self.state {\n                        XCTAssertNoThrow(\n                            try (context.channel as! EmbeddedChannel).writeInbound(slice.getSlice(at: i, length: 1))\n                        )\n                    }\n                    context.fireChannelRead(\n                        Self.wrapInboundOut(String(decoding: slice.readableBytesView, as: Unicode.UTF8.self))\n                    )\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            mutating func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                return try self.decode(context: context, buffer: &buffer)\n            }\n        }\n        let channel = EmbeddedChannel(\n            handler: ByteToMessageHandler(ProcessAndReentrantylyProcessExponentiallyLessStuffDecoder())\n        )\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"0123456789abcdef\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertNoThrow(XCTAssertEqual(\"0123456789abcdef\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"01234567\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"0123\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"01\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"0\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testReentrantChannelCloseInChannelRead() {\n        struct Take16BytesThenCloseAndPassOnDecoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                if let slice = buffer.readSlice(length: 16) {\n                    context.fireChannelRead(Self.wrapInboundOut(slice))\n                    context.channel.close().whenFailure { error in\n                        XCTFail(\"unexpected error: \\(error)\")\n                    }\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            mutating func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                context.fireChannelRead(Self.wrapInboundOut(buffer))\n                return .needMoreData\n            }\n        }\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(Take16BytesThenCloseAndPassOnDecoder()))\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"0123456789abcdefQWER\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"0123456789abcdef\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"QWER\",\n                try channel.readInbound(as: ByteBuffer.self).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testHandlerRemoveInChannelRead() {\n        struct Take16BytesThenCloseAndPassOnDecoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                if let slice = buffer.readSlice(length: 16) {\n                    context.fireChannelRead(Self.wrapInboundOut(slice))\n                    context.pipeline.syncOperations.removeHandler(context: context).whenFailure { error in\n                        XCTFail(\"unexpected error: \\(error)\")\n                    }\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            mutating func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertFalse(seenEOF)\n                context.fireChannelRead(Self.wrapInboundOut(buffer))\n                return .needMoreData\n            }\n        }\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(Take16BytesThenCloseAndPassOnDecoder()))\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"0123456789abcdefQWER\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertEqual(\n            \"0123456789abcdef\",\n            (try channel.readInbound() as ByteBuffer?).map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        channel.embeddedEventLoop.run()\n        XCTAssertEqual(\n            \"QWER\",\n            (try channel.readInbound() as ByteBuffer?).map {\n                String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n            }\n        )\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testChannelCloseInChannelRead() {\n        struct Take16BytesThenCloseAndPassOnDecoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                if let slice = buffer.readSlice(length: 16) {\n                    context.fireChannelRead(Self.wrapInboundOut(slice))\n                    context.close().whenFailure { error in\n                        XCTFail(\"unexpected error: \\(error)\")\n                    }\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            mutating func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                return .needMoreData\n            }\n        }\n        class DoNotForwardChannelInactiveHandler: ChannelInboundHandler {\n            typealias InboundIn = Never\n\n            func channelInactive(context: ChannelHandlerContext) {\n                // just eat this event\n            }\n        }\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(Take16BytesThenCloseAndPassOnDecoder()))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(DoNotForwardChannelInactiveHandler(), position: .first)\n        )\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"0123456789abcdefQWER\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                \"0123456789abcdef\",\n                (try channel.readInbound() as ByteBuffer?).map {\n                    String(decoding: $0.readableBytesView, as: Unicode.UTF8.self)\n                }\n            )\n        )\n        channel.embeddedEventLoop.run()\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))  // no leftovers are forwarded\n    }\n\n    func testDecodeLoopGetsInterruptedWhenRemovalIsTriggered() {\n        struct Decoder: ByteToMessageDecoder {\n            typealias InboundOut = String\n\n            var callsToDecode = 0\n            var callsToDecodeLast = 0\n\n            mutating func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTAssertEqual(9, buffer.readableBytes)\n                self.callsToDecode += 1\n                XCTAssertEqual(1, self.callsToDecode)\n                context.fireChannelRead(\n                    Self.wrapInboundOut(\n                        String(\n                            decoding: buffer.readBytes(length: 1)!,\n                            as: Unicode.UTF8.self\n                        )\n                    )\n                )\n                context.pipeline.syncOperations.removeHandler(context: context).whenFailure { error in\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n                return .continue\n            }\n\n            mutating func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertFalse(seenEOF)\n                self.callsToDecodeLast += 1\n                XCTAssertLessThanOrEqual(self.callsToDecodeLast, 2)\n                context.fireChannelRead(\n                    Self.wrapInboundOut(\n                        String(\n                            decoding: buffer.readBytes(length: 4) ?? [  // \"no bytes\"\n                                0x6e, 0x6f, 0x20,\n                                0x62, 0x79, 0x74, 0x65, 0x73,\n                            ],\n                            as: Unicode.UTF8.self\n                        ) + \"#\\(self.callsToDecodeLast)\"\n                    )\n                )\n                return .continue\n            }\n        }\n\n        let handler = ByteToMessageHandler(Decoder())\n        let channel = EmbeddedChannel(handler: handler)\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n\n        var buffer = channel.allocator.buffer(capacity: 9)\n        buffer.writeStaticString(\"012345678\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        channel.embeddedEventLoop.run()\n        XCTAssertEqual(1, handler.decoder?.callsToDecode)\n        XCTAssertEqual(2, handler.decoder?.callsToDecodeLast)\n        for expected in [\"0\", \"1234#1\", \"5678#2\"] {\n            func workaroundSR9815() {\n                XCTAssertNoThrow(XCTAssertEqual(expected, try channel.readInbound()))\n            }\n            workaroundSR9815()\n        }\n    }\n\n    func testDecodeLastIsInvokedOnceEvenIfNothingEverArrivedOnChannelClosed() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ()\n            var decodeLastCalls = 0\n\n            public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTFail(\"did not expect to see decode called\")\n                return .needMoreData\n            }\n\n            public func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                self.decodeLastCalls += 1\n                XCTAssertEqual(1, self.decodeLastCalls)\n                XCTAssertEqual(0, buffer.readableBytes)\n                context.fireChannelRead(Self.wrapInboundOut(()))\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertNoThrow(try channel.close().wait())\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testDecodeLastIsInvokedOnceEvenIfNothingEverArrivedOnChannelHalfClosure() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ()\n            var decodeLastCalls = 0\n\n            public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTFail(\"did not expect to see decode called\")\n                return .needMoreData\n            }\n\n            public func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertTrue(seenEOF)\n                self.decodeLastCalls += 1\n                XCTAssertEqual(1, self.decodeLastCalls)\n                XCTAssertEqual(0, buffer.readableBytes)\n                context.fireChannelRead(Self.wrapInboundOut(()))\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        XCTAssertNoThrow(XCTAssertNotNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testDecodeLastHasSeenEOFFalseOnHandlerRemoved() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ()\n            var decodeLastCalls = 0\n\n            public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTAssertEqual(1, buffer.readableBytes)\n                return .needMoreData\n            }\n\n            public func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                XCTAssertEqual(1, buffer.readableBytes)\n                XCTAssertEqual(1, self.decodeLastCalls)\n                XCTAssertFalse(seenEOF)\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"x\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        let removalFuture = channel.pipeline.context(handlerType: ByteToMessageHandler<Decoder>.self).flatMap {\n            channel.pipeline.syncOperations.removeHandler(context: $0)\n        }\n        channel.embeddedEventLoop.run()\n        XCTAssertNoThrow(try removalFuture.wait())\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testDecodeLastHasSeenEOFFalseOnHandlerRemovedEvenIfNoData() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ()\n            var decodeLastCalls = 0\n\n            public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTFail(\"shouldn't have been called\")\n                return .needMoreData\n            }\n\n            public func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                XCTAssertEqual(0, buffer.readableBytes)\n                XCTAssertEqual(1, self.decodeLastCalls)\n                XCTAssertFalse(seenEOF)\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        let removalFuture = channel.pipeline.context(handlerType: ByteToMessageHandler<Decoder>.self).flatMap {\n            channel.pipeline.syncOperations.removeHandler(context: $0)\n        }\n        channel.embeddedEventLoop.run()\n        XCTAssertNoThrow(try removalFuture.wait())\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testDecodeLastHasSeenEOFTrueOnChannelInactive() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ()\n            var decodeLastCalls = 0\n\n            public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTAssertEqual(1, buffer.readableBytes)\n                return .needMoreData\n            }\n\n            public func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                XCTAssertEqual(1, buffer.readableBytes)\n                XCTAssertEqual(1, self.decodeLastCalls)\n                XCTAssertTrue(seenEOF)\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"x\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testWriteObservingByteToMessageDecoderBasic() {\n        class Decoder: WriteObservingByteToMessageDecoder {\n            typealias OutboundIn = Int\n            typealias InboundOut = String\n\n            var allObservedWrites: [Int] = []\n\n            func write(data: Int) {\n                self.allObservedWrites.append(data)\n            }\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                if let string = buffer.readString(length: 1) {\n                    context.fireChannelRead(Self.wrapInboundOut(string))\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                while case .continue = try self.decode(context: context, buffer: &buffer) {}\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 3)\n        buffer.writeStaticString(\"abc\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(try channel.writeOutbound(1))\n        XCTAssertNoThrow(try channel.writeOutbound(2))\n        XCTAssertNoThrow(try channel.writeOutbound(3))\n        XCTAssertEqual([1, 2, 3], decoder.allObservedWrites)\n        XCTAssertNoThrow(XCTAssertEqual(\"a\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"b\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"c\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(1, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(2, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(3, try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testWriteObservingByteToMessageDecoderWhereWriteIsReentrantlyCalled() {\n        class Decoder: WriteObservingByteToMessageDecoder {\n            typealias OutboundIn = String\n            typealias InboundOut = String\n\n            var allObservedWrites: [String] = []\n            var decodeRun = 0\n\n            func write(data: String) {\n                self.allObservedWrites.append(data)\n            }\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeRun += 1\n                if let string = buffer.readString(length: 1) {\n                    context.fireChannelRead(Self.wrapInboundOut(\"I: \\(self.decodeRun): \\(string)\"))\n                    XCTAssertNoThrow(\n                        try (context.channel as! EmbeddedChannel).writeOutbound(\"O: \\(self.decodeRun): \\(string)\")\n                    )\n                    if self.decodeRun == 1 {\n                        var buffer = context.channel.allocator.buffer(capacity: 1)\n                        buffer.writeStaticString(\"X\")\n                        XCTAssertNoThrow(try (context.channel as! EmbeddedChannel).writeInbound(buffer))\n                    }\n                    return .continue\n                } else {\n                    return .needMoreData\n                }\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                while case .continue = try self.decode(context: context, buffer: &buffer) {}\n                return .needMoreData\n            }\n        }\n\n        class CheckStateOfDecoderHandler: ChannelOutboundHandler {\n            typealias OutboundIn = String\n            typealias OutboundOut = String\n\n            private let decoder: Decoder\n\n            init(decoder: Decoder) {\n                self.decoder = decoder\n            }\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                let string = Self.unwrapOutboundIn(data)\n                context.write(Self.wrapOutboundOut(\"\\(string) @ \\(decoder.decodeRun)\"), promise: promise)\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(\n                CheckStateOfDecoderHandler(decoder: decoder),\n                position: .first\n            )\n        )\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 3)\n        XCTAssertNoThrow(try channel.writeOutbound(\"before\"))\n        buffer.writeStaticString(\"ab\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        buffer.clear()\n        buffer.writeStaticString(\"xyz\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(try channel.writeOutbound(\"after\"))\n        XCTAssertEqual(\n            [\"before\", \"O: 1: a\", \"O: 2: b\", \"O: 3: X\", \"O: 4: x\", \"O: 5: y\", \"O: 6: z\", \"after\"],\n            decoder.allObservedWrites\n        )\n        XCTAssertNoThrow(XCTAssertEqual(\"I: 1: a\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"I: 2: b\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"I: 3: X\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"I: 4: x\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"I: 5: y\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"I: 6: z\", try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"before @ 0\", try channel.readOutbound()))\n        // in the next line, it's important that it ends in '@ 1' because that means the outbound write was forwarded\n        // when the Decoder was after decode run 1, ie. before it ever saw the 'b'. It's important we forward writes\n        // as soon as possible for correctness but also to keep as few queued writes as possible.\n        XCTAssertNoThrow(XCTAssertEqual(\"O: 1: a @ 1\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"O: 2: b @ 2\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"O: 3: X @ 3\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"O: 4: x @ 4\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"O: 5: y @ 5\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"O: 6: z @ 6\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertEqual(\"after @ 6\", try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testDecodeMethodsNoLongerCalledIfErrorInDecode() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            struct DecodeError: Error {}\n\n            private var errorThrownAlready = false\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTAssertFalse(self.errorThrownAlready)\n                self.errorThrownAlready = true\n                throw DecodeError()\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTFail(\"decodeLast should never be called\")\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n\n        var buffer = channel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"x\")\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssert(error is Decoder.DecodeError)\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            if case .some(ByteToMessageDecoderError.dataReceivedInErrorState(let error, let receivedBuffer)) =\n                error as? ByteToMessageDecoderError\n            {\n                XCTAssert(error is Decoder.DecodeError)\n                XCTAssertEqual(buffer, receivedBuffer)\n            } else {\n                XCTFail(\"wrong error: \\(error)\")\n            }\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n    }\n\n    func testDecodeMethodsNoLongerCalledIfErrorInDecodeLast() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            struct DecodeError: Error {}\n\n            private var errorThrownAlready = false\n            private var decodeCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeCalls += 1\n                XCTAssertEqual(1, self.decodeCalls)\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertFalse(self.errorThrownAlready)\n                self.errorThrownAlready = true\n                throw DecodeError()\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n\n        var buffer = channel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"x\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        XCTAssertThrowsError(try channel.finish()) { error in\n            XCTAssert(error is Decoder.DecodeError)\n        }\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        // this will go through because the decoder is already 'done'\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n    }\n\n    func testBasicLifecycle() {\n        class Decoder: ByteToMessageDecoder {\n            enum State {\n                case constructed\n                case added\n                case decode\n                case decodeLast\n                case removed\n            }\n            var state = State.constructed\n\n            typealias InboundOut = ()\n\n            func decoderAdded(context: ChannelHandlerContext) {\n                XCTAssertEqual(.constructed, self.state)\n                self.state = .added\n            }\n\n            func decoderRemoved(context: ChannelHandlerContext) {\n                XCTAssertEqual(.decodeLast, self.state)\n                self.state = .removed\n            }\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTAssertEqual(.added, self.state)\n                XCTAssertEqual(1, buffer.readableBytes)\n                self.state = .decode\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertEqual(.decode, self.state)\n                XCTAssertEqual(1, buffer.readableBytes)\n                self.state = .decodeLast\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"x\")\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(try channel.finish())\n        XCTAssertEqual(.removed, decoder.state)\n    }\n\n    func testDecodeLoopStopsOnChannelInactive() {\n        class CloseAfterThreeMessagesDecoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            var decodeCalls = 0\n            var decodeLastCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeCalls += 1\n                XCTAssert(buffer.readableBytes > 0)\n                context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: 1)!))\n                if self.decodeCalls == 3 {\n                    context.close(promise: nil)\n                }\n                return .continue\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                if buffer.readableBytes > 0 {\n                    context.fireErrorCaught(ByteToMessageDecoderError.leftoverDataWhenDone(buffer))\n                }\n                return .needMoreData\n            }\n        }\n\n        let decoder = CloseAfterThreeMessagesDecoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        defer {\n            XCTAssertFalse(channel.isActive)\n        }\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"0123456\")\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            if case .some(.leftoverDataWhenDone(let buffer)) = error as? ByteToMessageDecoderError {\n                XCTAssertEqual(\"3456\", buffer.getString(at: buffer.readerIndex, length: buffer.readableBytes))\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n        for i in 0..<3 {\n            buffer.clear()\n            buffer.writeString(\"\\(i)\")\n            XCTAssertNoThrow(XCTAssertEqual(buffer, try channel.readInbound(as: ByteBuffer.self)))\n        }\n        XCTAssertEqual(3, decoder.decodeCalls)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testDecodeLoopStopsOnInboundHalfClosure() {\n        class CloseAfterThreeMessagesDecoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            var decodeCalls = 0\n            var decodeLastCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeCalls += 1\n                XCTAssert(buffer.readableBytes > 0)\n                context.fireChannelRead(Self.wrapInboundOut(buffer.readSlice(length: 1)!))\n                if self.decodeCalls == 3 {\n                    context.channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n                }\n                return .continue\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                if buffer.readableBytes > 0 {\n                    context.fireErrorCaught(ByteToMessageDecoderError.leftoverDataWhenDone(buffer))\n                }\n                return .needMoreData\n            }\n        }\n\n        let decoder = CloseAfterThreeMessagesDecoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        defer {\n            XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        }\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"0123456\")\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            if case .some(.leftoverDataWhenDone(let buffer)) = error as? ByteToMessageDecoderError {\n                XCTAssertEqual(\"3456\", buffer.getString(at: buffer.readerIndex, length: buffer.readableBytes))\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n        for i in 0..<3 {\n            buffer.clear()\n            buffer.writeString(\"\\(i)\")\n            XCTAssertNoThrow(XCTAssertEqual(buffer, try channel.readInbound(as: ByteBuffer.self)))\n        }\n        XCTAssertEqual(3, decoder.decodeCalls)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n    }\n\n    func testWeForwardReadEOFAndChannelInactive() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            var decodeLastCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTFail(\"should not have been called\")\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                XCTAssertEqual(self.decodeLastCalls, 1)\n                XCTAssertTrue(seenEOF)\n                XCTAssertEqual(0, buffer.readableBytes)\n                return .needMoreData\n            }\n        }\n\n        class CheckThingsAreOkayHandler: ChannelInboundHandler {\n            typealias InboundIn = Never\n\n            var readEOFEvents = 0\n            var channelInactiveEvents = 0\n\n            func channelInactive(context: ChannelHandlerContext) {\n                self.channelInactiveEvents += 1\n                XCTAssertEqual(1, self.channelInactiveEvents)\n            }\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                if let event = event as? ChannelEvent, event == .inputClosed {\n                    self.readEOFEvents += 1\n                    XCTAssertEqual(1, self.readEOFEvents)\n                }\n            }\n        }\n\n        let decoder = Decoder()\n        let checker = CheckThingsAreOkayHandler()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(checker))\n        XCTAssertNoThrow(try channel.connect(to: SocketAddress(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertEqual(0, checker.channelInactiveEvents)\n        XCTAssertEqual(1, checker.readEOFEvents)\n        XCTAssertNoThrow(try channel.pipeline.close().wait())\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertEqual(1, checker.channelInactiveEvents)\n        XCTAssertEqual(1, checker.readEOFEvents)\n    }\n\n    func testErrorInDecodeLastWhenCloseIsReceivedReentrantlyInDecode() {\n        struct DummyError: Error {}\n        struct Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                // simulate a re-entrant trigger of reading EOF\n                context.channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertEqual(\"X\", buffer.readString(length: buffer.readableBytes))\n                throw DummyError()\n            }\n        }\n\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(Decoder()))\n        var buffer = channel.allocator.buffer(capacity: 1)\n        buffer.writeString(\"X\")\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertTrue(error is DummyError)\n        }\n    }\n\n    func testWeAreOkayWithReceivingDataAfterHalfClosureEOF() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            var decodeCalls = 0\n            var decodeLastCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeCalls += 1\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                return .needMoreData\n            }\n        }\n\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"abc\")\n\n        XCTAssertEqual(0, decoder.decodeCalls)\n        XCTAssertEqual(0, decoder.decodeLastCalls)\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertEqual(1, decoder.decodeCalls)\n        XCTAssertEqual(0, decoder.decodeLastCalls)\n        channel.pipeline.fireUserInboundEventTriggered(ChannelEvent.inputClosed)\n        XCTAssertEqual(1, decoder.decodeCalls)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertEqual(1, decoder.decodeCalls)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testWeAreOkayWithReceivingDataAfterFullClose() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            var decodeCalls = 0\n            var decodeLastCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeCalls += 1\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeLastCalls += 1\n                return .needMoreData\n            }\n        }\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder))\n        var buffer = channel.allocator.buffer(capacity: 16)\n        buffer.writeStaticString(\"abc\")\n\n        XCTAssertEqual(0, decoder.decodeCalls)\n        XCTAssertEqual(0, decoder.decodeLastCalls)\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertEqual(1, decoder.decodeCalls)\n        XCTAssertEqual(0, decoder.decodeLastCalls)\n        XCTAssertTrue(try channel.finish().isClean)\n        XCTAssertEqual(1, decoder.decodeCalls)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertEqual(1, decoder.decodeCalls)\n        XCTAssertEqual(1, decoder.decodeLastCalls)\n    }\n\n    func testPayloadTooLarge() {\n        struct Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                .needMoreData\n            }\n        }\n\n        let max = 100\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(Decoder(), maximumBufferSize: max))\n        var buffer = channel.allocator.buffer(capacity: max + 1)\n        buffer.writeString(String(repeating: \"*\", count: max + 1))\n        XCTAssertThrowsError(try channel.writeInbound(buffer)) { error in\n            XCTAssertTrue(error is ByteToMessageDecoderError.PayloadTooLargeError)\n        }\n    }\n\n    func testPayloadTooLargeButHandlerOk() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = ByteBuffer\n\n            var decodeCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                self.decodeCalls += 1\n                buffer.moveReaderIndex(to: buffer.readableBytes)\n                return .continue\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                self.decodeCalls += 1\n                buffer.moveReaderIndex(to: buffer.readableBytes)\n                return .continue\n            }\n        }\n\n        let max = 100\n        let decoder = Decoder()\n        let channel = EmbeddedChannel(handler: ByteToMessageHandler(decoder, maximumBufferSize: max))\n        var buffer = channel.allocator.buffer(capacity: max + 1)\n        buffer.writeString(String(repeating: \"*\", count: max + 1))\n        XCTAssertNoThrow(try channel.writeInbound(buffer))\n        XCTAssertNoThrow(XCTAssertTrue(try channel.finish().isClean))\n        XCTAssertGreaterThan(decoder.decodeCalls, 0)\n    }\n\n    func testRemoveHandlerBecauseOfChannelTearDownWhilstUserTriggeredRemovalIsInProgress() {\n        class Decoder: ByteToMessageDecoder {\n            typealias InboundOut = Never\n\n            var removedCalls = 0\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                XCTFail(\"\\(#function) should never have been called\")\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                XCTAssertEqual(0, buffer.readableBytes)\n                XCTAssertTrue(seenEOF)\n                return .needMoreData\n            }\n\n            func decoderRemoved(context: ChannelHandlerContext) {\n                self.removedCalls += 1\n                XCTAssertEqual(1, self.removedCalls)\n            }\n        }\n\n        let decoder = Decoder()\n        let decoderHandler = ByteToMessageHandler(decoder)\n        let channel = EmbeddedChannel(handler: decoderHandler)\n\n        XCTAssertNoThrow(try channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5)).wait())\n\n        // We are now trying to get the channel into the following states (ordered by time):\n        // 1. user-triggered removal is in progress (started but not completed)\n        // 2. `removeHandlers()` as part of the Channel teardown is called\n        // 3. user-triggered removal completes\n        //\n        // The way we can get into this situation might be slightly counter-intuitive but currently, the easiest way\n        // to trigger this is:\n        // 1. `channel.close()` (because `removeHandlers()` is called inside an `eventLoop.execute` so is delayed\n        // 2. user-triggered removal start (`channel.pipeline.removeHandler`) which will also use an\n        //    `eventLoop.execute` to ask for the handler to actually be removed.\n        // 3. run the event loop (this will now first call `removeHandlers()` which completes the channel tear down\n        //    and a little later will complete the user-triggered removal.\n\n        let closeFuture = channel.close()  // close the channel, `removeHandlers` will be called in next EL tick.\n\n        // user-trigger the handler removal (the actual removal will be done on the next EL tick too)\n        let removalFuture = channel.pipeline.syncOperations.removeHandler(decoderHandler)\n\n        // run the event loop, this will make `removeHandlers` run first because it was enqueued before the\n        // user-triggered handler removal\n        channel.embeddedEventLoop.run()\n\n        // just to make sure everything has completed.\n        XCTAssertNoThrow(try closeFuture.wait())\n        XCTAssertNoThrow(try removalFuture.wait())\n\n        XCTAssertThrowsError(try channel.finish()) { error in\n            XCTAssertEqual(ChannelError.alreadyClosed, error as? ChannelError)\n        }\n    }\n}\n\nfinal class MessageToByteEncoderTest: XCTestCase {\n    private struct Int32ToByteEncoder: MessageToByteEncoder {\n        typealias OutboundIn = Int32\n\n        public func encode(data value: Int32, out: inout ByteBuffer) throws {\n            out.writeInteger(value)\n        }\n    }\n\n    private final class Int32ToByteEncoderWithDefaultImpl: MessageToByteEncoder {\n        typealias OutboundIn = Int32\n\n        public func encode(data value: Int32, out: inout ByteBuffer) throws {\n            XCTAssertEqual(MemoryLayout<Int32>.size, 256)\n            out.writeInteger(value)\n        }\n    }\n\n    func testEncoderOverrideAllocateOutBuffer() throws {\n        try testEncoder(MessageToByteHandler(Int32ToByteEncoder()))\n    }\n\n    func testEncoder() throws {\n        try testEncoder(MessageToByteHandler(Int32ToByteEncoderWithDefaultImpl()))\n    }\n\n    private func testEncoder(_ handler: ChannelHandler, file: StaticString = #filePath, line: UInt = #line) throws {\n        let channel = EmbeddedChannel()\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(Int32ToByteEncoder())),\n            file: (file),\n            line: line\n        )\n\n        XCTAssertNoThrow(try channel.writeAndFlush(Int32(5)).wait(), file: (file), line: line)\n\n        if var buffer = try channel.readOutbound(as: ByteBuffer.self) {\n            XCTAssertEqual(Int32(5), buffer.readInteger())\n            XCTAssertEqual(0, buffer.readableBytes)\n        } else {\n            XCTFail(\"couldn't read ByteBuffer from channel\")\n        }\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testB2MHIsHappyNeverBeingAddedToAPipeline() {\n        @inline(never)\n        func createAndReleaseIt() {\n            struct Decoder: ByteToMessageDecoder {\n                typealias InboundOut = Never\n\n                func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                    XCTFail()\n                    return .needMoreData\n                }\n\n                func decodeLast(\n                    context: ChannelHandlerContext,\n                    buffer: inout ByteBuffer,\n                    seenEOF: Bool\n                ) throws -> DecodingState {\n                    XCTFail()\n                    return .needMoreData\n                }\n            }\n            _ = ByteToMessageHandler(Decoder())\n        }\n        createAndReleaseIt()\n    }\n\n    func testM2BHIsHappyNeverBeingAddedToAPipeline() {\n        @inline(never)\n        func createAndReleaseIt() {\n            struct Encoder: MessageToByteEncoder {\n                typealias OutboundIn = Void\n\n                func encode(data: Void, out: inout ByteBuffer) throws {\n                    XCTFail()\n                }\n            }\n            _ = MessageToByteHandler(Encoder())\n        }\n        createAndReleaseIt()\n    }\n\n}\n\nprivate class PairOfBytesDecoder: ByteToMessageDecoder {\n    typealias InboundOut = ByteBuffer\n\n    private let lastPromise: EventLoopPromise<ByteBuffer>\n    var decodeLastCalls = 0\n\n    init(lastPromise: EventLoopPromise<ByteBuffer>) {\n        self.lastPromise = lastPromise\n    }\n\n    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n        if let slice = buffer.readSlice(length: 2) {\n            context.fireChannelRead(Self.wrapInboundOut(slice))\n            return .continue\n        } else {\n            return .needMoreData\n        }\n    }\n\n    func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState {\n        self.decodeLastCalls += 1\n        XCTAssertEqual(1, self.decodeLastCalls)\n        self.lastPromise.succeed(buffer)\n        return .needMoreData\n    }\n}\n\nfinal class MessageToByteHandlerTest: XCTestCase {\n    private struct ThrowingMessageToByteEncoder: MessageToByteEncoder {\n        private struct HandlerError: Error {}\n\n        typealias OutboundIn = Int\n\n        public func encode(data value: Int, out: inout ByteBuffer) throws {\n            if value == 0 {\n                out.writeInteger(value)\n            } else {\n                throw HandlerError()\n            }\n        }\n    }\n\n    func testThrowingEncoderFailsPromises() {\n        let channel = EmbeddedChannel()\n\n        XCTAssertNoThrow(\n            try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(ThrowingMessageToByteEncoder()))\n        )\n\n        XCTAssertNoThrow(try channel.writeAndFlush(0).wait())\n\n        XCTAssertThrowsError(try channel.writeAndFlush(1).wait())\n\n        XCTAssertThrowsError(try channel.writeAndFlush(0).wait())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/ControlMessageTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\nimport XCTest\n\n@testable import NIOPosix\n\nextension UnsafeControlMessageCollection {\n    fileprivate init(controlBytes: UnsafeMutableRawBufferPointer) {\n        let msgHdr = msghdr(\n            msg_name: nil,\n            msg_namelen: 0,\n            msg_iov: nil,\n            msg_iovlen: 0,\n            msg_control: controlBytes.baseAddress,\n            msg_controllen: .init(controlBytes.count),\n            msg_flags: 0\n        )\n        self.init(messageHeader: msgHdr)\n    }\n}\n\nclass ControlMessageTests: XCTestCase {\n    var encoderBytes: UnsafeMutableRawBufferPointer?\n    var encoder: UnsafeOutboundControlBytes!\n\n    override func setUp() {\n        self.encoderBytes = UnsafeMutableRawBufferPointer.allocate(\n            byteCount: 1000,\n            alignment: MemoryLayout<Int>.alignment\n        )\n        self.encoder = UnsafeOutboundControlBytes(controlBytes: self.encoderBytes!)\n    }\n\n    override func tearDown() {\n        if let encoderBytes = self.encoderBytes {\n            self.encoderBytes = nil\n            encoderBytes.deallocate()\n        }\n    }\n\n    func testEmptyEncode() {\n        XCTAssertEqual(self.encoder.validControlBytes.count, 0)\n    }\n\n    struct DecodedMessage: Equatable {\n        var level: CInt\n        var type: CInt\n        var payload: CInt\n    }\n\n    func testEncodeDecode1() {\n        self.encoder.appendControlMessage(level: 1, type: 2, payload: 3)\n        let expected = [DecodedMessage(level: 1, type: 2, payload: 3)]\n        let encodedBytes = self.encoder.validControlBytes\n\n        let decoder = UnsafeControlMessageCollection(controlBytes: encodedBytes)\n        XCTAssertEqual(decoder.count, 1)\n        var decoded: [DecodedMessage] = []\n        for cmsg in decoder {\n            XCTAssertEqual(cmsg.data!.count, MemoryLayout<CInt>.size)\n            let payload = ControlMessageParser._readCInt(data: cmsg.data!)\n            decoded.append(DecodedMessage(level: cmsg.level, type: cmsg.type, payload: payload))\n        }\n        XCTAssertEqual(expected, decoded)\n    }\n\n    func testEncodeDecode2() {\n        self.encoder.appendControlMessage(level: 1, type: 2, payload: 3)\n        self.encoder.appendControlMessage(level: 4, type: 5, payload: 6)\n        let expected = [\n            DecodedMessage(level: 1, type: 2, payload: 3),\n            DecodedMessage(level: 4, type: 5, payload: 6),\n        ]\n        let encodedBytes = self.encoder.validControlBytes\n\n        let decoder = UnsafeControlMessageCollection(controlBytes: encodedBytes)\n        XCTAssertEqual(decoder.count, 2)\n        var decoded: [DecodedMessage] = []\n        for cmsg in decoder {\n            XCTAssertEqual(cmsg.data!.count, MemoryLayout<CInt>.size)\n            let payload = ControlMessageParser._readCInt(data: cmsg.data!)\n            decoded.append(DecodedMessage(level: cmsg.level, type: cmsg.type, payload: payload))\n        }\n        XCTAssertEqual(expected, decoded)\n    }\n\n    private func assertBuffersNonOverlapping(\n        _ b1: UnsafeMutableRawBufferPointer,\n        _ b2: UnsafeMutableRawBufferPointer,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) {\n        XCTAssert(\n            (b1.baseAddress! < b2.baseAddress! && (b1.baseAddress! + b1.count) <= b2.baseAddress!)\n                || (b2.baseAddress! < b1.baseAddress! && (b2.baseAddress! + b2.count) <= b1.baseAddress!),\n            file: (file),\n            line: line\n        )\n    }\n\n    func testStorageIndexing() {\n        var storage = UnsafeControlMessageStorage.allocate(msghdrCount: 3)\n        defer {\n            storage.deallocate()\n        }\n        // Check size\n        XCTAssertEqual(storage.count, 3)\n        // Buffers issued should not overlap.\n        assertBuffersNonOverlapping(storage[0], storage[1])\n        assertBuffersNonOverlapping(storage[0], storage[2])\n        assertBuffersNonOverlapping(storage[1], storage[2])\n        // Buffers should have a suitable size.\n        XCTAssertGreaterThan(storage[0].count, MemoryLayout<cmsghdr>.stride)\n        XCTAssertGreaterThan(storage[1].count, MemoryLayout<cmsghdr>.stride)\n        XCTAssertGreaterThan(storage[2].count, MemoryLayout<cmsghdr>.stride)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/DatagramChannelTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\n#if os(Linux)\nimport CNIOLinux\n#endif\n\nextension Channel {\n    func waitForDatagrams(count: Int) throws -> [AddressedEnvelope<ByteBuffer>] {\n        try self.pipeline.context(name: \"ByteReadRecorder\").flatMap { context in\n            if let future = (context.handler as? DatagramReadRecorder<ByteBuffer>)?.notifyForDatagrams(count) {\n                return future\n            }\n\n            XCTFail(\"Could not wait for reads\")\n            return self.eventLoop.makeSucceededFuture([] as [AddressedEnvelope<ByteBuffer>])\n        }.wait()\n    }\n\n    func waitForErrors(count: Int) throws -> [any Error] {\n        try self.pipeline.context(name: \"ByteReadRecorder\").flatMap { context in\n            if let future = (context.handler as? DatagramReadRecorder<ByteBuffer>)?.notifyForErrors(count) {\n                return future\n            }\n\n            XCTFail(\"Could not wait for errors\")\n            return self.eventLoop.makeSucceededFuture([])\n        }.wait()\n    }\n\n    func readCompleteCount() throws -> Int {\n        try self.pipeline.context(name: \"ByteReadRecorder\").map { context in\n            (context.handler as! DatagramReadRecorder<ByteBuffer>).readCompleteCount\n        }.wait()\n    }\n\n    func configureForRecvMmsg(messageCount: Int) throws {\n        let totalBufferSize = messageCount * 2048\n\n        try self.setOption(\n            .recvAllocator,\n            value: FixedSizeRecvByteBufferAllocator(capacity: totalBufferSize)\n        ).flatMap {\n            self.setOption(.datagramVectorReadMessageCount, value: messageCount)\n        }.wait()\n    }\n}\n\n/// A class that records datagrams received and forwards them on.\n///\n/// Used extensively in tests to validate messaging expectations.\nfinal class DatagramReadRecorder<DataType: Sendable>: ChannelInboundHandler {\n    typealias InboundIn = AddressedEnvelope<DataType>\n    typealias InboundOut = AddressedEnvelope<DataType>\n\n    enum State {\n        case fresh\n        case registered\n        case active\n    }\n\n    var reads: [AddressedEnvelope<DataType>] = []\n    var errors: [any Error] = []\n    var loop: EventLoop? = nil\n    var state: State = .fresh\n\n    var readWaiters: [Int: EventLoopPromise<[AddressedEnvelope<DataType>]>] = [:]\n    var errorWaiters: [Int: EventLoopPromise<[any Error]>] = [:]\n    var readCompleteCount = 0\n\n    func channelRegistered(context: ChannelHandlerContext) {\n        XCTAssertEqual(.fresh, self.state)\n        self.state = .registered\n        self.loop = context.eventLoop\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        XCTAssertEqual(.registered, self.state)\n        self.state = .active\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        XCTAssertEqual(.active, self.state)\n        let data = Self.unwrapInboundIn(data)\n        reads.append(data)\n\n        if let promise = readWaiters.removeValue(forKey: reads.count) {\n            promise.succeed(reads)\n        }\n\n        context.fireChannelRead(Self.wrapInboundOut(data))\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: any Error) {\n        self.errors.append(error)\n\n        if let promise = self.errorWaiters.removeValue(forKey: self.errors.count) {\n            promise.succeed(self.errors)\n        }\n\n        context.fireErrorCaught(error)\n    }\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        self.readCompleteCount += 1\n        context.fireChannelReadComplete()\n    }\n\n    func notifyForDatagrams(_ count: Int) -> EventLoopFuture<[AddressedEnvelope<DataType>]> {\n        guard reads.count < count else {\n            return loop!.makeSucceededFuture(.init(reads.prefix(count)))\n        }\n\n        readWaiters[count] = loop!.makePromise()\n        return readWaiters[count]!.futureResult\n    }\n\n    func notifyForErrors(_ count: Int) -> EventLoopFuture<[any Error]> {\n        guard self.errors.count < count else {\n            return self.loop!.makeSucceededFuture(.init(self.errors.prefix(count)))\n        }\n\n        self.errorWaiters[count] = self.loop!.makePromise()\n        return self.errorWaiters[count]!.futureResult\n    }\n}\n\nclass DatagramChannelTests: XCTestCase {\n    private var group: MultiThreadedEventLoopGroup! = nil\n    private var firstChannel: Channel! = nil\n    private var secondChannel: Channel! = nil\n    private var thirdChannel: Channel! = nil\n\n    private func buildChannel(group: EventLoopGroup, host: String = \"127.0.0.1\") throws -> Channel {\n        try DatagramBootstrap(group: group)\n            .channelOption(.socketOption(.so_reuseaddr), value: 1)\n            .channelInitializer { channel in\n                channel.pipeline.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: host, port: 0)\n            .wait()\n    }\n\n    private var supportsIPv6: Bool {\n        do {\n            let ipv6Loopback = try SocketAddress(ipAddress: \"::1\", port: 0)\n            return try System.enumerateDevices().contains(where: { $0.address == ipv6Loopback })\n        } catch {\n            return false\n        }\n    }\n\n    override func setUp() {\n        super.setUp()\n        self.continueAfterFailure = false\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        self.firstChannel = try! buildChannel(group: group)\n        self.secondChannel = try! buildChannel(group: group)\n        self.thirdChannel = try! buildChannel(group: group)\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.group.syncShutdownGracefully())\n        super.tearDown()\n    }\n\n    func testBasicChannelCommunication() throws {\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n\n        let reads = try self.secondChannel.waitForDatagrams(count: 1)\n        XCTAssertEqual(reads.count, 1)\n        let read = reads.first!\n        XCTAssertEqual(read.data, buffer)\n        XCTAssertEqual(read.remoteAddress, self.firstChannel.localAddress!)\n    }\n\n    func testEmptyDatagram() throws {\n        let buffer = self.firstChannel.allocator.buffer(capacity: 0)\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n\n        let reads = try self.secondChannel.waitForDatagrams(count: 1)\n        XCTAssertEqual(reads.count, 1)\n        let read = reads.first!\n        XCTAssertEqual(read.data, buffer)\n        XCTAssertEqual(read.remoteAddress, self.firstChannel.localAddress!)\n    }\n\n    func testManyWrites() throws {\n        var buffer = firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        var writeFutures: [EventLoopFuture<Void>] = []\n        for _ in 0..<5 {\n            writeFutures.append(self.firstChannel.write(writeData))\n        }\n        self.firstChannel.flush()\n        XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(writeFutures, on: self.firstChannel.eventLoop).wait())\n\n        let reads = try self.secondChannel.waitForDatagrams(count: 5)\n\n        // These short datagrams should not have been dropped by the kernel.\n        XCTAssertEqual(reads.count, 5)\n\n        for read in reads {\n            XCTAssertEqual(read.data, buffer)\n            XCTAssertEqual(read.remoteAddress, self.firstChannel.localAddress!)\n        }\n    }\n\n    func testDatagramChannelHasWatermark() throws {\n        _ = try self.firstChannel.setOption(\n            .writeBufferWaterMark,\n            value: ChannelOptions.Types.WriteBufferWaterMark(low: 1, high: 1024)\n        ).wait()\n\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeBytes([UInt8](repeating: 5, count: 256))\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        XCTAssertTrue(self.firstChannel.isWritable)\n        for _ in 0..<4 {\n            // We submit to the loop here to make sure that we synchronously process the writes and checks\n            // on writability.\n            let writable: Bool = try self.firstChannel.eventLoop.submit { [firstChannel] in\n                firstChannel!.write(writeData, promise: nil)\n                return firstChannel!.isWritable\n            }.wait()\n            XCTAssertTrue(writable)\n        }\n\n        let lastWritePromise = self.firstChannel.eventLoop.makePromise(of: Void.self)\n        // The last write will push us over the edge.\n        var writable: Bool = try self.firstChannel.eventLoop.submit { [firstChannel] in\n            firstChannel!.write(writeData, promise: lastWritePromise)\n            return firstChannel!.isWritable\n        }.wait()\n        XCTAssertFalse(writable)\n\n        // Now we're going to flush, and check the writability immediately after.\n        self.firstChannel.flush()\n        writable = try lastWritePromise.futureResult.map { [firstChannel] _ in\n            firstChannel!.isWritable\n        }.wait()\n        XCTAssertTrue(writable)\n    }\n\n    func testWriteFuturesFailWhenChannelClosed() throws {\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        let promises = (0..<5).map { _ in self.firstChannel.write(writeData) }\n\n        // Now close the channel. When that completes, all the futures should be complete too.\n        let fulfilled = try self.firstChannel.close().map {\n            promises.map { $0.isFulfilled }.allSatisfy { $0 }\n        }.wait()\n        XCTAssertTrue(fulfilled)\n\n        for promise in promises {\n            XCTAssertThrowsError(try promise.wait()) { error in\n                XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n            }\n        }\n    }\n\n    func testManyManyDatagramWrites() throws {\n        // We're going to try to write loads, and loads, and loads of data. In this case, one more\n        // write than the iovecs max.\n\n        var overall: EventLoopFuture<Void> = self.firstChannel.eventLoop.makeSucceededFuture(())\n        for _ in 0...Socket.writevLimitIOVectors {\n            let myPromise = self.firstChannel.eventLoop.makePromise(of: Void.self)\n            var buffer = self.firstChannel.allocator.buffer(capacity: 1)\n            buffer.writeString(\"a\")\n            let envelope = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n            self.firstChannel.write(envelope, promise: myPromise)\n            overall = EventLoopFuture.andAllSucceed([overall, myPromise.futureResult], on: self.firstChannel.eventLoop)\n        }\n        self.firstChannel.flush()\n        XCTAssertNoThrow(try overall.wait())\n        // We're not going to check that the datagrams arrive, because some kernels *will* drop them here.\n    }\n\n    func testSendmmsgLotsOfData() throws {\n        // We defer this work to the background thread because otherwise it incurs an enormous number of context\n        // switches.\n        let overall = try self.firstChannel.eventLoop.submit { [firstChannel, secondChannel] in\n            let myPromise = firstChannel!.eventLoop.makePromise(of: Void.self)\n            // For datagrams this buffer cannot be very large, because if it's larger than the path MTU it\n            // will cause EMSGSIZE.\n            let bufferSize = 1024 * 5\n            var buffer = firstChannel!.allocator.buffer(capacity: bufferSize)\n            buffer.writeRepeatingByte(4, count: bufferSize)\n            let envelope = AddressedEnvelope(remoteAddress: secondChannel!.localAddress!, data: buffer)\n\n            let lotsOfData = Int(Int32.max)\n            var written: Int64 = 0\n            var overall = firstChannel!.eventLoop.makeSucceededFuture(())\n            var datagrams = 0\n            while written <= lotsOfData {\n                firstChannel!.write(envelope, promise: myPromise)\n                overall = EventLoopFuture.andAllSucceed(\n                    [overall, myPromise.futureResult],\n                    on: firstChannel!.eventLoop\n                )\n                written += Int64(bufferSize)\n                datagrams += 1\n            }\n            return overall\n        }.wait()\n        self.firstChannel.flush()\n\n        XCTAssertNoThrow(try overall.wait())\n    }\n\n    func testLargeWritesFail() throws {\n        // We want to try to trigger EMSGSIZE. To be safe, we're going to allocate a 10MB buffer here and fill it.\n        let bufferSize = 1024 * 1024 * 10\n        var buffer = self.firstChannel.allocator.buffer(capacity: bufferSize)\n        buffer.writeRepeatingByte(4, count: bufferSize)\n        let envelope = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n\n        let writeFut = self.firstChannel.write(envelope)\n        self.firstChannel.flush()\n\n        XCTAssertThrowsError(try writeFut.wait()) { error in\n            XCTAssertEqual(.writeMessageTooLarge, error as? ChannelError)\n        }\n    }\n\n    func testOneLargeWriteDoesntPreventOthersWriting() throws {\n        // We want to try to trigger EMSGSIZE. To be safe, we're going to allocate a 10MB buffer here and fill it.\n        let bufferSize = 1024 * 1024 * 10\n        var buffer = self.firstChannel.allocator.buffer(capacity: bufferSize)\n        buffer.writeRepeatingByte(4, count: bufferSize)\n\n        // Now we want two envelopes. The first is small, the second is large.\n        let firstEnvelope = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer.getSlice(at: buffer.readerIndex, length: 100)!\n        )\n        let secondEnvelope = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n\n        // Now, three writes. We're sandwiching the big write between two small ones.\n        let firstWrite = self.firstChannel.write(firstEnvelope)\n        let secondWrite = self.firstChannel.write(secondEnvelope)\n        let thirdWrite = self.firstChannel.writeAndFlush(firstEnvelope)\n\n        // The first and third writes should be fine.\n        XCTAssertNoThrow(try firstWrite.wait())\n        XCTAssertNoThrow(try thirdWrite.wait())\n\n        // The second should have failed.\n        XCTAssertThrowsError(try secondWrite.wait()) { error in\n            XCTAssertEqual(.writeMessageTooLarge, error as? ChannelError)\n        }\n    }\n\n    func testClosingBeforeFlushFailsAllWrites() throws {\n        // We want to try to trigger EMSGSIZE. To be safe, we're going to allocate a 10MB buffer here and fill it.\n        let bufferSize = 1024 * 1024 * 10\n        var buffer = self.firstChannel.allocator.buffer(capacity: bufferSize)\n        buffer.writeRepeatingByte(4, count: bufferSize)\n\n        // Now we want two envelopes. The first is small, the second is large.\n        let firstEnvelope = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer.getSlice(at: buffer.readerIndex, length: 100)!\n        )\n        let secondEnvelope = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n\n        // Now, three writes. We're sandwiching the big write between two small ones.\n        let firstWrite = self.firstChannel.write(firstEnvelope)\n        let secondWrite = self.firstChannel.write(secondEnvelope)\n        let thirdWrite = self.firstChannel.writeAndFlush(firstEnvelope)\n\n        // The first and third writes should be fine.\n        XCTAssertNoThrow(try firstWrite.wait())\n        XCTAssertNoThrow(try thirdWrite.wait())\n\n        // The second should have failed.\n        XCTAssertThrowsError(try secondWrite.wait()) { error in\n            XCTAssertEqual(.writeMessageTooLarge, error as? ChannelError)\n        }\n    }\n\n    public func testRecvMsgFailsWithECONNREFUSED() throws {\n        try assertRecvMsgFails(error: ECONNREFUSED, active: true)\n    }\n\n    public func testRecvMsgFailsWithENOMEM() throws {\n        try assertRecvMsgFails(error: ENOMEM, active: true)\n    }\n\n    public func testRecvMsgFailsWithEFAULT() throws {\n        try assertRecvMsgFails(error: EFAULT, active: false)\n    }\n\n    private func assertRecvMsgFails(error: Int32, active: Bool) throws {\n        final class RecvFromHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = AddressedEnvelope<ByteBuffer>\n            typealias InboundOut = AddressedEnvelope<ByteBuffer>\n\n            private let promise: EventLoopPromise<IOError>\n\n            init(_ promise: EventLoopPromise<IOError>) {\n                self.promise = promise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTFail(\"Should not receive data but got \\(Self.unwrapInboundIn(data))\")\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                if let ioError = error as? IOError {\n                    self.promise.succeed(ioError)\n                }\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        class NonRecvFromSocket: Socket {\n            private var error: Int32?\n\n            init(error: Int32) throws {\n                self.error = error\n                try super.init(protocolFamily: .inet, type: .datagram, protocolSubtype: .default)\n            }\n\n            override func recvmsg(\n                pointer: UnsafeMutableRawBufferPointer,\n                storage: inout sockaddr_storage,\n                storageLen: inout socklen_t,\n                controlBytes: inout UnsafeReceivedControlBytes\n            )\n                throws -> IOResult<(Int)>\n            {\n                if let err = self.error {\n                    self.error = nil\n                    throw IOError(errnoCode: err, reason: \"recvfrom\")\n                }\n                return IOResult.wouldBlock(0)\n            }\n        }\n        let socket = try NonRecvFromSocket(error: error)\n        let channel = try DatagramChannel(socket: socket, eventLoop: group.next() as! SelectableEventLoop)\n        let promise = channel.eventLoop.makePromise(of: IOError.self)\n        XCTAssertNoThrow(try channel.register().wait())\n        XCTAssertNoThrow(try channel.pipeline.addHandler(RecvFromHandler(promise)).wait())\n        XCTAssertNoThrow(try channel.bind(to: SocketAddress.init(ipAddress: \"127.0.0.1\", port: 0)).wait())\n\n        XCTAssertEqual(\n            active,\n            try channel.eventLoop.submit {\n                channel.readable()\n                return channel.isActive\n            }.wait()\n        )\n\n        if active {\n            XCTAssertNoThrow(try channel.close().wait())\n        }\n        let ioError = try promise.futureResult.wait()\n        XCTAssertEqual(error, ioError.errnoCode)\n    }\n\n    public func testRecvMmsgFailsWithECONNREFUSED() throws {\n        try assertRecvMmsgFails(error: ECONNREFUSED, active: true)\n    }\n\n    public func testRecvMmsgFailsWithENOMEM() throws {\n        try assertRecvMmsgFails(error: ENOMEM, active: true)\n    }\n\n    public func testRecvMmsgFailsWithEFAULT() throws {\n        try assertRecvMmsgFails(error: EFAULT, active: false)\n    }\n\n    private func assertRecvMmsgFails(error: Int32, active: Bool) throws {\n        // Only run this test on platforms that support recvmmsg: the others won't even\n        // try.\n        #if os(Linux) || os(FreeBSD) || os(Android)\n        final class RecvMmsgHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = AddressedEnvelope<ByteBuffer>\n            typealias InboundOut = AddressedEnvelope<ByteBuffer>\n\n            private let promise: EventLoopPromise<IOError>\n\n            init(_ promise: EventLoopPromise<IOError>) {\n                self.promise = promise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTFail(\"Should not receive data but got \\(Self.unwrapInboundIn(data))\")\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                if let ioError = error as? IOError {\n                    self.promise.succeed(ioError)\n                }\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        class NonRecvMmsgSocket: Socket {\n            private var error: Int32?\n\n            init(error: Int32) throws {\n                self.error = error\n                try super.init(protocolFamily: .inet, type: .datagram)\n            }\n\n            override func recvmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int> {\n                if let err = self.error {\n                    self.error = nil\n                    throw IOError(errnoCode: err, reason: \"recvfrom\")\n                }\n                return IOResult.wouldBlock(0)\n            }\n        }\n        let socket = try NonRecvMmsgSocket(error: error)\n        let channel = try DatagramChannel(socket: socket, eventLoop: group.next() as! SelectableEventLoop)\n        let promise = channel.eventLoop.makePromise(of: IOError.self)\n        XCTAssertNoThrow(try channel.register().wait())\n        XCTAssertNoThrow(try channel.pipeline.addHandler(RecvMmsgHandler(promise)).wait())\n        XCTAssertNoThrow(try channel.configureForRecvMmsg(messageCount: 10))\n        XCTAssertNoThrow(try channel.bind(to: SocketAddress.init(ipAddress: \"127.0.0.1\", port: 0)).wait())\n\n        XCTAssertEqual(\n            active,\n            try channel.eventLoop.submit {\n                channel.readable()\n                return channel.isActive\n            }.wait()\n        )\n\n        if active {\n            XCTAssertNoThrow(try channel.close().wait())\n        }\n        let ioError = try promise.futureResult.wait()\n        XCTAssertEqual(error, ioError.errnoCode)\n        #endif\n    }\n\n    public func testSetGetOptionClosedDatagramChannel() throws {\n        try assertSetGetOptionOnOpenAndClosed(\n            channel: firstChannel,\n            option: .maxMessagesPerRead,\n            value: 1\n        )\n    }\n\n    func testWritesAreAccountedCorrectly() throws {\n        var buffer = firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n        let firstWrite = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer.getSlice(at: buffer.readerIndex, length: 5)!\n        )\n        let secondWrite = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        self.firstChannel.write(firstWrite, promise: nil)\n        self.firstChannel.write(secondWrite, promise: nil)\n        self.firstChannel.flush()\n\n        let reads = try self.secondChannel.waitForDatagrams(count: 2)\n\n        // These datagrams should not have been dropped by the kernel.\n        XCTAssertEqual(reads.count, 2)\n\n        XCTAssertEqual(reads[0].data, buffer.getSlice(at: buffer.readerIndex, length: 5)!)\n        XCTAssertEqual(reads[0].remoteAddress, self.firstChannel.localAddress!)\n        XCTAssertEqual(reads[1].data, buffer)\n        XCTAssertEqual(reads[1].remoteAddress, self.firstChannel.localAddress!)\n    }\n\n    func testSettingTwoDistinctChannelOptionsWorksForDatagramChannel() throws {\n        let channel = try assertNoThrowWithValue(\n            DatagramBootstrap(group: group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .channelOption(.socketOption(.so_timestamp), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try channel.close().wait())\n        }\n        XCTAssertTrue(try getBoolSocketOption(channel: channel, level: .socket, name: .so_reuseaddr))\n        XCTAssertTrue(try getBoolSocketOption(channel: channel, level: .socket, name: .so_timestamp))\n        XCTAssertFalse(try getBoolSocketOption(channel: channel, level: .socket, name: .so_keepalive))\n    }\n\n    func testUnprocessedOutboundUserEventFailsOnDatagramChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let channel = try DatagramChannel(\n            eventLoop: group.next() as! SelectableEventLoop,\n            protocolFamily: .inet,\n            protocolSubtype: .default\n        )\n        XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"event\").wait()) { (error: Error) in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.operationUnsupported, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testBasicMultipleReads() throws {\n        XCTAssertNoThrow(try self.secondChannel.configureForRecvMmsg(messageCount: 10))\n\n        // This test should exercise recvmmsg.\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n\n        // We write this in three times.\n        self.firstChannel.write(writeData, promise: nil)\n        self.firstChannel.write(writeData, promise: nil)\n        self.firstChannel.write(writeData, promise: nil)\n        self.firstChannel.flush()\n\n        let reads = try self.secondChannel.waitForDatagrams(count: 3)\n        XCTAssertEqual(reads.count, 3)\n\n        for (idx, read) in reads.enumerated() {\n            XCTAssertEqual(read.data, buffer, \"index: \\(idx)\")\n            XCTAssertEqual(read.remoteAddress, self.firstChannel.localAddress!, \"index: \\(idx)\")\n        }\n    }\n\n    func testMmsgWillTruncateWithoutChangeToAllocator() throws {\n        // This test validates that setting a small allocator will lead to datagram truncation.\n        // Right now we don't error on truncation, so this test looks for short receives.\n        // Setting the recv allocator to 30 bytes forces 3 bytes per message.\n        // Sadly, this test only truncates for the platforms with recvmmsg support: the rest don't truncate as 30 bytes is sufficient.\n        XCTAssertNoThrow(try self.secondChannel.configureForRecvMmsg(messageCount: 10))\n        XCTAssertNoThrow(\n            try self.secondChannel.setOption(\n                .recvAllocator,\n                value: FixedSizeRecvByteBufferAllocator(capacity: 30)\n            ).wait()\n        )\n\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n\n        // We write this in three times.\n        self.firstChannel.write(writeData, promise: nil)\n        self.firstChannel.write(writeData, promise: nil)\n        self.firstChannel.write(writeData, promise: nil)\n        self.firstChannel.flush()\n\n        let reads = try self.secondChannel.waitForDatagrams(count: 3)\n        XCTAssertEqual(reads.count, 3)\n\n        for (idx, read) in reads.enumerated() {\n            #if os(Linux) || os(FreeBSD) || os(Android)\n            XCTAssertEqual(read.data.readableBytes, 3, \"index: \\(idx)\")\n            #else\n            XCTAssertEqual(read.data.readableBytes, 13, \"index: \\(idx)\")\n            #endif\n            XCTAssertEqual(read.remoteAddress, self.firstChannel.localAddress!, \"index: \\(idx)\")\n        }\n    }\n\n    func testRecvMmsgForMultipleCycles() throws {\n        // The goal of this test is to provide more datagrams than can be received in a single invocation of\n        // recvmmsg, and to confirm that they all make it through.\n        // This test is allowed to run on systems without recvmmsg: it just exercises the serial read path.\n        XCTAssertNoThrow(try self.secondChannel.configureForRecvMmsg(messageCount: 10))\n\n        // We now turn off autoread.\n        XCTAssertNoThrow(try self.secondChannel.setOption(.autoRead, value: false).wait())\n        XCTAssertNoThrow(try self.secondChannel.setOption(.maxMessagesPerRead, value: 3).wait())\n\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"data\")\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n\n        // Ok, now we're good. Let's queue up a bunch of datagrams. We've configured to receive 10 at a time, so we'll send 30.\n        for _ in 0..<29 {\n            self.firstChannel.write(writeData, promise: nil)\n        }\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n\n        // Now we read. Rather than issue many read() calls, we'll turn autoread back on.\n        XCTAssertNoThrow(try self.secondChannel.setOption(.autoRead, value: true).wait())\n\n        // Wait for all 30 datagrams to come through. There should be no loss here, as this is small datagrams on loopback.\n        let reads = try self.secondChannel.waitForDatagrams(count: 30)\n        XCTAssertEqual(reads.count, 30)\n\n        // Now we want to count the number of readCompletes. On any platform without recvmmsg, we should have seen 10 or more\n        // (as max messages per read is 3). On platforms with recvmmsg, we would expect to see\n        // substantially fewer than 10, and potentially as low as 1.\n        #if os(Linux) || os(FreeBSD) || os(Android)\n        XCTAssertLessThan(try assertNoThrowWithValue(self.secondChannel.readCompleteCount()), 10)\n        XCTAssertGreaterThanOrEqual(try assertNoThrowWithValue(self.secondChannel.readCompleteCount()), 1)\n        #else\n        XCTAssertGreaterThanOrEqual(try assertNoThrowWithValue(self.secondChannel.readCompleteCount()), 10)\n        #endif\n    }\n\n    // Mostly to check the types don't go pop as internally converts between bool and int and back.\n    func testSetGetEcnNotificationOption() {\n        XCTAssertNoThrow(\n            try {\n                // IPv4\n                try self.firstChannel.setOption(.explicitCongestionNotification, value: true).wait()\n                XCTAssertTrue(try self.firstChannel.getOption(.explicitCongestionNotification).wait())\n\n                try self.secondChannel.setOption(.explicitCongestionNotification, value: false).wait()\n                XCTAssertFalse(try self.secondChannel.getOption(.explicitCongestionNotification).wait())\n\n                // IPv6\n                guard self.supportsIPv6 else {\n                    // Skip on non-IPv6 systems\n                    return\n                }\n\n                do {\n                    let channel1 = try buildChannel(group: self.group, host: \"::1\")\n                    try channel1.setOption(.explicitCongestionNotification, value: true).wait()\n                    XCTAssertTrue(try channel1.getOption(.explicitCongestionNotification).wait())\n\n                    let channel2 = try buildChannel(group: self.group, host: \"::1\")\n                    try channel2.setOption(.explicitCongestionNotification, value: false).wait()\n                    XCTAssertFalse(try channel2.getOption(.explicitCongestionNotification).wait())\n                } catch let error as SocketAddressError {\n                    switch error {\n                    case .unknown:\n                        // IPv6 resolution can fail even if supported.\n                        return\n                    case .unsupported, .unixDomainSocketPathTooLong, .failedToParseIPString:\n                        throw error\n                    }\n                }\n            }()\n        )\n    }\n\n    private func testEcnAndPacketInfoReceive(\n        address: String,\n        vectorRead: Bool,\n        vectorSend: Bool,\n        receivePacketInfo: Bool = false\n    ) {\n        XCTAssertNoThrow(\n            try {\n                // Fake sending packet to self on the loopback interface if requested\n                let expectedPacketInfo = receivePacketInfo ? try constructNIOPacketInfo(address: address) : nil\n                let receiveBootstrap: DatagramBootstrap\n                if vectorRead {\n                    receiveBootstrap = DatagramBootstrap(group: group)\n                        .channelOption(.datagramVectorReadMessageCount, value: 4)\n                } else {\n                    receiveBootstrap = DatagramBootstrap(group: group)\n                }\n\n                let receiveChannel =\n                    try receiveBootstrap\n                    .channelOption(.explicitCongestionNotification, value: true)\n                    .channelOption(.receivePacketInfo, value: receivePacketInfo)\n                    .channelInitializer { channel in\n                        channel.eventLoop.makeCompletedFuture {\n                            try channel.pipeline.syncOperations.addHandler(\n                                DatagramReadRecorder<ByteBuffer>(),\n                                name: \"ByteReadRecorder\"\n                            )\n                        }\n                    }\n                    .bind(host: address, port: 0)\n                    .wait()\n                defer {\n                    XCTAssertNoThrow(try receiveChannel.close().wait())\n                }\n                let sendChannel = try DatagramBootstrap(group: group)\n                    .bind(host: address, port: 0)\n                    .wait()\n                defer {\n                    XCTAssertNoThrow(try sendChannel.close().wait())\n                }\n\n                let ecnStates: [NIOExplicitCongestionNotificationState] = [\n                    .transportNotCapable,\n                    .congestionExperienced,\n                    .transportCapableFlag0,\n                    .transportCapableFlag1,\n                ]\n                // Datagrams may be received out-of-order, so we use a sequential integer in the payload.\n                let metadataWrites: [(Int, AddressedEnvelope<ByteBuffer>.Metadata?)] = try ecnStates.enumerated()\n                    .reduce(into: []) { metadataWrites, ecnState in\n                        let writeData = AddressedEnvelope(\n                            remoteAddress: receiveChannel.localAddress!,\n                            data: sendChannel.allocator.buffer(integer: ecnState.offset),\n                            metadata: .init(ecnState: ecnState.element, packetInfo: expectedPacketInfo)\n                        )\n                        // Sending extra data without flushing should trigger a vector send.\n                        if vectorSend {\n                            sendChannel.write(writeData, promise: nil)\n                            metadataWrites.append((ecnState.offset, writeData.metadata))\n                        }\n                        try sendChannel.writeAndFlush(writeData).wait()\n                        metadataWrites.append((ecnState.offset, writeData.metadata))\n                    }\n\n                let expectedNumReads = metadataWrites.count\n                let metadataReads = try receiveChannel.waitForDatagrams(count: expectedNumReads).map {\n                    ($0.data.getInteger(at: $0.data.readerIndex, as: Int.self)!, $0.metadata)\n                }\n\n                // Datagrams may be received out-of-order, so we order reads and writes by payload.\n                XCTAssertEqual(\n                    metadataReads.sorted { $0.0 < $1.0 }.map { $0.1 },\n                    metadataWrites.sorted { $0.0 < $1.0 }.map { $0.1 }\n                )\n            }()\n        )\n    }\n\n    private func constructNIOPacketInfo(address: String) throws -> NIOPacketInfo {\n        struct InterfaceIndexNotFound: Error {}\n        let destinationAddress = try SocketAddress(ipAddress: address, port: 0)\n        guard\n            let ingressIfaceIndex = try System.enumerateDevices()\n                .first(where: { $0.address == destinationAddress })?.interfaceIndex\n        else {\n            throw InterfaceIndexNotFound()\n        }\n        return NIOPacketInfo(destinationAddress: destinationAddress, interfaceIndex: ingressIfaceIndex)\n    }\n\n    func testEcnSendReceiveIPV4() {\n        testEcnAndPacketInfoReceive(address: \"127.0.0.1\", vectorRead: false, vectorSend: false)\n    }\n\n    func testEcnSendReceiveIPV6() {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        testEcnAndPacketInfoReceive(address: \"::1\", vectorRead: false, vectorSend: false)\n    }\n\n    func testEcnSendReceiveIPV4VectorRead() {\n        testEcnAndPacketInfoReceive(address: \"127.0.0.1\", vectorRead: true, vectorSend: false)\n    }\n\n    func testEcnSendReceiveIPV6VectorRead() {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        testEcnAndPacketInfoReceive(address: \"::1\", vectorRead: true, vectorSend: false)\n    }\n\n    func testEcnSendReceiveIPV4VectorReadVectorWrite() {\n        testEcnAndPacketInfoReceive(address: \"127.0.0.1\", vectorRead: true, vectorSend: true)\n    }\n\n    func testEcnSendReceiveIPV6VectorReadVectorWrite() {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        testEcnAndPacketInfoReceive(address: \"::1\", vectorRead: true, vectorSend: true)\n    }\n\n    func testWritabilityChangeDuringReentrantFlushNow() throws {\n        final class EnvelopingHandler: ChannelOutboundHandler, Sendable {\n            typealias OutboundIn = ByteBuffer\n            typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n            func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n                let buffer = Self.unwrapOutboundIn(data)\n                context.write(\n                    Self.wrapOutboundOut(AddressedEnvelope(remoteAddress: context.channel.localAddress!, data: buffer)),\n                    promise: promise\n                )\n            }\n        }\n\n        let loop = self.group.next()\n        let becameUnwritable = loop.makePromise(of: Void.self)\n        let becameWritable = loop.makePromise(of: Void.self)\n\n        let channel1Future = DatagramBootstrap(group: self.group)\n            .bind(host: \"localhost\", port: 0)\n        let channel1 = try assertNoThrowWithValue(try channel1Future.wait())\n        defer {\n            XCTAssertNoThrow(try channel1.close().wait())\n        }\n\n        let channel2Future = DatagramBootstrap(group: self.group)\n            .channelOption(.writeBufferWaterMark, value: ReentrantWritabilityChangingHandler.watermark)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let handler = ReentrantWritabilityChangingHandler(\n                        becameUnwritable: becameUnwritable,\n                        becameWritable: becameWritable\n                    )\n                    try channel.pipeline.syncOperations.addHandlers([EnvelopingHandler(), handler])\n                }\n            }\n            .bind(host: \"localhost\", port: 0)\n        let channel2 = try assertNoThrowWithValue(try channel2Future.wait())\n        defer {\n            XCTAssertNoThrow(try channel2.close().wait())\n        }\n\n        // Now wait.\n        XCTAssertNoThrow(try becameUnwritable.futureResult.wait())\n        XCTAssertNoThrow(try becameWritable.futureResult.wait())\n    }\n\n    func testSetGetPktInfoOption() {\n        XCTAssertNoThrow(\n            try {\n                // IPv4\n                try self.firstChannel.setOption(.receivePacketInfo, value: true).wait()\n                XCTAssertTrue(try self.firstChannel.getOption(.receivePacketInfo).wait())\n\n                try self.secondChannel.setOption(.receivePacketInfo, value: false).wait()\n                XCTAssertFalse(try self.secondChannel.getOption(.receivePacketInfo).wait())\n\n                // IPv6\n                guard self.supportsIPv6 else {\n                    // Skip on non-IPv6 systems\n                    return\n                }\n\n                do {\n                    let channel1 = try buildChannel(group: self.group, host: \"::1\")\n                    try channel1.setOption(.receivePacketInfo, value: true).wait()\n                    XCTAssertTrue(try channel1.getOption(.receivePacketInfo).wait())\n\n                    let channel2 = try buildChannel(group: self.group, host: \"::1\")\n                    try channel2.setOption(.receivePacketInfo, value: false).wait()\n                    XCTAssertFalse(try channel2.getOption(.receivePacketInfo).wait())\n                } catch let error as SocketAddressError {\n                    switch error {\n                    case .unknown:\n                        // IPv6 resolution can fail even if supported.\n                        return\n                    case .unsupported, .unixDomainSocketPathTooLong, .failedToParseIPString:\n                        throw error\n                    }\n                }\n            }()\n        )\n    }\n\n    private func testSimpleReceivePacketInfo(address: String) throws {\n        // Fake sending packet to self on the loopback interface\n        let expectedPacketInfo = try constructNIOPacketInfo(address: address)\n\n        let receiveChannel = try DatagramBootstrap(group: group)\n            .channelOption(.receivePacketInfo, value: true)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: address, port: 0)\n            .wait()\n        defer {\n            XCTAssertNoThrow(try receiveChannel.close().wait())\n        }\n        let sendChannel = try DatagramBootstrap(group: group)\n            .bind(host: address, port: 0)\n            .wait()\n        defer {\n            XCTAssertNoThrow(try sendChannel.close().wait())\n        }\n\n        var buffer = sendChannel.allocator.buffer(capacity: 1)\n        buffer.writeRepeatingByte(0, count: 1)\n\n        let writeData = AddressedEnvelope(\n            remoteAddress: receiveChannel.localAddress!,\n            data: buffer,\n            metadata: .init(\n                ecnState: .transportNotCapable,\n                packetInfo: expectedPacketInfo\n            )\n        )\n        try sendChannel.writeAndFlush(writeData).wait()\n\n        let expectedReads = 1\n        let reads = try receiveChannel.waitForDatagrams(count: 1)\n        XCTAssertEqual(reads.count, expectedReads)\n        XCTAssertEqual(reads[0].metadata?.packetInfo, expectedPacketInfo)\n    }\n\n    func testSimpleReceivePacketInfoIPV4() throws {\n        try testSimpleReceivePacketInfo(address: \"127.0.0.1\")\n    }\n\n    func testSimpleReceivePacketInfoIPV6() throws {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        try testSimpleReceivePacketInfo(address: \"::1\")\n    }\n\n    func testReceiveEcnAndPacketInfoIPV4() {\n        testEcnAndPacketInfoReceive(address: \"127.0.0.1\", vectorRead: false, vectorSend: false, receivePacketInfo: true)\n    }\n\n    func testReceiveEcnAndPacketInfoIPV6() {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        testEcnAndPacketInfoReceive(address: \"::1\", vectorRead: false, vectorSend: false, receivePacketInfo: true)\n    }\n\n    func testReceiveEcnAndPacketInfoIPV4VectorRead() {\n        testEcnAndPacketInfoReceive(address: \"127.0.0.1\", vectorRead: true, vectorSend: false, receivePacketInfo: true)\n    }\n\n    func testReceiveEcnAndPacketInfoIPV6VectorRead() {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        testEcnAndPacketInfoReceive(address: \"::1\", vectorRead: true, vectorSend: false, receivePacketInfo: true)\n    }\n\n    func testReceiveEcnAndPacketInfoIPV4VectorReadVectorWrite() {\n        testEcnAndPacketInfoReceive(address: \"127.0.0.1\", vectorRead: true, vectorSend: true, receivePacketInfo: true)\n    }\n\n    func testReceiveEcnAndPacketInfoIPV6VectorReadVectorWrite() {\n        guard System.supportsIPv6 else {\n            return  // need to skip IPv6 tests if we don't support it.\n        }\n        testEcnAndPacketInfoReceive(address: \"::1\", vectorRead: true, vectorSend: true, receivePacketInfo: true)\n    }\n\n    func testDoingICMPWithoutRoot() throws {\n        // This test validates we can send ICMP messages on a datagram socket without having root privilege.\n        //\n        // This doesn't always work: ability to do this on Linux is gated behind a sysctl (net.ipv4.ping_group_range)\n        // which may exclude us. So we have to tolerate this throwing EPERM as well.\n\n        final class EchoRequestHandler: ChannelInboundHandler {\n            typealias InboundIn = AddressedEnvelope<ByteBuffer>\n            typealias OutboundOut = AddressedEnvelope<ByteBuffer>\n\n            let completePromise: EventLoopPromise<ByteBuffer>\n\n            init(completePromise: EventLoopPromise<ByteBuffer>) {\n                self.completePromise = completePromise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                var buffer = context.channel.allocator.buffer(capacity: 32)\n\n                // We're going to write an ICMP echo packet from scratch, like heroes.\n                // Echo request is type 8, code 0.\n                // The checksum is tricky: on Linux, the kernel doesn't care what we set, it'll\n                // calculate it. On macOS, however, we have to calculate it. For both platforms, then,\n                // we calculate it.\n                // Identifier is irrelevant.\n                // Sequence number does matter, but we'll set to 0.\n                let type = UInt8(8)\n                let code = UInt8(0)\n                let fakeChecksum = UInt16(0)\n                let identifier = UInt16(0)\n                let sequenceNumber = UInt16(0)\n                buffer.writeMultipleIntegers(type, code, fakeChecksum, identifier, sequenceNumber)\n\n                // Then we write a payload, which will be \"hello from NIO\".\n                buffer.writeString(\"Hello from NIO\")\n\n                // Now calculate the checksum, and store it back at offset 2.\n                let checksum = buffer.readableBytesView.computeIPChecksum()\n                buffer.setInteger(checksum, at: 2)\n\n                // Now wrap it into an addressed envelope pointed at localhost.\n                let envelope = AddressedEnvelope(\n                    remoteAddress: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 0),\n                    data: buffer\n                )\n\n                context.writeAndFlush(Self.wrapOutboundOut(envelope)).cascadeFailure(to: self.completePromise)\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let envelope = Self.unwrapInboundIn(data)\n\n                // Complete with the payload.\n                self.completePromise.succeed(envelope.data)\n            }\n        }\n\n        let loop = self.group.next()\n        let completePromise = loop.makePromise(of: ByteBuffer.self)\n        do {\n            let channel = try DatagramBootstrap(group: group)\n                .protocolSubtype(.init(.icmp))\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            EchoRequestHandler(completePromise: completePromise)\n                        )\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n            defer {\n                XCTAssertNoThrow(try channel.close().wait())\n            }\n\n            // Let's try to send an ICMP echo request and get a response.\n            var response = try completePromise.futureResult.wait()\n\n            #if canImport(Darwin)\n            // Again, a platform difference. On Darwin, this returns a complete IP packet. On Linux, it does not.\n            // We assume the Linux platform is the more general approach, but if this test fails on your platform\n            // it is _probably_ because it behaves differently. To make this general, we can skip the IPv4 header.\n            //\n            // To do that, we have to work out how long that header is. That's held in bottom 4 bits of the first\n            // byte, which is the IHL field. This is in \"number of 32-bit words\".\n            guard let firstByte = response.getInteger(at: response.readerIndex, as: UInt8.self),\n                let _ = response.readSlice(length: Int(firstByte & 0x0F) * 4)\n            else {\n                XCTFail(\"Insufficient bytes for IPv4 header\")\n                return\n            }\n            #endif\n\n            // Now we've got the ICMP packet. Let's parse this.\n            guard let header = response.readMultipleIntegers(as: (UInt8, UInt8, UInt16, UInt16, UInt16).self) else {\n                XCTFail(\"Insufficient bytes for ICMP header\")\n                return\n            }\n\n            // Echo response has type 0, code 0, unpredictable checksum and identifier, same sequence number we sent.\n            // type\n            XCTAssertEqual(header.0, 0)\n            // code\n            XCTAssertEqual(header.1, 0)\n            // sequence number\n            XCTAssertEqual(header.4, 0)\n\n            // Remaining payload should have been our string.\n            XCTAssertEqual(String(buffer: response), \"Hello from NIO\")\n        } catch let error as IOError {\n            // Firstly, fail this promise in case it leaks.\n            completePromise.fail(error)\n            if error.errnoCode == EACCES {\n                // Acceptable\n                return\n            }\n            XCTFail(\"Unexpected IOError: \\(error)\")\n        }\n    }\n\n    func assertSending(\n        data: ByteBuffer,\n        from sourceChannel: Channel,\n        to destinationChannel: Channel,\n        wrappingInAddressedEnvelope shouldWrapInAddressedEnvelope: Bool,\n        resultsIn expectedResult: Result<Void, Error>,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        // Wrap data in AddressedEnvelope if required.\n        let writeResult: EventLoopFuture<Void>\n        if shouldWrapInAddressedEnvelope {\n            let envelope = AddressedEnvelope(remoteAddress: destinationChannel.localAddress!, data: data)\n            writeResult = sourceChannel.writeAndFlush(envelope)\n        } else {\n            writeResult = sourceChannel.writeAndFlush(data)\n        }\n\n        // Check the expected result.\n        switch expectedResult {\n        case .success:\n            // Check the write succeeded.\n            XCTAssertNoThrow(try writeResult.wait())\n\n            // Check the destination received the sent payload.\n            let reads = try destinationChannel.waitForDatagrams(count: 1)\n            XCTAssertEqual(reads.count, 1)\n            let read = reads.first!\n            XCTAssertEqual(read.data, data)\n            XCTAssertEqual(read.remoteAddress, sourceChannel.localAddress!)\n\n        case .failure(let expectedError):\n            // Check the error is of the expected type.\n            XCTAssertThrowsError(try writeResult.wait()) { error in\n                guard type(of: error) == type(of: expectedError) else {\n                    XCTFail(\n                        \"expected error of type \\(type(of: expectedError)), but caught other error of type (\\(type(of: error)): \\(error)\"\n                    )\n                    return\n                }\n            }\n        }\n    }\n\n    func assertSendingHelloWorld(\n        from sourceChannel: Channel,\n        to destinationChannel: Channel,\n        wrappingInAddressedEnvelope shouldWrapInAddressedEnvelope: Bool,\n        resultsIn expectedResult: Result<Void, Error>,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        try self.assertSending(\n            data: sourceChannel.allocator.buffer(staticString: \"hello, world!\"),\n            from: sourceChannel,\n            to: destinationChannel,\n            wrappingInAddressedEnvelope: shouldWrapInAddressedEnvelope,\n            resultsIn: expectedResult,\n            file: file,\n            line: line\n        )\n    }\n\n    func bufferWrite(\n        of data: ByteBuffer,\n        from sourceChannel: Channel,\n        to destinationChannel: Channel,\n        wrappingInAddressedEnvelope shouldWrapInAddressedEnvelope: Bool\n    ) -> EventLoopFuture<Void> {\n        if shouldWrapInAddressedEnvelope {\n            let envelope = AddressedEnvelope(remoteAddress: destinationChannel.localAddress!, data: data)\n            return sourceChannel.write(envelope)\n        } else {\n            return sourceChannel.write(data)\n        }\n    }\n\n    func bufferWriteOfHelloWorld(\n        from sourceChannel: Channel,\n        to destinationChannel: Channel,\n        wrappingInAddressedEnvelope shouldWrapInAddressedEnvelope: Bool\n    ) -> EventLoopFuture<Void> {\n        self.bufferWrite(\n            of: sourceChannel.allocator.buffer(staticString: \"hello, world!\"),\n            from: sourceChannel,\n            to: destinationChannel,\n            wrappingInAddressedEnvelope: shouldWrapInAddressedEnvelope\n        )\n    }\n\n    func testSendingAddressedEnvelopeOnUnconnectedSocketSucceeds() throws {\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: true,\n            resultsIn: .success(())\n        )\n    }\n\n    func testSendingByteBufferOnUnconnectedSocketFails() throws {\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: false,\n            resultsIn: .failure(DatagramChannelError.WriteOnUnconnectedSocketWithoutAddress())\n        )\n    }\n\n    func testSendingByteBufferOnConnectedSocketSucceeds() throws {\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.secondChannel.localAddress!).wait())\n\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: false,\n            resultsIn: .success(())\n        )\n    }\n\n    func testSendingAddressedEnvelopeOnConnectedSocketSucceeds() throws {\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.secondChannel.localAddress!).wait())\n\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: true,\n            resultsIn: .success(())\n        )\n    }\n\n    func testSendingAddressedEnvelopeOnConnectedSocketWithDifferentAddressFails() throws {\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.secondChannel.localAddress!).wait())\n\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.thirdChannel,\n            wrappingInAddressedEnvelope: true,\n            resultsIn: .failure(\n                DatagramChannelError.WriteOnConnectedSocketWithInvalidAddress(\n                    envelopeRemoteAddress: self.thirdChannel.localAddress!,\n                    connectedRemoteAddress: self.secondChannel.localAddress!\n                )\n            )\n        )\n    }\n\n    func testConnectingSocketAfterFlushingExistingMessages() throws {\n        // Send message from firstChannel to secondChannel.\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: true,\n            resultsIn: .success(())\n        )\n\n        // Connect firstChannel to thirdChannel.\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.thirdChannel.localAddress!).wait())\n\n        // Send message from firstChannel to thirdChannel.\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.thirdChannel,\n            wrappingInAddressedEnvelope: false,\n            resultsIn: .success(())\n        )\n    }\n\n    func testConnectingSocketFailsBufferedWrites() throws {\n        // Buffer message from firstChannel to secondChannel.\n        let bufferedWrite = bufferWriteOfHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: true\n        )\n\n        // Connect firstChannel to thirdChannel.\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.thirdChannel.localAddress!).wait())\n\n        // Check that the buffered write was failed.\n        XCTAssertThrowsError(try bufferedWrite.wait()) { error in\n            XCTAssertEqual(\n                (error as? IOError)?.errnoCode,\n                EISCONN,\n                \"expected EISCONN, but caught other error: \\(error)\"\n            )\n        }\n\n        // Send message from firstChannel to thirdChannel.\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.thirdChannel,\n            wrappingInAddressedEnvelope: false,\n            resultsIn: .success(())\n        )\n    }\n\n    func testReconnectingSocketFailsBufferedWrites() throws {\n        // Connect firstChannel to secondChannel.\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.secondChannel.localAddress!).wait())\n\n        // Buffer message from firstChannel to secondChannel.\n        let bufferedWrite = bufferWriteOfHelloWorld(\n            from: self.firstChannel,\n            to: self.secondChannel,\n            wrappingInAddressedEnvelope: false\n        )\n\n        // Connect firstChannel to thirdChannel.\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.thirdChannel.localAddress!).wait())\n\n        // Check that the buffered write was failed.\n        XCTAssertThrowsError(try bufferedWrite.wait()) { error in\n            XCTAssertEqual(\n                (error as? IOError)?.errnoCode,\n                EISCONN,\n                \"expected EISCONN, but caught other error: \\(error)\"\n            )\n        }\n\n        // Send message from firstChannel to thirdChannel.\n        try self.assertSendingHelloWorld(\n            from: self.firstChannel,\n            to: self.thirdChannel,\n            wrappingInAddressedEnvelope: false,\n            resultsIn: .success(())\n        )\n    }\n\n    func testGSOIsUnsupportedOnNonLinuxPlatforms() throws {\n        #if !os(Linux)\n        XCTAssertFalse(System.supportsUDPSegmentationOffload)\n        #endif\n    }\n\n    func testSetGSOOption() throws {\n        let didSet = self.firstChannel.setOption(.datagramSegmentSize, value: 1024)\n        if System.supportsUDPSegmentationOffload {\n            XCTAssertNoThrow(try didSet.wait())\n        } else {\n            XCTAssertThrowsError(try didSet.wait()) { error in\n                XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n            }\n        }\n    }\n\n    func testGetGSOOption() throws {\n        let getOption = self.firstChannel.getOption(.datagramSegmentSize)\n        if System.supportsUDPSegmentationOffload {\n            XCTAssertEqual(try getOption.wait(), 0)  // not-set\n        } else {\n            XCTAssertThrowsError(try getOption.wait()) { error in\n                XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n            }\n        }\n    }\n\n    func testLargeScalarWriteWithGSO() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // We're going to enable GSO with a segment size of 1000, send one large buffer which\n        // contains ten 1000-byte segments. Each segment will contain the bytes corresponding to\n        // the index of the segment. We validate that the receiver receives 10 datagrams, each\n        // corresponding to one segment from the buffer.\n        let segmentSize: CInt = 1000\n        let segments = 10\n\n        // Enable GSO\n        let didSet = self.firstChannel.setOption(.datagramSegmentSize, value: segmentSize)\n        XCTAssertNoThrow(try didSet.wait())\n\n        // Form a handful of segments\n        let buffers = (0..<segments).map { i in\n            ByteBuffer(repeating: UInt8(i), count: Int(segmentSize))\n        }\n\n        // Coalesce the segments into a single buffer.\n        var buffer = self.firstChannel.allocator.buffer(capacity: segments * Int(segmentSize))\n        for segment in buffers {\n            buffer.writeImmutableBuffer(segment)\n        }\n\n        for byte in UInt8(0)..<UInt8(10) {\n            buffer.writeRepeatingByte(byte, count: Int(segmentSize))\n        }\n\n        // Write the single large buffer.\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n\n        // The receiver will receive separate segments.\n        let receivedBuffers = try self.secondChannel.waitForDatagrams(count: segments)\n        let receivedBytes = receivedBuffers.map { $0.data.readableBytes }.reduce(0, +)\n        XCTAssertEqual(Int(segmentSize) * segments, receivedBytes)\n\n        var unusedIndexes = Set(buffers.indices)\n        for envelope in receivedBuffers {\n            if let index = buffers.firstIndex(of: envelope.data) {\n                XCTAssertNotNil(unusedIndexes.remove(index))\n            } else {\n                XCTFail(\"No matching buffer\")\n            }\n        }\n    }\n\n    func testLargeVectorWriteWithGSO() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // Similar to the test above, but with multiple writes.\n        let segmentSize: CInt = 1000\n        let segments = 10\n\n        // Enable GSO\n        let didSet = self.firstChannel.setOption(.datagramSegmentSize, value: segmentSize)\n        XCTAssertNoThrow(try didSet.wait())\n\n        // Form a handful of segments\n        let buffers = (0..<segments).map { i in\n            ByteBuffer(repeating: UInt8(i), count: Int(segmentSize))\n        }\n\n        // Coalesce the segments into a single buffer.\n        var buffer = self.firstChannel.allocator.buffer(capacity: segments * Int(segmentSize))\n        for segment in buffers {\n            buffer.writeImmutableBuffer(segment)\n        }\n\n        for byte in UInt8(0)..<UInt8(10) {\n            buffer.writeRepeatingByte(byte, count: Int(segmentSize))\n        }\n\n        // Write the single large buffer.\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        let write1 = self.firstChannel.write(writeData)\n        let write2 = self.firstChannel.write(writeData)\n        self.firstChannel.flush()\n        XCTAssertNoThrow(try write1.wait())\n        XCTAssertNoThrow(try write2.wait())\n\n        // The receiver will receive separate segments.\n        let receivedBuffers = try self.secondChannel.waitForDatagrams(count: segments)\n        let receivedBytes = receivedBuffers.map { $0.data.readableBytes }.reduce(0, +)\n        XCTAssertEqual(Int(segmentSize) * segments, receivedBytes)\n\n        let keysWithValues = buffers.indices.map { index in (index, 2) }\n        var indexCounts = Dictionary(uniqueKeysWithValues: keysWithValues)\n        for envelope in receivedBuffers {\n            if let index = buffers.firstIndex(of: envelope.data) {\n                indexCounts[index, default: 0] -= 1\n                XCTAssertGreaterThanOrEqual(indexCounts[index]!, 0)\n            } else {\n                XCTFail(\"No matching buffer\")\n            }\n        }\n    }\n\n    func testWriteBufferAtGSOSegmentCountLimit() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // Newer kernels raised this; use the lower value to ensure the segment count is within the\n        // limit.\n        let udpMaxSegments = 64\n\n        var segments = udpMaxSegments\n\n        let segmentSize = 10\n        let didSet = self.firstChannel.setOption(.datagramSegmentSize, value: CInt(segmentSize))\n        XCTAssertNoThrow(try didSet.wait())\n\n        func send(byteCount: Int) throws {\n            let buffer = self.firstChannel.allocator.buffer(repeating: 1, count: byteCount)\n            let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n            try self.firstChannel.writeAndFlush(writeData).wait()\n        }\n\n        do {\n            try send(byteCount: segments * segmentSize)\n        } catch let e as IOError where e.errnoCode == EINVAL {\n            // Some older kernel versions report EINVAL with 64 segments. Tolerate that\n            // failure and try again with a lower limit.\n            self.firstChannel = try self.buildChannel(group: self.group)\n            let didSet = self.firstChannel.setOption(.datagramSegmentSize, value: CInt(segmentSize))\n            XCTAssertNoThrow(try didSet.wait())\n            segments = udpMaxSegments - 3\n            try send(byteCount: segments * segmentSize)\n        }\n\n        let read = try self.secondChannel.waitForDatagrams(count: segments)\n        XCTAssertEqual(read.map { $0.data.readableBytes }.reduce(0, +), segments * segmentSize)\n    }\n\n    func testWriteBufferAboveGSOSegmentCountLimitShouldError() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // This is lower (64) in older kernels, but a too-high value is fine.\n        let udpMaxSegments = 128\n\n        let segmentSize = 10\n        let didSet = self.firstChannel.setOption(.datagramSegmentSize, value: CInt(segmentSize))\n        XCTAssertNoThrow(try didSet.wait())\n\n        let buffer = self.firstChannel.allocator.buffer(repeating: 1, count: segmentSize * udpMaxSegments + 1)\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        // The kernel limits messages to a maximum of UDP_MAX_SEGMENTS segments; any more should result in an error.\n        XCTAssertThrowsError(try self.firstChannel.writeAndFlush(writeData).wait()) {\n            XCTAssert($0 is IOError)\n        }\n    }\n\n    func testGROIsUnsupportedOnNonLinuxPlatforms() throws {\n        #if !os(Linux)\n        XCTAssertFalse(System.supportsUDPReceiveOffload)\n        #endif\n    }\n\n    func testSetGROOption() throws {\n        let didSet = self.firstChannel.setOption(.datagramReceiveOffload, value: true)\n        if System.supportsUDPReceiveOffload {\n            XCTAssertNoThrow(try didSet.wait())\n        } else {\n            XCTAssertThrowsError(try didSet.wait()) { error in\n                XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n            }\n        }\n    }\n\n    func testGetGROOption() throws {\n        let getOption = self.firstChannel.getOption(.datagramReceiveOffload)\n        if System.supportsUDPReceiveOffload {\n            XCTAssertEqual(try getOption.wait(), false)  // not-set\n\n            // Now set and check.\n            XCTAssertNoThrow(try self.firstChannel.setOption(.datagramReceiveOffload, value: true).wait())\n            XCTAssertTrue(try self.firstChannel.getOption(.datagramReceiveOffload).wait())\n        } else {\n            XCTAssertThrowsError(try getOption.wait()) { error in\n                XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n            }\n        }\n    }\n\n    func testReceiveLargeBufferWithGRO(segments: Int, segmentSize: Int, writes: Int, vectorReads: Int? = nil) throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n        try XCTSkipUnless(System.supportsUDPReceiveOffload, \"UDP_GRO is not supported on this platform\")\n        try XCTSkipUnless(try self.hasGoodGROSupport())\n\n        /// Set GSO on the first channel.\n        XCTAssertNoThrow(\n            try self.firstChannel.setOption(.datagramSegmentSize, value: CInt(segmentSize)).wait()\n        )\n        /// Set GRO on the second channel.\n        XCTAssertNoThrow(try self.secondChannel.setOption(.datagramReceiveOffload, value: true).wait())\n        /// The third channel has neither set.\n\n        // Enable on second channel\n        if let vectorReads = vectorReads {\n            XCTAssertNoThrow(\n                try self.secondChannel.setOption(.datagramVectorReadMessageCount, value: vectorReads)\n                    .wait()\n            )\n        }\n\n        /// Increase the size of the read buffer for the second and third channels.\n        let fixed = FixedSizeRecvByteBufferAllocator(capacity: 1 << 16)\n        XCTAssertNoThrow(try self.secondChannel.setOption(.recvAllocator, value: fixed).wait())\n        XCTAssertNoThrow(try self.thirdChannel.setOption(.recvAllocator, value: fixed).wait())\n\n        // Write a large datagrams on the first channel. They should be split and then accumulated on the receive side.\n        // Form a large buffer to write from the first channel.\n        let buffer = self.firstChannel.allocator.buffer(repeating: 1, count: segmentSize * segments)\n\n        // Write to the channel with GRO enabled.\n        do {\n            let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n            let promises = (0..<writes).map { _ in self.firstChannel.write(writeData) }\n            self.firstChannel.flush()\n            XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait())\n\n            // GRO is well supported; we expect `writes` datagrams.\n            let datagrams = try self.secondChannel.waitForDatagrams(count: writes)\n            for datagram in datagrams {\n                XCTAssertEqual(datagram.data.readableBytes, segments * segmentSize)\n            }\n        }\n\n        // Write to the channel whithout GRO.\n        do {\n            let writeData = AddressedEnvelope(remoteAddress: self.thirdChannel.localAddress!, data: buffer)\n            let promises = (0..<writes).map { _ in self.firstChannel.write(writeData) }\n            self.firstChannel.flush()\n            XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait())\n\n            // GRO is not enabled so we expect a `writes * segments` datagrams.\n            let datagrams = try self.thirdChannel.waitForDatagrams(count: writes * segments)\n            for datagram in datagrams {\n                XCTAssertEqual(datagram.data.readableBytes, segmentSize)\n            }\n        }\n    }\n\n    func testChannelCanReceiveLargeBufferWithGROUsingScalarReads() throws {\n        try self.testReceiveLargeBufferWithGRO(segments: 10, segmentSize: 1000, writes: 1)\n    }\n\n    func testChannelCanReceiveLargeBufferWithGROUsingVectorReads() throws {\n        try self.testReceiveLargeBufferWithGRO(segments: 10, segmentSize: 1000, writes: 1, vectorReads: 4)\n    }\n\n    func testChannelCanReceiveMultipleLargeBuffersWithGROUsingScalarReads() throws {\n        try self.testReceiveLargeBufferWithGRO(segments: 10, segmentSize: 1000, writes: 4)\n    }\n\n    func testChannelCanReceiveMultipleLargeBuffersWithGROUsingVectorReads() throws {\n        try self.testReceiveLargeBufferWithGRO(segments: 10, segmentSize: 1000, writes: 4, vectorReads: 4)\n    }\n\n    func testChannelCanReportWritableBufferedBytes() throws {\n        let buffer = self.firstChannel.allocator.buffer(string: \"abcd\")\n        let data = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        let writeCount = 3\n\n        let promises = (0..<writeCount).map { _ in self.firstChannel.write(data) }\n        let bufferedAmount = try self.firstChannel.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(bufferedAmount, buffer.readableBytes * writeCount)\n        self.firstChannel.flush()\n        let bufferedAmountAfterFlush = try self.firstChannel.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(bufferedAmountAfterFlush, 0)\n        XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait())\n        let datagrams = try self.secondChannel.waitForDatagrams(count: writeCount)\n\n        for datagram in datagrams {\n            XCTAssertEqual(datagram.data.readableBytes, buffer.readableBytes)\n        }\n    }\n\n    func testChannelCanReportWritableBufferedBytesWithDataLargerThanSendBuffer() throws {\n        self.firstChannel = try DatagramBootstrap(group: self.group)\n            .channelOption(.socketOption(.so_sndbuf), value: 16)\n            .channelOption(.socketOption(.so_reuseaddr), value: 1)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: \"127.0.0.1\", port: 0)\n            .wait()\n        let buffer = self.firstChannel.allocator.buffer(repeating: 0xff, count: 16)\n        let data = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        let writeCount = 10\n        var promises: [EventLoopFuture<Void>] = []\n\n        for i in 0..<writeCount {\n            let promise = self.firstChannel.write(data)\n            promises.append(promise)\n            do {\n                if i % 2 == 0 {\n                    self.firstChannel.flush()\n                    XCTAssertNoThrow(\n                        try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait()\n                    )\n                    let bufferedAmount = try self.firstChannel.getOption(.bufferedWritableBytes).wait()\n                    XCTAssertEqual(bufferedAmount, 0)\n                } else {\n                    let bufferedAmount = try self.firstChannel.getOption(.bufferedWritableBytes).wait()\n                    XCTAssertEqual(bufferedAmount, buffer.readableBytes)\n                }\n            } catch {\n                XCTFail(\"firstChannel should not throw any error, but threw \\(error)\")\n            }\n        }\n\n        self.firstChannel.flush()\n        XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait())\n        let finalBufferedAmount = try self.firstChannel.getOption(.bufferedWritableBytes).wait()\n        XCTAssertEqual(finalBufferedAmount, 0)\n        let datagrams = try self.secondChannel.waitForDatagrams(count: writeCount)\n\n        XCTAssertEqual(datagrams.count, writeCount)\n        for datagram in datagrams {\n            XCTAssertEqual(datagram.data.readableBytes, buffer.readableBytes)\n        }\n    }\n\n    func testShutdownReadOnConnectedUDP() throws {\n        var buffer = self.firstChannel.allocator.buffer(capacity: 256)\n        buffer.writeStaticString(\"hello, world!\")\n\n        // Connect and write\n        XCTAssertNoThrow(try self.firstChannel.connect(to: self.secondChannel.localAddress!).wait())\n\n        let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n        _ = try self.secondChannel.waitForDatagrams(count: 1)\n\n        // Ok, close on the second channel.\n        XCTAssertNoThrow(try self.secondChannel.close(mode: .all).wait())\n        print(\"closed\")\n\n        // Write again.\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n\n        // This should trigger an error.\n        let errors = try self.firstChannel.waitForErrors(count: 1)\n        XCTAssertEqual((errors[0] as? IOError)?.errnoCode, ECONNREFUSED)\n    }\n\n    private func hasGoodGROSupport() throws -> Bool {\n        // Source code for UDP_GRO was added in Linux 5.0. However, this support is somewhat limited\n        // and some sources indicate support was actually added in 5.10 (perhaps more widely\n        // supported). There is no way (or at least, no obvious way) to detect when support was\n        // properly fleshed out on a given kernel version.\n        //\n        // Anecdotally we have observed UDP_GRO works on 5.15 but not on 5.4. The effect of UDP_GRO\n        // not working is that datagrams aren't agregated... in other words, GRO not being enabled.\n        // This is fine because it's not always the case that datagrams can be aggregated so\n        // applications must be able to tolerate this.\n        //\n        // It does however make testing GRO somewhat challenging. We need to know when we can assert\n        // that datagrams will be aggregated. To do this we run a simple check on loopback (as we\n        // use this for all other UDP_GRO tests) and check whether datagrams are aggregated on the\n        // receive side. If they aren't then we we don't bother with further testing and instead\n        // validate that our kernel is older than 5.15.\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n        try XCTSkipUnless(System.supportsUDPReceiveOffload, \"UDP_GRO is not supported on this platform\")\n        let sender = try! self.buildChannel(group: self.group)\n        let receiver = try! self.buildChannel(group: self.group)\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n            XCTAssertNoThrow(try receiver.close().wait())\n        }\n\n        let segments = 2\n        let segmentSize = 1000\n\n        XCTAssertNoThrow(try sender.setOption(.datagramSegmentSize, value: CInt(segmentSize)).wait())\n        XCTAssertNoThrow(try receiver.setOption(.datagramReceiveOffload, value: true).wait())\n        let allocator = FixedSizeRecvByteBufferAllocator(capacity: 1 << 16)\n        XCTAssertNoThrow(try receiver.setOption(.recvAllocator, value: allocator).wait())\n\n        let buffer = self.firstChannel.allocator.buffer(repeating: 1, count: segmentSize * segments)\n        let writeData = AddressedEnvelope(remoteAddress: receiver.localAddress!, data: buffer)\n        XCTAssertNoThrow(try sender.writeAndFlush(writeData).wait())\n\n        let received = try receiver.waitForDatagrams(count: 1)\n        let hasGoodGROSupport = received.first!.data.readableBytes == buffer.readableBytes\n\n        if !hasGoodGROSupport {\n            // Not well supported: check we receive enough datagrams of the expected size.\n            let datagrams = try receiver.waitForDatagrams(count: segments)\n            for datagram in datagrams {\n                XCTAssertEqual(datagram.data.readableBytes, segmentSize)\n            }\n\n            #if os(Linux)\n            let info = System.systemInfo\n            // If our kernel is more recent than 5.15 and we don't have good GRO support then\n            // something has gone wrong (or our assumptions about kernel support are incorrect).\n            if let major = info.release.major, let minor = info.release.minor {\n                if major >= 6 || (major == 5 && minor >= 15) {\n                    XCTFail(\"Platform does not have good GRO support: \\(info.release.release)\")\n                }\n            } else {\n                XCTFail(\"Unable to determine Linux x.y release from '\\(info.release.release)'\")\n            }\n            #endif\n        }\n\n        return hasGoodGROSupport\n    }\n\n    // MARK: - Per-Message GSO Tests\n\n    func testLargeScalarWriteWithPerMessageGSO() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // We're going to send one large buffer with per-message GSO metadata.\n        // The kernel should split it into multiple segments.\n        let segmentSize = 1000\n        let segments = 10\n\n        // Form a handful of segments\n        let buffers = (0..<segments).map { i in\n            ByteBuffer(repeating: UInt8(i), count: segmentSize)\n        }\n\n        // Coalesce the segments into a single buffer.\n        var buffer = self.firstChannel.allocator.buffer(capacity: segments * segmentSize)\n        for segment in buffers {\n            buffer.writeImmutableBuffer(segment)\n        }\n\n        // Write the single large buffer with per-message GSO metadata.\n        let writeData = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer,\n            metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: segmentSize)\n        )\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(writeData).wait())\n\n        // The receiver will receive separate segments.\n        let receivedBuffers = try self.secondChannel.waitForDatagrams(count: segments)\n        let receivedBytes = receivedBuffers.map { $0.data.readableBytes }.reduce(0, +)\n        XCTAssertEqual(segmentSize * segments, receivedBytes)\n\n        var unusedIndexes = Set(buffers.indices)\n        for envelope in receivedBuffers {\n            if let index = buffers.firstIndex(of: envelope.data) {\n                XCTAssertNotNil(unusedIndexes.remove(index))\n            } else {\n                XCTFail(\"No matching buffer\")\n            }\n        }\n    }\n\n    func testLargeVectorWriteWithPerMessageGSO() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // Similar to the test above, but with multiple writes using different segment sizes.\n        let segmentSize1 = 1000\n        let segments1 = 10\n        let segmentSize2 = 500\n        let segments2 = 5\n\n        // Form segments for first write\n        let buffers1 = (0..<segments1).map { i in\n            ByteBuffer(repeating: UInt8(i), count: segmentSize1)\n        }\n        var buffer1 = self.firstChannel.allocator.buffer(capacity: segments1 * segmentSize1)\n        for segment in buffers1 {\n            buffer1.writeImmutableBuffer(segment)\n        }\n\n        // Form segments for second write\n        let buffers2 = (0..<segments2).map { i in\n            ByteBuffer(repeating: UInt8(100 + i), count: segmentSize2)\n        }\n        var buffer2 = self.firstChannel.allocator.buffer(capacity: segments2 * segmentSize2)\n        for segment in buffers2 {\n            buffer2.writeImmutableBuffer(segment)\n        }\n\n        // Write both buffers with different segment sizes.\n        let writeData1 = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer1,\n            metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: segmentSize1)\n        )\n        let writeData2 = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer2,\n            metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: segmentSize2)\n        )\n        let write1 = self.firstChannel.write(writeData1)\n        let write2 = self.firstChannel.write(writeData2)\n        self.firstChannel.flush()\n        XCTAssertNoThrow(try write1.wait())\n        XCTAssertNoThrow(try write2.wait())\n\n        // The receiver will receive separate segments from both writes.\n        let receivedBuffers = try self.secondChannel.waitForDatagrams(count: segments1 + segments2)\n        XCTAssertEqual(receivedBuffers.count, segments1 + segments2)\n    }\n\n    func testMixedGSOAndNonGSO() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // Send some messages with GSO and some without.\n        let segmentSize = 1000\n        let segments = 5\n\n        // GSO message\n        var gsoBuffer = self.firstChannel.allocator.buffer(capacity: segments * segmentSize)\n        for _ in 0..<segments {\n            gsoBuffer.writeRepeatingByte(1, count: segmentSize)\n        }\n        let gsoEnvelope = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: gsoBuffer,\n            metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: segmentSize)\n        )\n\n        // Non-GSO message\n        var normalBuffer = self.firstChannel.allocator.buffer(capacity: 100)\n        normalBuffer.writeRepeatingByte(2, count: 100)\n        let normalEnvelope = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: normalBuffer\n        )\n\n        // Send both\n        let write1 = self.firstChannel.write(gsoEnvelope)\n        let write2 = self.firstChannel.write(normalEnvelope)\n        self.firstChannel.flush()\n        XCTAssertNoThrow(try write1.wait())\n        XCTAssertNoThrow(try write2.wait())\n\n        // Should receive 5 segments + 1 normal message\n        let received = try self.secondChannel.waitForDatagrams(count: segments + 1)\n        XCTAssertEqual(received.count, segments + 1)\n    }\n\n    func testPerMessageGSOOverridesChannelLevel() throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n\n        // Set channel-level GSO to one value\n        XCTAssertNoThrow(try self.firstChannel.setOption(.datagramSegmentSize, value: CInt(500)).wait())\n\n        // But use per-message GSO with a different value\n        let segmentSize = 1000\n        let segments = 5\n\n        var buffer = self.firstChannel.allocator.buffer(capacity: segments * segmentSize)\n        for i in 0..<segments {\n            buffer.writeRepeatingByte(UInt8(i), count: segmentSize)\n        }\n\n        let envelope = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer,\n            metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: segmentSize)\n        )\n\n        XCTAssertNoThrow(try self.firstChannel.writeAndFlush(envelope).wait())\n\n        // Should receive segments of size 1000, not 500\n        let received = try self.secondChannel.waitForDatagrams(count: segments)\n        for datagram in received {\n            XCTAssertEqual(datagram.data.readableBytes, segmentSize)\n        }\n    }\n\n    func testPerMessageGSOThrowsOnNonLinux() throws {\n        #if os(Linux)\n        try XCTSkipIf(true, \"This test only runs on non-Linux platforms\")\n        #else\n        // On non-Linux platforms, setting segmentSize in metadata should throw an error\n        var buffer = self.firstChannel.allocator.buffer(capacity: 1000)\n        buffer.writeRepeatingByte(1, count: 1000)\n\n        let envelope = AddressedEnvelope(\n            remoteAddress: self.secondChannel.localAddress!,\n            data: buffer,\n            metadata: .init(ecnState: .transportNotCapable, packetInfo: nil, segmentSize: 500)\n        )\n\n        XCTAssertThrowsError(try self.firstChannel.writeAndFlush(envelope).wait()) { error in\n            XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n        }\n        #endif\n    }\n\n    // MARK: - Per-Message GRO Tests\n\n    func testReceiveLargeBufferWithPerMessageGRO(\n        segments: Int,\n        segmentSize: Int,\n        writes: Int,\n        vectorReads: Int? = nil\n    ) throws {\n        try XCTSkipUnless(System.supportsUDPSegmentationOffload, \"UDP_SEGMENT (GSO) is not supported on this platform\")\n        try XCTSkipUnless(System.supportsUDPReceiveOffload, \"UDP_GRO is not supported on this platform\")\n        try XCTSkipUnless(try self.hasGoodGROSupport())\n\n        /// Set GSO on the first channel.\n        XCTAssertNoThrow(\n            try self.firstChannel.setOption(.datagramSegmentSize, value: CInt(segmentSize)).wait()\n        )\n        /// Set GRO on the second channel.\n        XCTAssertNoThrow(try self.secondChannel.setOption(.datagramReceiveOffload, value: true).wait())\n        /// Enable per-message GRO segment size reporting on the second channel.\n        XCTAssertNoThrow(try self.secondChannel.setOption(.datagramReceiveSegmentSize, value: true).wait())\n        /// The third channel has neither set.\n\n        // Enable on second channel\n        if let vectorReads = vectorReads {\n            XCTAssertNoThrow(\n                try self.secondChannel.setOption(.datagramVectorReadMessageCount, value: vectorReads)\n                    .wait()\n            )\n        }\n\n        /// Increase the size of the read buffer for the second and third channels.\n        let fixed = FixedSizeRecvByteBufferAllocator(capacity: 1 << 16)\n        XCTAssertNoThrow(try self.secondChannel.setOption(.recvAllocator, value: fixed).wait())\n        XCTAssertNoThrow(try self.thirdChannel.setOption(.recvAllocator, value: fixed).wait())\n\n        // Write a large datagrams on the first channel. They should be split and then accumulated on the receive side.\n        // Form a large buffer to write from the first channel.\n        let buffer = self.firstChannel.allocator.buffer(repeating: 1, count: segmentSize * segments)\n\n        // Write to the channel with per-message GRO enabled.\n        do {\n            let writeData = AddressedEnvelope(remoteAddress: self.secondChannel.localAddress!, data: buffer)\n            let promises = (0..<writes).map { _ in self.firstChannel.write(writeData) }\n            self.firstChannel.flush()\n            XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait())\n\n            // GRO is well supported; we expect `writes` datagrams.\n            let datagrams = try self.secondChannel.waitForDatagrams(count: writes)\n            for datagram in datagrams {\n                XCTAssertEqual(datagram.data.readableBytes, segments * segmentSize)\n                // Verify that the metadata contains the segment size\n                XCTAssertNotNil(datagram.metadata, \"Expected metadata to be present\")\n                XCTAssertEqual(\n                    datagram.metadata?.segmentSize,\n                    segmentSize,\n                    \"Expected segment size to be \\(segmentSize)\"\n                )\n            }\n        }\n\n        // Write to the channel without GRO.\n        do {\n            let writeData = AddressedEnvelope(remoteAddress: self.thirdChannel.localAddress!, data: buffer)\n            let promises = (0..<writes).map { _ in self.firstChannel.write(writeData) }\n            self.firstChannel.flush()\n            XCTAssertNoThrow(try EventLoopFuture.andAllSucceed(promises, on: self.firstChannel.eventLoop).wait())\n\n            // GRO is not enabled so we expect a `writes * segments` datagrams without segment size metadata.\n            let datagrams = try self.thirdChannel.waitForDatagrams(count: writes * segments)\n            for datagram in datagrams {\n                XCTAssertEqual(datagram.data.readableBytes, segmentSize)\n                // Without per-message GRO enabled, there should be no segment size in metadata\n                XCTAssertNil(datagram.metadata?.segmentSize)\n            }\n        }\n    }\n\n    func testChannelCanReceiveLargeBufferWithPerMessageGROUsingScalarReads() throws {\n        try self.testReceiveLargeBufferWithPerMessageGRO(segments: 10, segmentSize: 1000, writes: 1)\n    }\n\n    func testChannelCanReceiveLargeBufferWithPerMessageGROUsingVectorReads() throws {\n        try self.testReceiveLargeBufferWithPerMessageGRO(segments: 10, segmentSize: 1000, writes: 1, vectorReads: 4)\n    }\n\n    func testChannelCanReceiveMultipleLargeBuffersWithPerMessageGROUsingScalarReads() throws {\n        try self.testReceiveLargeBufferWithPerMessageGRO(segments: 10, segmentSize: 1000, writes: 4)\n    }\n\n    func testChannelCanReceiveMultipleLargeBuffersWithPerMessageGROUsingVectorReads() throws {\n        try self.testReceiveLargeBufferWithPerMessageGRO(segments: 10, segmentSize: 1000, writes: 4, vectorReads: 4)\n    }\n\n    func testGetPerMessageGROOption() throws {\n        let getOption = self.firstChannel.getOption(.datagramReceiveSegmentSize)\n        if System.supportsUDPReceiveOffload {\n            XCTAssertEqual(try getOption.wait(), false)  // not-set\n\n            // Now set and check.\n            XCTAssertNoThrow(try self.firstChannel.setOption(.datagramReceiveSegmentSize, value: true).wait())\n            XCTAssertTrue(try self.firstChannel.getOption(.datagramReceiveSegmentSize).wait())\n        } else {\n            XCTAssertThrowsError(try getOption.wait()) { error in\n                XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n            }\n        }\n    }\n\n    func testPerMessageGROThrowsOnNonLinux() throws {\n        #if !os(Linux)\n        // On non-Linux platforms, setting datagramReceiveSegmentSize should throw an error\n        XCTAssertThrowsError(try self.firstChannel.setOption(.datagramReceiveSegmentSize, value: true).wait()) {\n            error in\n            XCTAssertEqual(error as? ChannelError, .operationUnsupported)\n        }\n        #endif\n    }\n}\n\nextension System {\n    #if os(Linux)\n    internal static let systemInfo: SystemInfo = {\n        var info = utsname()\n        let rc = CNIOLinux_system_info(&info)\n        assert(rc == 0)\n        return SystemInfo(utsname: info)\n    }()\n\n    struct SystemInfo {\n        var machine: String\n        var nodeName: String\n        var sysName: String\n        var release: Release\n        var version: String\n\n        struct Release {\n            var release: String\n\n            var major: Int?\n            var minor: Int?\n\n            init(parsing release: String) {\n                self.release = release\n\n                let components = release.split(separator: \".\", maxSplits: 1)\n\n                if components.count == 2 {\n                    self.major = Int(components[0])\n                    self.minor = components[1].split(separator: \".\").first.map(String.init).flatMap(Int.init)\n                } else {\n                    self.major = nil\n                    self.minor = nil\n                }\n            }\n        }\n\n        init(utsname info: utsname) {\n            self.machine = withUnsafeBytes(of: info.machine) { bytes in\n                let pointer = bytes.baseAddress?.assumingMemoryBound(to: CChar.self)\n                return pointer.map { String(cString: $0) } ?? \"\"\n            }\n\n            self.nodeName = withUnsafeBytes(of: info.nodename) { bytes in\n                let pointer = bytes.baseAddress?.assumingMemoryBound(to: CChar.self)\n                return pointer.map { String(cString: $0) } ?? \"\"\n            }\n\n            self.sysName = withUnsafeBytes(of: info.sysname) { bytes in\n                let pointer = bytes.baseAddress?.assumingMemoryBound(to: CChar.self)\n                return pointer.map { String(cString: $0) } ?? \"\"\n            }\n\n            self.version = withUnsafeBytes(of: info.version) { bytes in\n                let pointer = bytes.baseAddress?.assumingMemoryBound(to: CChar.self)\n                return pointer.map { String(cString: $0) } ?? \"\"\n            }\n\n            self.release = withUnsafeBytes(of: info.release) { bytes in\n                let pointer = bytes.baseAddress?.assumingMemoryBound(to: CChar.self)\n                let release = pointer.map { String(cString: $0) } ?? \"\"\n                return Release(parsing: release)\n            }\n        }\n    }\n    #endif\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/EchoServerClientTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport Dispatch\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass EchoServerClientTest: XCTestCase {\n    func testEcho() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let numBytes = 16 * 1024\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(numBytes: numBytes, promise: promise)\n                        )\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n\n        for i in 0..<numBytes {\n            buffer.writeInteger(UInt8(i % 256))\n        }\n\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        XCTAssertEqual(try promise.futureResult.wait(), buffer)\n    }\n\n    func testLotsOfUnflushedWrites() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.pipeline.addHandler(WriteALotHandler())\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let sync = channel.pipeline.syncOperations\n                        try sync.addHandler(WriteOnConnectHandler(toWrite: \"X\"))\n                        try sync.addHandler(ByteCountingHandler(numBytes: 10000, promise: promise))\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        defer {\n            _ = clientChannel.close()\n        }\n\n        let bytes = try promise.futureResult.wait()\n        let expected = String(decoding: Array(repeating: \"X\".utf8.first!, count: 10000), as: Unicode.UTF8.self)\n        XCTAssertEqual(expected, bytes.getString(at: bytes.readerIndex, length: bytes.readableBytes))\n    }\n\n    func testEchoUnixDomainSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        try withTemporaryUnixDomainSocketPathName { udsPath in\n            let numBytes = 16 * 1024\n            let promise = group.next().makePromise(of: ByteBuffer.self)\n            let serverChannel = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                    // Set the handlers that are appled to the accepted Channels\n                    .childChannelInitializer { channel in\n                        channel.eventLoop.makeCompletedFuture {\n                            let countingHandler = ByteCountingHandler(numBytes: numBytes, promise: promise)\n                            try channel.pipeline.syncOperations.addHandler(countingHandler)\n                        }\n                    }.bind(unixDomainSocketPath: udsPath).wait()\n            )\n\n            defer {\n                XCTAssertNoThrow(try serverChannel.close().wait())\n            }\n\n            let clientChannel = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .connect(to: serverChannel.localAddress!)\n                    .wait()\n            )\n\n            defer {\n                XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n            }\n\n            var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n\n            for i in 0..<numBytes {\n                buffer.writeInteger(UInt8(i % 256))\n            }\n\n            XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n\n            XCTAssertEqual(try promise.futureResult.wait(), buffer)\n        }\n    }\n\n    func testConnectUnixDomainSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        try withTemporaryUnixDomainSocketPathName { udsPath in\n            let numBytes = 16 * 1024\n            let promise = group.next().makePromise(of: ByteBuffer.self)\n            let serverChannel = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n                    // Set the handlers that are appled to the accepted Channels\n                    .childChannelInitializer { channel in\n                        channel.eventLoop.makeCompletedFuture {\n                            let countingHandler = ByteCountingHandler(numBytes: numBytes, promise: promise)\n                            try channel.pipeline.syncOperations.addHandler(countingHandler)\n                        }\n                    }.bind(unixDomainSocketPath: udsPath).wait()\n            )\n\n            defer {\n                XCTAssertNoThrow(try serverChannel.close().wait())\n            }\n\n            let clientChannel = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .connect(unixDomainSocketPath: udsPath)\n                    .wait()\n            )\n\n            defer {\n                XCTAssertNoThrow(try clientChannel.close().wait())\n            }\n\n            var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n\n            for i in 0..<numBytes {\n                buffer.writeInteger(UInt8(i % 256))\n            }\n\n            try clientChannel.writeAndFlush(buffer).wait()\n\n            XCTAssertEqual(try promise.futureResult.wait(), buffer)\n        }\n    }\n\n    func testCleanupUnixDomainSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        try withTemporaryUnixDomainSocketPathName { udsPath in\n            let bootstrap = ServerBootstrap(group: group)\n\n            let serverChannel = try assertNoThrowWithValue(\n                bootstrap.bind(unixDomainSocketPath: udsPath).wait()\n            )\n\n            XCTAssertNoThrow(try serverChannel.close().wait())\n\n            let reusedPathServerChannel = try assertNoThrowWithValue(\n                bootstrap.bind(\n                    unixDomainSocketPath: udsPath,\n                    cleanupExistingSocketFile: true\n                ).wait()\n            )\n\n            XCTAssertNoThrow(try reusedPathServerChannel.close().wait())\n        }\n    }\n\n    func testBootstrapUnixDomainSocketNameClash() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        try withTemporaryUnixDomainSocketPathName { udsPath in\n            // Bootstrap should not overwrite an existing file unless it is a socket\n            _ = FileManager.default.createFile(atPath: udsPath, contents: nil, attributes: nil)\n            let bootstrap = ServerBootstrap(group: group)\n\n            XCTAssertThrowsError(\n                try bootstrap.bind(unixDomainSocketPath: udsPath).wait()\n            )\n        }\n    }\n\n    func testEchoVsock() throws {\n        try XCTSkipUnless(System.supportsVsockLoopback, \"No vsock loopback transport available\")\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let numBytes = 16 * 1024\n        let port = VsockAddress.Port(1234)\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let countingHandler = ByteCountingHandler(numBytes: numBytes, promise: promise)\n                        try channel.pipeline.syncOperations.addHandler(countingHandler)\n                    }\n                }\n                .bind(to: VsockAddress(cid: .any, port: port))\n        )\n        .wait()\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        #if canImport(Darwin)\n        let connectAddress = VsockAddress(cid: .any, port: port)\n        #elseif os(Linux) || os(Android)\n        let connectAddress = VsockAddress(cid: .local, port: port)\n        #endif\n        let clientChannel = try assertNoThrowWithValue(ClientBootstrap(group: group).connect(to: connectAddress).wait())\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n\n        for i in 0..<numBytes {\n            buffer.writeInteger(UInt8(i % 256))\n        }\n\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        XCTAssertEqual(try promise.futureResult.wait(), buffer)\n    }\n\n    func testChannelActiveOnConnect() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let promise = group.next().makePromise(of: Void.self)\n        let handler = ChannelActiveHandler(promise: promise)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { $0.pipeline.addHandler(handler) }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        XCTAssertNoThrow(try handler.assertChannelActiveFired())\n    }\n\n    func testWriteThenRead() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(EchoServer())\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let numBytes = 16 * 1024\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let countingHandler = ByteCountingHandler(numBytes: numBytes, promise: promise)\n                        try channel.pipeline.syncOperations.addHandler(countingHandler)\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n        for i in 0..<numBytes {\n            buffer.writeInteger(UInt8(i % 256))\n        }\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n\n        XCTAssertEqual(try promise.futureResult.wait(), buffer)\n    }\n\n    private final class ChannelActiveHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = ByteBuffer\n\n        private let promise: EventLoopPromise<Void>\n\n        init(promise: EventLoopPromise<Void>) {\n            self.promise = promise\n        }\n\n        func channelActive(context: ChannelHandlerContext) {\n            promise.succeed(())\n            context.fireChannelActive()\n        }\n\n        func assertChannelActiveFired() throws {\n            try promise.futureResult.wait()\n        }\n    }\n\n    private final class EchoServer: ChannelInboundHandler {\n        typealias InboundIn = ByteBuffer\n        typealias OutboundOut = ByteBuffer\n\n        func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            context.write(data, promise: nil)\n        }\n\n        func channelReadComplete(context: ChannelHandlerContext) {\n            context.flush()\n        }\n    }\n\n    private final class EchoAndEchoAgainAfterSomeTimeServer: ChannelInboundHandler {\n        typealias InboundIn = ByteBuffer\n        typealias InboundOut = ByteBuffer\n        typealias OutboundOut = ByteBuffer\n\n        private let timeAmount: TimeAmount\n        private let group = DispatchGroup()\n        private var numberOfReads: Int = 0\n        private let calloutQ = DispatchQueue(label: \"EchoAndEchoAgainAfterSomeTimeServer callback queue\")\n\n        public init(time: TimeAmount, secondWriteDoneHandler: @escaping () -> Void) {\n            self.timeAmount = time\n            self.group.enter()\n            self.group.notify(queue: self.calloutQ) {\n                secondWriteDoneHandler()\n            }\n        }\n\n        func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            let bytes = Self.unwrapInboundIn(data)\n            self.numberOfReads += 1\n            precondition(self.numberOfReads == 1, \"\\(self) is only ever allowed to read once\")\n            let loopBoundContext = context.loopBound\n            _ = context.eventLoop.scheduleTask(in: self.timeAmount) { [group] in\n                let context = loopBoundContext.value\n                context.writeAndFlush(Self.wrapInboundOut(bytes), promise: nil)\n                group.leave()\n            }.futureResult.recover { [group] e in\n                XCTFail(\"we failed to schedule the task: \\(e)\")\n                group.leave()\n            }\n            context.writeAndFlush(data, promise: nil)\n        }\n    }\n\n    private final class WriteALotHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = ByteBuffer\n        typealias OutboundOut = ByteBuffer\n\n        func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n            for _ in 0..<10000 {\n                context.write(data, promise: nil)\n            }\n        }\n\n        func channelReadComplete(context: ChannelHandlerContext) {\n            context.flush()\n        }\n    }\n\n    private final class CloseInInActiveAndUnregisteredChannelHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = Never\n        let alreadyClosedInChannelInactive = ManagedAtomic(false)\n        let alreadyClosedInChannelUnregistered = ManagedAtomic(false)\n        let channelUnregisteredPromise: EventLoopPromise<Void>\n        let channelInactivePromise: EventLoopPromise<Void>\n\n        public init(\n            channelUnregisteredPromise: EventLoopPromise<Void>,\n            channelInactivePromise: EventLoopPromise<Void>\n        ) {\n            self.channelUnregisteredPromise = channelUnregisteredPromise\n            self.channelInactivePromise = channelInactivePromise\n        }\n\n        public func channelActive(context: ChannelHandlerContext) {\n            context.close().whenFailure { error in\n                XCTFail(\"bad, initial close failed (\\(error))\")\n            }\n        }\n\n        public func channelInactive(context: ChannelHandlerContext) {\n            if alreadyClosedInChannelInactive.compareExchange(expected: false, desired: true, ordering: .relaxed)\n                .exchanged\n            {\n                XCTAssertFalse(\n                    self.channelUnregisteredPromise.futureResult.isFulfilled,\n                    \"channelInactive should fire before channelUnregistered\"\n                )\n                context.close().map {\n                    XCTFail(\"unexpected success\")\n                }.recover { err in\n                    switch err {\n                    case ChannelError.alreadyClosed:\n                        // OK\n                        ()\n                    default:\n                        XCTFail(\"unexpected error: \\(err)\")\n                    }\n                }.whenComplete { [channelInactivePromise] (_: Result<Void, Error>) in\n                    channelInactivePromise.succeed(())\n                }\n            }\n        }\n\n        public func channelUnregistered(context: ChannelHandlerContext) {\n            if alreadyClosedInChannelUnregistered.compareExchange(expected: false, desired: true, ordering: .relaxed)\n                .exchanged\n            {\n                XCTAssertTrue(\n                    self.channelInactivePromise.futureResult.isFulfilled,\n                    \"when channelUnregister fires, channelInactive should already have fired\"\n                )\n                context.close().map {\n                    XCTFail(\"unexpected success\")\n                }.recover { err in\n                    switch err {\n                    case ChannelError.alreadyClosed:\n                        // OK\n                        ()\n                    default:\n                        XCTFail(\"unexpected error: \\(err)\")\n                    }\n                }.whenComplete { [channelUnregisteredPromise] (_: Result<Void, Error>) in\n                    channelUnregisteredPromise.succeed(())\n                }\n            }\n        }\n    }\n\n    /// A channel handler that calls write on connect.\n    private final class WriteOnConnectHandler: ChannelInboundHandler, Sendable {\n        typealias InboundIn = ByteBuffer\n\n        private let toWrite: String\n\n        init(toWrite: String) {\n            self.toWrite = toWrite\n        }\n\n        func channelActive(context: ChannelHandlerContext) {\n            let dataToWrite = context.channel.allocator.buffer(string: toWrite)\n            context.writeAndFlush(NIOAny(dataToWrite), promise: nil)\n            context.fireChannelActive()\n        }\n    }\n\n    func testCloseInInactive() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let inactivePromise = group.next().makePromise() as EventLoopPromise<Void>\n        let unregistredPromise = group.next().makePromise() as EventLoopPromise<Void>\n        let handler = CloseInInActiveAndUnregisteredChannelHandler(\n            channelUnregisteredPromise: unregistredPromise,\n            channelInactivePromise: inactivePromise\n        )\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n\n                .childChannelInitializer { channel in\n                    channel.pipeline.addHandler(handler)\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            _ = clientChannel.close()\n        }\n\n        _ = try inactivePromise.futureResult.and(unregistredPromise.futureResult).wait()\n\n        XCTAssertTrue(handler.alreadyClosedInChannelInactive.load(ordering: .relaxed))\n        XCTAssertTrue(handler.alreadyClosedInChannelUnregistered.load(ordering: .relaxed))\n    }\n\n    func testFlushOnEmpty() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let writingBytes = \"hello\"\n        let bytesReceivedPromise = group.next().makePromise(of: ByteBuffer.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    // When we've received all the bytes we know the connection is up. Remove the handler.\n                    channel.eventLoop.makeCompletedFuture {\n                        let byteCountingHandler = ByteCountingHandler(\n                            numBytes: writingBytes.utf8.count,\n                            promise: bytesReceivedPromise\n                        )\n\n                        _ = bytesReceivedPromise.futureResult.hop(\n                            to: channel.eventLoop\n                        ).assumeIsolated().flatMapThrowing { (_: ByteBuffer) in\n                            channel.pipeline.syncOperations.removeHandler(byteCountingHandler)\n                        }\n\n                        try channel.pipeline.syncOperations.addHandler(byteCountingHandler)\n                    }\n\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        defer {\n            _ = clientChannel.close()\n        }\n\n        // First we confirm that the channel really is up by sending in the appropriate number of bytes.\n        let bytesToWrite = clientChannel.allocator.buffer(string: writingBytes)\n        let lastWriteFuture = clientChannel.writeAndFlush(bytesToWrite)\n\n        // When we've received all the bytes we know the connection is up.\n        _ = try bytesReceivedPromise.futureResult.wait()\n\n        // Now, with an empty write pipeline, we want to flush. This should complete immediately and without error.\n        clientChannel.flush()\n        lastWriteFuture.whenFailure { err in\n            XCTFail(\"\\(err)\")\n        }\n        try lastWriteFuture.wait()\n    }\n\n    func testWriteOnConnect() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(EchoServer())\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let stringToWrite = \"hello\"\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let sync = channel.pipeline.syncOperations\n                        try sync.addHandler(WriteOnConnectHandler(toWrite: stringToWrite))\n                        try sync.addHandler(ByteCountingHandler(numBytes: stringToWrite.utf8.count, promise: promise))\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        defer {\n            _ = clientChannel.close()\n        }\n\n        let bytes = try promise.futureResult.wait()\n        XCTAssertEqual(bytes.getString(at: bytes.readerIndex, length: bytes.readableBytes), stringToWrite)\n    }\n\n    func testWriteOnAccept() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let stringToWrite = \"hello\"\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.pipeline.addHandler(WriteOnConnectHandler(toWrite: stringToWrite))\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(numBytes: stringToWrite.utf8.count, promise: promise)\n                        )\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.close().wait())\n        }\n\n        let bytes = try assertNoThrowWithValue(promise.futureResult.wait())\n        XCTAssertEqual(bytes.getString(at: bytes.readerIndex, length: bytes.readableBytes), stringToWrite)\n    }\n\n    func testWriteAfterChannelIsDead() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let dpGroup = DispatchGroup()\n\n        dpGroup.enter()\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            EchoAndEchoAgainAfterSomeTimeServer(\n                                time: .seconds(1),\n                                secondWriteDoneHandler: {\n                                    dpGroup.leave()\n                                }\n                            )\n                        )\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let str = \"hi there\"\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(numBytes: str.utf8.count, promise: promise)\n                        )\n                    }\n                }\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n\n        let buffer = clientChannel.allocator.buffer(string: str)\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        XCTAssertEqual(try promise.futureResult.wait(), buffer)\n\n        // close the client channel so that the second write should fail\n        try clientChannel.close().wait()\n\n        dpGroup.wait()  // make sure we stick around until the second write has happened\n    }\n\n    func testPendingReadProcessedAfterWriteError() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        let loop1 = group.next()\n        let loop2 = group.next()\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let dpGroup = DispatchGroup()\n        dpGroup.enter()\n\n        let str = \"hi there\"\n\n        class WriteHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private var writeFailed = false\n\n            func channelActive(context: ChannelHandlerContext) {\n                var buffer = context.channel.allocator.buffer(capacity: 4)\n                buffer.writeString(\"test\")\n                Self.writeUntilFailed(context, buffer)\n            }\n\n            private static func writeUntilFailed(_ context: ChannelHandlerContext, _ buffer: ByteBuffer) {\n                let loopBoundContext = context.loopBound\n                context.writeAndFlush(NIOAny(buffer)).whenSuccess { [eventLoop = context.eventLoop] in\n                    eventLoop.assumeIsolated().execute {\n                        let context = loopBoundContext.value\n                        Self.writeUntilFailed(context, buffer)\n                    }\n                }\n            }\n        }\n\n        class WriteWhenActiveHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            let str: String\n            let dpGroup: DispatchGroup\n\n            init(_ str: String, _ dpGroup: DispatchGroup) {\n                self.str = str\n                self.dpGroup = dpGroup\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                context.fireChannelActive()\n                let buffer = context.channel.allocator.buffer(string: str)\n\n                // write it four times and then close the connect.\n                let loopBoundContext = context.loopBound\n                context.writeAndFlush(NIOAny(buffer)).flatMap {\n                    let context = loopBoundContext.value\n                    return context.writeAndFlush(NIOAny(buffer))\n                }.flatMap {\n                    let context = loopBoundContext.value\n                    return context.writeAndFlush(NIOAny(buffer))\n                }.flatMap {\n                    let context = loopBoundContext.value\n                    return context.writeAndFlush(NIOAny(buffer))\n                }.flatMap {\n                    let context = loopBoundContext.value\n                    return context.close()\n                }.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                    self.dpGroup.leave()\n                }\n            }\n        }\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: loop1)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(WriteWhenActiveHandler(str, dpGroup))\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: loop2)\n                // We will only start reading once we wrote all data on the accepted channel.\n                //.channelOption(.autoRead, value: false)\n                .channelOption(.recvAllocator, value: FixedSizeRecvByteBufferAllocator(capacity: 2))\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(WriteHandler())\n                    }.flatMapThrowing {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(numBytes: str.utf8.count * 4, promise: promise)\n                        )\n                    }\n                }.connect(to: serverChannel.localAddress!).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n        dpGroup.wait()\n\n        var completeBuffer = clientChannel.allocator.buffer(capacity: str.utf8.count * 4)\n        completeBuffer.writeString(str)\n        completeBuffer.writeString(str)\n        completeBuffer.writeString(str)\n        completeBuffer.writeString(str)\n\n        XCTAssertEqual(try promise.futureResult.wait(), completeBuffer)\n    }\n\n    func testChannelErrorEOFNotFiredThroughPipeline() throws {\n\n        class ErrorHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private let promise: EventLoopPromise<Void>\n\n            init(_ promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            public func errorCaught(context: ChannelHandlerContext, error: Error) {\n                if let err = error as? ChannelError {\n                    XCTAssertNotEqual(ChannelError.eof, err)\n                }\n            }\n\n            public func channelInactive(context: ChannelHandlerContext) {\n                self.promise.succeed(())\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let promise = group.next().makePromise(of: Void.self)\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(ErrorHandler(promise))\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!).wait()\n        )\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        XCTAssertNoThrow(try promise.futureResult.wait())\n    }\n\n    func testPortNumbers() throws {\n        var atLeastOneSucceeded = false\n        for host in [\"127.0.0.1\", \"::1\"] {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n            defer {\n                XCTAssertNoThrow(try group.syncShutdownGracefully())\n            }\n            let acceptedRemotePort = ManagedAtomic<Int>(-1)\n            let acceptedLocalPort = ManagedAtomic<Int>(-2)\n            let sem = DispatchSemaphore(value: 0)\n\n            let serverChannel: Channel\n            do {\n                serverChannel = try ServerBootstrap(group: group)\n                    .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .childChannelInitializer { channel in\n                        acceptedRemotePort.store(channel.remoteAddress?.port ?? -3, ordering: .relaxed)\n                        acceptedLocalPort.store(channel.localAddress?.port ?? -4, ordering: .relaxed)\n                        sem.signal()\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }.bind(host: host, port: 0).wait()\n            } catch let e as SocketAddressError {\n                if case .unknown(host, port: 0) = e {\n                    // this can happen if the system isn't configured for both IPv4 and IPv6\n                    continue\n                } else {\n                    // nope, that's a different socket error\n                    XCTFail(\"unexpected SocketAddressError: \\(e)\")\n                    break\n                }\n            } catch {\n                // other unknown error\n                XCTFail(\"unexpected error: \\(error)\")\n                break\n            }\n            atLeastOneSucceeded = true\n            defer {\n                XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n            }\n\n            let clientChannel = try assertNoThrowWithValue(\n                ClientBootstrap(group: group).connect(\n                    host: host,\n                    port: Int(serverChannel.localAddress!.port!)\n                ).wait()\n            )\n            defer {\n                XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n            }\n            sem.wait()\n            XCTAssertEqual(serverChannel.localAddress?.port, clientChannel.remoteAddress?.port)\n            XCTAssertEqual(acceptedLocalPort.load(ordering: .relaxed), clientChannel.remoteAddress?.port ?? -5)\n            XCTAssertEqual(acceptedRemotePort.load(ordering: .relaxed), clientChannel.localAddress?.port ?? -6)\n        }\n        XCTAssertTrue(atLeastOneSucceeded)\n    }\n\n    func testConnectingToIPv4And6ButServerOnlyWaitsOnIPv4() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let numBytes = 16 * 1024\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n\n        // we're binding to IPv4 only\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let countingHandler = ByteCountingHandler(numBytes: numBytes, promise: promise)\n                        try channel.pipeline.syncOperations.addHandler(countingHandler)\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        // but we're trying to connect to (depending on the system configuration and resolver) IPv4 and IPv6\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(host: \"localhost\", port: Int(serverChannel.localAddress!.port!))\n                .flatMapError {\n                    promise.fail($0)\n                    return group.next().makeFailedFuture($0)\n                }\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n\n        for i in 0..<numBytes {\n            buffer.writeInteger(UInt8(i % 256))\n        }\n\n        try clientChannel.writeAndFlush(buffer).wait()\n\n        XCTAssertEqual(try promise.futureResult.wait(), buffer)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/EventLoopFutureIsolatedTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOEmbedded\nimport NIOPosix\nimport XCTest\n\nfinal class SuperNotSendable {\n    var x: Int = 5\n}\n\n@available(*, unavailable)\nextension SuperNotSendable: Sendable {}\n\n// A very stupid event loop that implements as little of the protocol as possible.\n//\n// We use this to confirm that the fallback path for the isolated views works, by not implementing\n// their fast-paths. Instead, we forward to the underlying implementation. We use `AsyncTestingEventLoop`\n// to provide the backing implementation.\nprivate final class FallbackEventLoop: RunnableEventLoop {\n    private let base: NIOAsyncTestingEventLoop\n\n    init() {\n        self.base = .init()\n    }\n\n    var now: NIODeadline {\n        self.base.now\n    }\n\n    var inEventLoop: Bool {\n        self.base.inEventLoop\n    }\n\n    func execute(_ task: @escaping @Sendable () -> Void) {\n        self.base.execute(task)\n    }\n\n    func scheduleTask<T>(\n        deadline: NIOCore.NIODeadline,\n        _ task: @escaping @Sendable () throws -> T\n    ) -> NIOCore.Scheduled<T> {\n        self.base.scheduleTask(deadline: deadline, task)\n    }\n\n    func scheduleTask<T>(\n        in delay: NIOCore.TimeAmount,\n        _ task: @escaping @Sendable () throws -> T\n    ) -> NIOCore.Scheduled<T> {\n        self.base.scheduleTask(in: delay, task)\n    }\n\n    func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable ((any Error)?) -> Void) {\n        self.base.shutdownGracefully(queue: queue, callback)\n    }\n\n    func runForTests() {\n        self.base.runForTests()\n    }\n\n    func advanceTimeForTests(by amount: TimeAmount) {\n        self.base.advanceTimeForTests(by: amount)\n    }\n}\n\nprivate protocol RunnableEventLoop: EventLoop {\n    func runForTests()\n    func advanceTimeForTests(by: TimeAmount)\n}\n\nextension EmbeddedEventLoop: RunnableEventLoop {\n    fileprivate func runForTests() {\n        self.run()\n    }\n\n    fileprivate func advanceTimeForTests(by amount: TimeAmount) {\n        self.advanceTime(by: amount)\n    }\n}\n\nextension NIOAsyncTestingEventLoop: RunnableEventLoop {\n    fileprivate func runForTests() {\n        // This is horrible, but it's the only general-purpose implementation.\n        let promise = self.makePromise(of: Void.self)\n        promise.completeWithTask {\n            await self.run()\n        }\n        try! promise.futureResult.wait()\n    }\n\n    fileprivate func advanceTimeForTests(by amount: TimeAmount) {\n        // This is horrible, but it's the only general-purpose implementation.\n        let promise = self.makePromise(of: Void.self)\n        promise.completeWithTask {\n            await self.advanceTime(by: amount)\n        }\n        try! promise.futureResult.wait()\n    }\n}\n\nfinal class EventLoopFutureIsolatedTest: XCTestCase {\n    func _completingPromiseWithNonSendableValue(loop: any EventLoop) throws {\n        let f = loop.flatSubmit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let value = SuperNotSendable()\n            promise.assumeIsolated().succeed(value)\n            return promise.futureResult.assumeIsolated().map { val in\n                XCTAssertIdentical(val, value)\n            }.nonisolated()\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _completingPromiseWithNonSendableResult(loop: any EventLoop) throws {\n        let f = loop.flatSubmit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let value = SuperNotSendable()\n            promise.assumeIsolated().completeWith(.success(value))\n            return promise.futureResult.assumeIsolated().map { val in\n                XCTAssertIdentical(val, value)\n            }.nonisolated()\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _completingPromiseWithNonSendableValueUnchecked(loop: any EventLoop) throws {\n        let f = loop.flatSubmit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let value = SuperNotSendable()\n            promise.assumeIsolatedUnsafeUnchecked().succeed(value)\n            return promise.futureResult.assumeIsolatedUnsafeUnchecked().map { val in\n                XCTAssertIdentical(val, value)\n            }.nonisolated()\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _completingPromiseWithNonSendableResultUnchecked(loop: any EventLoop) throws {\n        let f = loop.flatSubmit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let value = SuperNotSendable()\n            promise.assumeIsolatedUnsafeUnchecked().completeWith(.success(value))\n            return promise.futureResult.assumeIsolatedUnsafeUnchecked().map { val in\n                XCTAssertIdentical(val, value)\n            }.nonisolated()\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _backAndForthUnwrapping(loop: any EventLoop) throws {\n        let f = loop.submit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let future = promise.futureResult\n\n            XCTAssertEqual(promise.assumeIsolated().nonisolated(), promise)\n            XCTAssertEqual(future.assumeIsolated().nonisolated(), future)\n            promise.assumeIsolated().succeed(SuperNotSendable())\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _backAndForthUnwrappingUnchecked(loop: any EventLoop) throws {\n        let f = loop.submit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let future = promise.futureResult\n\n            XCTAssertEqual(promise.assumeIsolatedUnsafeUnchecked().nonisolated(), promise)\n            XCTAssertEqual(future.assumeIsolatedUnsafeUnchecked().nonisolated(), future)\n            promise.assumeIsolated().succeed(SuperNotSendable())\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _futureChaining(loop: any EventLoop) throws {\n        enum TestError: Error {\n            case error\n        }\n\n        let f = loop.flatSubmit {\n            let promise = loop.makePromise(of: SuperNotSendable.self)\n            let future = promise.futureResult.assumeIsolated()\n            let originalValue = SuperNotSendable()\n\n            // Note that for this test it is _very important_ that all of these\n            // close over `originalValue`. This proves the non-Sendability of\n            // the closure.\n\n            // This block is the main happy path.\n            let newFuture = future.flatMap { result in\n                XCTAssertIdentical(originalValue, result)\n                let promise = loop.makePromise(of: Int.self)\n                promise.succeed(4)\n                return promise.futureResult\n            }.map { (result: Int) in\n                XCTAssertEqual(result, 4)\n                return originalValue\n            }.flatMapThrowing { (result: SuperNotSendable) in\n                XCTAssertIdentical(originalValue, result)\n                return SuperNotSendable()\n            }.flatMapResult { (result: SuperNotSendable) -> Result<SuperNotSendable, any Error> in\n                XCTAssertNotIdentical(originalValue, result)\n                return .failure(TestError.error)\n            }.recover { err in\n                XCTAssertTrue(err is TestError)\n                return originalValue\n            }.always { val in\n                XCTAssertNotNil(try? val.get())\n            }\n\n            newFuture.whenComplete { result in\n                guard case .success(let r) = result else {\n                    XCTFail(\"Unexpected error\")\n                    return\n                }\n                XCTAssertIdentical(r, originalValue)\n            }\n            newFuture.whenSuccess { result in\n                XCTAssertIdentical(result, originalValue)\n            }\n\n            // This block covers the flatMapError and whenFailure tests\n            let throwingFuture = newFuture.flatMapThrowing { (_: SuperNotSendable) throws -> SuperNotSendable in\n                XCTAssertEqual(originalValue.x, 5)\n                throw TestError.error\n            }\n            throwingFuture.whenFailure { error in\n                // Supurious but forces the closure.\n                XCTAssertEqual(originalValue.x, 5)\n                guard let error = error as? TestError, error == .error else {\n                    XCTFail(\"Invalid passed error: \\(error)\")\n                    return\n                }\n            }\n            throwingFuture.flatMapErrorThrowing { error in\n                guard let error = error as? TestError, error == .error else {\n                    XCTFail(\"Invalid passed error: \\(error)\")\n                    throw error\n                }\n                return originalValue\n            }.whenComplete { result in\n                guard case .success(let r) = result else {\n                    XCTFail(\"Unexpected error\")\n                    return\n                }\n                XCTAssertIdentical(r, originalValue)\n            }\n            throwingFuture.map { _ in 5 }.flatMapError { (error: any Error) -> EventLoopFuture<Int> in\n                guard let error = error as? TestError, error == .error else {\n                    XCTFail(\"Invalid passed error: \\(error)\")\n                    return loop.makeSucceededFuture(originalValue.x)\n                }\n                return loop.makeSucceededFuture(originalValue.x - 1)\n            }.whenComplete { (result: Result<Int, any Error>) in\n                guard case .success(let r) = result else {\n                    XCTFail(\"Unexpected error\")\n                    return\n                }\n                XCTAssertEqual(r, originalValue.x - 1)\n            }\n            throwingFuture.map { _ in 5 }.flatMapError { (error: any Error) -> EventLoopFuture<Int>.Isolated in\n                guard let error = error as? TestError, error == .error else {\n                    XCTFail(\"Invalid passed error: \\(error)\")\n                    return loop.makeSucceededIsolatedFuture(originalValue.x)\n                }\n                return loop.makeSucceededIsolatedFuture(originalValue.x - 2)\n            }.whenComplete { (result: Result<Int, any Error>) in\n                guard case .success(let r) = result else {\n                    XCTFail(\"Unexpected error\")\n                    return\n                }\n                XCTAssertEqual(r, originalValue.x - 2)\n            }\n\n            // This block handles unwrap.\n            newFuture.map { x -> SuperNotSendable? in\n                XCTAssertEqual(originalValue.x, 5)\n                return nil\n            }.unwrap(orReplace: originalValue).unwrap(\n                orReplace: SuperNotSendable()\n            ).map { x -> SuperNotSendable? in\n                XCTAssertIdentical(x, originalValue)\n                return nil\n            }.unwrap(orElse: {\n                originalValue\n            }).unwrap(orElse: {\n                SuperNotSendable()\n            }).whenSuccess { x in\n                XCTAssertIdentical(x, originalValue)\n            }\n\n            promise.assumeIsolated().succeed(originalValue)\n            return newFuture.map { _ in }.nonisolated()\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.runForTests()\n        }\n        try f.wait()\n    }\n\n    func _eventLoopIsolated(loop: any EventLoop) throws {\n        let f = loop.flatSubmit {\n            let value = SuperNotSendable()\n            value.x = 4\n\n            // Again, all of these need to close over value. In addition,\n            // many need to return it as well.\n            let isolated = loop.assumeIsolated()\n            XCTAssertIdentical(isolated.nonisolated(), loop)\n            isolated.execute {\n                XCTAssertEqual(value.x, 4)\n                value.x = 5\n            }\n            let firstFuture = isolated.submit {\n                let val = SuperNotSendable()\n                val.x = value.x + 1\n                return val\n            }.map { $0.x }\n\n            let secondFuture = isolated.scheduleTask(deadline: loop.now + .milliseconds(50)) {\n                let val = SuperNotSendable()\n                val.x = value.x + 1\n                return val\n            }.futureResult.map { $0.x }\n\n            let thirdFuture = isolated.scheduleTask(in: .milliseconds(50)) {\n                let val = SuperNotSendable()\n                val.x = value.x + 1\n                return val\n            }.futureResult.map { $0.x }\n\n            let fourthFuture = isolated.flatScheduleTask(deadline: loop.now + .milliseconds(50)) {\n                let promise = loop.makePromise(of: Int.self)\n                promise.succeed(value.x + 1)\n                return promise.futureResult\n            }.futureResult.map { $0 }\n\n            return EventLoopFuture.reduce(\n                into: 0,\n                [firstFuture, secondFuture, thirdFuture, fourthFuture],\n                on: loop\n            ) { $0 += $1 }\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.advanceTimeForTests(by: .milliseconds(51))\n        }\n        let result = try f.wait()\n\n        XCTAssertEqual(result, 6 * 4)\n    }\n\n    func _eventLoopIsolatedUnchecked(loop: any EventLoop) throws {\n        let f = loop.flatSubmit {\n            let value = SuperNotSendable()\n\n            // Again, all of these need to close over value. In addition,\n            // many need to return it as well.\n            let isolated = loop.assumeIsolatedUnsafeUnchecked()\n            XCTAssertIdentical(isolated.nonisolated(), loop)\n            isolated.execute {\n                XCTAssertEqual(value.x, 5)\n            }\n            let firstFuture = isolated.submit {\n                let val = SuperNotSendable()\n                val.x = value.x + 1\n                return val\n            }.map { $0.x }\n\n            let secondFuture = isolated.scheduleTask(deadline: loop.now + .milliseconds(50)) {\n                let val = SuperNotSendable()\n                val.x = value.x + 1\n                return val\n            }.futureResult.map { $0.x }\n\n            let thirdFuture = isolated.scheduleTask(in: .milliseconds(50)) {\n                let val = SuperNotSendable()\n                val.x = value.x + 1\n                return val\n            }.futureResult.map { $0.x }\n\n            let fourthFuture = isolated.flatScheduleTask(deadline: loop.now + .milliseconds(50)) {\n                let promise = loop.makePromise(of: Int.self)\n                promise.succeed(value.x + 1)\n                return promise.futureResult\n            }.futureResult.map { $0 }\n\n            return EventLoopFuture.reduce(\n                into: 0,\n                [firstFuture, secondFuture, thirdFuture, fourthFuture],\n                on: loop\n            ) { $0 += $1 }\n        }\n        if let runnable = loop as? RunnableEventLoop {\n            runnable.advanceTimeForTests(by: .milliseconds(50))\n        }\n        let result = try f.wait()\n\n        XCTAssertEqual(result, 6 * 4)\n    }\n\n    // MARK: SelectableEL\n    func testCompletingPromiseWithNonSendableValue_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._completingPromiseWithNonSendableValue(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResult_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._completingPromiseWithNonSendableResult(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableValueUnchecked_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._completingPromiseWithNonSendableValueUnchecked(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResultUnchecked_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._completingPromiseWithNonSendableResultUnchecked(loop: loop)\n    }\n\n    func testBackAndForthUnwrapping_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._backAndForthUnwrapping(loop: loop)\n    }\n\n    func testBackAndForthUnwrappingUnchecked_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._backAndForthUnwrappingUnchecked(loop: loop)\n    }\n\n    func testFutureChaining_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._futureChaining(loop: loop)\n    }\n\n    func testEventLoopIsolated_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._eventLoopIsolated(loop: loop)\n    }\n\n    func testEventLoopIsolatedUnchecked_SelectableEL() throws {\n        let loop = MultiThreadedEventLoopGroup.singleton.next()\n        try self._eventLoopIsolatedUnchecked(loop: loop)\n    }\n\n    // MARK: EmbeddedEL\n    func testCompletingPromiseWithNonSendableValue_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._completingPromiseWithNonSendableValue(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResult_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._completingPromiseWithNonSendableResult(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableValueUnchecked_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._completingPromiseWithNonSendableValueUnchecked(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResultUnchecked_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._completingPromiseWithNonSendableResultUnchecked(loop: loop)\n    }\n\n    func testBackAndForthUnwrapping_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._backAndForthUnwrapping(loop: loop)\n    }\n\n    func testBackAndForthUnwrappingUnchecked_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._backAndForthUnwrappingUnchecked(loop: loop)\n    }\n\n    func testFutureChaining_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._futureChaining(loop: loop)\n    }\n\n    func testEventLoopIsolated_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._eventLoopIsolated(loop: loop)\n    }\n\n    func testEventLoopIsolatedUnchecked_EmbeddedEL() throws {\n        let loop = EmbeddedEventLoop()\n        try self._eventLoopIsolatedUnchecked(loop: loop)\n    }\n\n    // MARK: AsyncTestingEL\n    func testCompletingPromiseWithNonSendableValue_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._completingPromiseWithNonSendableValue(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResult_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._completingPromiseWithNonSendableResult(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableValueUnchecked_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._completingPromiseWithNonSendableValueUnchecked(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResultUnchecked_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._completingPromiseWithNonSendableResultUnchecked(loop: loop)\n    }\n\n    func testBackAndForthUnwrapping_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._backAndForthUnwrapping(loop: loop)\n    }\n\n    func testBackAndForthUnwrappingUnchecked_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._backAndForthUnwrappingUnchecked(loop: loop)\n    }\n\n    func testFutureChaining_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._futureChaining(loop: loop)\n    }\n\n    func testEventLoopIsolated_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._eventLoopIsolated(loop: loop)\n    }\n\n    func testEventLoopIsolatedUnchecked_AsyncTestingEL() throws {\n        let loop = NIOAsyncTestingEventLoop()\n        try self._eventLoopIsolatedUnchecked(loop: loop)\n    }\n\n    // MARK: Fallback\n    func testCompletingPromiseWithNonSendableValue_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._completingPromiseWithNonSendableValue(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResult_() throws {\n        let loop = FallbackEventLoop()\n        try self._completingPromiseWithNonSendableResult(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableValueUnchecked_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._completingPromiseWithNonSendableValueUnchecked(loop: loop)\n    }\n\n    func testCompletingPromiseWithNonSendableResultUnchecked_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._completingPromiseWithNonSendableResultUnchecked(loop: loop)\n    }\n\n    func testBackAndForthUnwrapping_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._backAndForthUnwrapping(loop: loop)\n    }\n\n    func testBackAndForthUnwrappingUnchecked_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._backAndForthUnwrappingUnchecked(loop: loop)\n    }\n\n    func testFutureChaining_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._futureChaining(loop: loop)\n    }\n\n    func testEventLoopIsolated_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._eventLoopIsolated(loop: loop)\n    }\n\n    func testEventLoopIsolatedUnchecked_Fallback() throws {\n        let loop = FallbackEventLoop()\n        try self._eventLoopIsolatedUnchecked(loop: loop)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/EventLoopFutureTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport NIOPosix\nimport Testing\n\n@testable import NIOCore\n\nenum EventLoopFutureTestError: Error {\n    case example\n}\n\n@Suite(\"EventLoopFutureTest\", .serialized)\nclass EventLoopFutureTest {\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFutureFulfilledIfHasResult() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let f = EventLoopFuture(eventLoop: eventLoop, value: 5)\n        #expect(f.isFulfilled)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFutureFulfilledIfHasError() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let f = EventLoopFuture<Void>(eventLoop: eventLoop, error: EventLoopFutureTestError.example)\n        #expect(f.isFulfilled)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithMultipleEventLoops() throws {\n        let nThreads = 3\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: nThreads)\n        defer {\n            #expect(throws: Never.self) { try eventLoopGroup.syncShutdownGracefully() }\n        }\n\n        let eventLoop0 = eventLoopGroup.next()\n        let eventLoop1 = eventLoopGroup.next()\n        let eventLoop2 = eventLoopGroup.next()\n\n        #expect(eventLoop0 !== eventLoop1)\n        #expect(eventLoop1 !== eventLoop2)\n        #expect(eventLoop0 !== eventLoop2)\n\n        let f0: EventLoopFuture<[Int]> = eventLoop0.submit { [0] }\n        let f1s: [EventLoopFuture<Int>] = (1...4).map { id in eventLoop1.submit { id } }\n        let f2s: [EventLoopFuture<Int>] = (5...8).map { id in eventLoop2.submit { id } }\n\n        var fN = f0.fold(f1s) { (f1Value: [Int], f2Value: Int) -> EventLoopFuture<[Int]> in\n            #expect(eventLoop0.inEventLoop)\n            return eventLoop1.makeSucceededFuture(f1Value + [f2Value])\n        }\n\n        fN = fN.fold(f2s) { (f1Value: [Int], f2Value: Int) -> EventLoopFuture<[Int]> in\n            #expect(eventLoop0.inEventLoop)\n            return eventLoop2.makeSucceededFuture(f1Value + [f2Value])\n        }\n\n        let allValues = try fN.wait()\n        #expect(fN.eventLoop === f0.eventLoop)\n        #expect(fN.isFulfilled)\n        #expect(allValues == [0, 1, 2, 3, 4, 5, 6, 7, 8])\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithSuccessAndAllSuccesses() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let secondEventLoop = EmbeddedEventLoop()\n        let f0 = eventLoop.makeSucceededFuture([0])\n\n        let futures: [EventLoopFuture<Int>] = (1...5).map { (id: Int) in\n            secondEventLoop.makeSucceededFuture(id)\n        }\n\n        let fN = f0.fold(futures) { (f1Value: [Int], f2Value: Int) -> EventLoopFuture<[Int]> in\n            #expect(eventLoop.inEventLoop)\n            return secondEventLoop.makeSucceededFuture(f1Value + [f2Value])\n        }\n\n        let allValues = try fN.wait()\n        #expect(fN.eventLoop === f0.eventLoop)\n        #expect(fN.isFulfilled)\n        #expect(allValues == [0, 1, 2, 3, 4, 5])\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithSuccessAndOneFailure() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let secondEventLoop = EmbeddedEventLoop()\n        let f0: EventLoopFuture<Int> = eventLoop.makeSucceededFuture(0)\n\n        let promises: [EventLoopPromise<Int>] = (0..<100).map { (_: Int) in\n            secondEventLoop.makePromise()\n        }\n        var futures = promises.map { $0.futureResult }\n        let failedFuture: EventLoopFuture<Int> = secondEventLoop.makeFailedFuture(E())\n        futures.insert(failedFuture, at: futures.startIndex)\n\n        let fN = f0.fold(futures) { (f1Value: Int, f2Value: Int) -> EventLoopFuture<Int> in\n            #expect(eventLoop.inEventLoop)\n            return secondEventLoop.makeSucceededFuture(f1Value + f2Value)\n        }\n\n        _ = promises.map { $0.succeed(0) }\n        #expect(fN.isFulfilled)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithSuccessAndEmptyFutureList() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let f0 = eventLoop.makeSucceededFuture(0)\n\n        let futures: [EventLoopFuture<Int>] = []\n\n        let fN = f0.fold(futures) { (f1Value: Int, f2Value: Int) -> EventLoopFuture<Int> in\n            #expect(eventLoop.inEventLoop)\n            return eventLoop.makeSucceededFuture(f1Value + f2Value)\n        }\n\n        let summationResult = try fN.wait()\n        #expect(fN.isFulfilled)\n        #expect(summationResult == 0)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithFailureAndEmptyFutureList() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let f0: EventLoopFuture<Int> = eventLoop.makeFailedFuture(E())\n\n        let futures: [EventLoopFuture<Int>] = []\n\n        let fN = f0.fold(futures) { (f1Value: Int, f2Value: Int) -> EventLoopFuture<Int> in\n            #expect(eventLoop.inEventLoop)\n            return eventLoop.makeSucceededFuture(f1Value + f2Value)\n        }\n\n        #expect(fN.isFulfilled)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithFailureAndAllSuccesses() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let secondEventLoop = EmbeddedEventLoop()\n        let f0: EventLoopFuture<Int> = eventLoop.makeFailedFuture(E())\n\n        let promises: [EventLoopPromise<Int>] = (0..<100).map { (_: Int) in\n            secondEventLoop.makePromise()\n        }\n        let futures = promises.map { $0.futureResult }\n\n        let fN = f0.fold(futures) { (f1Value: Int, f2Value: Int) -> EventLoopFuture<Int> in\n            #expect(eventLoop.inEventLoop)\n            return secondEventLoop.makeSucceededFuture(f1Value + f2Value)\n        }\n\n        _ = promises.map { $0.succeed(1) }\n        #expect(fN.isFulfilled)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithFailureAndAllUnfulfilled() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let secondEventLoop = EmbeddedEventLoop()\n        let f0: EventLoopFuture<Int> = eventLoop.makeFailedFuture(E())\n\n        let promises: [EventLoopPromise<Int>] = (0..<100).map { (_: Int) in\n            secondEventLoop.makePromise()\n        }\n        let futures = promises.map { $0.futureResult }\n\n        let fN = f0.fold(futures) { (f1Value: Int, f2Value: Int) -> EventLoopFuture<Int> in\n            #expect(eventLoop.inEventLoop)\n            return secondEventLoop.makeSucceededFuture(f1Value + f2Value)\n        }\n\n        #expect(fN.isFulfilled)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithFailureAndAllFailures() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let secondEventLoop = EmbeddedEventLoop()\n        let f0: EventLoopFuture<Int> = eventLoop.makeFailedFuture(E())\n\n        let futures: [EventLoopFuture<Int>] = (0..<100).map { (_: Int) in\n            secondEventLoop.makeFailedFuture(E())\n        }\n\n        let fN = f0.fold(futures) { (f1Value: Int, f2Value: Int) -> EventLoopFuture<Int> in\n            #expect(eventLoop.inEventLoop)\n            return secondEventLoop.makeSucceededFuture(f1Value + f2Value)\n        }\n\n        #expect(fN.isFulfilled)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllWithEmptyFutureList() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let futures: [EventLoopFuture<Void>] = []\n\n        let fN = EventLoopFuture.andAllSucceed(futures, on: eventLoop)\n\n        #expect(fN.isFulfilled)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllWithAllSuccesses() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let promises: [EventLoopPromise<Void>] = (0..<100).map { (_: Int) in eventLoop.makePromise() }\n        let futures = promises.map { $0.futureResult }\n\n        let fN = EventLoopFuture.andAllSucceed(futures, on: eventLoop)\n        _ = promises.map { $0.succeed(()) }\n        () = try fN.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllWithAllFailures() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let promises: [EventLoopPromise<Void>] = (0..<100).map { (_: Int) in eventLoop.makePromise() }\n        let futures = promises.map { $0.futureResult }\n\n        let fN = EventLoopFuture.andAllSucceed(futures, on: eventLoop)\n        _ = promises.map { $0.fail(E()) }\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllWithOneFailure() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        var promises: [EventLoopPromise<Void>] = (0..<100).map { (_: Int) in eventLoop.makePromise() }\n        _ = promises.map { $0.succeed(()) }\n        let failedPromise = eventLoop.makePromise(of: Void.self)\n        failedPromise.fail(E())\n        promises.append(failedPromise)\n\n        let futures = promises.map { $0.futureResult }\n\n        let fN = EventLoopFuture.andAllSucceed(futures, on: eventLoop)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceWithAllSuccesses() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let promises: [EventLoopPromise<Int>] = (0..<5).map { (_: Int) in eventLoop.makePromise() }\n        let futures = promises.map { $0.futureResult }\n\n        let fN: EventLoopFuture<[Int]> = EventLoopFuture<[Int]>.reduce(into: [], futures, on: eventLoop) {\n            $0.append($1)\n        }\n        for i in 1...5 {\n            promises[i - 1].succeed((i))\n        }\n        let results = try fN.wait()\n        #expect(results == [1, 2, 3, 4, 5])\n        #expect(fN.eventLoop === eventLoop)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceWithOnlyInitialValue() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let futures: [EventLoopFuture<Int>] = []\n\n        let fN: EventLoopFuture<[Int]> = EventLoopFuture<[Int]>.reduce(into: [], futures, on: eventLoop) {\n            $0.append($1)\n        }\n\n        let results = try fN.wait()\n        #expect(results == [])\n        #expect(fN.eventLoop === eventLoop)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceWithAllFailures() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let promises: [EventLoopPromise<Int>] = (0..<100).map { (_: Int) in eventLoop.makePromise() }\n        let futures = promises.map { $0.futureResult }\n\n        let fN: EventLoopFuture<Int> = EventLoopFuture<Int>.reduce(0, futures, on: eventLoop) {\n            $0 + $1\n        }\n        _ = promises.map { $0.fail(E()) }\n        #expect(fN.eventLoop === eventLoop)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceWithOneFailure() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        var promises: [EventLoopPromise<Int>] = (0..<100).map { (_: Int) in eventLoop.makePromise() }\n        _ = promises.map { $0.succeed((1)) }\n        let failedPromise = eventLoop.makePromise(of: Int.self)\n        failedPromise.fail(E())\n        promises.append(failedPromise)\n\n        let futures = promises.map { $0.futureResult }\n\n        let fN: EventLoopFuture<Int> = EventLoopFuture<Int>.reduce(0, futures, on: eventLoop) {\n            $0 + $1\n        }\n        #expect(fN.eventLoop === eventLoop)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceWhichDoesFailFast() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        var promises: [EventLoopPromise<Int>] = (0..<100).map { (_: Int) in eventLoop.makePromise() }\n\n        let failedPromise = eventLoop.makePromise(of: Int.self)\n        promises.insert(failedPromise, at: promises.startIndex)\n\n        let futures = promises.map { $0.futureResult }\n        let fN: EventLoopFuture<Int> = EventLoopFuture<Int>.reduce(0, futures, on: eventLoop) {\n            $0 + $1\n        }\n\n        failedPromise.fail(E())\n\n        #expect(fN.isFulfilled)\n        #expect(fN.eventLoop === eventLoop)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceIntoWithAllSuccesses() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let futures: [EventLoopFuture<Int>] = [1, 2, 2, 3, 3, 3].map { (id: Int) in\n            eventLoop.makeSucceededFuture(id)\n        }\n\n        let fN: EventLoopFuture<[Int: Int]> = EventLoopFuture<[Int: Int]>.reduce(\n            into: [:],\n            futures,\n            on: eventLoop\n        ) {\n            (freqs, elem) in\n            if let value = freqs[elem] {\n                freqs[elem] = value + 1\n            } else {\n                freqs[elem] = 1\n            }\n        }\n\n        let results = try fN.wait()\n        #expect(results == [1: 1, 2: 2, 3: 3])\n        #expect(fN.eventLoop === eventLoop)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceIntoWithEmptyFutureList() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let futures: [EventLoopFuture<Int>] = []\n\n        let fN: EventLoopFuture<[Int: Int]> = EventLoopFuture<[Int: Int]>.reduce(\n            into: [:],\n            futures,\n            on: eventLoop\n        ) {\n            (freqs, elem) in\n            if let value = freqs[elem] {\n                freqs[elem] = value + 1\n            } else {\n                freqs[elem] = 1\n            }\n        }\n\n        let results = try fN.wait()\n        #expect(results.isEmpty)\n        #expect(fN.eventLoop === eventLoop)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceIntoWithAllFailure() throws {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let futures: [EventLoopFuture<Int>] = [1, 2, 2, 3, 3, 3].map { (id: Int) in\n            eventLoop.makeFailedFuture(E())\n        }\n\n        let fN: EventLoopFuture<[Int: Int]> = EventLoopFuture<[Int: Int]>.reduce(\n            into: [:],\n            futures,\n            on: eventLoop\n        ) {\n            (freqs, elem) in\n            if let value = freqs[elem] {\n                freqs[elem] = value + 1\n            } else {\n                freqs[elem] = 1\n            }\n        }\n\n        #expect(fN.isFulfilled)\n        #expect(fN.eventLoop === eventLoop)\n        #expect(throws: E.self) {\n            try fN.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testReduceIntoWithMultipleEventLoops() throws {\n        let nThreads = 3\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: nThreads)\n        defer {\n            #expect(throws: Never.self) { try eventLoopGroup.syncShutdownGracefully() }\n        }\n\n        let eventLoop0 = eventLoopGroup.next()\n        let eventLoop1 = eventLoopGroup.next()\n        let eventLoop2 = eventLoopGroup.next()\n\n        #expect(eventLoop0 !== eventLoop1)\n        #expect(eventLoop1 !== eventLoop2)\n        #expect(eventLoop0 !== eventLoop2)\n\n        let f0: EventLoopFuture<[Int: Int]> = eventLoop0.submit { [:] }\n        let f1s: [EventLoopFuture<Int>] = (1...4).map { id in eventLoop1.submit { id / 2 } }\n        let f2s: [EventLoopFuture<Int>] = (5...8).map { id in eventLoop2.submit { id / 2 } }\n\n        let fN = EventLoopFuture<[Int: Int]>.reduce(into: [:], f1s + f2s, on: eventLoop0) {\n            (freqs, elem) in\n            #expect(eventLoop0.inEventLoop)\n            if let value = freqs[elem] {\n                freqs[elem] = value + 1\n            } else {\n                freqs[elem] = 1\n            }\n        }\n\n        let allValues = try fN.wait()\n        #expect(fN.eventLoop === f0.eventLoop)\n        #expect(fN.isFulfilled)\n        #expect(allValues == [0: 1, 1: 2, 2: 2, 3: 2, 4: 1])\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testThenThrowingWhichDoesNotThrow() throws {\n        let eventLoop = EmbeddedEventLoop()\n        var ran = false\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.map {\n            $0.count\n        }.flatMapThrowing {\n            1 + $0\n        }.assumeIsolated().whenSuccess {\n            ran = true\n            #expect($0 == 6)\n        }\n        p.succeed(\"hello\")\n        #expect(ran)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testThenThrowingWhichDoesThrow() throws {\n        enum DummyError: Error, Equatable {\n            case dummyError\n        }\n        let eventLoop = EmbeddedEventLoop()\n        var ran = false\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.map {\n            $0.count\n        }.flatMapThrowing { (x: Int) throws -> Int in\n            #expect(5 == x)\n            throw DummyError.dummyError\n        }.map { (x: Int) -> Int in\n            Issue.record(\"shouldn't have been called\")\n            return x\n        }.assumeIsolated().whenFailure {\n            ran = true\n            #expect(.some(DummyError.dummyError) == $0 as? DummyError)\n        }\n        p.succeed(\"hello\")\n        #expect(ran)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testflatMapErrorThrowingWhichDoesNotThrow() throws {\n        enum DummyError: Error, Equatable {\n            case dummyError\n        }\n        let eventLoop = EmbeddedEventLoop()\n        var ran = false\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.map {\n            $0.count\n        }.flatMapErrorThrowing {\n            #expect(.some(DummyError.dummyError) == $0 as? DummyError)\n            return 5\n        }.flatMapErrorThrowing { (_: Error) in\n            Issue.record(\"shouldn't have been called\")\n            return 5\n        }.assumeIsolated().whenSuccess {\n            ran = true\n            #expect($0 == 5)\n        }\n        p.fail(DummyError.dummyError)\n        #expect(ran)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testflatMapErrorThrowingWhichDoesThrow() throws {\n        enum DummyError: Error, Equatable {\n            case dummyError1\n            case dummyError2\n        }\n        let eventLoop = EmbeddedEventLoop()\n        var ran = false\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.map {\n            $0.count\n        }.flatMapErrorThrowing { (x: Error) throws -> Int in\n            #expect(.some(DummyError.dummyError1) == x as? DummyError)\n            throw DummyError.dummyError2\n        }.map { (x: Int) -> Int in\n            Issue.record(\"shouldn't have been called\")\n            return x\n        }.assumeIsolated().whenFailure {\n            ran = true\n            #expect(.some(DummyError.dummyError2) == $0 as? DummyError)\n        }\n        p.fail(DummyError.dummyError1)\n        #expect(ran)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testOrderOfFutureCompletion() throws {\n        let eventLoop = EmbeddedEventLoop()\n        var state = 0\n        let p: EventLoopPromise<Void> = EventLoopPromise(\n            eventLoop: eventLoop,\n            file: #filePath,\n            line: #line\n        )\n        p.futureResult.assumeIsolated().map {\n            #expect(state == 0)\n            state += 1\n        }.map {\n            #expect(state == 1)\n            state += 1\n        }.whenSuccess {\n            #expect(state == 2)\n            state += 1\n        }\n        p.succeed(())\n        #expect(p.futureResult.isFulfilled)\n        #expect(state == 3)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopHoppingInThen() throws {\n        let n = 20\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: n)\n        var prev: EventLoopFuture<Int> = elg.next().makeSucceededFuture(0)\n        for i in (1..<20) {\n            let p = elg.next().makePromise(of: Int.self)\n            prev.flatMap { (i2: Int) -> EventLoopFuture<Int> in\n                #expect(i - 1 == i2)\n                p.succeed(i)\n                return p.futureResult\n            }.whenSuccess { i2 in\n                #expect(i == i2)\n            }\n            prev = p.futureResult\n        }\n        let result = try prev.wait()\n        #expect(n - 1 == result)\n        #expect(throws: Never.self) { try elg.syncShutdownGracefully() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopHoppingInThenWithFailures() throws {\n        enum DummyError: Error {\n            case dummy\n        }\n        let n = 20\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: n)\n        var prev: EventLoopFuture<Int> = elg.next().makeSucceededFuture(0)\n        for i in (1..<n) {\n            let p = elg.next().makePromise(of: Int.self)\n            prev.flatMap { (i2: Int) -> EventLoopFuture<Int> in\n                #expect(i - 1 == i2)\n                if i == n / 2 {\n                    p.fail(DummyError.dummy)\n                } else {\n                    p.succeed(i)\n                }\n                return p.futureResult\n            }.flatMapError { error in\n                p.fail(error)\n                return p.futureResult\n            }.whenSuccess { i2 in\n                #expect(i == i2)\n            }\n            prev = p.futureResult\n        }\n        #expect(throws: DummyError.self) {\n            try prev.wait()\n        }\n        #expect(throws: Never.self) { try elg.syncShutdownGracefully() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopHoppingAndAll() throws {\n        let n = 20\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: n)\n        let ps = (0..<n).map { (_: Int) -> EventLoopPromise<Void> in\n            elg.next().makePromise()\n        }\n        let allOfEm = EventLoopFuture.andAllSucceed(ps.map { $0.futureResult }, on: elg.next())\n        for promise in ps.reversed() {\n            DispatchQueue.global().async {\n                promise.succeed(())\n            }\n        }\n        try allOfEm.wait()\n        #expect(throws: Never.self) { try elg.syncShutdownGracefully() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopHoppingAndAllWithFailures() throws {\n        enum DummyError: Error { case dummy }\n        let n = 20\n        let fireBackEl = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: n)\n        let ps = (0..<n).map { (_: Int) -> EventLoopPromise<Void> in\n            elg.next().makePromise()\n        }\n        let allOfEm = EventLoopFuture.andAllSucceed(ps.map { $0.futureResult }, on: fireBackEl.next())\n        for (index, promise) in ps.reversed().enumerated() {\n            DispatchQueue.global().async {\n                if index == n / 2 {\n                    promise.fail(DummyError.dummy)\n                } else {\n                    promise.succeed(())\n                }\n            }\n        }\n        #expect(throws: DummyError.self) {\n            try allOfEm.wait()\n        }\n        #expect(throws: Never.self) { try elg.syncShutdownGracefully() }\n        #expect(throws: Never.self) { try fireBackEl.syncShutdownGracefully() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFutureInVariousScenarios() throws {\n        enum DummyError: Error {\n            case dummy0\n            case dummy1\n        }\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        let el1 = elg.next()\n        let el2 = elg.next()\n        precondition(el1 !== el2)\n        let q1 = DispatchQueue(label: \"q1\")\n        let q2 = DispatchQueue(label: \"q2\")\n\n        // this determines which promise is fulfilled first (and (true, true) meaning they race)\n        for whoGoesFirst in [(false, true), (true, false), (true, true)] {\n            // this determines what EventLoops the Promises are created on\n            for eventLoops in [(el1, el1), (el1, el2), (el2, el1), (el2, el2)] {\n                // this determines if the promises fail or succeed\n                for whoSucceeds in [(false, false), (false, true), (true, false), (true, true)] {\n                    let p0 = eventLoops.0.makePromise(of: Int.self)\n                    let p1 = eventLoops.1.makePromise(of: String.self)\n                    let fAll = p0.futureResult.and(p1.futureResult)\n\n                    // preheat both queues so we have a better chance of racing\n                    let sem1 = DispatchSemaphore(value: 0)\n                    let sem2 = DispatchSemaphore(value: 0)\n                    let g = DispatchGroup()\n                    q1.async(group: g) {\n                        sem2.signal()\n                        sem1.wait()\n                    }\n                    q2.async(group: g) {\n                        sem1.signal()\n                        sem2.wait()\n                    }\n                    g.wait()\n\n                    if whoGoesFirst.0 {\n                        q1.async {\n                            if whoSucceeds.0 {\n                                p0.succeed(7)\n                            } else {\n                                p0.fail(DummyError.dummy0)\n                            }\n                            if !whoGoesFirst.1 {\n                                q2.asyncAfter(deadline: .now() + 0.1) {\n                                    if whoSucceeds.1 {\n                                        p1.succeed(\"hello\")\n                                    } else {\n                                        p1.fail(DummyError.dummy1)\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    if whoGoesFirst.1 {\n                        q2.async {\n                            if whoSucceeds.1 {\n                                p1.succeed(\"hello\")\n                            } else {\n                                p1.fail(DummyError.dummy1)\n                            }\n                            if !whoGoesFirst.0 {\n                                q1.asyncAfter(deadline: .now() + 0.1) {\n                                    if whoSucceeds.0 {\n                                        p0.succeed(7)\n                                    } else {\n                                        p0.fail(DummyError.dummy0)\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    do {\n                        let result = try fAll.wait()\n                        if !whoSucceeds.0 || !whoSucceeds.1 {\n                            Issue.record(\"unexpected success\")\n                        } else {\n                            #expect((7, \"hello\") == result)\n                        }\n                    } catch let e as DummyError {\n                        switch e {\n                        case .dummy0:\n                            #expect(!whoSucceeds.0)\n                        case .dummy1:\n                            #expect(!whoSucceeds.1)\n                        }\n                    } catch {\n                        Issue.record(\"unexpected error: \\(error)\")\n                    }\n                }\n            }\n        }\n\n        #expect(throws: Never.self) { try elg.syncShutdownGracefully() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testLoopHoppingHelperSuccess() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n        let loop1 = group.next()\n        let loop2 = group.next()\n        #expect(!(loop1 === loop2))\n\n        let succeedingPromise = loop1.makePromise(of: Void.self)\n        let succeedingFuture = succeedingPromise.futureResult.map {\n            #expect(loop1.inEventLoop)\n        }.hop(to: loop2).map {\n            #expect(loop2.inEventLoop)\n        }\n        succeedingPromise.succeed(())\n        #expect(throws: Never.self) { try succeedingFuture.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testLoopHoppingHelperFailure() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        let loop1 = group.next()\n        let loop2 = group.next()\n        #expect(!(loop1 === loop2))\n\n        let failingPromise = loop2.makePromise(of: Void.self)\n        let failingFuture = failingPromise.futureResult.flatMapErrorThrowing { error in\n            #expect(error as? EventLoopFutureTestError == EventLoopFutureTestError.example)\n            #expect(loop2.inEventLoop)\n            throw error\n        }.hop(to: loop1).recover { error in\n            #expect(error as? EventLoopFutureTestError == EventLoopFutureTestError.example)\n            #expect(loop1.inEventLoop)\n        }\n\n        failingPromise.fail(EventLoopFutureTestError.example)\n        #expect(throws: Never.self) { try failingFuture.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testLoopHoppingHelperNoHopping() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n        let loop1 = group.next()\n        let loop2 = group.next()\n        #expect(!(loop1 === loop2))\n\n        let noHoppingPromise = loop1.makePromise(of: Void.self)\n        let noHoppingFuture = noHoppingPromise.futureResult.hop(to: loop1)\n        #expect(noHoppingFuture === noHoppingPromise.futureResult)\n        noHoppingPromise.succeed(())\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFlatMapResultHappyPath() {\n        let el = EmbeddedEventLoop()\n        defer {\n            #expect(throws: Never.self) { try el.syncShutdownGracefully() }\n        }\n\n        let p = el.makePromise(of: Int.self)\n        let f = p.futureResult.flatMapResult { (_: Int) in\n            Result<String, Never>.success(\"hello world\")\n        }\n        p.succeed(1)\n        #expect(throws: Never.self) {\n            let result = try f.wait()\n            #expect(\"hello world\" == result)\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFlatMapResultFailurePath() {\n        struct DummyError: Error {}\n        let el = EmbeddedEventLoop()\n        defer {\n            #expect(throws: Never.self) { try el.syncShutdownGracefully() }\n        }\n\n        let p = el.makePromise(of: Int.self)\n        let f = p.futureResult.flatMapResult { (_: Int) in\n            Result<Int, Error>.failure(DummyError())\n        }\n        p.succeed(1)\n        #expect(throws: DummyError.self) { try f.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllSucceedFailsImmediately() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        func doTest(promise: EventLoopPromise<[Int]>?) {\n            let promises = [\n                group.next().makePromise(of: Int.self),\n                group.next().makePromise(of: Int.self),\n            ]\n            let futures = promises.map { $0.futureResult }\n            let futureResult: EventLoopFuture<[Int]>\n\n            if let promise = promise {\n                futureResult = promise.futureResult\n                EventLoopFuture.whenAllSucceed(futures, promise: promise)\n            } else {\n                futureResult = EventLoopFuture.whenAllSucceed(futures, on: group.next())\n            }\n\n            promises[0].fail(EventLoopFutureTestError.example)\n            #expect(throws: EventLoopFutureTestError.self) {\n                try futureResult.wait()\n            }\n        }\n\n        doTest(promise: nil)\n        doTest(promise: group.next().makePromise())\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllSucceedResolvesAfterFutures() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 6)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        func doTest(promise: EventLoopPromise<[Int]>?) throws {\n            let promises = (0..<5).map { _ in group.next().makePromise(of: Int.self) }\n            let futures = promises.map { $0.futureResult }\n\n            let succeeded = NIOLockedValueBox(false)\n            let completedPromises = NIOLockedValueBox(false)\n\n            let mainFuture: EventLoopFuture<[Int]>\n\n            if let promise = promise {\n                mainFuture = promise.futureResult\n                EventLoopFuture.whenAllSucceed(futures, promise: promise)\n            } else {\n                mainFuture = EventLoopFuture.whenAllSucceed(futures, on: group.next())\n            }\n\n            mainFuture.whenSuccess { _ in\n                #expect(completedPromises.withLockedValue { $0 })\n                #expect(!succeeded.withLockedValue { $0 })\n                succeeded.withLockedValue { $0 = true }\n            }\n\n            // Should be false, as none of the promises have completed yet\n            #expect(!succeeded.withLockedValue { $0 })\n\n            // complete the first four promises\n            for (index, promise) in promises.dropLast().enumerated() {\n                promise.succeed(index)\n            }\n\n            // Should still be false, as one promise hasn't completed yet\n            #expect(!succeeded.withLockedValue { $0 })\n\n            // Complete the last promise\n            completedPromises.withLockedValue { $0 = true }\n            promises.last!.succeed(4)\n\n            let results = try assertNoThrowWithValue(mainFuture.wait())\n            #expect(results == [0, 1, 2, 3, 4])\n        }\n\n        #expect(throws: Never.self) { try doTest(promise: nil) }\n        #expect(throws: Never.self) { try doTest(promise: group.next().makePromise()) }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllSucceedIsIndependentOfFulfillmentOrder() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 6)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        func doTest(promise: EventLoopPromise<[Int]>?) throws {\n            let expected = Array(0..<1000)\n            let promises = expected.map { _ in group.next().makePromise(of: Int.self) }\n            let futures = promises.map { $0.futureResult }\n\n            let succeeded = NIOLockedValueBox(false)\n            let completedPromises = NIOLockedValueBox(false)\n\n            let mainFuture: EventLoopFuture<[Int]>\n\n            if let promise = promise {\n                mainFuture = promise.futureResult\n                EventLoopFuture.whenAllSucceed(futures, promise: promise)\n            } else {\n                mainFuture = EventLoopFuture.whenAllSucceed(futures, on: group.next())\n            }\n\n            mainFuture.whenSuccess { _ in\n                #expect(completedPromises.withLockedValue { $0 })\n                #expect(!succeeded.withLockedValue { $0 })\n                succeeded.withLockedValue { $0 = true }\n            }\n\n            for index in expected.reversed() {\n                if index == 0 {\n                    completedPromises.withLockedValue { $0 = true }\n                }\n                promises[index].succeed(index)\n            }\n\n            let results = try assertNoThrowWithValue(mainFuture.wait())\n            #expect(results == expected)\n        }\n\n        #expect(throws: Never.self) { try doTest(promise: nil) }\n        #expect(throws: Never.self) { try doTest(promise: group.next().makePromise()) }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllCompleteResultsWithFailuresStillSucceed() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        func doTest(promise: EventLoopPromise<[Result<Bool, Error>]>?) {\n            let futures: [EventLoopFuture<Bool>] = [\n                group.next().makeFailedFuture(EventLoopFutureTestError.example),\n                group.next().makeSucceededFuture(true),\n            ]\n            let future: EventLoopFuture<[Result<Bool, Error>]>\n\n            if let promise = promise {\n                future = promise.futureResult\n                EventLoopFuture.whenAllComplete(futures, promise: promise)\n            } else {\n                future = EventLoopFuture.whenAllComplete(futures, on: group.next())\n            }\n\n            #expect(throws: Never.self) { try future.wait() }\n        }\n\n        doTest(promise: nil)\n        doTest(promise: group.next().makePromise())\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllCompleteResults() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        func doTest(promise: EventLoopPromise<[Result<Int, Error>]>?) throws {\n            let futures: [EventLoopFuture<Int>] = [\n                group.next().makeSucceededFuture(3),\n                group.next().makeFailedFuture(EventLoopFutureTestError.example),\n                group.next().makeSucceededFuture(10),\n                group.next().makeFailedFuture(EventLoopFutureTestError.example),\n                group.next().makeSucceededFuture(5),\n            ]\n            let future: EventLoopFuture<[Result<Int, Error>]>\n\n            if let promise = promise {\n                future = promise.futureResult\n                EventLoopFuture.whenAllComplete(futures, promise: promise)\n            } else {\n                future = EventLoopFuture.whenAllComplete(futures, on: group.next())\n            }\n\n            let results = try assertNoThrowWithValue(future.wait())\n\n            #expect(try results[0].get() == 3)\n            #expect(throws: Error.self) { try results[1].get() }\n            #expect(try results[2].get() == 10)\n            #expect(throws: Error.self) { try results[3].get() }\n            #expect(try results[4].get() == 5)\n        }\n\n        #expect(throws: Never.self) { try doTest(promise: nil) }\n        #expect(throws: Never.self) { try doTest(promise: group.next().makePromise()) }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllCompleteResolvesAfterFutures() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 6)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        func doTest(promise: EventLoopPromise<[Result<Int, Error>]>?) throws {\n            let promises = (0..<5).map { _ in group.next().makePromise(of: Int.self) }\n            let futures = promises.map { $0.futureResult }\n\n            let succeeded = NIOLockedValueBox(false)\n            let completedPromises = NIOLockedValueBox(false)\n\n            let mainFuture: EventLoopFuture<[Result<Int, Error>]>\n\n            if let promise = promise {\n                mainFuture = promise.futureResult\n                EventLoopFuture.whenAllComplete(futures, promise: promise)\n            } else {\n                mainFuture = EventLoopFuture.whenAllComplete(futures, on: group.next())\n            }\n\n            mainFuture.whenSuccess { _ in\n                #expect(completedPromises.withLockedValue { $0 })\n                #expect(!succeeded.withLockedValue { $0 })\n                succeeded.withLockedValue { $0 = true }\n            }\n\n            // Should be false, as none of the promises have completed yet\n            #expect(!succeeded.withLockedValue { $0 })\n\n            // complete the first four promises\n            for (index, promise) in promises.dropLast().enumerated() {\n                promise.succeed(index)\n            }\n\n            // Should still be false, as one promise hasn't completed yet\n            #expect(!succeeded.withLockedValue { $0 })\n\n            // Complete the last promise\n            completedPromises.withLockedValue { $0 = true }\n            promises.last!.succeed(4)\n\n            let results = try assertNoThrowWithValue(mainFuture.wait().map { try $0.get() })\n            #expect(results == [0, 1, 2, 3, 4])\n        }\n\n        #expect(throws: Never.self) { try doTest(promise: nil) }\n        #expect(throws: Never.self) { try doTest(promise: group.next().makePromise()) }\n    }\n\n    struct DatabaseError: Error {}\n    final class Database: Sendable {\n        private let query: @Sendable () -> EventLoopFuture<[String]>\n        private let _closed = NIOLockedValueBox(false)\n\n        var closed: Bool {\n            self._closed.withLockedValue { $0 }\n        }\n\n        init(query: @escaping @Sendable () -> EventLoopFuture<[String]>) {\n            self.query = query\n        }\n\n        func runQuery() -> EventLoopFuture<[String]> {\n            self.query()\n        }\n\n        func close() {\n            self._closed.withLockedValue { $0 = true }\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAlways() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n        let db = Database { loop.makeSucceededFuture([\"Item 1\", \"Item 2\", \"Item 3\"]) }\n\n        #expect(!db.closed)\n        let _ = try assertNoThrowWithValue(\n            db.runQuery().always { result in\n                assertSuccess(result)\n                db.close()\n            }.map { $0.map { $0.uppercased() } }.wait()\n        )\n        #expect(db.closed)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAlwaysWithFailingPromise() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n        let db = Database { loop.makeFailedFuture(DatabaseError()) }\n\n        #expect(!db.closed)\n\n        #expect(throws: DatabaseError.self) {\n            try db.runQuery().always { result in\n                assertFailure(result)\n                db.close()\n            }.map { $0.map { $0.uppercased() } }.wait()\n        }\n        #expect(db.closed)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseCompletedWithSuccessfulFuture() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n\n        let future = loop.makeSucceededFuture(\"yay\")\n        let promise = loop.makePromise(of: String.self)\n\n        promise.completeWith(future)\n        #expect(try promise.futureResult.wait() == \"yay\")\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFutureFulfilledIfHasNonSendableResult() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let f = EventLoopFuture(eventLoop: eventLoop, isolatedValue: NonSendableObject(value: 5))\n        #expect(f.isFulfilled)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testSucceededIsolatedFutureIsCompleted() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n\n        let value = NonSendableObject(value: 4)\n\n        let future = loop.makeSucceededIsolatedFuture(value)\n\n        future.whenComplete { result in\n            switch result {\n            case .success(let nonSendableStruct):\n                #expect(nonSendableStruct == value)\n            case .failure(let error):\n                Issue.record(\"\\(error)\")\n            }\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseCompletedWithFailedFuture() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n\n        let future: EventLoopFuture<EventLoopFutureTestError> = loop.makeFailedFuture(\n            EventLoopFutureTestError.example\n        )\n        let promise = loop.makePromise(of: EventLoopFutureTestError.self)\n\n        promise.completeWith(future)\n        #expect(throws: EventLoopFutureTestError.self) {\n            try promise.futureResult.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseCompletedWithSuccessfulResult() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n\n        let promise = loop.makePromise(of: Void.self)\n\n        let result: Result<Void, Error> = .success(())\n        promise.completeWith(result)\n        #expect(throws: Never.self) { try promise.futureResult.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseCompletedWithFailedResult() throws {\n        let group = EmbeddedEventLoop()\n        let loop = group.next()\n\n        let promise = loop.makePromise(of: Void.self)\n\n        let result: Result<Void, Error> = .failure(EventLoopFutureTestError.example)\n        promise.completeWith(result)\n        #expect(throws: EventLoopFutureTestError.self) {\n            try promise.futureResult.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllCompleteWithZeroFutures() {\n        let eventLoop = EmbeddedEventLoop()\n        let done = DispatchSemaphore(value: 0)\n        EventLoopFuture<Void>.andAllComplete([], on: eventLoop).whenComplete {\n            (result: Result<Void, Error>) in\n            _ = result.mapError { error -> Error in\n                Issue.record(\"unexpected error \\(error)\")\n                return error\n            }\n            done.signal()\n        }\n        done.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllSucceedWithZeroFutures() {\n        let eventLoop = EmbeddedEventLoop()\n        let done = DispatchSemaphore(value: 0)\n        EventLoopFuture<Void>.andAllSucceed([], on: eventLoop).whenComplete { result in\n            _ = result.mapError { error -> Error in\n                Issue.record(\"unexpected error \\(error)\")\n                return error\n            }\n            done.signal()\n        }\n        done.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllCompleteWithPreSucceededFutures() {\n        let eventLoop = EmbeddedEventLoop()\n        let succeeded = eventLoop.makeSucceededFuture(())\n\n        for i in 0..<10 {\n            #expect(throws: Never.self) {\n                try EventLoopFuture<Void>.andAllComplete(\n                    Array(repeating: succeeded, count: i),\n                    on: eventLoop\n                ).wait()\n            }\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllCompleteWithPreFailedFutures() {\n        struct Dummy: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let failed: EventLoopFuture<Void> = eventLoop.makeFailedFuture(Dummy())\n\n        for i in 0..<10 {\n            #expect(throws: Never.self) {\n                try EventLoopFuture<Void>.andAllComplete(\n                    Array(repeating: failed, count: i),\n                    on: eventLoop\n                ).wait()\n            }\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAndAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures() {\n        struct Dummy: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let succeeded = eventLoop.makeSucceededFuture(())\n        let incompletes = [\n            eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),\n            eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),\n            eventLoop.makePromise(of: Void.self),\n        ]\n        var futures: [EventLoopFuture<Void>] = []\n\n        for i in 0..<10 {\n            if i % 2 == 0 {\n                futures.append(succeeded)\n            } else {\n                futures.append(incompletes[i / 2].futureResult)\n            }\n        }\n\n        let overall = EventLoopFuture<Void>.andAllComplete(futures, on: eventLoop)\n        #expect(!overall.isFulfilled)\n        for (idx, incomplete) in incompletes.enumerated() {\n            #expect(!overall.isFulfilled)\n            if idx % 2 == 0 {\n                incomplete.succeed(())\n            } else {\n                incomplete.fail(Dummy())\n            }\n        }\n        #expect(throws: Never.self) { try overall.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures() {\n        struct Dummy: Error {}\n        let eventLoop = EmbeddedEventLoop()\n        let succeeded = eventLoop.makeSucceededFuture(())\n        let incompletes = [\n            eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),\n            eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),\n            eventLoop.makePromise(of: Void.self),\n        ]\n        var futures: [EventLoopFuture<Void>] = []\n\n        for i in 0..<10 {\n            if i % 2 == 0 {\n                futures.append(succeeded)\n            } else {\n                futures.append(incompletes[i / 2].futureResult)\n            }\n        }\n\n        let overall = EventLoopFuture<Void>.whenAllComplete(futures, on: eventLoop)\n        #expect(!overall.isFulfilled)\n        for (idx, incomplete) in incompletes.enumerated() {\n            #expect(!overall.isFulfilled)\n            if idx % 2 == 0 {\n                incomplete.succeed(())\n            } else {\n                incomplete.fail(Dummy())\n            }\n        }\n        let expected: [Result<Void, Error>] = [\n            .success(()), .success(()),\n            .success(()), .failure(Dummy()),\n            .success(()), .success(()),\n            .success(()), .failure(Dummy()),\n            .success(()), .success(()),\n        ]\n        func assertIsEqual(_ expecteds: [Result<Void, Error>], _ actuals: [Result<Void, Error>]) {\n            #expect(expecteds.count == actuals.count, \"counts not equal\")\n            for i in expecteds.indices {\n                let expected = expecteds[i]\n                let actual = actuals[i]\n                switch (expected, actual) {\n                case (.success(()), .success(())):\n                    ()\n                case (.failure(let le), .failure(let re)):\n                    #expect(le is Dummy)\n                    #expect(re is Dummy)\n                default:\n                    Issue.record(\"\\(expecteds) and \\(actuals) not equal\")\n                }\n            }\n        }\n        #expect(throws: Never.self) { assertIsEqual(expected, try overall.wait()) }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testRepeatedTaskOffEventLoopGroupFuture() throws {\n        let elg1: EventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) { try elg1.syncShutdownGracefully() }\n        }\n\n        let elg2: EventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) { try elg2.syncShutdownGracefully() }\n        }\n\n        let exitPromise: EventLoopPromise<Void> = elg1.next().makePromise()\n        let callNumber = NIOLockedValueBox(0)\n        _ = elg1.next().scheduleRepeatedAsyncTask(initialDelay: .nanoseconds(0), delay: .nanoseconds(0)) { task in\n            struct Dummy: Error {}\n\n            callNumber.withLockedValue { $0 += 1 }\n            switch callNumber.withLockedValue({ $0 }) {\n            case 1:\n                return elg2.next().makeSucceededFuture(())\n            case 2:\n                task.cancel(promise: exitPromise)\n                return elg2.next().makeFailedFuture(Dummy())\n            default:\n                Issue.record(\"shouldn't be called \\(callNumber)\")\n                return elg2.next().makeFailedFuture(Dummy())\n            }\n        }\n\n        try exitPromise.futureResult.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopFutureOrErrorNoThrow() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let promise = eventLoop.makePromise(of: Int?.self)\n        let result: Result<Int?, Error> = .success(42)\n        promise.completeWith(result)\n\n        #expect(try promise.futureResult.unwrap(orError: EventLoopFutureTestError.example).wait() == 42)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopFutureOrThrows() {\n        let eventLoop = EmbeddedEventLoop()\n        let promise = eventLoop.makePromise(of: Int?.self)\n        let result: Result<Int?, Error> = .success(nil)\n        promise.completeWith(result)\n\n        #expect(throws: EventLoopFutureTestError.example) {\n            try promise.futureResult.unwrap(orError: EventLoopFutureTestError.example).wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopFutureOrNoReplacement() {\n        let eventLoop = EmbeddedEventLoop()\n        let promise = eventLoop.makePromise(of: Int?.self)\n        let result: Result<Int?, Error> = .success(42)\n        promise.completeWith(result)\n\n        #expect(try! promise.futureResult.unwrap(orReplace: 41).wait() == 42)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopFutureOrReplacement() {\n        let eventLoop = EmbeddedEventLoop()\n        let promise = eventLoop.makePromise(of: Int?.self)\n        let result: Result<Int?, Error> = .success(nil)\n        promise.completeWith(result)\n\n        #expect(try! promise.futureResult.unwrap(orReplace: 42).wait() == 42)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopFutureOrNoElse() {\n        let eventLoop = EmbeddedEventLoop()\n        let promise = eventLoop.makePromise(of: Int?.self)\n        let result: Result<Int?, Error> = .success(42)\n        promise.completeWith(result)\n\n        #expect(try! promise.futureResult.unwrap(orElse: { 41 }).wait() == 42)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testEventLoopFutureOrElse() {\n        let eventLoop = EmbeddedEventLoop()\n        let promise = eventLoop.makePromise(of: Int?.self)\n        let result: Result<Int?, Error> = .success(4)\n        promise.completeWith(result)\n\n        let x = 2\n        #expect(try! promise.futureResult.unwrap(orElse: { x * 2 }).wait() == 4)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFlatBlockingMapOnto() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) { try group.syncShutdownGracefully() }\n        }\n\n        let eventLoop = group.next()\n        let p = eventLoop.makePromise(of: String.self)\n        let sem = DispatchSemaphore(value: 0)\n        let blockingRan = ManagedAtomic(false)\n        let nonBlockingRan = ManagedAtomic(false)\n        p.futureResult.map {\n            $0.count\n        }.flatMapBlocking(onto: DispatchQueue.global()) { value -> Int in\n            sem.wait()  // Block in chained EventLoopFuture\n            blockingRan.store(true, ordering: .sequentiallyConsistent)\n            return 1 + value\n        }.whenSuccess {\n            #expect($0 == 6)\n            let blockingRanResult = blockingRan.load(ordering: .sequentiallyConsistent)\n            #expect(blockingRanResult)\n            let nonBlockingRanResult = nonBlockingRan.load(ordering: .sequentiallyConsistent)\n            #expect(nonBlockingRanResult)\n        }\n        p.succeed(\"hello\")\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.store(true, ordering: .sequentiallyConsistent)\n        }\n        p2.succeed(true)\n\n        sem.signal()\n\n        // Wait for the flatMapBlocking chain to complete before shutdown. Without this,\n        // on slow environments (e.g. iOS simulator) the event loop can shut down before\n        // the GCD dispatch delivers its result back, causing a crash.\n        _ = try p.futureResult.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenSuccessBlocking() {\n        let eventLoop = EmbeddedEventLoop()\n        let sem = DispatchSemaphore(value: 0)\n        let nonBlockingRan = NIOLockedValueBox(false)\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.whenSuccessBlocking(onto: DispatchQueue.global()) {\n            sem.wait()  // Block in callback\n            #expect($0 == \"hello\")\n            nonBlockingRan.withLockedValue { #expect($0) }\n\n        }\n        p.succeed(\"hello\")\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.withLockedValue { $0 = true }\n        }\n        p2.succeed(true)\n\n        let didRun = try! p2.futureResult.wait()\n        #expect(didRun)\n        sem.signal()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenFailureBlocking() {\n        let eventLoop = EmbeddedEventLoop()\n        let sem = DispatchSemaphore(value: 0)\n        let nonBlockingRan = NIOLockedValueBox(false)\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.whenFailureBlocking(onto: DispatchQueue.global()) { err in\n            sem.wait()  // Block in callback\n            #expect(err as! EventLoopFutureTestError == EventLoopFutureTestError.example)\n            #expect(nonBlockingRan.withLockedValue { $0 })\n        }\n        p.fail(EventLoopFutureTestError.example)\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.withLockedValue { $0 = true }\n        }\n        p2.succeed(true)\n\n        let didRun = try! p2.futureResult.wait()\n        #expect(didRun)\n        sem.signal()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenCompleteBlockingSuccess() {\n        let eventLoop = EmbeddedEventLoop()\n        let sem = DispatchSemaphore(value: 0)\n        let nonBlockingRan = NIOLockedValueBox(false)\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.whenCompleteBlocking(onto: DispatchQueue.global()) { _ in\n            sem.wait()  // Block in callback\n            #expect(nonBlockingRan.withLockedValue { $0 })\n        }\n        p.succeed(\"hello\")\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.withLockedValue { $0 = true }\n        }\n        p2.succeed(true)\n\n        let didRun = try! p2.futureResult.wait()\n        #expect(didRun)\n        sem.signal()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testWhenCompleteBlockingFailure() {\n        let eventLoop = EmbeddedEventLoop()\n        let sem = DispatchSemaphore(value: 0)\n        let nonBlockingRan = NIOLockedValueBox(false)\n        let p = eventLoop.makePromise(of: String.self)\n        p.futureResult.whenCompleteBlocking(onto: DispatchQueue.global()) { _ in\n            sem.wait()  // Block in callback\n            #expect(nonBlockingRan.withLockedValue { $0 })\n        }\n        p.fail(EventLoopFutureTestError.example)\n\n        let p2 = eventLoop.makePromise(of: Bool.self)\n        p2.futureResult.whenSuccess { _ in\n            nonBlockingRan.withLockedValue { $0 = true }\n        }\n        p2.succeed(true)\n\n        let didRun = try! p2.futureResult.wait()\n        #expect(didRun)\n        sem.signal()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFlatMapWithEL() throws {\n        let el = EmbeddedEventLoop()\n\n        let result = try el.makeSucceededFuture(1).flatMapWithEventLoop { one, el2 in\n            #expect(el === el2)\n            return el2.makeSucceededFuture(one + 1)\n        }.wait()\n        #expect(2 == result)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFlatMapErrorWithEL() throws {\n        let el = EmbeddedEventLoop()\n        struct E: Error {}\n\n        let result = try el.makeFailedFuture(E()).flatMapErrorWithEventLoop { error, el2 in\n            #expect(error is E)\n            return el2.makeSucceededFuture(1)\n        }.wait()\n        #expect(1 == result)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testFoldWithEL() throws {\n        let el = EmbeddedEventLoop()\n\n        let futures = (1...10).map { el.makeSucceededFuture($0) }\n\n        let calls = NIOLockedValueBox(0)\n        let all = el.makeSucceededFuture(0).foldWithEventLoop(futures) { l, r, el2 in\n            calls.withLockedValue { $0 += 1 }\n            #expect(el === el2)\n            #expect(calls.withLockedValue { $0 } == r)\n            return el2.makeSucceededFuture(l + r)\n        }\n\n        let expectedResult = (1...10).reduce(0, +)\n        let result = try all.wait()\n        #expect(expectedResult == result)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAssertSuccess() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise = eventLoop.makePromise(of: String.self)\n        let assertedFuture = promise.futureResult.assertSuccess()\n        promise.succeed(\"hello\")\n\n        #expect(throws: Never.self) { try assertedFuture.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAssertFailure() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise = eventLoop.makePromise(of: String.self)\n        let assertedFuture = promise.futureResult.assertFailure()\n        promise.fail(EventLoopFutureTestError.example)\n\n        #expect(throws: EventLoopFutureTestError.example) {\n            try assertedFuture.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPreconditionSuccess() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise = eventLoop.makePromise(of: String.self)\n        let preconditionedFuture = promise.futureResult.preconditionSuccess()\n        promise.succeed(\"hello\")\n\n        #expect(throws: Never.self) { try preconditionedFuture.wait() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPreconditionFailure() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise = eventLoop.makePromise(of: String.self)\n        let preconditionedFuture = promise.futureResult.preconditionFailure()\n        promise.fail(EventLoopFutureTestError.example)\n\n        #expect(throws: EventLoopFutureTestError.example) {\n            try preconditionedFuture.wait()\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testSetOrCascadeReplacesNil() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        var promise: EventLoopPromise<Void>? = nil\n        let other = eventLoop.makePromise(of: Void.self)\n        promise.setOrCascade(to: other)\n        #expect(promise != nil)\n        promise?.succeed()\n        try other.futureResult.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testSetOrCascadeCascadesToExisting() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        var promise: EventLoopPromise<Void>? = eventLoop.makePromise(of: Void.self)\n        let other = eventLoop.makePromise(of: Void.self)\n        promise.setOrCascade(to: other)\n        promise?.succeed()\n        try other.futureResult.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testSetOrCascadeNoOpOnNil() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        var promise: EventLoopPromise<Void>? = eventLoop.makePromise(of: Void.self)\n        promise.setOrCascade(to: nil)\n        #expect(promise != nil)\n        promise?.succeed()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseEquatable() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise1 = eventLoop.makePromise(of: Void.self)\n        let promise2 = eventLoop.makePromise(of: Void.self)\n        let promise3 = promise1\n        #expect(promise1 == promise3)\n        #expect(promise1 != promise2)\n        #expect(promise3 != promise2)\n\n        promise1.succeed()\n        promise2.succeed()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseEquatable_WhenSucceeded() {\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise1 = eventLoop.makePromise(of: Void.self)\n        let promise2 = eventLoop.makePromise(of: Void.self)\n        let promise3 = promise1\n\n        promise1.succeed()\n        promise2.succeed()\n        #expect(promise1 == promise3)\n        #expect(promise1 != promise2)\n        #expect(promise3 != promise2)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testPromiseEquatable_WhenFailed() {\n        struct E: Error {}\n        let eventLoop = EmbeddedEventLoop()\n\n        let promise1 = eventLoop.makePromise(of: Void.self)\n        let promise2 = eventLoop.makePromise(of: Void.self)\n        let promise3 = promise1\n\n        promise1.fail(E())\n        promise2.fail(E())\n        #expect(promise1 == promise3)\n        #expect(promise1 != promise2)\n        #expect(promise3 != promise2)\n    }\n}\n\nclass NonSendableObject: Equatable {\n    var value: Int\n    init(value: Int) {\n        self.value = value\n    }\n\n    static func == (lhs: NonSendableObject, rhs: NonSendableObject) -> Bool {\n        lhs.value == rhs.value\n    }\n}\n@available(*, unavailable)\nextension NonSendableObject: Sendable {}\n"
  },
  {
    "path": "Tests/NIOPosixTests/EventLoopMetricsDelegateTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nfinal class RecorderDelegate: NIOEventLoopMetricsDelegate, Sendable {\n\n    private let _infos: NIOLockedValueBox<[NIOEventLoopTickInfo]> = .init([])\n\n    var infos: [NIOEventLoopTickInfo] {\n        _infos.withLockedValue { $0 }\n    }\n\n    func processedTick(info: NIOPosix.NIOEventLoopTickInfo) {\n        _infos.withLockedValue {\n            $0.append(info)\n        }\n    }\n}\n\nfinal class EventLoopMetricsDelegateTests: XCTestCase {\n    func testMetricsDelegateNotCalledWhenNoEvents() throws {\n        let delegate = RecorderDelegate()\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1, metricsDelegate: delegate)\n        XCTAssertEqual(delegate.infos.count, 0)\n        try group.syncShutdownGracefully()\n    }\n\n    func testMetricsDelegateTickInfo() {\n        let delegate = RecorderDelegate()\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1, metricsDelegate: delegate)\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n        let el = elg.any()\n        let testStartTime = NIODeadline.now()\n\n        XCTAssertEqual(delegate.infos.count, 0)\n\n        let promise = el.makePromise(of: Void.self)\n        el.scheduleTask(in: .milliseconds(100)) {\n            // Nop. Ensures that we collect multiple tick infos.\n        }\n        el.scheduleTask(in: .seconds(1)) {\n            promise.succeed()\n        }\n\n        promise.futureResult.whenSuccess {\n            // There are 4 tasks here:\n            // 1. scheduleTask in 100ms,\n            // 2. scheduleTask in 1s,\n            // 3. whenSuccess (this callback),\n            // 4. wait() (which is secrectly a whenComplete)\n            //\n            // These can run in 2...6 event loop ticks. The worst case happens when:\n            // 1. The selector blocks after the EL is created and is woken by the 100ms task being\n            //    scheduled. The EL wakes up but has no tasks to run so goes blocks until no later\n            //    than the 100ms task needs running.\n            // 2. The 1s task is scheduled which causes the selector to wakeup again but it has\n            //    nothing to do. It goes back to sleep blocking until the 100ms task is run.\n            // 3. whenSuccess is called which wakes the selector as whenSuccess executes onto\n            //    the EL to enqueue the task. The selector goes back to sleep waiting for the\n            //    100ms task.\n            // 4. wait() is called which under the hood does a whenComplete which can then wake the\n            //    as per (3). The selector goes back to sleep waiting for the 100ms task.\n            // 5. The EL wakes up and runs the 100ms task. It goes back to sleep waiting for the\n            //    1s task.\n            // 6. The 1s task is run which succeeds the promise and runs both this whenSuccess\n            //    callback and the whenComplete in the wait().\n            //\n            // Why a maximum of five? I literally just listed six times the loop can tick. This\n            // task (whenSuccess) is running as part of the last tick, and so the info hasn't\n            // been published to the delegate yet.\n            XCTAssertTrue((2...5).contains(delegate.infos.count), \"Expected 2...5 ticks, got \\(delegate.infos.count)\")\n\n            // The total number of tasks across these ticks should be 3. Not four, because this\n            // task is the fourth and it hasn't finished running yet.\n            let totalTasks = delegate.infos.map { $0.numberOfTasks }.reduce(0, +)\n            XCTAssertEqual(totalTasks, 3, \"Expected 3 tasks, got \\(totalTasks)\")\n            // All tasks were run by the same event loop. The measurements are monotonically increasing.\n            var lastEndTime: NIODeadline?\n            for info in delegate.infos {\n                XCTAssertEqual(info.eventLoopID, ObjectIdentifier(el))\n                XCTAssertTrue(info.startTime < info.endTime)\n                // If this is not the first tick, verify the sleep time.\n                if let lastEndTime {\n                    XCTAssertTrue(lastEndTime < info.startTime)\n                    XCTAssertEqual(lastEndTime + info.sleepTime, info.startTime)\n                }\n                // Keep track of the last event time to verify the sleep interval.\n                lastEndTime = info.endTime\n            }\n            if let lastTickStartTime = delegate.infos.last?.startTime {\n                let timeSinceStart = lastTickStartTime - testStartTime\n                // This should be near instantly after the delay of the first run.\n                XCTAssertLessThan(timeSinceStart.nanoseconds, 200_000_000)\n                XCTAssertGreaterThan(timeSinceStart.nanoseconds, 0)\n            }\n        }\n        try? promise.futureResult.wait()\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/EventLoopTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport Dispatch\nimport Foundation\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport Testing\n\n@testable import NIOCore\n@testable import NIOPosix\n\n@Suite(\"MultiThreadedEventLoopGroupTests\", .serialized)\nfinal class MultiThreadedEventLoopGroupTests {\n    @Test\n    func testSchedule() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        let scheduled = eventLoop.scheduleTask(in: .seconds(1)) { true }\n\n        var result: Bool?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n        eventLoop.run()  // run without time advancing should do nothing\n        #expect(scheduled.futureResult.isFulfilled == false)\n        #expect(result == nil)\n\n        eventLoop.advanceTime(by: .seconds(1))  // should fire now\n\n        #expect(scheduled.futureResult.isFulfilled)\n        #expect(result != nil)\n        #expect(result == true)\n    }\n\n    @Test\n    func testFlatSchedule() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        let scheduled = eventLoop.flatScheduleTask(in: .seconds(1)) {\n            eventLoop.makeSucceededFuture(true)\n        }\n\n        var result: Bool?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n\n        eventLoop.run()  // run without time advancing should do nothing\n        #expect(scheduled.futureResult.isFulfilled == false)\n        #expect(result == nil)\n\n        eventLoop.advanceTime(by: .seconds(1))  // should fire now\n        #expect(scheduled.futureResult.isFulfilled)\n\n        #expect(result != nil)\n        #expect(result == true)\n    }\n\n    func testScheduleWithDelay() throws {\n        let smallAmount: TimeAmount = .milliseconds(100)\n        let longAmount: TimeAmount = .seconds(1)\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        // First, we create a server and client channel, but don't connect them.\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: eventLoopGroup)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n        let clientBootstrap = ClientBootstrap(group: eventLoopGroup)\n\n        // Now, schedule two tasks: one that takes a while, one that doesn't.\n        let nanos: NIODeadline = .now()\n        let longFuture = eventLoopGroup.next().scheduleTask(in: longAmount) {\n            true\n        }.futureResult\n\n        #expect(\n            try assertNoThrowWithValue(\n                try eventLoopGroup.next().scheduleTask(in: smallAmount) {\n                    true\n                }.futureResult.wait()\n            )\n        )\n\n        // Ok, the short one has happened. Now we should try connecting them. This connect should happen\n        // faster than the final task firing.\n        _ = try assertNoThrowWithValue(clientBootstrap.connect(to: serverChannel.localAddress!).wait()) as Channel\n        #expect((NIODeadline.now() - nanos < longAmount))\n\n        // Now wait for the long-delayed task.\n        #expect(try assertNoThrowWithValue(try longFuture.wait()))\n        // Now we're ok.\n        #expect((NIODeadline.now() - nanos >= longAmount))\n    }\n\n    @Test\n    func testScheduleCancelled() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        let scheduled = eventLoop.scheduleTask(in: .seconds(1)) { true }\n\n        var result: Bool?\n        var error: Error?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n        scheduled.futureResult.assumeIsolated().whenFailure { error = $0 }\n\n        eventLoop.advanceTime(by: .milliseconds(500))  // advance halfway to firing time\n        scheduled.cancel()\n        eventLoop.advanceTime(by: .milliseconds(500))  // advance the rest of the way\n\n        #expect(scheduled.futureResult.isFulfilled)\n        #expect(result == nil)\n        #expect(error as? EventLoopError == .cancelled)\n    }\n\n    @Test\n    func testFlatScheduleCancelled() throws {\n        let eventLoop = EmbeddedEventLoop()\n\n        let scheduled = eventLoop.flatScheduleTask(in: .seconds(1)) {\n            eventLoop.makeSucceededFuture(true)\n        }\n\n        var result: Bool?\n        var error: Error?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n        scheduled.futureResult.assumeIsolated().whenFailure { error = $0 }\n\n        eventLoop.advanceTime(by: .milliseconds(500))  // advance halfway to firing time\n        scheduled.cancel()\n        eventLoop.advanceTime(by: .milliseconds(500))  // advance the rest of the way\n\n        #expect(scheduled.futureResult.isFulfilled)\n        #expect(result == nil)\n        #expect(error as? EventLoopError == .cancelled)\n    }\n\n    @Test\n    func testScheduleRepeatedTask() throws {\n        let nanos: NIODeadline = .now()\n        let initialDelay: TimeAmount = .milliseconds(5)\n        let delay: TimeAmount = .milliseconds(10)\n        let count = 5\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let counter = ManagedAtomic<Int>(0)\n        let loop = eventLoopGroup.next()\n        let allDone = DispatchGroup()\n        allDone.enter()\n        loop.scheduleRepeatedTask(initialDelay: initialDelay, delay: delay) { repeatedTask -> Void in\n            #expect(loop.inEventLoop)\n            let initialValue = counter.load(ordering: .relaxed)\n            counter.wrappingIncrement(ordering: .relaxed)\n            if initialValue == 0 {\n                #expect(NIODeadline.now() - nanos >= initialDelay)\n            } else if initialValue == count {\n                repeatedTask.cancel()\n                allDone.leave()\n            }\n        }\n\n        allDone.wait()\n\n        #expect(counter.load(ordering: .relaxed) == count + 1)\n        #expect(NIODeadline.now() - nanos >= initialDelay + Int64(count) * delay)\n    }\n\n    @Test\n    func testScheduledTaskThatIsImmediatelyCancelledNeverFires() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let scheduled = eventLoop.scheduleTask(in: .seconds(1)) { true }\n\n        var result: Bool?\n        var error: Error?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n        scheduled.futureResult.assumeIsolated().whenFailure { error = $0 }\n\n        scheduled.cancel()\n        eventLoop.advanceTime(by: .seconds(1))\n\n        #expect(scheduled.futureResult.isFulfilled)\n        #expect(result == nil)\n        #expect(error as? EventLoopError == .cancelled)\n    }\n\n    @Test\n    func testScheduledTasksAreOrdered() throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = eventLoopGroup.next()\n        let now = NIODeadline.now()\n\n        let result = NIOLockedValueBox([Int]())\n        var lastScheduled: Scheduled<Void>?\n        for i in 0...100 {\n            lastScheduled = eventLoop.scheduleTask(deadline: now) {\n                result.withLockedValue { $0.append(i) }\n            }\n        }\n        try lastScheduled?.futureResult.wait()\n        #expect(result.withLockedValue { $0 } == Array(0...100))\n    }\n\n    @Test\n    func testFlatScheduledTaskThatIsImmediatelyCancelledNeverFires() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let scheduled = eventLoop.flatScheduleTask(in: .seconds(1)) {\n            eventLoop.makeSucceededFuture(true)\n        }\n\n        var result: Bool?\n        var error: Error?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n        scheduled.futureResult.assumeIsolated().whenFailure { error = $0 }\n\n        scheduled.cancel()\n        eventLoop.advanceTime(by: .seconds(1))\n\n        #expect(scheduled.futureResult.isFulfilled)\n        #expect(result == nil)\n        #expect(error as? EventLoopError == .cancelled)\n    }\n\n    @Test\n    func testRepeatedTaskThatIsImmediatelyCancelledNeverFires() throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let loop = eventLoopGroup.next()\n        loop.execute {\n            let task = loop.scheduleRepeatedTask(initialDelay: .milliseconds(0), delay: .milliseconds(0)) { task in\n                Issue.record()\n            }\n            task.cancel()\n        }\n        Thread.sleep(until: .init(timeIntervalSinceNow: 0.1))\n    }\n\n    @Test\n    func testScheduleRepeatedTaskCancelFromDifferentThread() throws {\n        let nanos: NIODeadline = .now()\n        let initialDelay: TimeAmount = .milliseconds(5)\n        // this will actually force the race from issue #554 to happen frequently\n        let delay: TimeAmount = .milliseconds(0)\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let hasFiredGroup = DispatchGroup()\n        let isCancelledGroup = DispatchGroup()\n        let loop = eventLoopGroup.next()\n        hasFiredGroup.enter()\n        isCancelledGroup.enter()\n\n        let (isAllowedToFire, hasFired) = try! loop.submit {\n            let isAllowedToFire = NIOLoopBoundBox(true, eventLoop: loop)\n            let hasFired = NIOLoopBoundBox(false, eventLoop: loop)\n            return (isAllowedToFire, hasFired)\n        }.wait()\n\n        let repeatedTask = loop.scheduleRepeatedTask(initialDelay: initialDelay, delay: delay) {\n            (_: RepeatedTask) -> Void in\n            #expect(loop.inEventLoop)\n            if !hasFired.value {\n                // we can only do this once as we can only leave the DispatchGroup once but we might lose a race and\n                // the timer might fire more than once (until `shouldNoLongerFire` becomes true).\n                hasFired.value = true\n                hasFiredGroup.leave()\n            }\n            #expect(isAllowedToFire.value)\n        }\n        hasFiredGroup.notify(queue: DispatchQueue.global()) {\n            repeatedTask.cancel()\n            loop.execute {\n                // only now do we know that the `cancel` must have gone through\n                isAllowedToFire.value = false\n                isCancelledGroup.leave()\n            }\n        }\n\n        hasFiredGroup.wait()\n        #expect(NIODeadline.now() - nanos >= initialDelay)\n        isCancelledGroup.wait()\n    }\n\n    @Test\n    func testScheduleRepeatedTaskToNotRetainRepeatedTask() throws {\n        let initialDelay: TimeAmount = .milliseconds(5)\n        let delay: TimeAmount = .milliseconds(10)\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n\n        weak var weakRepeated: RepeatedTask?\n        do {\n            let repeated = eventLoopGroup.next().scheduleRepeatedTask(\n                initialDelay: initialDelay,\n                delay: delay\n            ) {\n                (_: RepeatedTask) -> Void in\n            }\n            weakRepeated = repeated\n            #expect(weakRepeated != nil)\n            repeated.cancel()\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n        assert(weakRepeated == nil, within: .seconds(1))\n    }\n\n    @Test\n    func testScheduleRepeatedTaskToNotRetainEventLoop() throws {\n        weak var weakEventLoop: EventLoop? = nil\n        do {\n            let initialDelay: TimeAmount = .milliseconds(5)\n            let delay: TimeAmount = .milliseconds(10)\n            let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n            weakEventLoop = eventLoopGroup.next()\n            #expect(weakEventLoop != nil)\n\n            eventLoopGroup.next().scheduleRepeatedTask(initialDelay: initialDelay, delay: delay) {\n                (_: RepeatedTask) -> Void in\n            }\n\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n        assert(weakEventLoop == nil, within: .seconds(1))\n    }\n\n    @Test\n    func testScheduledRepeatedAsyncTask() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let counter = NIOLoopBoundBox(0, eventLoop: eventLoop)\n\n        let repeatedTask = eventLoop.scheduleRepeatedAsyncTask(\n            initialDelay: .milliseconds(10),\n            delay: .milliseconds(10)\n        ) { (_: RepeatedTask) in\n            counter.value += 1\n            let p = eventLoop.makePromise(of: Void.self)\n            _ = eventLoop.scheduleTask(in: .milliseconds(10)) {\n\n                p.succeed(())\n            }\n            return p.futureResult\n        }\n        for _ in 0..<10 {\n            // just running shouldn't do anything\n            eventLoop.run()\n        }\n\n        // t == 0: nothing\n        #expect(0 == counter.value)\n\n        // t == 5: nothing\n        eventLoop.advanceTime(by: .milliseconds(5))\n        #expect(0 == counter.value)\n\n        // t == 10: once\n        eventLoop.advanceTime(by: .milliseconds(5))\n        #expect(1 == counter.value)\n\n        // t == 15: still once\n        eventLoop.advanceTime(by: .milliseconds(5))\n        #expect(1 == counter.value)\n\n        // t == 20: still once (because the task takes 10ms to execute)\n        eventLoop.advanceTime(by: .milliseconds(5))\n        #expect(1 == counter.value)\n\n        // t == 25: still once (because the task takes 10ms to execute)\n        eventLoop.advanceTime(by: .milliseconds(5))\n        #expect(1 == counter.value)\n\n        // t == 30: twice\n        eventLoop.advanceTime(by: .milliseconds(5))\n        #expect(2 == counter.value)\n\n        // t == 40: twice\n        eventLoop.advanceTime(by: .milliseconds(10))\n        #expect(2 == counter.value)\n\n        // t == 50: three times\n        eventLoop.advanceTime(by: .milliseconds(10))\n        #expect(3 == counter.value)\n\n        // t == 60: three times\n        eventLoop.advanceTime(by: .milliseconds(10))\n        #expect(3 == counter.value)\n\n        // t == 89: four times\n        eventLoop.advanceTime(by: .milliseconds(29))\n        #expect(4 == counter.value)\n\n        // t == 90: five times\n        eventLoop.advanceTime(by: .milliseconds(1))\n        #expect(5 == counter.value)\n\n        repeatedTask.cancel()\n\n        eventLoop.run()\n        #expect(5 == counter.value)\n\n        eventLoop.advanceTime(by: .hours(10))\n        #expect(5 == counter.value)\n    }\n\n    @Test\n    func testScheduledRepeatedAsyncTaskIsJittered() throws {\n        let initialDelay = TimeAmount.minutes(5)\n        let delay = TimeAmount.minutes(2)\n        let maximumAllowableJitter = TimeAmount.minutes(1)\n        let counter = ManagedAtomic<Int64>(0)\n        let loop = EmbeddedEventLoop()\n\n        _ = loop.scheduleRepeatedAsyncTask(\n            initialDelay: initialDelay,\n            delay: delay,\n            maximumAllowableJitter: maximumAllowableJitter,\n            { _ in\n                counter.wrappingIncrement(ordering: .relaxed)\n                let p = loop.makePromise(of: Void.self)\n                _ = loop.scheduleTask(in: .milliseconds(10)) {\n                    p.succeed(())\n                }\n                return p.futureResult\n            }\n        )\n\n        for _ in 0..<10 {\n            // just running shouldn't do anything\n            loop.run()\n        }\n\n        let timeRange = TimeAmount.hours(1)\n        // Due to jittered delays is not possible to exactly know how many tasks will be executed in a given time range,\n        // instead calculate a range representing an estimate of the number of tasks executed during that given time range.\n        let minNumberOfExecutedTasks =\n            (timeRange.nanoseconds - initialDelay.nanoseconds)\n            / (delay.nanoseconds + maximumAllowableJitter.nanoseconds)\n        let maxNumberOfExecutedTasks =\n            (timeRange.nanoseconds - initialDelay.nanoseconds) / delay.nanoseconds + 1\n\n        loop.advanceTime(by: timeRange)\n        #expect(\n            (minNumberOfExecutedTasks...maxNumberOfExecutedTasks).contains(\n                counter.load(ordering: .relaxed)\n            )\n        )\n    }\n\n    @Test\n    func testEventLoopGroupMakeIterator() throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        var counter = 0\n        var innerCounter = 0\n        for loop in eventLoopGroup.makeIterator() {\n            counter += 1\n            for _ in loop.makeIterator() {\n                innerCounter += 1\n            }\n        }\n\n        #expect(counter == System.coreCount)\n        #expect(innerCounter == System.coreCount)\n    }\n\n    @Test\n    func testEventLoopMakeIterator() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let iterator = eventLoop.makeIterator()\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoop.syncShutdownGracefully()\n            }\n        }\n\n        var counter = 0\n        for loop in iterator {\n            #expect(loop === eventLoop)\n            counter += 1\n        }\n\n        #expect(counter == 1)\n    }\n\n    @Test\n    func testMultipleShutdown() throws {\n        // This test catches a regression that causes it to intermittently fail: it reveals bugs in synchronous shutdown.\n        // Do not ignore intermittent failures in this test!\n        let threads = 8\n        let numBytes = 256\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: threads)\n\n        // Create a server channel.\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        // We now want to connect to it. To try to slow this stuff down, we're going to use a multiple of the number\n        // of event loops.\n        for _ in 0..<(threads * 5) {\n            let clientChannel = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .connect(to: serverChannel.localAddress!)\n                    .wait()\n            )\n\n            var buffer = clientChannel.allocator.buffer(capacity: numBytes)\n            for i in 0..<numBytes {\n                buffer.writeInteger(UInt8(i % 256))\n            }\n\n            try clientChannel.writeAndFlush(buffer).wait()\n        }\n\n        // We should now shut down gracefully.\n        try group.syncShutdownGracefully()\n    }\n\n    @Test\n    func testShuttingDownFailsRegistration() throws {\n        // This test catches a regression where the selectable event loop would allow a socket registration while\n        // it was nominally \"shutting down\". To do this, we take advantage of the fact that the event loop attempts\n        // to cleanly shut down all the channels before it actually closes. We add a custom channel that we can use\n        // to wedge the event loop in the \"shutting down\" state, ensuring that we have plenty of time to attempt the\n        // registration.\n        class WedgeOpenHandler: ChannelDuplexHandler {\n            typealias InboundIn = Any\n            typealias OutboundIn = Any\n            typealias OutboundOut = Any\n\n            private let promiseRegisterCallback: (EventLoopPromise<Void>) -> Void\n\n            var closePromise: EventLoopPromise<Void>? = nil\n            private let channelActivePromise: EventLoopPromise<Void>?\n\n            init(\n                channelActivePromise: EventLoopPromise<Void>? = nil,\n                _ promiseRegisterCallback: @escaping (EventLoopPromise<Void>) -> Void\n            ) {\n                self.promiseRegisterCallback = promiseRegisterCallback\n                self.channelActivePromise = channelActivePromise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                self.channelActivePromise?.succeed(())\n            }\n\n            func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n                guard self.closePromise == nil else {\n                    Issue.record(\"Attempted to create duplicate close promise\")\n                    return\n                }\n                #expect(context.channel.isActive)\n                self.closePromise = context.eventLoop.makePromise()\n                let loopBoundContext = context.loopBound\n                self.closePromise!.futureResult.whenSuccess {\n                    let context = loopBoundContext.value\n                    context.close(mode: mode, promise: promise)\n                }\n                promiseRegisterCallback(self.closePromise!)\n            }\n        }\n\n        let promises = NIOLockedValueBox<[EventLoopPromise<Void>]>([])\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: EventLoopError.self) {\n                do {\n                    try group.syncShutdownGracefully()\n                } catch {\n                    #expect(.shutdown == error as? EventLoopError)\n                    // re-throw error if caught to satisfy expectation that error is thrown\n                    throw error\n                }\n            }\n        }\n        let loop = group.next() as! SelectableEventLoop\n\n        let serverChannelUp = group.next().makePromise(of: Void.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            WedgeOpenHandler(channelActivePromise: serverChannelUp) { promise in\n                                promises.withLockedValue { $0.append(promise) }\n                            }\n                        )\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n        defer {\n            #expect(serverChannel.isActive == false)\n        }\n        let connectPromise = loop.makePromise(of: Void.self)\n\n        // We're going to create and register a channel, but not actually attempt to do anything with it.\n        let channel = try SocketChannel(eventLoop: loop, protocolFamily: .inet)\n        try channel.eventLoop.submit {\n            channel.eventLoop.makeCompletedFuture {\n                let wedgeHandler = WedgeOpenHandler { promise in\n                    promises.withLockedValue { $0.append(promise) }\n                }\n                try channel.pipeline.syncOperations.addHandler(wedgeHandler)\n            }.flatMap {\n                channel.register()\n            }.flatMap {\n                // connecting here to stop epoll from throwing EPOLLHUP at us\n                channel.connect(to: serverChannel.localAddress!)\n            }.cascade(to: connectPromise)\n        }.wait()\n\n        // Wait for the connect to complete.\n        #expect(throws: Never.self) {\n            try connectPromise.futureResult.wait()\n            try serverChannelUp.futureResult.wait()\n        }\n\n        let g = DispatchGroup()\n        let q = DispatchQueue(label: \"\\(#filePath)/\\(#line)\")\n        g.enter()\n        // Now we're going to start closing the event loop. This should not immediately succeed.\n        loop.initiateClose(queue: q) { result in\n            func workaroundSR9815() {\n                #expect(throws: Never.self) {\n                    try result.get()\n                }\n            }\n            workaroundSR9815()\n            g.leave()\n        }\n\n        // Now we're going to attempt to register a new channel. This should immediately fail.\n        let newChannel = try SocketChannel(eventLoop: loop, protocolFamily: .inet)\n\n        #expect(throws: EventLoopError.self) {\n            do {\n                try newChannel.register().wait()\n            } catch {\n                #expect(.shutdown == error as? EventLoopError)\n                throw error\n            }\n        }\n\n        // Confirm that the loop still hasn't closed.\n        #expect(.timedOut == g.wait(timeout: .now()))\n\n        // Now let it close.\n        let promisesToSucceed = promises.withLockedValue { $0 }\n        for promise in promisesToSucceed {\n            promise.succeed(())\n        }\n        #expect(throws: Never.self) {\n            g.wait()\n        }\n    }\n\n    @Test\n    func testEventLoopThreads() throws {\n        var counter = 0\n        let body: ThreadInitializer = { t in\n            counter += 1\n        }\n        let threads: [ThreadInitializer] = [body, body]\n\n        let group = MultiThreadedEventLoopGroup(threadInitializers: threads, metricsDelegate: nil)\n\n        #expect(2 == counter)\n        #expect(throws: Never.self) {\n            try group.syncShutdownGracefully()\n        }\n    }\n\n    @Test\n    func testEventLoopPinned() throws {\n        #if os(Linux) || os(Android)\n        let target = NIOThread.currentAffinity.cpuIds.first!\n        let body: ThreadInitializer = { t in\n            let set = LinuxCPUSet(target)\n            precondition(t.isCurrentSlow)\n            NIOThread.currentAffinity = set\n            #expect(set == NIOThread.currentAffinity)\n        }\n        let threads: [ThreadInitializer] = [body, body]\n\n        let group = MultiThreadedEventLoopGroup(threadInitializers: threads, metricsDelegate: nil)\n\n        #expect(throws: Never.self) {\n            try group.syncShutdownGracefully()\n        }\n        #endif\n    }\n\n    @Test\n    func testEventLoopPinnedCPUIdsConstructor() throws {\n        #if os(Linux) || os(Android)\n        let target = NIOThread.currentAffinity.cpuIds.first!\n        let group = MultiThreadedEventLoopGroup(pinnedCPUIDs: [target])\n        let eventLoop = group.next()\n        let set = try eventLoop.submit {\n            NIOThread.currentAffinity\n        }.wait()\n\n        #expect(LinuxCPUSet(target) == set)\n        #expect(throws: Never.self) {\n            try group.syncShutdownGracefully()\n        }\n        #endif\n    }\n\n    @Test\n    func testCurrentEventLoop() throws {\n        class EventLoopHolder {\n            weak var loop: EventLoop?\n            init(_ loop: EventLoop) {\n                self.loop = loop\n            }\n        }\n\n        func assertCurrentEventLoop0() throws -> EventLoopHolder {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n\n            let loop1 = group.next()\n            let currentLoop1 = try loop1.submit {\n                MultiThreadedEventLoopGroup.currentEventLoop\n            }.wait()\n            #expect(loop1 === currentLoop1)\n\n            let loop2 = group.next()\n            let currentLoop2 = try loop2.submit {\n                MultiThreadedEventLoopGroup.currentEventLoop\n            }.wait()\n            #expect(loop2 === currentLoop2)\n            #expect((loop1 === loop2) == false)\n\n            let holder = EventLoopHolder(loop2)\n            #expect(holder.loop != nil)\n            #expect(MultiThreadedEventLoopGroup.currentEventLoop == nil)\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n            return holder\n        }\n\n        let holder = try assertCurrentEventLoop0()\n\n        // We loop as the Thread used by SelectableEventLoop may not be gone yet.\n        // In the next major version we should ensure to join all threads and so be sure all are gone when\n        // syncShutdownGracefully returned.\n        var tries = 0\n        while holder.loop != nil {\n            #expect(tries < 5, \"Reference to EventLoop still alive after 5 seconds\")\n            sleep(1)\n            tries += 1\n        }\n    }\n\n    @Test\n    func testShutdownWhileScheduledTasksNotReady() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let eventLoop = group.next()\n        _ = eventLoop.scheduleTask(in: .hours(1)) {}\n        try group.syncShutdownGracefully()\n    }\n\n    @Test\n    func testCloseFutureNotifiedBeforeUnblock() throws {\n        final class AssertHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Any\n\n            let groupIsShutdown = ManagedAtomic(false)\n            let removed = ManagedAtomic(false)\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                #expect(groupIsShutdown.load(ordering: .relaxed) == false)\n                #expect(removed.compareExchange(expected: false, desired: true, ordering: .relaxed).exchanged)\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let eventLoop = group.next()\n        let assertHandler = AssertHandler()\n        let serverSocket = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"localhost\", port: 0).wait()\n        )\n        let channel = try assertNoThrowWithValue(\n            SocketChannel(\n                eventLoop: eventLoop as! SelectableEventLoop,\n                protocolFamily: serverSocket.localAddress!.protocol\n            )\n        )\n        #expect(throws: Never.self) {\n            try channel.pipeline.addHandler(assertHandler).wait() as Void\n            try channel.eventLoop.flatSubmit {\n                channel.register().flatMap {\n                    channel.connect(to: serverSocket.localAddress!)\n                }\n            }.wait() as Void\n        }\n        let closeFutureFulfilledEventually = ManagedAtomic(false)\n        #expect(channel.closeFuture.isFulfilled == false)\n        channel.closeFuture.whenSuccess {\n            #expect(\n                closeFutureFulfilledEventually.compareExchange(expected: false, desired: true, ordering: .relaxed)\n                    .exchanged\n            )\n        }\n        #expect(throws: Never.self) {\n            try group.syncShutdownGracefully()\n        }\n        #expect(\n            assertHandler.groupIsShutdown.compareExchange(expected: false, desired: true, ordering: .relaxed).exchanged\n        )\n        #expect(assertHandler.removed.load(ordering: .relaxed) == true)\n        #expect(channel.isActive == false)\n        #expect(closeFutureFulfilledEventually.load(ordering: .relaxed) == true)\n    }\n\n    @Test\n    func testScheduleMultipleTasks() throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = eventLoopGroup.next()\n        let array = try! eventLoop.submit {\n            NIOLoopBoundBox([(Int, NIODeadline)](), eventLoop: eventLoop)\n        }.wait()\n        let scheduled1 = eventLoop.scheduleTask(in: .milliseconds(500)) {\n            array.value.append((1, .now()))\n        }\n\n        let scheduled2 = eventLoop.scheduleTask(in: .milliseconds(100)) {\n            array.value.append((2, .now()))\n        }\n\n        let scheduled3 = eventLoop.scheduleTask(in: .milliseconds(1000)) {\n            array.value.append((3, .now()))\n        }\n\n        var result = try eventLoop.scheduleTask(in: .milliseconds(1000)) {\n            array.value\n        }.futureResult.wait()\n\n        #expect(scheduled1.futureResult.isFulfilled)\n        #expect(scheduled2.futureResult.isFulfilled)\n        #expect(scheduled3.futureResult.isFulfilled)\n\n        let first = result.removeFirst()\n        #expect(2 == first.0)\n        let second = result.removeFirst()\n        #expect(1 == second.0)\n        let third = result.removeFirst()\n        #expect(3 == third.0)\n\n        #expect(first.1 < second.1)\n        #expect(second.1 < third.1)\n\n        #expect(result.isEmpty)\n    }\n\n    @Test\n    func testRepeatedTaskThatIsImmediatelyCancelledNotifies() async throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let loop = eventLoopGroup.next()\n        let promise1: EventLoopPromise<Void> = loop.makePromise()\n        let promise2: EventLoopPromise<Void> = loop.makePromise()\n        try await confirmation(expectedCount: 2) { confirmation in\n            promise1.futureResult.whenSuccess { confirmation() }\n            promise2.futureResult.whenSuccess { confirmation() }\n            loop.execute {\n                let task = loop.scheduleRepeatedTask(\n                    initialDelay: .milliseconds(0),\n                    delay: .milliseconds(0),\n                    notifying: promise1\n                ) { task in\n                    Issue.record()\n                }\n                task.cancel(promise: promise2)\n            }\n\n            try await Task.sleep(nanoseconds: 100_000_000)\n        }\n    }\n\n    @Test\n    func testRepeatedTaskThatIsCancelledAfterRunningAtLeastTwiceNotifies() async throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let loop = eventLoopGroup.next()\n        let promise1: EventLoopPromise<Void> = loop.makePromise()\n        let promise2: EventLoopPromise<Void> = loop.makePromise()\n\n        // Wait for task to notify twice\n        var task: RepeatedTask?\n        let initialConfirmCount = ManagedAtomic<Int>(0)\n        let minimumExpectedCount = 2\n        try await confirmation(expectedCount: minimumExpectedCount) { confirm in\n            task = loop.scheduleRepeatedTask(\n                initialDelay: .milliseconds(0),\n                delay: .milliseconds(10),\n                notifying: promise1\n            ) { task in\n                // We need to confirm two or more occur\n                if initialConfirmCount.loadThenWrappingIncrement(ordering: .sequentiallyConsistent)\n                    < minimumExpectedCount\n                {\n                    confirm()\n                }\n            }\n            try await Task.sleep(nanoseconds: 100_000_000)\n        }\n        let cancellationHandle = try #require(task)\n\n        try await confirmation(expectedCount: 2) { confirmation in\n            promise1.futureResult.whenSuccess { confirmation() }\n            promise2.futureResult.whenSuccess { confirmation() }\n            cancellationHandle.cancel(promise: promise2)\n            try await Task.sleep(nanoseconds: 1_000_000_000)\n        }\n    }\n\n    @Test\n    func testRepeatedTaskThatCancelsItselfNotifiesOnlyWhenFinished() async throws {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let loop = eventLoopGroup.next()\n        let promise1: EventLoopPromise<Void> = loop.makePromise()\n        let promise2: EventLoopPromise<Void> = loop.makePromise()\n        let semaphore = DispatchSemaphore(value: 0)\n\n        loop.scheduleRepeatedTask(\n            initialDelay: .milliseconds(0),\n            delay: .milliseconds(0),\n            notifying: promise1\n        ) { task in\n            task.cancel(promise: promise2)\n            semaphore.wait()\n        }\n\n        // Phase 1 — promises must NOT complete within 0.5s\n        try await confirmation(expectedCount: 0) { confirm in\n            promise1.futureResult.whenSuccess {\n                confirm()  // would fail the test if called, because we expect 0 confirmations\n            }\n            promise2.futureResult.whenSuccess {\n                confirm()  // would fail the test if called, because we expect 0 confirmations\n            }\n\n            // Allow 0.5 seconds for promises to incorrectly fulfill\n            try await Task.sleep(nanoseconds: 500_000_000)\n        }\n\n        // Phase 2 — now allow completion and verify they DO complete\n\n        semaphore.signal()\n\n        try await confirmation(expectedCount: 2) { confirm in\n            promise1.futureResult.whenSuccess {\n                confirm()\n            }\n            promise2.futureResult.whenSuccess {\n                confirm()\n            }\n\n            // Allow 0.5 seconds for promises to correctly fulfill\n            try await Task.sleep(nanoseconds: 500_000_000)\n        }\n    }\n\n    @Test\n    func testRepeatedTaskIsJittered() throws {\n        let initialDelay = TimeAmount.minutes(5)\n        let delay = TimeAmount.minutes(2)\n        let maximumAllowableJitter = TimeAmount.minutes(1)\n        let counter = ManagedAtomic<Int64>(0)\n        let loop = EmbeddedEventLoop()\n\n        _ = loop.scheduleRepeatedTask(\n            initialDelay: initialDelay,\n            delay: delay,\n            maximumAllowableJitter: maximumAllowableJitter,\n            { _ in\n                counter.wrappingIncrement(ordering: .relaxed)\n            }\n        )\n\n        let timeRange = TimeAmount.hours(1)\n        // Due to jittered delays is not possible to exactly know how many tasks will be executed in a given time range,\n        // instead calculate a range representing an estimate of the number of tasks executed during that given time range.\n        let minNumberOfExecutedTasks =\n            (timeRange.nanoseconds - initialDelay.nanoseconds)\n            / (delay.nanoseconds + maximumAllowableJitter.nanoseconds)\n        let maxNumberOfExecutedTasks =\n            (timeRange.nanoseconds - initialDelay.nanoseconds) / delay.nanoseconds + 1\n\n        loop.advanceTime(by: timeRange)\n        #expect(\n            (minNumberOfExecutedTasks...maxNumberOfExecutedTasks).contains(\n                counter.load(ordering: .relaxed)\n            )\n        )\n    }\n\n    @Test\n    func testCancelledScheduledTasksDoNotHoldOnToRunClosure() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        class Thing: @unchecked Sendable {\n            private let deallocated: ConditionLock<Int>\n\n            init(_ deallocated: ConditionLock<Int>) {\n                self.deallocated = deallocated\n            }\n\n            deinit {\n                self.deallocated.lock()\n                self.deallocated.unlock(withValue: 1)\n            }\n        }\n\n        func make(deallocated: ConditionLock<Int>) -> Scheduled<Never> {\n            let aThing = Thing(deallocated)\n            return group.next().scheduleTask(in: .hours(1)) {\n                preconditionFailure(\"this should definitely not run: \\(aThing)\")\n            }\n        }\n\n        let deallocated = ConditionLock(value: 0)\n        let scheduled = make(deallocated: deallocated)\n        scheduled.cancel()\n        if deallocated.lock(whenValue: 1, timeoutSeconds: 60) {\n            deallocated.unlock()\n        } else {\n            Issue.record(\"Timed out waiting for lock\")\n        }\n\n        #expect(throws: EventLoopError.cancelled) {\n            try scheduled.futureResult.wait()\n        }\n    }\n\n    @Test\n    func testCancelledScheduledTasksDoNotHoldOnToRunClosureEvenIfTheyWereTheNextTaskToExecute()\n        throws\n    {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        final class Thing: Sendable {\n            private let deallocated: ConditionLock<Int>\n\n            init(_ deallocated: ConditionLock<Int>) {\n                self.deallocated = deallocated\n            }\n\n            deinit {\n                self.deallocated.lock()\n                self.deallocated.unlock(withValue: 1)\n            }\n        }\n\n        func make(deallocated: ConditionLock<Int>) -> Scheduled<Void> {\n            let aThing = Thing(deallocated)\n            return group.next().scheduleTask(in: .hours(1)) {\n                preconditionFailure(\"this should definitely not run: \\(aThing)\")\n            }\n        }\n\n        // What are we doing here?\n        //\n        // Our goal is to arrange for our scheduled task to become \"nextReadyTask\" in SelectableEventLoop, so that\n        // when we cancel it there is still a copy aliasing it. This reproduces a subtle correctness bug that\n        // existed in NIO 2.48.0 and earlier.\n        //\n        // This will happen if:\n        //\n        // 1. We schedule a task for the future\n        // 2. The event loop begins a tick.\n        // 3. The event loop finds our scheduled task in the future.\n        //\n        // We can make that happen by scheduling our task and then waiting for a tick to pass, which we can\n        // achieve using `submit`.\n        //\n        // However, if there are no _other_, _even later_ tasks, we'll free the reference. This is\n        // because the nextReadyTask is cleared if the list of scheduled tasks ends up empty, so we don't want that to happen.\n        //\n        // So the order of operations is:\n        //\n        // 1. Schedule the task for the future.\n        // 2. Schedule another, even later, task.\n        // 3. Wait for a tick to pass.\n        // 4. Cancel our scheduled.\n        //\n        // In the correct code, this should invoke deinit. In the buggy code, it does not.\n        //\n        // Unfortunately, this window is very hard to hit. Cancelling the scheduled task wakes the loop up, and if it is\n        // still awake by the time we run the cancellation handler it'll notice the change. So we have to tolerate\n        // a somewhat flaky test.\n        let deallocated = ConditionLock(value: 0)\n        let scheduled = make(deallocated: deallocated)\n        scheduled.futureResult.eventLoop.scheduleTask(in: .hours(2)) {}\n        try! scheduled.futureResult.eventLoop.submit {}.wait()\n        scheduled.cancel()\n        if deallocated.lock(whenValue: 1, timeoutSeconds: 60) {\n            deallocated.unlock()\n        } else {\n            Issue.record(\"Timed out waiting for lock\")\n        }\n\n        #expect(throws: EventLoopError.cancelled) {\n            try scheduled.futureResult.wait()\n        }\n    }\n\n    @Test\n    func testIllegalCloseOfEventLoopFails() {\n        // Vapor 3 closes EventLoops directly which is illegal and makes the `shutdownGracefully` of the owning\n        // MultiThreadedEventLoopGroup never succeed.\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        #expect(throws: EventLoopError.unsupportedOperation) {\n            try group.next().syncShutdownGracefully()\n        }\n    }\n\n    @Test\n    func testSubtractingDeadlineFromPastAndFuturesDeadlinesWorks() throws {\n        let older = NIODeadline.now()\n        Thread.sleep(until: Date().addingTimeInterval(0.02))\n        let newer = NIODeadline.now()\n\n        #expect(older - newer < .nanoseconds(0))\n        #expect(newer - older > .nanoseconds(0))\n    }\n\n    @Test\n    func testCallingSyncShutdownGracefullyMultipleTimesShouldNotHang() throws {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 4)\n        try elg.syncShutdownGracefully()\n        try elg.syncShutdownGracefully()\n        try elg.syncShutdownGracefully()\n    }\n\n    @Test\n    func testCallingShutdownGracefullyMultipleTimesShouldExecuteAllCallbacks() throws {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 4)\n        let condition: ConditionLock<Int> = ConditionLock(value: 0)\n        elg.shutdownGracefully { _ in\n            if condition.lock(whenValue: 0, timeoutSeconds: 1) {\n                condition.unlock(withValue: 1)\n            }\n        }\n        elg.shutdownGracefully { _ in\n            if condition.lock(whenValue: 1, timeoutSeconds: 1) {\n                condition.unlock(withValue: 2)\n            }\n        }\n        elg.shutdownGracefully { _ in\n            if condition.lock(whenValue: 2, timeoutSeconds: 1) {\n                condition.unlock(withValue: 3)\n            }\n        }\n\n        guard condition.lock(whenValue: 3, timeoutSeconds: 1) else {\n            Issue.record(\"Not all shutdown callbacks have been executed\")\n            return\n        }\n        condition.unlock()\n    }\n\n    @Test\n    func testEdgeCasesNIODeadlineMinusNIODeadline() {\n        let smallestPossibleDeadline = NIODeadline.uptimeNanoseconds(.min)\n        let largestPossibleDeadline = NIODeadline.uptimeNanoseconds(.max)\n        let distantFuture = NIODeadline.distantFuture\n        let distantPast = NIODeadline.distantPast\n        let zeroDeadline = NIODeadline.uptimeNanoseconds(0)\n        let nowDeadline = NIODeadline.now()\n\n        let allDeadlines = [\n            smallestPossibleDeadline, largestPossibleDeadline, distantPast, distantFuture,\n            zeroDeadline, nowDeadline,\n        ]\n\n        for deadline1 in allDeadlines {\n            for deadline2 in allDeadlines {\n                if deadline1 > deadline2 {\n                    #expect(deadline1 - deadline2 > TimeAmount.nanoseconds(0))\n                } else if deadline1 < deadline2 {\n                    #expect(deadline1 - deadline2 < TimeAmount.nanoseconds(0))\n                } else {\n                    // they're equal.\n                    #expect(deadline1 - deadline2 == TimeAmount.nanoseconds(0))\n                }\n            }\n        }\n    }\n\n    @Test\n    func testEdgeCasesNIODeadlinePlusTimeAmount() {\n        let smallestPossibleTimeAmount = TimeAmount.nanoseconds(.min)\n        let largestPossibleTimeAmount = TimeAmount.nanoseconds(.max)\n        let zeroTimeAmount = TimeAmount.nanoseconds(0)\n\n        let smallestPossibleDeadline = NIODeadline.uptimeNanoseconds(.min)\n        let largestPossibleDeadline = NIODeadline.uptimeNanoseconds(.max)\n        let distantFuture = NIODeadline.distantFuture\n        let distantPast = NIODeadline.distantPast\n        let zeroDeadline = NIODeadline.uptimeNanoseconds(0)\n        let nowDeadline = NIODeadline.now()\n\n        for timeAmount in [smallestPossibleTimeAmount, largestPossibleTimeAmount, zeroTimeAmount] {\n            for deadline in [\n                smallestPossibleDeadline, largestPossibleDeadline, distantPast, distantFuture,\n                zeroDeadline, nowDeadline,\n            ] {\n                let (partial, overflow) = Int64(deadline.uptimeNanoseconds).addingReportingOverflow(\n                    timeAmount.nanoseconds\n                )\n                let expectedValue: UInt64\n                if overflow {\n                    #expect(timeAmount.nanoseconds >= 0)\n                    #expect(deadline.uptimeNanoseconds >= 0)\n                    // we cap at distantFuture towards +inf\n                    expectedValue = NIODeadline.distantFuture.uptimeNanoseconds\n                } else if partial < 0 {\n                    // we cap at 0 towards -inf\n                    expectedValue = 0\n                } else {\n                    // otherwise we have a result\n                    expectedValue = .init(partial)\n                }\n                #expect((deadline + timeAmount).uptimeNanoseconds == expectedValue)\n            }\n        }\n    }\n\n    @Test\n    func testEdgeCasesNIODeadlineMinusTimeAmount() {\n        let smallestPossibleTimeAmount = TimeAmount.nanoseconds(.min)\n        let largestPossibleTimeAmount = TimeAmount.nanoseconds(.max)\n        let zeroTimeAmount = TimeAmount.nanoseconds(0)\n\n        let smallestPossibleDeadline = NIODeadline.uptimeNanoseconds(.min)\n        let largestPossibleDeadline = NIODeadline.uptimeNanoseconds(.max)\n        let distantFuture = NIODeadline.distantFuture\n        let distantPast = NIODeadline.distantPast\n        let zeroDeadline = NIODeadline.uptimeNanoseconds(0)\n        let nowDeadline = NIODeadline.now()\n\n        for timeAmount in [smallestPossibleTimeAmount, largestPossibleTimeAmount, zeroTimeAmount] {\n            for deadline in [\n                smallestPossibleDeadline, largestPossibleDeadline, distantPast, distantFuture,\n                zeroDeadline, nowDeadline,\n            ] {\n                let (partial, overflow) = Int64(deadline.uptimeNanoseconds).subtractingReportingOverflow(\n                    timeAmount.nanoseconds\n                )\n                let expectedValue: UInt64\n                if overflow {\n                    #expect(timeAmount.nanoseconds < 0)\n                    #expect(deadline.uptimeNanoseconds >= 0)\n                    // we cap at distantFuture towards +inf\n                    expectedValue = NIODeadline.distantFuture.uptimeNanoseconds\n                } else if partial < 0 {\n                    // we cap at 0 towards -inf\n                    expectedValue = 0\n                } else {\n                    // otherwise we have a result\n                    expectedValue = .init(partial)\n                }\n                #expect((deadline - timeAmount).uptimeNanoseconds == expectedValue)\n            }\n        }\n    }\n\n    @Test\n    func testSuccessfulFlatSubmit() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let future = eventLoop.flatSubmit {\n            eventLoop.makeSucceededFuture(1)\n        }\n        eventLoop.run()\n        #expect(throws: Never.self) {\n            let result = try future.wait()\n            #expect(result == 1)\n        }\n    }\n\n    @Test\n    func testFailingFlatSubmit() throws {\n        enum TestError: Error { case failed }\n\n        let eventLoop = EmbeddedEventLoop()\n        let future = eventLoop.flatSubmit { () -> EventLoopFuture<Int> in\n            eventLoop.makeFailedFuture(TestError.failed)\n        }\n        eventLoop.run()\n        #expect(throws: TestError.failed) {\n            try future.wait()\n        }\n    }\n\n    @Test\n    func testSchedulingTaskOnTheEventLoopWithinTheEventLoopsOnlyTask() throws {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n\n        let el = elg.next()\n        let g = DispatchGroup()\n        g.enter()\n        el.execute {\n            // We're the last and only task running, scheduling another task here makes sure that despite not waking\n            // up the selector, we will still run this task.\n            el.execute {\n                g.leave()\n            }\n        }\n        g.wait()\n    }\n\n    @Test\n    func testSchedulingTaskOnTheEventLoopWithinTheEventLoopsOnlyIOOperation() {\n        final class ExecuteSomethingOnEventLoop: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            static let numberOfInstances = ManagedAtomic<Int>(0)\n            let groupToNotify: DispatchGroup\n\n            init(groupToNotify: DispatchGroup) {\n                #expect(\n                    0\n                        == ExecuteSomethingOnEventLoop.numberOfInstances.loadThenWrappingIncrement(ordering: .relaxed)\n                )\n                self.groupToNotify = groupToNotify\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.eventLoop.assumeIsolated().execute {\n                    self.groupToNotify.leave()\n                }\n            }\n        }\n\n        let elg1 = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let elg2 = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg1.syncShutdownGracefully()\n                try elg2.syncShutdownGracefully()\n            }\n        }\n\n        let g = DispatchGroup()\n        g.enter()\n        var maybeServer: Channel?\n        #expect(throws: Never.self) {\n            maybeServer = try ServerBootstrap(group: elg2)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .serverChannelOption(.autoRead, value: false)\n                .serverChannelOption(.maxMessagesPerRead, value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(ExecuteSomethingOnEventLoop(groupToNotify: g))\n                    }\n                }\n                .bind(to: .init(ipAddress: \"127.0.0.1\", port: 0))\n                .wait()\n        }\n        maybeServer?.read()  // this should accept one client\n\n        var maybeClient: Channel?\n        #expect(throws: Never.self) {\n            maybeClient = try ClientBootstrap(group: elg1)\n                .connect(\n                    to: maybeServer?.localAddress ?? SocketAddress(unixDomainSocketPath: \"/dev/null/does/not/exist\")\n                )\n                .wait()\n        }\n\n        guard let client = maybeClient else {\n            Issue.record(\"couldn't connect\")\n            return\n        }\n\n        var buffer = client.allocator.buffer(capacity: 1)\n        buffer.writeString(\"X\")\n\n        // Now let's trigger a channelRead in the accepted channel which should schedule running an EventLoop task\n        // with no outstanding operations on the EventLoop (no IO, nor tasks left to do).\n        #expect(throws: Never.self) {\n            try client.writeAndFlush(buffer).wait()\n        }\n\n        // The executed task should've notified this DispatchGroup\n        g.wait()\n    }\n\n    @Test\n    func testCancellingTheLastOutstandingTask() throws {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n\n        let el = elg.next()\n        let task = el.scheduleTask(in: .milliseconds(10)) {}\n        task.cancel()\n        // sleep for 15ms which should have the above scheduled (and cancelled) task have caused an unnecessary wakeup.\n        Thread.sleep(forTimeInterval: 0.015)  // 15 ms\n    }\n\n    @Test\n    func testSchedulingTaskOnTheEventLoopWithinTheEventLoopsOnlyScheduledTask() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n\n        let el = elg.next()\n        let g = DispatchGroup()\n        g.enter()\n        el.scheduleTask(in: .nanoseconds(10)) {  // something non-0\n            el.execute {\n                g.leave()\n            }\n        }\n        g.wait()\n    }\n\n    @Test\n    func testSelectableEventLoopDescription() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n\n        let el: EventLoop = elg.next()\n        let expectedPrefix = \"SelectableEventLoop { \"\n        let expectedContains = \"thread = NIOThread(name = NIO-ELT-\"\n        let expectedSuffix = \" }\"\n        let desc = el.description\n        #expect(el.description.starts(with: expectedPrefix), Comment(rawValue: desc))\n        #expect(el.description.reversed().starts(with: expectedSuffix.reversed()), Comment(rawValue: desc))\n        // let's check if any substring contains the `expectedContains`\n        #expect(\n            desc.indices.contains { startIndex in\n                desc[startIndex...].starts(with: expectedContains)\n            },\n            Comment(rawValue: desc)\n        )\n    }\n\n    @Test\n    func testMultiThreadedEventLoopGroupDescription() {\n        let elg: EventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n\n        #expect(\n            elg.description.starts(with: \"MultiThreadedEventLoopGroup { threadPattern = NIO-ELT-\"),\n            Comment(rawValue: elg.description)\n        )\n    }\n\n    @Test\n    func testSafeToExecuteTrue() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n        let loop = elg.next() as! SelectableEventLoop\n        #expect(loop.testsOnly_validExternalStateToScheduleTasks)\n        #expect(loop.testsOnly_validExternalStateToScheduleTasks)\n    }\n\n    @Test\n    func testSafeToExecuteFalse() {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let loop = elg.next() as! SelectableEventLoop\n        try? elg.syncShutdownGracefully()\n        #expect(loop.testsOnly_validExternalStateToScheduleTasks == false)\n        #expect(loop.testsOnly_validExternalStateToScheduleTasks == false)\n    }\n\n    @Test\n    func testTakeOverThreadAndAlsoTakeItBack() {\n        let currentNIOThread = NIOThread.currentThreadID\n        let currentNSThread = Thread.current\n        let hasBeenShutdown = NIOLockedValueBox(false)\n        let allDoneGroup = DispatchGroup()\n        allDoneGroup.enter()\n        MultiThreadedEventLoopGroup.withCurrentThreadAsEventLoop { loop in\n            #expect(currentNIOThread == NIOThread.currentThreadID)\n            #expect(currentNSThread == Thread.current)\n            #expect(loop === MultiThreadedEventLoopGroup.currentEventLoop)\n            loop.shutdownGracefully(queue: DispatchQueue.global()) { error in\n                #expect(error == nil)\n                hasBeenShutdown.withLockedValue {\n                    $0 = error == nil\n                }\n                allDoneGroup.leave()\n            }\n        }\n        allDoneGroup.wait()\n        #expect(hasBeenShutdown.withLockedValue { $0 })\n    }\n\n    @Test\n    func testThreadTakeoverUnsetsCurrentEventLoop() {\n        #expect(MultiThreadedEventLoopGroup.currentEventLoop == nil)\n\n        MultiThreadedEventLoopGroup.withCurrentThreadAsEventLoop { el in\n            #expect(el === MultiThreadedEventLoopGroup.currentEventLoop)\n            el.shutdownGracefully { error in\n                #expect(error == nil)\n            }\n        }\n\n        #expect(MultiThreadedEventLoopGroup.currentEventLoop == nil)\n    }\n\n    @Test\n    func testWeCanDoTrulySingleThreadedNetworking() {\n        final class SaveReceivedByte: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            init(received: NIOLockedValueBox<UInt8?>) {\n                self.received = received\n            }\n\n            // For once, we don't need thread-safety as we're taking the calling thread :)\n            let received: NIOLockedValueBox<UInt8?>\n            var readCalls: Int = 0\n            var allDonePromise: EventLoopPromise<Void>? = nil\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                self.readCalls += 1\n                #expect(1 == self.readCalls)\n\n                var data = Self.unwrapInboundIn(data)\n                #expect(1 == data.readableBytes)\n\n                #expect(self.received.withLockedValue { $0 } == nil)\n                self.received.withLockedValue { $0 = data.readInteger() }\n\n                self.allDonePromise?.succeed(())\n\n                context.close(promise: nil)\n            }\n        }\n\n        let received = NIOLockedValueBox<UInt8?>(nil)\n        MultiThreadedEventLoopGroup.withCurrentThreadAsEventLoop { loop in\n            // There'll be just one connection, we can share.\n            let receiveHandler = NIOLoopBound(SaveReceivedByte(received: received), eventLoop: loop)\n\n            ServerBootstrap(group: loop)\n                .serverChannelOption(ChannelOptions.socket(.init(SOL_SOCKET), .init(SO_REUSEADDR)), value: 1)\n                .childChannelInitializer { accepted in\n                    accepted.eventLoop.makeCompletedFuture {\n                        try accepted.pipeline.syncOperations.addHandler(receiveHandler.value)\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .flatMap { serverChannel in\n                    ClientBootstrap(group: loop).connect(to: serverChannel.localAddress!).flatMap { clientChannel in\n                        var buffer = clientChannel.allocator.buffer(capacity: 1)\n                        buffer.writeString(\"J\")\n                        return clientChannel.writeAndFlush(buffer)\n                    }.flatMap {\n                        #expect(receiveHandler.value.allDonePromise == nil)\n                        receiveHandler.value.allDonePromise = loop.makePromise()\n                        return receiveHandler.value.allDonePromise!.futureResult\n                    }.flatMap {\n                        serverChannel.close()\n                    }\n                }.whenComplete { (result: Result<Void, Error>) -> Void in\n                    func workaroundSR9815withAUselessFunction() {\n                        #expect(throws: Never.self) {\n                            try result.get()\n                        }\n                    }\n                    workaroundSR9815withAUselessFunction()\n\n                    // All done, let's return back into the calling thread.\n                    loop.shutdownGracefully { error in\n                        #expect(error == nil)\n                    }\n                }\n        }\n\n        // All done, the EventLoop is terminated so we should be able to check the results.\n        #expect(UInt8(ascii: \"J\") == received.withLockedValue { $0 })\n    }\n\n    @Test\n    func testWeFailOutstandingScheduledTasksOnELShutdown() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let scheduledTask = group.next().scheduleTask(in: .hours(24)) {\n            Issue.record(\"We lost the 24 hour race and aren't even in Le Mans.\")\n        }\n        let waiter = DispatchGroup()\n        waiter.enter()\n        scheduledTask.futureResult.map { _ in\n            Issue.record(\"didn't expect success\")\n        }.whenFailure { error in\n            #expect(.shutdown == error as? EventLoopError)\n            waiter.leave()\n        }\n\n        #expect(throws: Never.self) {\n            try group.syncShutdownGracefully()\n        }\n        waiter.wait()\n    }\n\n    @Test\n    func testSchedulingTaskOnFutureFailedByELShutdownDoesNotMakeUsExplode() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let scheduledTask = group.next().scheduleTask(in: .hours(24)) {\n            Issue.record(\"Task was scheduled in 24 hours, yet it executed.\")\n        }\n        let waiter = DispatchGroup()\n        waiter.enter()  // first scheduled task\n        waiter.enter()  // scheduled task in the first task's whenFailure.\n        scheduledTask.futureResult\n            .map { _ in\n                Issue.record(\"didn't expect success\")\n            }\n            .whenFailure { error in\n                #expect(.shutdown == error as? EventLoopError)\n                group.next().execute {}  // This previously blew up\n                group.next().scheduleTask(in: .hours(24)) {\n                    Issue.record(\"Task was scheduled in 24 hours, yet it executed.\")\n                }.futureResult.map {\n                    Issue.record(\"didn't expect success\")\n                }.whenFailure { error in\n                    #expect(.shutdown == error as? EventLoopError)\n                    waiter.leave()\n                }\n                waiter.leave()\n            }\n\n        #expect(throws: Never.self) {\n            try group.syncShutdownGracefully()\n        }\n        waiter.wait()\n    }\n\n    @Test\n    func testEventLoopGroupProvider() {\n        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoopGroup.syncShutdownGracefully()\n            }\n        }\n\n        let provider = NIOEventLoopGroupProvider.shared(eventLoopGroup)\n\n        if case .shared(let sharedEventLoopGroup) = provider {\n            #expect(sharedEventLoopGroup is MultiThreadedEventLoopGroup)\n            #expect(sharedEventLoopGroup === eventLoopGroup)\n        } else {\n            Issue.record(\"Not the same\")\n        }\n    }\n\n    // Test that scheduling a task at the maximum value doesn't crash.\n    // (Crashing resulted from an EINVAL/IOException thrown by the kevent\n    // syscall when the timeout value exceeded the maximum supported by\n    // the Darwin kernel #1056).\n    @Test\n    func testScheduleMaximum() throws {\n        let eventLoop = EmbeddedEventLoop()\n        let maxAmount: TimeAmount = .nanoseconds(.max)\n        let scheduled = eventLoop.scheduleTask(in: maxAmount) { true }\n\n        var result: Bool?\n        var error: Error?\n        scheduled.futureResult.assumeIsolated().whenSuccess { result = $0 }\n        scheduled.futureResult.assumeIsolated().whenFailure { error = $0 }\n\n        scheduled.cancel()\n\n        #expect(scheduled.futureResult.isFulfilled)\n        #expect(result == nil)\n        #expect(error as? EventLoopError == .cancelled)\n    }\n\n    @Test\n    func testEventLoopsWithPreSucceededFuturesCacheThem() {\n        let el = EventLoopWithPreSucceededFuture()\n        defer {\n            #expect(throws: Never.self) {\n                try el.syncShutdownGracefully()\n            }\n        }\n\n        let future1 = el.makeSucceededFuture(())\n        let future2 = el.makeSucceededFuture(())\n        let future3 = el.makeSucceededVoidFuture()\n\n        #expect(future1 === future2)\n        #expect(future2 === future3)\n    }\n\n    @Test\n    func testEventLoopsWithoutPreSucceededFuturesDoNotCacheThem() {\n        let el = EventLoopWithoutPreSucceededFuture()\n        defer {\n            #expect(throws: Never.self) {\n                try el.syncShutdownGracefully()\n            }\n        }\n\n        let future1 = el.makeSucceededFuture(())\n        let future2 = el.makeSucceededFuture(())\n        let future3 = el.makeSucceededVoidFuture()\n\n        #expect(future1 !== future2)\n        #expect(future2 !== future3)\n        #expect(future1 !== future3)\n    }\n\n    @Test\n    func testSelectableEventLoopHasPreSucceededFuturesOnlyOnTheEventLoop() throws {\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try elg.syncShutdownGracefully()\n            }\n        }\n\n        let el = elg.next()\n\n        let futureOutside1 = el.makeSucceededVoidFuture()\n        let futureOutside2 = el.makeSucceededFuture(())\n        #expect(futureOutside1 !== futureOutside2)\n\n        #expect(throws: Never.self) {\n            try el.submit {\n                let futureInside1 = el.makeSucceededVoidFuture()\n                let futureInside2 = el.makeSucceededFuture(())\n\n                #expect(futureOutside1 !== futureInside1)\n                #expect(futureInside1 === futureInside2)\n            }.wait()\n        }\n    }\n\n    @Test\n    func testMakeCompletedFuture() throws {\n        let eventLoop = EmbeddedEventLoop()\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoop.syncShutdownGracefully()\n            }\n        }\n\n        #expect(try eventLoop.makeCompletedFuture(.success(\"foo\")).wait() == \"foo\")\n\n        struct DummyError: Error {}\n        let future = eventLoop.makeCompletedFuture(Result<String, Error>.failure(DummyError()))\n        #expect(throws: DummyError.self) {\n            try future.wait()\n        }\n    }\n\n    @Test\n    func testMakeCompletedFutureWithResultOf() throws {\n        let eventLoop = EmbeddedEventLoop()\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoop.syncShutdownGracefully()\n            }\n        }\n\n        #expect(try eventLoop.makeCompletedFuture(withResultOf: { \"foo\" }).wait() == \"foo\")\n\n        struct DummyError: Error {}\n        func throwError() throws {\n            throw DummyError()\n        }\n\n        let future = eventLoop.makeCompletedFuture(withResultOf: throwError)\n        #expect(throws: DummyError.self) {\n            try future.wait()\n        }\n    }\n\n    @Test\n    func testMakeCompletedVoidFuture() {\n        let eventLoop = EventLoopWithPreSucceededFuture()\n        defer {\n            #expect(throws: Never.self) {\n                try eventLoop.syncShutdownGracefully()\n            }\n        }\n\n        let future1 = eventLoop.makeCompletedFuture(.success(()))\n        let future2 = eventLoop.makeSucceededVoidFuture()\n        let future3 = eventLoop.makeSucceededFuture(())\n        #expect(future1 === future2)\n        #expect(future2 === future3)\n    }\n\n    @Test\n    func testEventLoopGroupsWithoutAnyImplementationAreValid() throws {\n        let group = EventLoopGroupOf3WithoutAnAnyImplementation()\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let submitDone = group.any().submit {\n            let el1 = group.any()\n            let el2 = group.any()\n            // our group doesn't support `any()` and will fall back to `next()`.\n            #expect(el1 !== el2)\n        }\n        for el in group.makeIterator() {\n            (el as! EmbeddedEventLoop).run()\n        }\n        #expect(throws: Never.self) {\n            try submitDone.wait()\n        }\n    }\n\n    @Test\n    func testCallingAnyOnAnMTELGThatIsNotSelfDoesNotReturnItself() {\n        let group1 = MultiThreadedEventLoopGroup(numberOfThreads: 3)\n        let group2 = MultiThreadedEventLoopGroup(numberOfThreads: 3)\n        defer {\n            #expect(throws: Never.self) {\n                try group2.syncShutdownGracefully()\n                try group1.syncShutdownGracefully()\n            }\n        }\n\n        #expect(throws: Never.self) {\n            try group1.any().submit {\n                let el1_1 = group1.any()\n                let el1_2 = group1.any()\n                let el2_1 = group2.any()\n                let el2_2 = group2.any()\n\n                // MTELG _does_ supprt `any()` so all these `EventLoop`s should be the same.\n                #expect(el1_1 === el1_2)\n                // MTELG _does_ supprt `any()` but this `any()` call went across `group`s.\n                #expect(el2_1 !== el2_2)\n                // different groups...\n                #expect(el1_1 !== el2_1)\n                // different groups...\n                #expect(el1_1 !== el2_2)\n\n                #expect(el1_1 === MultiThreadedEventLoopGroup.currentEventLoop!)\n            }.wait()\n        }\n    }\n\n    @Test\n    func testMultiThreadedEventLoopGroupSupportsStickyAnyImplementation() {\n        guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return }\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 3)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        #expect(throws: Never.self) {\n            try group.any().submit {\n                let el1 = group.any()\n                let el2 = group.any()\n                #expect(el1 === el2)  // MTELG _does_ supprt `any()` so all these `EventLoop`s should be the same.\n                #expect(el1 === MultiThreadedEventLoopGroup.currentEventLoop!)\n            }.wait()\n        }\n    }\n\n    @Test\n    func testAsyncToFutureConversionSuccess() throws {\n        guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return }\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let result = try group.next().makeFutureWithTask {\n            try await Task.sleep(nanoseconds: 37)\n            return \"hello from async\"\n        }.wait()\n        #expect(\"hello from async\" == result)\n    }\n\n    @Test\n    func testAsyncToFutureConversionFailure() throws {\n        guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return }\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        struct DummyError: Error {}\n\n        #expect(throws: DummyError.self) {\n            try group.next().makeFutureWithTask {\n                try await Task.sleep(nanoseconds: 37)\n                throw DummyError()\n            }.wait()\n        }\n    }\n\n    // Test for possible starvation discussed here: https://github.com/apple/swift-nio/pull/2645#discussion_r1486747118\n    @Test\n    func testNonStarvation() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = group.next()\n        let stop = try eventLoop.submit { NIOLoopBoundBox(false, eventLoop: eventLoop) }.wait()\n\n        @Sendable\n        func reExecuteTask() {\n            if !stop.value {\n                eventLoop.execute {\n                    reExecuteTask()\n                }\n            }\n        }\n\n        eventLoop.execute {\n            // SelectableEventLoop runs batches of up to 4096.\n            // Submit significantly over that for good measure.\n            for _ in (0..<10000) {\n                eventLoop.assumeIsolated().execute(reExecuteTask)\n            }\n        }\n        let stopTask = eventLoop.scheduleTask(in: .microseconds(10)) {\n            stop.value = true\n        }\n        try stopTask.futureResult.wait()\n    }\n\n    @Test\n    func testMixedImmediateAndScheduledTasks() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = group.next()\n        let scheduledTaskMagic = 17\n        let scheduledTask = eventLoop.scheduleTask(in: .microseconds(10)) {\n            scheduledTaskMagic\n        }\n\n        let immediateTaskMagic = 18\n        let immediateTask = eventLoop.submit {\n            immediateTaskMagic\n        }\n\n        let scheduledTaskMagicOut = try scheduledTask.futureResult.wait()\n        #expect(scheduledTaskMagicOut == scheduledTaskMagic)\n\n        let immediateTaskMagicOut = try immediateTask.wait()\n        #expect(immediateTaskMagicOut == immediateTaskMagic)\n    }\n\n    @Test\n    func testLotsOfMixedImmediateAndScheduledTasks() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = group.next()\n        struct Counter: Sendable {\n            private var _submitCount = NIOLockedValueBox(0)\n            var submitCount: Int {\n                get { self._submitCount.withLockedValue { $0 } }\n                nonmutating set { self._submitCount.withLockedValue { $0 = newValue } }\n            }\n            private var _scheduleCount = NIOLockedValueBox(0)\n            var scheduleCount: Int {\n                get { self._scheduleCount.withLockedValue { $0 } }\n                nonmutating set { self._scheduleCount.withLockedValue { $0 = newValue } }\n            }\n        }\n\n        let achieved = Counter()\n        var immediateTasks = [EventLoopFuture<Void>]()\n        var scheduledTasks = [Scheduled<Void>]()\n        for _ in (0..<100_000) {\n            if Bool.random() {\n                let task = eventLoop.submit {\n                    achieved.submitCount += 1\n                }\n                immediateTasks.append(task)\n            }\n            if Bool.random() {\n                let task = eventLoop.scheduleTask(in: .microseconds(10)) {\n                    achieved.scheduleCount += 1\n                }\n                scheduledTasks.append(task)\n            }\n        }\n\n        let submitCount = try EventLoopFuture.whenAllSucceed(immediateTasks, on: eventLoop).map({\n            _ in\n            achieved.submitCount\n        }).wait()\n        #expect(submitCount == achieved.submitCount)\n\n        let scheduleCount = try EventLoopFuture.whenAllSucceed(\n            scheduledTasks.map { $0.futureResult },\n            on: eventLoop\n        )\n        .map({ _ in\n            achieved.scheduleCount\n        }).wait()\n        #expect(scheduleCount == scheduledTasks.count)\n    }\n\n    @Test\n    func testLotsOfMixedImmediateAndScheduledTasksFromEventLoop() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = group.next()\n        struct Counter: Sendable {\n            private var _submitCount = NIOLockedValueBox(0)\n            var submitCount: Int {\n                get { self._submitCount.withLockedValue { $0 } }\n                nonmutating set { self._submitCount.withLockedValue { $0 = newValue } }\n            }\n            private var _scheduleCount = NIOLockedValueBox(0)\n            var scheduleCount: Int {\n                get { self._scheduleCount.withLockedValue { $0 } }\n                nonmutating set { self._scheduleCount.withLockedValue { $0 = newValue } }\n            }\n        }\n\n        let achieved = Counter()\n        let (immediateTasks, scheduledTasks) = try eventLoop.submit {\n            var immediateTasks = [EventLoopFuture<Void>]()\n            var scheduledTasks = [Scheduled<Void>]()\n            for _ in (0..<100_000) {\n                if Bool.random() {\n                    let task = eventLoop.submit {\n                        achieved.submitCount += 1\n                    }\n                    immediateTasks.append(task)\n                }\n                if Bool.random() {\n                    let task = eventLoop.scheduleTask(in: .microseconds(10)) {\n                        achieved.scheduleCount += 1\n                    }\n                    scheduledTasks.append(task)\n                }\n            }\n            return (immediateTasks, scheduledTasks)\n        }.wait()\n\n        let submitCount = try EventLoopFuture.whenAllSucceed(immediateTasks, on: eventLoop)\n            .map({ _ in\n                achieved.submitCount\n            }).wait()\n        #expect(submitCount == achieved.submitCount)\n\n        let scheduleCount = try EventLoopFuture.whenAllSucceed(\n            scheduledTasks.map { $0.futureResult },\n            on: eventLoop\n        )\n        .map({ _ in\n            achieved.scheduleCount\n        }).wait()\n        #expect(scheduleCount == scheduledTasks.count)\n    }\n\n    @Test\n    func testImmediateTasksDontGetStuck() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            #expect(throws: Never.self) {\n                try group.syncShutdownGracefully()\n            }\n        }\n\n        let eventLoop = group.next()\n        let testEventLoop = MultiThreadedEventLoopGroup.singleton.any()\n\n        let longWait = TimeAmount.seconds(60)\n        let failDeadline = NIODeadline.now() + longWait\n        let (immediateTasks, scheduledTask) = try eventLoop.submit {\n            // Submit over the 4096 immediate tasks, and some scheduled tasks\n            // with expiry deadline in (nearish) future.\n            // We want to make sure immediate tasks, even those that don't fit\n            // in the first batch, don't get stuck waiting for scheduled task\n            // expiry\n            let immediateTasks = (0..<5000).map { _ in\n                eventLoop.submit {}.hop(to: testEventLoop)\n            }\n            let scheduledTask = eventLoop.scheduleTask(in: longWait) {\n            }\n\n            return (immediateTasks, scheduledTask)\n        }.wait()\n\n        // The immediate tasks should all succeed ~immediately.\n        // We're testing for a case where the EventLoop gets confused\n        // into waiting for the scheduled task expiry to complete\n        // some immediate tasks.\n        _ = try EventLoopFuture.whenAllSucceed(immediateTasks, on: testEventLoop).wait()\n        #expect(.now() < failDeadline)\n\n        scheduledTask.cancel()\n    }\n\n    @Test\n    func testInEventLoopABAProblem() throws {\n        // Older SwiftNIO versions had a bug here, they held onto `pthread_t`s for ever (which is illegal) and then\n        // used `pthread_equal(pthread_self(), myPthread)`. `pthread_equal` just compares the pointer values which\n        // means there's an ABA problem here. This test checks that we don't suffer from that issue now.\n        let allELs: NIOLockedValueBox<[any EventLoop]> = NIOLockedValueBox([])\n\n        for _ in 0..<100 {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: 4)\n            defer {\n                #expect(throws: Never.self) {\n                    try group.syncShutdownGracefully()\n                }\n            }\n            for loop in group.makeIterator() {\n                try! loop.submit {\n                    allELs.withLockedValue { allELs in\n                        #expect(loop.inEventLoop)\n                        for otherEL in allELs {\n                            #expect(\n                                !otherEL.inEventLoop,\n                                \"should only be in \\(loop) but turns out also in \\(otherEL)\"\n                            )\n                        }\n                        allELs.append(loop)\n                    }\n                }.wait()\n            }\n        }\n    }\n\n    @Test\n    func testStructuredConcurrencyMTELGStartStop() async throws {\n        let loops = try await MultiThreadedEventLoopGroup.withEventLoopGroup(\n            numberOfThreads: 3\n        ) { group in\n            let loops = Array(group.makeIterator()).map { $0 as! SelectableEventLoop }\n            for loop in loops {\n                #expect(\n                    loop.debugDescription.contains(\"state = open\"),\n                    Comment(rawValue: loop.debugDescription)\n                )\n                #expect(\n                    loop.debugDescription.contains(\"selector = Selector { descriptor = -1 }\") == false,\n                    Comment(rawValue: loop.debugDescription)\n                )\n            }\n            return loops\n        }\n        #expect(3 == loops.count)\n        for loop in loops {\n            #expect(\n                loop.debugDescription.contains(\"state = resourcesReclaimed\"),\n                Comment(rawValue: loop.debugDescription)\n            )\n            #expect(loop.debugDescription.contains(\"selector = Selector { descriptor = -1 }\"))\n        }\n    }\n\n    @Test\n    func testStructuredConcurrencyMTELGStartStopUserCannotStopMidWay() async throws {\n        let threadCount = try await MultiThreadedEventLoopGroup.withEventLoopGroup(\n            numberOfThreads: 3\n        ) { group in\n            do {\n                try await group.shutdownGracefully()\n                Issue.record(\"shutdown worked, it shouldn't have\")\n            } catch EventLoopError.unsupportedOperation {\n                // okay\n                return Array(group.makeIterator()).count\n            }\n            return -1\n        }\n        #expect(3 == threadCount)\n    }\n\n    @Test\n    func testStructuredConcurrencyMTELGStartStopCanDoBasicAsyncStuff() async throws {\n        let actual = try await MultiThreadedEventLoopGroup.withEventLoopGroup(\n            numberOfThreads: 3\n        ) { group in\n            try await group.any().scheduleTask(in: .milliseconds(10), { \"cool\" }).futureResult.get()\n        }\n        #expect(\"cool\" == actual)\n    }\n\n    @Test\n    func testRegressionSelectableEventLoopDeadlock() throws {\n        let iterations = 1_000\n        let loop = MultiThreadedEventLoopGroup.singleton.next() as! SelectableEventLoop\n        let threadsReadySem = DispatchSemaphore(value: 0)\n        let go = DispatchSemaphore(value: 0)\n\n        let scheduleds = NIOThreadPool.singleton.runIfActive(eventLoop: loop) {\n            threadsReadySem.signal()\n            go.wait()\n            var tasks: [Scheduled<()>] = []\n            for _ in 0..<iterations {\n                tasks.append(loop.scheduleTask(in: .milliseconds(1)) {})\n            }\n            return tasks\n        }\n\n        let descriptions = NIOThreadPool.singleton.runIfActive(eventLoop: loop) {\n            threadsReadySem.signal()\n            go.wait()\n            var descriptions: [String] = []\n            for _ in 0..<iterations {\n                descriptions.append(loop.debugDescription)\n            }\n            return descriptions\n        }\n\n        threadsReadySem.wait()\n        threadsReadySem.wait()\n        go.signal()\n        go.signal()\n        let scheduledsCount = try scheduleds.wait().map { $0.cancel() }.count\n        #expect(iterations == scheduledsCount)\n        let descriptionsCount = try descriptions.wait().count\n        #expect(iterations == descriptionsCount)\n    }\n}\n\nprivate final class EventLoopWithPreSucceededFuture: EventLoop {\n    var inEventLoop: Bool {\n        true\n    }\n\n    func execute(_ task: @escaping () -> Void) {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func submit<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        preconditionFailure(\"not implemented\")\n    }\n\n    var now: NIODeadline {\n        preconditionFailure(\"not implemented\")\n    }\n\n    @discardableResult\n    func scheduleTask<T>(deadline: NIODeadline, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        preconditionFailure(\"not implemented\")\n    }\n\n    @discardableResult\n    func scheduleTask<T>(in: TimeAmount, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func preconditionInEventLoop(file: StaticString, line: UInt) {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func preconditionNotInEventLoop(file: StaticString, line: UInt) {\n        preconditionFailure(\"not implemented\")\n    }\n\n    // We'd need to use an IUO here in order to use a loop-bound here (self needs to be initialized\n    // to create the loop-bound box). That'd require the use of unchecked Sendable. A locked value\n    // box is fine, it's only tests.\n    private let _succeededVoidFuture: NIOLockedValueBox<EventLoopFuture<Void>?>\n\n    func makeSucceededVoidFuture() -> EventLoopFuture<Void> {\n        guard self.inEventLoop, let voidFuture = self._succeededVoidFuture.withLockedValue({ $0 }) else {\n            return self.makeSucceededFuture(())\n        }\n        return voidFuture\n    }\n\n    init() {\n        self._succeededVoidFuture = NIOLockedValueBox(nil)\n        self._succeededVoidFuture.withLockedValue {\n            $0 = EventLoopFuture(eventLoop: self, value: ())\n        }\n    }\n\n    func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable (Error?) -> Void) {\n        self._succeededVoidFuture.withLockedValue { $0 = nil }\n        queue.async {\n            callback(nil)\n        }\n    }\n}\n\nprivate final class EventLoopWithoutPreSucceededFuture: EventLoop {\n    var inEventLoop: Bool {\n        true\n    }\n\n    func execute(_ task: @escaping () -> Void) {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func submit<T>(_ task: @escaping () throws -> T) -> EventLoopFuture<T> {\n        preconditionFailure(\"not implemented\")\n    }\n\n    var now: NIODeadline {\n        preconditionFailure(\"not implemented\")\n    }\n\n    @discardableResult\n    func scheduleTask<T>(deadline: NIODeadline, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        preconditionFailure(\"not implemented\")\n    }\n\n    @discardableResult\n    func scheduleTask<T>(in: TimeAmount, _ task: @escaping () throws -> T) -> Scheduled<T> {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func preconditionInEventLoop(file: StaticString, line: UInt) {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func preconditionNotInEventLoop(file: StaticString, line: UInt) {\n        preconditionFailure(\"not implemented\")\n    }\n\n    func shutdownGracefully(queue: DispatchQueue, _ callback: @Sendable @escaping (Error?) -> Void) {\n        queue.async {\n            callback(nil)\n        }\n    }\n}\n\nfinal class EventLoopGroupOf3WithoutAnAnyImplementation: EventLoopGroup {\n    private let eventloops = [EmbeddedEventLoop(), EmbeddedEventLoop(), EmbeddedEventLoop()]\n    private let nextID = ManagedAtomic<UInt64>(0)\n\n    func next() -> EventLoop {\n        self.eventloops[Int(self.nextID.loadThenWrappingIncrement(ordering: .relaxed) % UInt64(self.eventloops.count))]\n    }\n\n    func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void) {\n        let g = DispatchGroup()\n\n        for el in self.eventloops {\n            g.enter()\n            el.shutdownGracefully(queue: queue) { error in\n                #expect(error == nil)\n                g.leave()\n            }\n        }\n\n        g.notify(queue: queue) {\n            callback(nil)\n        }\n    }\n\n    func makeIterator() -> EventLoopIterator {\n        .init(self.eventloops)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/FileRegionTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass FileRegionTest: XCTestCase {\n\n    func testWriteFileRegion() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let numBytes = 16 * 1024\n\n        var content = \"\"\n        for i in 0..<numBytes {\n            content.append(\"\\(i)\")\n        }\n        let bytes = Array(content.utf8)\n\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(\n                                numBytes: bytes.count,\n                                promise: promise\n                            )\n                        )\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.close().wait())\n        }\n\n        try withTemporaryFile { _, filePath in\n            try content.write(toFile: filePath, atomically: false, encoding: .ascii)\n            try clientChannel.eventLoop.submit {\n                try NIOFileHandle(_deprecatedPath: filePath)\n            }.flatMap { (handle: NIOFileHandle) in\n                let fr = FileRegion(fileHandle: handle, readerIndex: 0, endIndex: bytes.count)\n                let promise = clientChannel.eventLoop.makePromise(of: Void.self)\n                clientChannel.pipeline.syncOperations.writeAndFlush(\n                    NIOAny(fr),\n                    promise: promise\n                )\n\n                let bound = NIOLoopBound(handle, eventLoop: clientChannel.eventLoop)\n                return promise.futureResult.flatMapErrorThrowing { error in\n                    try? bound.value.close()\n                    throw error\n                }.flatMapThrowing {\n                    try bound.value.close()\n                }\n            }.wait()\n\n            var buffer = clientChannel.allocator.buffer(capacity: bytes.count)\n            buffer.writeBytes(bytes)\n            XCTAssertEqual(try promise.futureResult.wait(), buffer)\n        }\n    }\n\n    func testWriteEmptyFileRegionDoesNotHang() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(\n                                numBytes: 0,\n                                promise: promise\n                            )\n                        )\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.close().wait())\n        }\n\n        try withTemporaryFile { _, filePath in\n            try \"\".write(toFile: filePath, atomically: false, encoding: .ascii)\n\n            try clientChannel.eventLoop.submit {\n                try NIOFileHandle(_deprecatedPath: filePath)\n            }.flatMap { (handle: NIOFileHandle) in\n                let fr = FileRegion(fileHandle: handle, readerIndex: 0, endIndex: 0)\n                var futures: [EventLoopFuture<Void>] = []\n                for _ in 0..<10 {\n                    futures.append(clientChannel.pipeline.syncOperations.write(NIOAny(fr)))\n                }\n                futures.append(clientChannel.pipeline.syncOperations.writeAndFlush(NIOAny(fr)))\n\n                let bound = NIOLoopBound(handle, eventLoop: clientChannel.eventLoop)\n                return .andAllSucceed(futures, on: clientChannel.eventLoop).flatMapErrorThrowing { error in\n                    try? bound.value.close()\n                    throw error\n                }.flatMapThrowing {\n                    try bound.value.close()\n                }\n            }.wait()\n        }\n    }\n\n    func testOutstandingFileRegionsWork() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let numBytes = 16 * 1024\n\n        var content = \"\"\n        for i in 0..<numBytes {\n            content.append(\"\\(i)\")\n        }\n        let bytes = Array(content.utf8)\n\n        let promise = group.next().makePromise(of: ByteBuffer.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandler(\n                            ByteCountingHandler(numBytes: bytes.count, promise: promise)\n                        )\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try clientChannel.syncCloseAcceptingAlreadyClosed())\n        }\n\n        try withTemporaryFile { fd, filePath in\n            try content.write(toFile: filePath, atomically: false, encoding: .ascii)\n\n            let future = clientChannel.eventLoop.submit {\n                let fh1 = try NIOFileHandle(_deprecatedPath: filePath)\n                let fh2 = try NIOFileHandle(_deprecatedPath: filePath)\n                return (fh1, fh2)\n            }.flatMap { (fh1, fh2) in\n                let fr1 = FileRegion(fileHandle: fh1, readerIndex: 0, endIndex: bytes.count)\n                let fr2 = FileRegion(fileHandle: fh2, readerIndex: 0, endIndex: bytes.count)\n\n                let loopBoundFr2 = NIOLoopBound(fr2, eventLoop: clientChannel.eventLoop)\n                let loopBoundHandles = NIOLoopBound((fh1, fh2), eventLoop: clientChannel.eventLoop)\n\n                return clientChannel.pipeline.syncOperations.writeAndFlush(NIOAny(fr1)).flatMap {\n                    () -> EventLoopFuture<Void> in\n                    let frFuture = clientChannel.pipeline.syncOperations.write(NIOAny(loopBoundFr2.value))\n                    var buffer = clientChannel.allocator.buffer(capacity: bytes.count)\n                    buffer.writeBytes(bytes)\n                    let bbFuture = clientChannel.pipeline.syncOperations.write(NIOAny(buffer))\n                    clientChannel.close(promise: nil)\n                    clientChannel.flush()\n                    return frFuture.flatMap { bbFuture }\n                }.flatMapErrorThrowing { error in\n                    let (fh1, fh2) = loopBoundHandles.value\n                    try? fh1.close()\n                    try? fh2.close()\n                    throw error\n                }.flatMapThrowing {\n                    let (fh1, fh2) = loopBoundHandles.value\n                    do {\n                        try fh1.close()\n                    } catch {\n                        try? fh2.close()\n                        throw error\n                    }\n                    try fh2.close()\n                }\n            }\n            XCTAssertThrowsError(\n                try future.wait()\n            ) { error in\n                XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n            }\n\n            var buffer = clientChannel.allocator.buffer(capacity: bytes.count)\n            buffer.writeBytes(bytes)\n            XCTAssertEqual(try promise.futureResult.wait(), buffer)\n        }\n    }\n\n    func testWholeFileFileRegion() throws {\n        try withTemporaryFile(content: \"hello\") { fd, path in\n            let handle = try NIOFileHandle(_deprecatedPath: path)\n            let region = try FileRegion(fileHandle: handle)\n            defer {\n                XCTAssertNoThrow(try handle.close())\n            }\n            XCTAssertEqual(0, region.readerIndex)\n            XCTAssertEqual(5, region.readableBytes)\n            XCTAssertEqual(5, region.endIndex)\n        }\n    }\n\n    func testWholeEmptyFileFileRegion() throws {\n        try withTemporaryFile(content: \"\") { _, path in\n            let handle = try NIOFileHandle(_deprecatedPath: path)\n            let region = try FileRegion(fileHandle: handle)\n            defer {\n                XCTAssertNoThrow(try handle.close())\n            }\n            XCTAssertEqual(0, region.readerIndex)\n            XCTAssertEqual(0, region.readableBytes)\n            XCTAssertEqual(0, region.endIndex)\n        }\n    }\n\n    func testFileRegionDuplicatesShareSeekPointer() throws {\n        try withTemporaryFile(content: \"0123456789\") { fh1, path in\n            let fh2 = try fh1.duplicate()\n\n            var fr1Bytes: [UInt8] = Array(repeating: 0, count: 5)\n            var fr2Bytes = fr1Bytes\n            try fh1.withUnsafeFileDescriptor { fd in\n                let r = try Posix.read(descriptor: fd, pointer: &fr1Bytes, size: 5)\n                XCTAssertEqual(r, IOResult<Int>.processed(5))\n            }\n            try fh2.withUnsafeFileDescriptor { fd in\n                let r = try Posix.read(descriptor: fd, pointer: &fr2Bytes, size: 5)\n                XCTAssertEqual(r, IOResult<Int>.processed(5))\n            }\n            defer {\n                // fr2's underlying fd must be closed by us.\n                XCTAssertNoThrow(try fh2.close())\n            }\n\n            XCTAssertEqual(Array(\"01234\".utf8), fr1Bytes)\n            XCTAssertEqual(Array(\"56789\".utf8), fr2Bytes)\n        }\n    }\n\n    func testMassiveFileRegionThatJustAboutWorks() {\n        withTemporaryFile(content: \"0123456789\") { fh, path in\n            // just in case someone uses 32bit platforms\n            let readerIndex = UInt64(_UInt56.max) < UInt64(Int.max) ? Int(_UInt56.max) : Int.max\n            let fr = FileRegion(fileHandle: fh, readerIndex: readerIndex, endIndex: Int.max)\n            XCTAssertEqual(readerIndex, fr.readerIndex)\n            XCTAssertEqual(Int.max, fr.endIndex)\n        }\n    }\n\n    func testMassiveFileRegionReaderIndexWorks() {\n        withTemporaryFile(content: \"0123456789\") { fh, path in\n            // just in case someone uses 32bit platforms\n            let readerIndex = (UInt64(_UInt56.max) < UInt64(Int.max) ? Int(_UInt56.max) : Int.max) - 1000\n            var fr = FileRegion(fileHandle: fh, readerIndex: readerIndex, endIndex: Int.max)\n            for i in 0..<1000 {\n                XCTAssertEqual(readerIndex + i, fr.readerIndex)\n                XCTAssertEqual(Int.max, fr.endIndex)\n                fr.moveReaderIndex(forwardBy: 1)\n            }\n        }\n    }\n\n    func testFileRegionAndIODataFitsInACoupleOfEnums() throws {\n        enum Level4 {\n            case case1(FileRegion)\n            case case2(FileRegion)\n            case case3(IOData)\n            case case4(IOData)\n        }\n        enum Level3 {\n            case case1(Level4)\n            case case2(Level4)\n            case case3(Level4)\n            case case4(Level4)\n        }\n        enum Level2 {\n            case case1(Level3)\n            case case2(Level3)\n            case case3(Level3)\n            case case4(Level3)\n        }\n        enum Level1 {\n            case case1(Level2)\n            case case2(Level2)\n            case case3(Level2)\n            case case4(Level2)\n        }\n\n        XCTAssertLessThanOrEqual(MemoryLayout<FileRegion>.size, 23)\n        XCTAssertLessThanOrEqual(MemoryLayout<Level1>.size, 24)\n\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"0123456789\") { fh, path in\n                let fr = try FileRegion(fileHandle: fh)\n                XCTAssertLessThanOrEqual(\n                    MemoryLayout.size(ofValue: Level1.case1(.case2(.case3(.case4(.fileRegion(fr)))))),\n                    24\n                )\n                XCTAssertLessThanOrEqual(MemoryLayout.size(ofValue: Level1.case1(.case3(.case4(.case1(fr))))), 24)\n            }\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/GetAddrInfoResolverTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass GetaddrinfoResolverTest: XCTestCase {\n\n    func testResolveNoDuplicatesV4() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let resolver = GetaddrinfoResolver(loop: group.next(), aiSocktype: .stream, aiProtocol: .tcp)\n        let v4Future = resolver.initiateAQuery(host: \"127.0.0.1\", port: 12345)\n        let v6Future = resolver.initiateAAAAQuery(host: \"127.0.0.1\", port: 12345)\n\n        let addressV4 = try v4Future.wait()\n        let addressV6 = try v6Future.wait()\n        XCTAssertEqual(1, addressV4.count)\n        XCTAssertEqual(try SocketAddress(ipAddress: \"127.0.0.1\", port: 12345), addressV4[0])\n        XCTAssertTrue(addressV6.isEmpty)\n    }\n\n    func testResolveNoDuplicatesV6() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let resolver = GetaddrinfoResolver(loop: group.next(), aiSocktype: .stream, aiProtocol: .tcp)\n        let v4Future = resolver.initiateAQuery(host: \"::1\", port: 12345)\n        let v6Future = resolver.initiateAAAAQuery(host: \"::1\", port: 12345)\n\n        let addressV4 = try v4Future.wait()\n        let addressV6 = try v6Future.wait()\n        XCTAssertEqual(1, addressV6.count)\n        XCTAssertEqual(try SocketAddress(ipAddress: \"::1\", port: 12345), addressV6[0])\n        XCTAssertTrue(addressV4.isEmpty)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/HappyEyeballsTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOPosix\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\nimport Glibc\n#elseif canImport(Bionic)\nimport Bionic\n#else\n#error(\"The Happy Eyeballs test module was unable to identify your C library.\")\n#endif\n\nprivate let CONNECT_RECORDER = \"connectRecorder\"\nprivate let CONNECT_DELAYER = \"connectDelayer\"\nprivate let SINGLE_IPv6_RESULT = [SocketAddress(host: \"example.com\", ipAddress: \"fe80::1\", port: 80)]\nprivate let SINGLE_IPv4_RESULT = [SocketAddress(host: \"example.com\", ipAddress: \"10.0.0.1\", port: 80)]\nprivate let MANY_IPv6_RESULTS = (1...10).map { SocketAddress(host: \"example.com\", ipAddress: \"fe80::\\($0)\", port: 80) }\nprivate let MANY_IPv4_RESULTS = (1...10).map { SocketAddress(host: \"example.com\", ipAddress: \"10.0.0.\\($0)\", port: 80) }\n\nextension Array where Element == Channel {\n    fileprivate func finishAll() {\n        for element in self {\n            do {\n                _ = try (element as! EmbeddedChannel).finish()\n                // We're happy with no error\n            } catch ChannelError.alreadyClosed {\n                return  // as well as already closed.\n            } catch {\n                XCTFail(\"Finishing got error \\(error)\")\n            }\n        }\n    }\n}\n\nprivate final class DummyError: Error, Equatable {\n    // For dummy error equality is identity.\n    static func == (lhs: DummyError, rhs: DummyError) -> Bool {\n        ObjectIdentifier(lhs) == ObjectIdentifier(rhs)\n    }\n}\n\nprivate class ConnectRecorder: ChannelOutboundHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Any\n\n    enum State {\n        case idle\n        case connected\n        case closed\n    }\n\n    var targetHost: String?\n    var state: State = .idle\n\n    public func connect(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.targetHost = to.toString()\n        let connectPromise = promise ?? context.eventLoop.makePromise()\n        connectPromise.futureResult.hop(to: context.eventLoop).assumeIsolated().whenSuccess {\n            self.state = .connected\n        }\n        context.connect(to: to, promise: connectPromise)\n    }\n\n    public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        let connectPromise = promise ?? context.eventLoop.makePromise()\n        connectPromise.futureResult.hop(to: context.eventLoop).assumeIsolated().whenComplete {\n            (_: Result<Void, Error>) in\n            self.state = .closed\n        }\n        context.close(promise: connectPromise)\n    }\n}\n\nprivate class ConnectionDelayer: ChannelOutboundHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Any\n\n    var connectPromise: EventLoopPromise<Void>?\n\n    func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.connectPromise = promise\n    }\n}\n\nextension Channel {\n    fileprivate func connectTarget() -> String? {\n        try! self.pipeline.context(name: CONNECT_RECORDER).map {\n            ($0.handler as! ConnectRecorder).targetHost\n        }.wait()\n    }\n\n    fileprivate func succeedConnection() {\n        try! self.pipeline.context(name: CONNECT_DELAYER).map {\n            ($0.handler as! ConnectionDelayer).connectPromise!.succeed(())\n        }.wait()\n    }\n\n    fileprivate func failConnection(error: Error) {\n        try! self.pipeline.context(name: CONNECT_DELAYER).map {\n            ($0.handler as! ConnectionDelayer).connectPromise!.fail(error)\n        }.wait()\n    }\n\n    fileprivate func state() -> ConnectRecorder.State {\n        try! self.pipeline.context(name: CONNECT_RECORDER).map {\n            ($0.handler as! ConnectRecorder).state\n        }.flatMapErrorThrowing {\n            switch $0 {\n            case ChannelPipelineError.notFound:\n                return .closed\n            default:\n                throw $0\n            }\n        }.wait()\n    }\n}\n\nextension SocketAddress {\n    fileprivate init(host: String, ipAddress: String, port: Int) {\n        do {\n            var v4addr = in_addr()\n            try NIOBSDSocket.inet_pton(addressFamily: .inet, addressDescription: ipAddress, address: &v4addr)\n\n            var sockaddr = sockaddr_in()\n            sockaddr.sin_family = sa_family_t(NIOBSDSocket.AddressFamily.inet.rawValue)\n            sockaddr.sin_port = in_port_t(port).bigEndian\n            sockaddr.sin_addr = v4addr\n            self = .init(sockaddr, host: host)\n        } catch {\n            do {\n                var v6addr = in6_addr()\n                try NIOBSDSocket.inet_pton(addressFamily: .inet6, addressDescription: ipAddress, address: &v6addr)\n\n                var sockaddr = sockaddr_in6()\n                sockaddr.sin6_family = sa_family_t(NIOBSDSocket.AddressFamily.inet6.rawValue)\n                sockaddr.sin6_port = in_port_t(port).bigEndian\n                sockaddr.sin6_flowinfo = 0\n                sockaddr.sin6_scope_id = 0\n                sockaddr.sin6_addr = v6addr\n                self = .init(sockaddr, host: host)\n            } catch {\n                fatalError(\"Unable to convert to IP\")\n            }\n        }\n    }\n\n    fileprivate func toString() -> String {\n        let ptr = UnsafeMutableRawPointer.allocate(byteCount: 256, alignment: 1).bindMemory(\n            to: Int8.self,\n            capacity: 256\n        )\n        switch self {\n        case .v4(let address):\n            var baseAddress = address.address\n            try! NIOBSDSocket.inet_ntop(\n                addressFamily: .inet,\n                addressBytes: &baseAddress.sin_addr,\n                addressDescription: ptr,\n                addressDescriptionLength: 256\n            )\n        case .v6(let address):\n            var baseAddress = address.address\n            try! NIOBSDSocket.inet_ntop(\n                addressFamily: .inet6,\n                addressBytes: &baseAddress.sin6_addr,\n                addressDescription: ptr,\n                addressDescriptionLength: 256\n            )\n        case .unixDomainSocket:\n            fatalError(\"No UDS support in happy eyeballs.\")\n        }\n\n        let ipString = String(cString: ptr)\n        ptr.deinitialize(count: 256).deallocate()\n        return ipString\n    }\n}\n\nextension EventLoopFuture {\n    fileprivate func getError() -> Error? {\n        guard self.isFulfilled else { return nil }\n\n        let errorBox = NIOLockedValueBox<Error?>(nil)\n        self.whenFailure { error in\n            errorBox.withLockedValue { $0 = error }\n        }\n        return errorBox.withLockedValue { $0! }\n    }\n}\n\n// A simple resolver that allows control over the DNS resolution process.\nprivate final class DummyResolver: Resolver, Sendable {\n    let v4Promise: EventLoopPromise<[SocketAddress]>\n    let v6Promise: EventLoopPromise<[SocketAddress]>\n\n    enum Event: Sendable {\n        case a(host: String, port: Int)\n        case aaaa(host: String, port: Int)\n        case cancel\n    }\n\n    private let _events: NIOLockedValueBox<[Event]>\n\n    var events: [Event] {\n        self._events.withLockedValue { $0 }\n    }\n\n    init(loop: EventLoop) {\n        self._events = NIOLockedValueBox([])\n        self.v4Promise = loop.makePromise()\n        self.v6Promise = loop.makePromise()\n    }\n\n    func initiateAQuery(host: String, port: Int) -> EventLoopFuture<[SocketAddress]> {\n        self._events.withLockedValue { $0.append(.a(host: host, port: port)) }\n        return self.v4Promise.futureResult\n    }\n\n    func initiateAAAAQuery(host: String, port: Int) -> EventLoopFuture<[SocketAddress]> {\n        self._events.withLockedValue { $0.append(.aaaa(host: host, port: port)) }\n        return self.v6Promise.futureResult\n    }\n\n    func cancelQueries() {\n        self._events.withLockedValue { $0.append(.cancel) }\n    }\n}\n\nextension DummyResolver.Event: Equatable {\n}\n\n@Sendable\nprivate func defaultChannelBuilder(loop: EventLoop, family: NIOBSDSocket.ProtocolFamily) -> EventLoopFuture<Channel> {\n    let channel = EmbeddedChannel(loop: loop as! EmbeddedEventLoop)\n    XCTAssertNoThrow(\n        try channel.pipeline.syncOperations.addHandler(ConnectRecorder(), name: CONNECT_RECORDER)\n    )\n    return loop.makeSucceededFuture(channel)\n}\n\nprivate func buildEyeballer(\n    host: String,\n    port: Int,\n    connectTimeout: TimeAmount = .seconds(10),\n    channelBuilderCallback: @escaping @Sendable (EventLoop, NIOBSDSocket.ProtocolFamily) -> EventLoopFuture<Channel> =\n        defaultChannelBuilder\n) -> (eyeballer: HappyEyeballsConnector<Void>, resolver: DummyResolver, loop: EmbeddedEventLoop) {\n    let loop = EmbeddedEventLoop()\n    let resolver = DummyResolver(loop: loop)\n    let eyeballer = HappyEyeballsConnector(\n        resolver: resolver,\n        loop: loop,\n        host: host,\n        port: port,\n        connectTimeout: connectTimeout,\n        channelBuilderCallback: channelBuilderCallback\n    )\n    return (eyeballer: eyeballer, resolver: resolver, loop: loop)\n}\n\nfinal class HappyEyeballsTest: XCTestCase {\n    func testIPv4OnlyResolution() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        loop.run()\n        resolver.v6Promise.fail(DummyError())\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n\n        // No time should have needed to pass: we return only one target and it connects immediately.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"10.0.0.1\")\n\n        // We should have had queries for AAAA and A.\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        XCTAssertEqual(resolver.events, expectedQueries)\n    }\n\n    func testIPv6OnlyResolution() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        loop.run()\n        resolver.v4Promise.fail(DummyError())\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        loop.run()\n\n        // No time should have needed to pass: we return only one target and it connects immediately.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"fe80::1\")\n\n        // We should have had queries for AAAA and A.\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        XCTAssertEqual(resolver.events, expectedQueries)\n    }\n\n    func testTimeOutDuringDNSResolution() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80, connectTimeout: .seconds(10))\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertFalse(channelFuture.isFulfilled)\n        XCTAssertEqual(resolver.events, expectedQueries)\n\n        loop.advanceTime(by: .seconds(9))\n        XCTAssertFalse(channelFuture.isFulfilled)\n        XCTAssertEqual(resolver.events, expectedQueries)\n\n        loop.advanceTime(by: .seconds(1))\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n\n        if case .some(ChannelError.connectTimeout(let amount)) = channelFuture.getError() {\n            XCTAssertEqual(amount, .seconds(10))\n        } else {\n            XCTFail(\"Got \\(String(describing: channelFuture.getError()))\")\n        }\n\n        // We now want to confirm that nothing awful happens if those DNS results\n        // return late.\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n    }\n\n    func testAAAAQueryReturningFirst() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        loop.run()\n\n        // No time should have needed to pass: we return only one target and it connects immediately.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"fe80::1\")\n\n        // We should have had queries for AAAA and A. We should then have had a cancel, because the A\n        // never returned.\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n\n        // Now return a result for the IPv4 query. Nothing bad should happen.\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n    }\n\n    func testAQueryReturningFirstDelayElapses() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n\n        // There should have been no connection attempt yet.\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        // Let the resolution delay (default of 50 ms) elapse.\n        loop.advanceTime(by: .milliseconds(49))\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n        loop.advanceTime(by: .milliseconds(1))\n\n        // The connection attempt should have been made with the IPv4 result.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"10.0.0.1\")\n\n        // We should have had queries for AAAA and A. We should then have had a cancel, because the A\n        // never returned.\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n\n        // Now return a result for the IPv6 query. Nothing bad should happen.\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n    }\n\n    func testAQueryReturningFirstThenAAAAReturns() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n\n        // There should have been no connection attempt yet.\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        // Now the AAAA returns.\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        loop.run()\n\n        // The connection attempt should have been made with the IPv6 result.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"fe80::1\")\n\n        // We should have had queries for AAAA and A, with no cancel.\n        XCTAssertEqual(resolver.events, expectedQueries)\n    }\n\n    func testAQueryReturningFirstThenAAAAErrors() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n\n        // There should have been no connection attempt yet.\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        // Now the AAAA fails.\n        resolver.v6Promise.fail(DummyError())\n        loop.run()\n\n        // The connection attempt should have been made with the IPv4 result.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"10.0.0.1\")\n\n        // We should have had queries for AAAA and A, with no cancel.\n        XCTAssertEqual(resolver.events, expectedQueries)\n    }\n\n    func testAQueryReturningFirstThenEmptyAAAA() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n\n        // There should have been no connection attempt yet.\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(targetFuture.isFulfilled)\n\n        // Now the AAAA returns empty.\n        resolver.v6Promise.succeed([])\n        loop.run()\n\n        // The connection attempt should have been made with the IPv4 result.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"10.0.0.1\")\n\n        // We should have had queries for AAAA and A, with no cancel.\n        XCTAssertEqual(resolver.events, expectedQueries)\n    }\n\n    func testEmptyResultsFail() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        resolver.v4Promise.succeed([])\n        resolver.v6Promise.succeed([])\n        loop.run()\n\n        // We should have had queries for AAAA and A, with no cancel.\n        XCTAssertEqual(resolver.events, expectedQueries)\n\n        // But we should have failed.\n        if let error = channelFuture.getError() as? NIOConnectionError {\n            XCTAssertEqual(error.host, \"example.com\")\n            XCTAssertEqual(error.port, 80)\n            XCTAssertNil(error.dnsAError)\n            XCTAssertNil(error.dnsAAAAError)\n            XCTAssertEqual(error.connectionErrors.count, 0)\n        } else {\n            XCTFail(\"Got \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testAllDNSFail() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80)\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        let v4Error = DummyError()\n        let v6Error = DummyError()\n        resolver.v4Promise.fail(v4Error)\n        resolver.v6Promise.fail(v6Error)\n        loop.run()\n\n        // We should have had queries for AAAA and A, with no cancel.\n        XCTAssertEqual(resolver.events, expectedQueries)\n\n        // But we should have failed.\n        if let error = channelFuture.getError() as? NIOConnectionError {\n            XCTAssertEqual(error.host, \"example.com\")\n            XCTAssertEqual(error.port, 80)\n            XCTAssertEqual(error.dnsAError as? DummyError ?? DummyError(), v4Error)\n            XCTAssertEqual(error.dnsAAAAError as? DummyError ?? DummyError(), v6Error)\n            XCTAssertEqual(error.connectionErrors.count, 0)\n        } else {\n            XCTFail(\"Got \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testMaximalConnectionDelay() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80, connectTimeout: .hours(1)) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // We're providing the IPv4 and IPv6 results. This will lead to 20 total hosts\n        // for us to try to connect to.\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n\n        for connectionCount in 1...20 {\n            XCTAssertEqual(channels.count, connectionCount)\n            loop.advanceTime(by: .milliseconds(249))\n            XCTAssertEqual(channels.count, connectionCount)\n            loop.advanceTime(by: .milliseconds(1))\n        }\n\n        // Now there will be no further connection attempts, even if we advance by a few minutes.\n        loop.advanceTime(by: .minutes(5))\n        XCTAssertEqual(channels.count, 20)\n\n        // Check that we attempted to connect to these hosts in the appropriate interleaved\n        // order.\n        var expectedAddresses = [String]()\n        for endIndex in 1...10 {\n            expectedAddresses.append(\"fe80::\\(endIndex)\")\n            expectedAddresses.append(\"10.0.0.\\(endIndex)\")\n        }\n        let actualAddresses = channels.map { $0.connectTarget()! }\n        XCTAssertEqual(actualAddresses, expectedAddresses)\n\n        // We still shouldn't have actually connected.\n        XCTAssertFalse(channelFuture.isFulfilled)\n        for channel in channels {\n            XCTAssertEqual(channel.state(), .idle)\n        }\n\n        // Connect the last channel. This should immediately succeed the\n        // future.\n        channels.last!.succeedConnection()\n        XCTAssertTrue(channelFuture.isFulfilled)\n        let connectedChannel = try! channelFuture.wait()\n        XCTAssertTrue(connectedChannel === channels.last)\n        XCTAssertEqual(connectedChannel.state(), .connected)\n\n        // The other channels should be closed.\n        for channel in channels.dropLast() {\n            XCTAssertEqual(channel.state(), .closed)\n        }\n    }\n\n    func testAllConnectionsFail() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80, connectTimeout: .hours(1)) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // We're providing the IPv4 and IPv6 results. This will lead to 20 total hosts\n        // for us to try to connect to.\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n\n        // Let all the connections fire.\n        for _ in 1...20 {\n            loop.advanceTime(by: .milliseconds(250))\n        }\n\n        // We still shouldn't have actually connected.\n        XCTAssertEqual(channels.count, 20)\n        XCTAssertFalse(channelFuture.isFulfilled)\n        for channel in channels {\n            XCTAssertEqual(channel.state(), .idle)\n        }\n\n        // Fail all the connection attempts.\n        var errors = [DummyError]()\n        for channel in channels.dropLast() {\n            let error = DummyError()\n            errors.append(error)\n            channel.failConnection(error: error)\n            XCTAssertFalse(channelFuture.isFulfilled)\n        }\n\n        // Fail the last channel. This should immediately fail the future.\n        errors.append(DummyError())\n        channels.last!.failConnection(error: errors.last!)\n        XCTAssertTrue(channelFuture.isFulfilled)\n\n        // Check the error.\n        if let error = channelFuture.getError() as? NIOConnectionError {\n            XCTAssertEqual(error.host, \"example.com\")\n            XCTAssertEqual(error.port, 80)\n            XCTAssertNil(error.dnsAError)\n            XCTAssertNil(error.dnsAAAAError)\n            XCTAssertEqual(error.connectionErrors.count, 20)\n\n            for (idx, error) in error.connectionErrors.enumerated() {\n                XCTAssertEqual(error.error as? DummyError, errors[idx])\n            }\n        } else {\n            XCTFail(\"Got \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testDelayedAAAAResult() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80, connectTimeout: .hours(1)) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Provide the IPv4 results and let five connection attempts play out.\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        loop.advanceTime(by: .milliseconds(50))\n\n        for connectionCount in 1...4 {\n            XCTAssertEqual(channels.last!.connectTarget()!, \"10.0.0.\\(connectionCount)\")\n            loop.advanceTime(by: .milliseconds(250))\n        }\n        XCTAssertEqual(channels.last!.connectTarget()!, \"10.0.0.5\")\n\n        // Now the IPv6 results come in.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n\n        // The next 10 connection attempts will interleave the IPv6 and IPv4 results,\n        // starting with IPv6.\n        for connectionCount in 1...5 {\n            loop.advanceTime(by: .milliseconds(250))\n            XCTAssertEqual(channels.last!.connectTarget()!, \"fe80::\\(connectionCount)\")\n            loop.advanceTime(by: .milliseconds(250))\n            XCTAssertEqual(channels.last!.connectTarget()!, \"10.0.0.\\(connectionCount + 5)\")\n        }\n\n        // We're now out of IPv4 addresses, so the last 5 will be IPv6.\n        for connectionCount in 6...10 {\n            loop.advanceTime(by: .milliseconds(250))\n            XCTAssertEqual(channels.last!.connectTarget()!, \"fe80::\\(connectionCount)\")\n        }\n    }\n\n    func testTimeoutWaitingForAAAA() throws {\n        let (eyeballer, resolver, loop) = buildEyeballer(\n            host: \"example.com\",\n            port: 80,\n            connectTimeout: .milliseconds(49)\n        )\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the A result returns, but the timeout is sufficiently low that the connect attempt\n        // times out before the AAAA can return.\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.advanceTime(by: .milliseconds(48))\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        loop.advanceTime(by: .milliseconds(1))\n        XCTAssertTrue(channelFuture.isFulfilled)\n\n        // We should have had queries for AAAA and A. We should then have had a cancel, because the AAAA\n        // never returned.\n        XCTAssertEqual(resolver.events, expectedQueries + [.cancel])\n        switch channelFuture.getError() {\n        case .some(ChannelError.connectTimeout(.milliseconds(49))):\n            break\n        default:\n            XCTFail(\"Got unexpected error: \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testTimeoutAfterAQuery() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(\n            host: \"example.com\",\n            port: 80,\n            connectTimeout: .milliseconds(100)\n        ) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the A result returns, but the timeout is sufficiently low that the connect attempt\n        // times out before the AAAA can return and before the connection succeeds.\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.advanceTime(by: .milliseconds(99))\n        XCTAssertFalse(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 1)\n        XCTAssertEqual(channels.first!.state(), .idle)\n\n        // Now the timeout fires.\n        loop.advanceTime(by: .milliseconds(1))\n        XCTAssertTrue(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 1)\n        XCTAssertEqual(channels.first!.state(), .closed)\n\n        switch channelFuture.getError() {\n        case .some(ChannelError.connectTimeout(.milliseconds(100))):\n            break\n        default:\n            XCTFail(\"Got unexpected error: \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testAConnectFailsWaitingForAAAA() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(\n            host: \"example.com\",\n            port: 80,\n            connectTimeout: .milliseconds(100)\n        ) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the A result returns and a connection attempt is made. This fails, and we test that\n        // we wait for the AAAA query to come in before acting. That connection attempt then times out.\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.advanceTime(by: .milliseconds(50))\n        XCTAssertFalse(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 1)\n        XCTAssertEqual(channels.first!.state(), .idle)\n\n        // The connection attempt fails. We still have no answer.\n        channels.first!.failConnection(error: DummyError())\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Now the AAAA returns.\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        XCTAssertFalse(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 2)\n        XCTAssertEqual(channels.last!.state(), .idle)\n\n        // Now the timeout fires.\n        loop.advanceTime(by: .milliseconds(50))\n        XCTAssertTrue(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 2)\n        XCTAssertEqual(channels.last!.state(), .closed)\n\n        switch channelFuture.getError() {\n        case .some(ChannelError.connectTimeout(.milliseconds(100))):\n            break\n        default:\n            XCTFail(\"Got unexpected error: \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testDelayedAResult() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80, connectTimeout: .hours(1)) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Provide the IPv6 results and let all 10 connection attempts play out.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n\n        for connectionCount in 1...10 {\n            XCTAssertEqual(channels.last!.connectTarget()!, \"fe80::\\(connectionCount)\")\n            loop.advanceTime(by: .milliseconds(250))\n        }\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Advance time by 30 minutes just to prove that we'll wait a long, long time for the\n        // A result.\n        loop.advanceTime(by: .minutes(30))\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Now the IPv4 results come in. Let all 10 connection attempts play out.\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        for connectionCount in 1...10 {\n            XCTAssertEqual(channels.last!.connectTarget()!, \"10.0.0.\\(connectionCount)\")\n            loop.advanceTime(by: .milliseconds(250))\n        }\n        XCTAssertFalse(channelFuture.isFulfilled)\n    }\n\n    func testTimeoutBeforeAResponse() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(\n            host: \"example.com\",\n            port: 80,\n            connectTimeout: .milliseconds(100)\n        ) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the AAAA result returns, but the timeout is sufficiently low that the connect attempt\n        // times out before the A returns.\n        resolver.v6Promise.succeed(SINGLE_IPv6_RESULT)\n        loop.advanceTime(by: .milliseconds(99))\n        XCTAssertFalse(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 1)\n        XCTAssertEqual(channels.first!.state(), .idle)\n\n        // Now the timeout fires.\n        loop.advanceTime(by: .milliseconds(1))\n        XCTAssertTrue(channelFuture.isFulfilled)\n        XCTAssertEqual(channels.count, 1)\n        XCTAssertEqual(channels.first!.state(), .closed)\n\n        switch channelFuture.getError() {\n        case .some(ChannelError.connectTimeout(.milliseconds(100))):\n            break\n        default:\n            XCTFail(\"Got unexpected error: \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testAllConnectionsFailImmediately() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the AAAA and A results return. We are going to fail the connections\n        // instantly, which should cause all 20 to appear.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n        for channelCount in 1...10 {\n            XCTAssertFalse(channelFuture.isFulfilled)\n            XCTAssertEqual(channels.count, channelCount)\n            XCTAssertEqual(channels.last!.state(), .idle)\n            channels.last?.failConnection(error: DummyError())\n        }\n\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        for channelCount in 11...20 {\n            XCTAssertFalse(channelFuture.isFulfilled)\n            XCTAssertEqual(channels.count, channelCount)\n            XCTAssertEqual(channels.last!.state(), .idle)\n            channels.last?.failConnection(error: DummyError())\n        }\n\n        XCTAssertTrue(channelFuture.isFulfilled)\n        switch channelFuture.getError() {\n        case is NIOConnectionError:\n            break\n        default:\n            XCTFail(\"Got unexpected error: \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testLaterConnections() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the AAAA results return. Let all the connection attempts go out.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n        for channelCount in 1...10 {\n            XCTAssertEqual(channels.count, channelCount)\n            loop.advanceTime(by: .milliseconds(250))\n        }\n\n        // Now we want to connect the first of these. This should lead to success.\n        channels.first!.succeedConnection()\n        XCTAssertTrue((try? channelFuture.wait()) === channels.first)\n\n        // Now we're going to accept the second connection as well. This should lead to\n        // a call to close.\n        channels[1].succeedConnection()\n        XCTAssertEqual(channels[1].state(), .closed)\n        XCTAssertTrue((try? channelFuture.wait()) === channels.first)\n\n        // Now fail the third. This shouldn't change anything.\n        channels[2].failConnection(error: DummyError())\n        XCTAssertTrue((try? channelFuture.wait()) === channels.first)\n    }\n\n    func testDelayedChannelCreation() throws {\n        // This lock isn't really needed as the test is single-threaded, but because\n        // the buildEyeballer function constructs the event loop we can't use a LoopBoundBox.\n        // This is fine anyway.\n        let ourChannelFutures: NIOLockedValueBox<[EventLoopPromise<Channel>]> = NIOLockedValueBox([])\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80) { loop, _ in\n            ourChannelFutures.withLockedValue {\n                $0.append(loop.makePromise())\n                return $0.last!.futureResult\n            }\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Return the IPv6 results and observe the channel creation attempts.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n        for channelCount in 1...10 {\n            XCTAssertEqual(\n                ourChannelFutures.withLockedValue { $0.count },\n                channelCount\n            )\n            loop.advanceTime(by: .milliseconds(250))\n        }\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Succeed the first channel future, which will connect because the default\n        // channel builder always does.\n        defaultChannelBuilder(loop: loop, family: .inet6).whenSuccess { result in\n            ourChannelFutures.withLockedValue {\n                $0.first!.succeed(result)\n            }\n            XCTAssertEqual(result.state(), .connected)\n        }\n        XCTAssertTrue(channelFuture.isFulfilled)\n\n        // Ok, now succeed the second channel future. This should cause the channel to immediately be closed.\n        defaultChannelBuilder(loop: loop, family: .inet6).whenSuccess { result in\n            ourChannelFutures.withLockedValue {\n                $0[1].succeed(result)\n            }\n            XCTAssertEqual(result.state(), .closed)\n        }\n\n        try ourChannelFutures.withLockedValue {\n            // Ok, now fail the third channel future. Nothing bad should happen here.\n            $0[2].fail(DummyError())\n\n            // Verify that the first channel is the one listed as connected.\n            XCTAssertTrue((try $0.first!.futureResult.wait()) === (try channelFuture.wait()))\n        }\n    }\n\n    func testChannelCreationFails() throws {\n        // This lock isn't really needed as the test is single-threaded, but because\n        // the buildEyeballer function constructs the event loop we can't use a LoopBoundBox.\n        // This is fine anyway.\n        let errors: NIOLockedValueBox<[DummyError]> = NIOLockedValueBox([])\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80) { loop, _ in\n            errors.withLockedValue {\n                $0.append(DummyError())\n                return loop.makeFailedFuture($0.last!)\n            }\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the AAAA and A results return. We are going to fail the channel creation\n        // instantly, which should cause all 20 to appear.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n        XCTAssertEqual(errors.withLockedValue { $0.count }, 10)\n        XCTAssertFalse(channelFuture.isFulfilled)\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        XCTAssertEqual(errors.withLockedValue { $0.count }, 20)\n\n        XCTAssertTrue(channelFuture.isFulfilled)\n        if let error = channelFuture.getError() as? NIOConnectionError {\n            XCTAssertEqual(error.connectionErrors.map { $0.error as! DummyError }, errors.withLockedValue { $0 })\n        } else {\n            XCTFail(\"Got unexpected error: \\(String(describing: channelFuture.getError()))\")\n        }\n    }\n\n    func testCancellationSyncWithConnectDelay() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(\n            host: \"example.com\",\n            port: 80,\n            connectTimeout: .milliseconds(250)\n        ) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the AAAA results return. Let the first connection attempt go out.\n        resolver.v6Promise.succeed(MANY_IPv6_RESULTS)\n        XCTAssertEqual(channels.count, 1)\n\n        // Advance time by 250 ms.\n        loop.advanceTime(by: .milliseconds(250))\n\n        // At this time the connection attempt should have failed, as the connect timeout\n        // fired.\n        XCTAssertThrowsError(try channelFuture.wait()) { error in\n            XCTAssertEqual(.connectTimeout(.milliseconds(250)), error as? ChannelError)\n        }\n\n        // There may be one or two channels, depending on ordering, but both\n        // should be closed.\n        XCTAssertTrue(channels.count == 1 || channels.count == 2, \"Unexpected channel count: \\(channels.count)\")\n        for channel in channels {\n            XCTAssertEqual(channel.state(), .closed)\n        }\n    }\n\n    func testCancellationSyncWithResolutionDelay() throws {\n        let channels = ChannelSet()\n        defer {\n            channels.finishAll()\n        }\n\n        let (eyeballer, resolver, loop) = buildEyeballer(\n            host: \"example.com\",\n            port: 80,\n            connectTimeout: .milliseconds(50)\n        ) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let channelFuture = eyeballer.resolveAndConnect()\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        loop.run()\n        XCTAssertEqual(resolver.events, expectedQueries)\n        XCTAssertFalse(channelFuture.isFulfilled)\n\n        // Here the A results return. Let the first connection attempt go out.\n        resolver.v4Promise.succeed(MANY_IPv4_RESULTS)\n        XCTAssertEqual(channels.count, 0)\n\n        // Advance time by 50 ms.\n        loop.advanceTime(by: .milliseconds(50))\n\n        // At this time the connection attempt should have failed, as the connect timeout\n        // fired.\n        XCTAssertThrowsError(try channelFuture.wait()) { error in\n            XCTAssertEqual(.connectTimeout(.milliseconds(50)), error as? ChannelError)\n        }\n\n        // There may be zero or one channels, depending on ordering, but if there is one it\n        // should be closed\n        XCTAssertTrue(channels.count == 0 || channels.count == 1, \"Unexpected channel count: \\(channels.count)\")\n        for channel in channels {\n            XCTAssertEqual(channel.state(), .closed)\n        }\n    }\n\n    func testResolverOnDifferentEventLoop() throws {\n        // Tests a regression where the happy eyeballs connector would update its state on the event\n        // loop of the future returned by the resolver (which may be different to its own). Prior\n        // to the fix this test would trigger TSAN warnings.\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let server = try ServerBootstrap(group: group)\n            .bind(host: \"localhost\", port: 0)\n            .wait()\n\n        defer {\n            XCTAssertNoThrow(try server.close().wait())\n        }\n\n        // Run the resolver and connection on different event loops.\n        let resolverLoop = group.next()\n        let connectionLoop = group.next()\n        XCTAssertNotIdentical(resolverLoop, connectionLoop)\n        let resolver = GetaddrinfoResolver(loop: resolverLoop, aiSocktype: .stream, aiProtocol: .tcp)\n        let client = try ClientBootstrap(group: connectionLoop)\n            .resolver(resolver)\n            .connect(host: \"localhost\", port: server.localAddress!.port!)\n            .wait()\n\n        XCTAssertNoThrow(try client.close().wait())\n    }\n\n    func testResolutionTimeoutAndResolutionInSameTick() throws {\n        let channels = ChannelSet()\n        let (eyeballer, resolver, loop) = buildEyeballer(host: \"example.com\", port: 80) {\n            let channelFuture = defaultChannelBuilder(loop: $0, family: $1)\n            channelFuture.whenSuccess { channel in\n                try! channel.pipeline.syncOperations.addHandler(\n                    ConnectionDelayer(),\n                    name: CONNECT_DELAYER,\n                    position: .first\n                )\n                channels.append(channel)\n            }\n            return channelFuture\n        }\n        let targetFuture = eyeballer.resolveAndConnect().flatMapThrowing { (channel) -> String? in\n            let target = channel.connectTarget()\n            _ = try (channel as! EmbeddedChannel).finish()\n            return target\n        }\n        loop.run()\n\n        // Then, queue a task to resolve the v6 promise after 50ms.\n        // Why 50ms? This is the same time as the resolution delay.\n        let promise = resolver.v6Promise\n        loop.scheduleTask(in: .milliseconds(50)) {\n            promise.fail(DummyError())\n        }\n\n        // Kick off the IPv4 resolution. This triggers the timer for the resolution delay.\n        resolver.v4Promise.succeed(SINGLE_IPv4_RESULT)\n        loop.run()\n\n        // Advance time 50ms.\n        loop.advanceTime(by: .milliseconds(50))\n\n        // Then complete the connection future.\n        XCTAssertEqual(channels.count, 1)\n        channels.first!.succeedConnection()\n\n        // Should be done.\n        let target = try targetFuture.wait()\n        XCTAssertEqual(target!, \"10.0.0.1\")\n\n        // We should have had queries for AAAA and A.\n        let expectedQueries: [DummyResolver.Event] = [\n            .aaaa(host: \"example.com\", port: 80),\n            .a(host: \"example.com\", port: 80),\n        ]\n        XCTAssertEqual(resolver.events, expectedQueries)\n    }\n}\n\nstruct ChannelSet: Sendable, Sequence {\n    private let channels: NIOLockedValueBox<[Channel]> = .init([])\n\n    func append(_ channel: Channel) {\n        self.channels.withLockedValue { $0.append(channel) }\n    }\n\n    var first: Channel? {\n        self.channels.withLockedValue { $0.first }\n    }\n\n    var last: Channel? {\n        self.channels.withLockedValue { $0.last }\n    }\n\n    var count: Int {\n        self.channels.withLockedValue { $0.count }\n    }\n\n    subscript(index: Int) -> Channel {\n        self.channels.withLockedValue { $0[index] }\n    }\n\n    func makeIterator() -> some IteratorProtocol<Channel> {\n        self.channels.withLockedValue { $0.makeIterator() }\n    }\n\n    func finishAll() {\n        self.channels.withLockedValue { $0 }.finishAll()\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/IPv4Header.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\n\nstruct IPv4Address: Hashable {\n    var rawValue: UInt32\n}\n\nextension IPv4Address {\n    init(_ v1: UInt8, _ v2: UInt8, _ v3: UInt8, _ v4: UInt8) {\n        rawValue = UInt32(v1) << 24 | UInt32(v2) << 16 | UInt32(v3) << 8 | UInt32(v4)\n    }\n}\n\nextension IPv4Address: CustomStringConvertible {\n    var description: String {\n        let v1 = rawValue >> 24\n        let v2 = rawValue >> 16 & 0b1111_1111\n        let v3 = rawValue >> 8 & 0b1111_1111\n        let v4 = rawValue & 0b1111_1111\n        return \"\\(v1).\\(v2).\\(v3).\\(v4)\"\n    }\n}\n\nstruct IPv4Header: Hashable {\n    static let size: Int = 20\n\n    fileprivate var versionAndIhl: UInt8\n    var version: UInt8 {\n        get {\n            versionAndIhl >> 4\n        }\n        set {\n            precondition(newValue & 0b1111_0000 == 0)\n            versionAndIhl = newValue << 4 | (0b0000_1111 & versionAndIhl)\n            assert(newValue == version, \"\\(newValue) != \\(version) \\(versionAndIhl)\")\n        }\n    }\n    var internetHeaderLength: UInt8 {\n        get {\n            versionAndIhl & 0b0000_1111\n        }\n        set {\n            precondition(newValue & 0b1111_0000 == 0)\n            versionAndIhl = newValue | (0b1111_0000 & versionAndIhl)\n            assert(newValue == internetHeaderLength)\n        }\n    }\n    fileprivate var dscpAndEcn: UInt8\n    var differentiatedServicesCodePoint: UInt8 {\n        get {\n            dscpAndEcn >> 2\n        }\n        set {\n            precondition(newValue & 0b0000_0011 == 0)\n            dscpAndEcn = newValue << 2 | (0b0000_0011 & dscpAndEcn)\n            assert(newValue == differentiatedServicesCodePoint)\n        }\n    }\n    var explicitCongestionNotification: UInt8 {\n        get {\n            dscpAndEcn & 0b0000_0011\n        }\n        set {\n            precondition(newValue & 0b0000_0011 == 0)\n            dscpAndEcn = newValue | (0b1111_1100 & dscpAndEcn)\n            assert(newValue == explicitCongestionNotification)\n        }\n    }\n    var totalLength: UInt16\n    var identification: UInt16\n    fileprivate var flagsAndFragmentOffset: UInt16\n    var flags: UInt8 {\n        get {\n            UInt8(flagsAndFragmentOffset >> 13)\n        }\n        set {\n            precondition(newValue & 0b0000_0111 == 0)\n            flagsAndFragmentOffset = UInt16(newValue) << 13 | (0b0001_1111_1111_1111 & flagsAndFragmentOffset)\n            assert(newValue == flags)\n        }\n    }\n    var fragmentOffset: UInt16 {\n        get {\n            flagsAndFragmentOffset & 0b0001_1111_1111_1111\n        }\n        set {\n            precondition(newValue & 0b1110_0000_0000_0000 == 0)\n            flagsAndFragmentOffset = newValue | (0b1110_0000_0000_0000 & flagsAndFragmentOffset)\n            assert(newValue == fragmentOffset)\n        }\n    }\n    var timeToLive: UInt8\n    var `protocol`: NIOIPProtocol\n    var headerChecksum: UInt16\n    var sourceIpAddress: IPv4Address\n    var destinationIpAddress: IPv4Address\n\n    fileprivate init(\n        versionAndIhl: UInt8,\n        dscpAndEcn: UInt8,\n        totalLength: UInt16,\n        identification: UInt16,\n        flagsAndFragmentOffset: UInt16,\n        timeToLive: UInt8,\n        `protocol`: NIOIPProtocol,\n        headerChecksum: UInt16,\n        sourceIpAddress: IPv4Address,\n        destinationIpAddress: IPv4Address\n    ) {\n        self.versionAndIhl = versionAndIhl\n        self.dscpAndEcn = dscpAndEcn\n        self.totalLength = totalLength\n        self.identification = identification\n        self.flagsAndFragmentOffset = flagsAndFragmentOffset\n        self.timeToLive = timeToLive\n        self.`protocol` = `protocol`\n        self.headerChecksum = headerChecksum\n        self.sourceIpAddress = sourceIpAddress\n        self.destinationIpAddress = destinationIpAddress\n    }\n\n    init() {\n        self.versionAndIhl = 0\n        self.dscpAndEcn = 0\n        self.totalLength = 0\n        self.identification = 0\n        self.flagsAndFragmentOffset = 0\n        self.timeToLive = 0\n        self.`protocol` = .init(rawValue: 0)\n        self.headerChecksum = 0\n        self.sourceIpAddress = .init(rawValue: 0)\n        self.destinationIpAddress = .init(rawValue: 0)\n    }\n}\n\nextension FixedWidthInteger {\n    func convertEndianness(to endianness: Endianness) -> Self {\n        switch endianness {\n        case .little:\n            return self.littleEndian\n        case .big:\n            return self.bigEndian\n        }\n    }\n}\n\nextension ByteBuffer {\n    mutating func readIPv4Header() -> IPv4Header? {\n        guard\n            let (\n                versionAndIhl,\n                dscpAndEcn,\n                totalLength,\n                identification,\n                flagsAndFragmentOffset,\n                timeToLive,\n                `protocol`,\n                headerChecksum,\n                sourceIpAddress,\n                destinationIpAddress\n            ) = self.readMultipleIntegers(\n                as: (\n                    UInt8,\n                    UInt8,\n                    UInt16,\n                    UInt16,\n                    UInt16,\n                    UInt8,\n                    UInt8,\n                    UInt16,\n                    UInt32,\n                    UInt32\n                ).self\n            )\n        else { return nil }\n        return .init(\n            versionAndIhl: versionAndIhl,\n            dscpAndEcn: dscpAndEcn,\n            totalLength: totalLength,\n            identification: identification,\n            flagsAndFragmentOffset: flagsAndFragmentOffset,\n            timeToLive: timeToLive,\n            protocol: .init(rawValue: `protocol`),\n            headerChecksum: headerChecksum,\n            sourceIpAddress: .init(rawValue: sourceIpAddress),\n            destinationIpAddress: .init(rawValue: destinationIpAddress)\n        )\n    }\n\n    mutating func readIPv4HeaderFromBSDRawSocket() -> IPv4Header? {\n        guard var header = self.readIPv4Header() else { return nil }\n        // On BSD, the total length is in host byte order\n        header.totalLength = header.totalLength.convertEndianness(to: .big)\n        // TODO: fragmentOffset is in host byte order as well but it is always zero in our tests\n        // and fragmentOffset is 13 bits in size so we can't just use readInteger(endianness: .host)\n        return header\n    }\n\n    mutating func readIPv4HeaderFromOSRawSocket() -> IPv4Header? {\n        #if canImport(Darwin)\n        return self.readIPv4HeaderFromBSDRawSocket()\n        #else\n        return self.readIPv4Header()\n        #endif\n    }\n}\n\nextension ByteBuffer {\n    @discardableResult\n    mutating func writeIPv4Header(_ header: IPv4Header) -> Int {\n        assert(\n            {\n                var buffer = ByteBuffer()\n                buffer._writeIPv4Header(header)\n                let writtenHeader = buffer.readIPv4Header()\n                return header == writtenHeader\n            }()\n        )\n        return self._writeIPv4Header(header)\n    }\n\n    @discardableResult\n    private mutating func _writeIPv4Header(_ header: IPv4Header) -> Int {\n        self.writeMultipleIntegers(\n            header.versionAndIhl,\n            header.dscpAndEcn,\n            header.totalLength,\n            header.identification,\n            header.flagsAndFragmentOffset,\n            header.timeToLive,\n            header.`protocol`.rawValue,\n            header.headerChecksum,\n            header.sourceIpAddress.rawValue,\n            header.destinationIpAddress.rawValue\n        )\n    }\n\n    @discardableResult\n    mutating func writeIPv4HeaderToBSDRawSocket(_ header: IPv4Header) -> Int {\n        assert(\n            {\n                var buffer = ByteBuffer()\n                buffer._writeIPv4HeaderToBSDRawSocket(header)\n                let writtenHeader = buffer.readIPv4HeaderFromBSDRawSocket()\n                return header == writtenHeader\n            }()\n        )\n        return self._writeIPv4HeaderToBSDRawSocket(header)\n    }\n\n    @discardableResult\n    private mutating func _writeIPv4HeaderToBSDRawSocket(_ header: IPv4Header) -> Int {\n        var header = header\n        // On BSD, the total length needs to be in host byte order\n        header.totalLength = header.totalLength.convertEndianness(to: .big)\n        // TODO: fragmentOffset needs to be in host byte order as well but it is always zero in our tests\n        // and fragmentOffset is 13 bits in size so we can't just use writeInteger(endianness: .host)\n        return self._writeIPv4Header(header)\n    }\n\n    @discardableResult\n    mutating func writeIPv4HeaderToOSRawSocket(_ header: IPv4Header) -> Int {\n        #if canImport(Darwin)\n        self.writeIPv4HeaderToBSDRawSocket(header)\n        #else\n        self.writeIPv4Header(header)\n        #endif\n    }\n}\n\nextension IPv4Header {\n    func computeChecksum() -> UInt16 {\n        let checksum = ~[\n            UInt16(versionAndIhl) << 8 | UInt16(dscpAndEcn),\n            totalLength,\n            identification,\n            flagsAndFragmentOffset,\n            UInt16(timeToLive) << 8 | UInt16(`protocol`.rawValue),\n            UInt16(sourceIpAddress.rawValue >> 16),\n            UInt16(sourceIpAddress.rawValue & 0b0000_0000_0000_0000_1111_1111_1111_1111),\n            UInt16(destinationIpAddress.rawValue >> 16),\n            UInt16(destinationIpAddress.rawValue & 0b0000_0000_0000_0000_1111_1111_1111_1111),\n        ].reduce(UInt16(0), onesComplementAdd)\n        assert(isValidChecksum(checksum))\n        return checksum\n    }\n    mutating func setChecksum() {\n        self.headerChecksum = computeChecksum()\n    }\n    func isValidChecksum(_ headerChecksum: UInt16) -> Bool {\n        let sum = ~[\n            UInt16(versionAndIhl) << 8 | UInt16(dscpAndEcn),\n            totalLength,\n            identification,\n            flagsAndFragmentOffset,\n            UInt16(timeToLive) << 8 | UInt16(`protocol`.rawValue),\n            headerChecksum,\n            UInt16(sourceIpAddress.rawValue >> 16),\n            UInt16(sourceIpAddress.rawValue & 0b0000_0000_0000_0000_1111_1111_1111_1111),\n            UInt16(destinationIpAddress.rawValue >> 16),\n            UInt16(destinationIpAddress.rawValue & 0b0000_0000_0000_0000_1111_1111_1111_1111),\n        ].reduce(UInt16(0), onesComplementAdd)\n        return sum == 0\n    }\n    func isValidChecksum() -> Bool {\n        isValidChecksum(headerChecksum)\n    }\n}\n\nextension Sequence where Element == UInt8 {\n    func computeIPChecksum() -> UInt16 {\n        var sum = UInt16(0)\n\n        var iterator = self.makeIterator()\n\n        while let nextHigh = iterator.next() {\n            let nextLow = iterator.next() ?? 0\n            let next = (UInt16(nextHigh) << 8) | UInt16(nextLow)\n            sum = onesComplementAdd(lhs: sum, rhs: next)\n        }\n\n        return ~sum\n    }\n}\n\nprivate func onesComplementAdd<Integer: FixedWidthInteger>(lhs: Integer, rhs: Integer) -> Integer {\n    var (sum, overflowed) = lhs.addingReportingOverflow(rhs)\n    if overflowed {\n        sum &+= 1\n    }\n    return sum\n}\n\nextension IPv4Header {\n    var platformIndependentTotalLengthForReceivedPacketFromRawSocket: UInt16 {\n        #if canImport(Darwin)\n        // On BSD the IP header will only contain the size of the ip packet body, not the header.\n        // This is known bug which can't be fixed without breaking old apps which already workaround the issue\n        // like e.g. we do now too.\n        return totalLength + 20\n        #else\n        return totalLength\n        #endif\n    }\n    var platformIndependentChecksumForReceivedPacketFromRawSocket: UInt16 {\n        #if canImport(Darwin)\n        // On BSD the checksum is always zero and we need to compute it\n        precondition(headerChecksum == 0)\n        return computeChecksum()\n        #else\n        return headerChecksum\n        #endif\n    }\n}\n\nextension IPv4Header: CustomStringConvertible {\n    var description: String {\n        \"\"\"\n        Version: \\(version)\n        Header Length: \\(internetHeaderLength * 4) bytes\n        Differentiated Services: \\(String(differentiatedServicesCodePoint, radix: 2))\n        Explicit Congestion Notification: \\(String(explicitCongestionNotification, radix: 2))\n        Total Length: \\(totalLength) bytes\n        Identification: \\(identification)\n        Flags: \\(String(flags, radix: 2))\n        Fragment Offset: \\(fragmentOffset) bytes\n        Time to Live: \\(timeToLive)\n        Protocol: \\(`protocol`)\n        Header Checksum: \\(headerChecksum) (\\(isValidChecksum() ? \"valid\" : \"*not* valid\"))\n        Source IP Address: \\(sourceIpAddress)\n        Destination IP Address: \\(destinationIpAddress)\n        \"\"\"\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/IdleStateHandlerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport NIOPosix\nimport XCTest\n\n@testable import NIOCore\n\nclass IdleStateHandlerTest: XCTestCase {\n\n    func testIdleRead() throws {\n        try testIdle(IdleStateHandler(readTimeout: .seconds(1)), false, { $0 == IdleStateHandler.IdleStateEvent.read })\n    }\n\n    func testIdleWrite() throws {\n        try testIdle(IdleStateHandler(writeTimeout: .seconds(1)), true, { $0 == IdleStateHandler.IdleStateEvent.write })\n    }\n\n    func testIdleAllWrite() throws {\n        try testIdle(IdleStateHandler(allTimeout: .seconds(1)), true, { $0 == IdleStateHandler.IdleStateEvent.all })\n    }\n\n    func testIdleAllRead() throws {\n        try testIdle(IdleStateHandler(allTimeout: .seconds(1)), false, { $0 == IdleStateHandler.IdleStateEvent.all })\n    }\n\n    private func testIdle(\n        _ handler: @escaping @Sendable @autoclosure () -> IdleStateHandler,\n        _ writeToChannel: Bool,\n        _ assertEventFn: @escaping @Sendable (IdleStateHandler.IdleStateEvent) -> Bool\n    ) throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class TestWriteHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var read = false\n            private let writeToChannel: Bool\n            private let assertEventFn: (IdleStateHandler.IdleStateEvent) -> Bool\n\n            init(_ writeToChannel: Bool, _ assertEventFn: @escaping (IdleStateHandler.IdleStateEvent) -> Bool) {\n                self.writeToChannel = writeToChannel\n                self.assertEventFn = assertEventFn\n            }\n\n            public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                self.read = true\n            }\n\n            public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                if !self.writeToChannel {\n                    XCTAssertTrue(self.read)\n                }\n\n                XCTAssertTrue(assertEventFn(event as! IdleStateHandler.IdleStateEvent))\n                context.close(promise: nil)\n            }\n\n            public func channelActive(context: ChannelHandlerContext) {\n                if writeToChannel {\n                    var buffer = context.channel.allocator.buffer(capacity: 4)\n                    buffer.writeStaticString(\"test\")\n                    context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n                }\n            }\n        }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let handler = handler()\n                        try channel.pipeline.syncOperations.addHandler(handler)\n                        try channel.pipeline.syncOperations.addHandler(TestWriteHandler(writeToChannel, assertEventFn))\n                    }\n                }.bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n        if !writeToChannel {\n            var buffer = clientChannel.allocator.buffer(capacity: 4)\n            buffer.writeStaticString(\"test\")\n            XCTAssertNoThrow(try clientChannel.writeAndFlush(buffer).wait())\n        }\n        XCTAssertNoThrow(try clientChannel.closeFuture.wait())\n    }\n\n    func testPropagateInboundEvents() {\n        class EventHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n\n            var active = false\n            var inactive = false\n            var read = false\n            var readComplete = false\n            var writabilityChanged = false\n            var eventTriggered = false\n            var errorCaught = false\n            var registered = false\n            var unregistered = false\n\n            func channelActive(context: ChannelHandlerContext) {\n                self.active = true\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                self.inactive = true\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                self.read = true\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                self.readComplete = true\n            }\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                self.writabilityChanged = true\n            }\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                self.eventTriggered = true\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                self.errorCaught = true\n            }\n\n            func channelRegistered(context: ChannelHandlerContext) {\n                self.registered = true\n            }\n\n            func channelUnregistered(context: ChannelHandlerContext) {\n                self.unregistered = true\n            }\n\n            func assertAllEventsReceived() {\n                XCTAssertTrue(self.active)\n                XCTAssertTrue(self.inactive)\n                XCTAssertTrue(self.read)\n                XCTAssertTrue(self.readComplete)\n                XCTAssertTrue(self.writabilityChanged)\n                XCTAssertTrue(self.eventTriggered)\n                XCTAssertTrue(self.errorCaught)\n                XCTAssertTrue(self.registered)\n                XCTAssertTrue(self.unregistered)\n            }\n        }\n        let eventHandler = EventHandler()\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(IdleStateHandler()))\n        XCTAssertNoThrow(try channel.pipeline.syncOperations.addHandler(eventHandler))\n\n        channel.pipeline.fireChannelRegistered()\n        channel.pipeline.fireChannelActive()\n        channel.pipeline.fireChannelRead(\"\")\n        channel.pipeline.fireChannelReadComplete()\n        channel.pipeline.fireErrorCaught(ChannelError.alreadyClosed)\n        channel.pipeline.fireUserInboundEventTriggered(\"\")\n\n        channel.pipeline.fireChannelWritabilityChanged()\n        channel.pipeline.fireChannelInactive()\n        channel.pipeline.fireChannelUnregistered()\n\n        XCTAssertTrue(try channel.finish().isClean)\n        eventHandler.assertAllEventsReceived()\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/IntegerBitPackingTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport XCTest\n\n@testable import NIOPosix\n\nfinal class IntegerBitPackingTests: XCTestCase {\n    func testAllUInt8PairsRoundtrip() {\n        for i in UInt16.min...UInt16.max {\n            let unpacked = IntegerBitPacking.unpackUInt8UInt8(i)\n            XCTAssertEqual(i, IntegerBitPacking.packUInt8UInt8(unpacked.0, unpacked.1))\n        }\n    }\n\n    func testExtremesWorkForUInt32UInt16UInt8() {\n        XCTAssert(\n            (.max, .max, .max)\n                == IntegerBitPacking.unpackUInt32UInt16UInt8(\n                    IntegerBitPacking.packUInt32UInt16UInt8(\n                        .max,\n                        .max,\n                        .max\n                    )\n                )\n        )\n\n        XCTAssert(\n            (0, 0, 0) == IntegerBitPacking.unpackUInt32UInt16UInt8(IntegerBitPacking.packUInt32UInt16UInt8(0, 0, 0))\n        )\n\n        XCTAssert(\n            (UInt32(1) << 31 | 1, UInt16(1) << 15 | 1, UInt8(1) << 7 | 1)\n                == IntegerBitPacking.unpackUInt32UInt16UInt8(\n                    IntegerBitPacking.packUInt32UInt16UInt8(\n                        UInt32(1) << 31 | 1,\n                        UInt16(1) << 15 | 1,\n                        UInt8(1) << 7 | 1\n                    )\n                )\n        )\n\n        let randomUInt32 = UInt32.random(in: .min ... .max)\n        let randomUInt16 = UInt16.random(in: .min ... .max)\n        let randomUInt8 = UInt8.random(in: .min ... .max)\n        XCTAssert(\n            (randomUInt32, randomUInt16, randomUInt8)\n                == IntegerBitPacking.unpackUInt32UInt16UInt8(\n                    IntegerBitPacking.packUInt32UInt16UInt8(randomUInt32, randomUInt16, randomUInt8)\n                ),\n            \"\\((randomUInt32, randomUInt16, randomUInt8)) didn't roundtrip\"\n        )\n    }\n\n    func testExtremesWorkForUInt16UInt8() {\n        XCTAssert((.max, .max) == IntegerBitPacking.unpackUInt16UInt8(IntegerBitPacking.packUInt16UInt8(.max, .max)))\n\n        XCTAssert((0, 0) == IntegerBitPacking.unpackUInt16UInt8(IntegerBitPacking.packUInt16UInt8(0, 0)))\n\n        XCTAssert(\n            (UInt16(1) << 15 | 1, UInt8(1) << 7 | 1)\n                == IntegerBitPacking.unpackUInt16UInt8(\n                    IntegerBitPacking.packUInt16UInt8(\n                        UInt16(1) << 15 | 1,\n                        UInt8(1) << 7 | 1\n                    )\n                )\n        )\n    }\n\n    func testExtremesWorkForUInt32CInt() {\n        XCTAssert((.max, .max) == IntegerBitPacking.unpackUInt32CInt(IntegerBitPacking.packUInt32CInt(.max, .max)))\n\n        XCTAssert((0, 0) == IntegerBitPacking.unpackUInt32CInt(IntegerBitPacking.packUInt32CInt(0, 0)))\n\n        XCTAssert((.min, -1) == IntegerBitPacking.unpackUInt32CInt(IntegerBitPacking.packUInt32CInt(.min, -1)))\n\n        XCTAssert((.min, .min) == IntegerBitPacking.unpackUInt32CInt(IntegerBitPacking.packUInt32CInt(.min, .min)))\n\n        XCTAssert(\n            (UInt32(1) << 31 | 1, CInt(1) << 31)\n                == IntegerBitPacking.unpackUInt32CInt(\n                    IntegerBitPacking.packUInt32CInt(\n                        UInt32(1) << 31 | 1,\n                        CInt(1) << 31\n                    )\n                )\n        )\n\n        let randomUInt32 = UInt32.random(in: .min ... .max)\n        let randomCInt = CInt.random(in: .min ... .max)\n        XCTAssert(\n            (randomUInt32, randomCInt)\n                == IntegerBitPacking.unpackUInt32CInt(IntegerBitPacking.packUInt32CInt(randomUInt32, randomCInt)),\n            \"\\((randomUInt32, randomCInt)) didn't roundtrip\"\n        )\n    }\n\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/MulticastTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport CNIOLinux\nimport NIOCore\nimport NIOPosix\nimport XCTest\n\nfinal class PromiseOnReadHandler: ChannelInboundHandler, Sendable {\n    typealias InboundIn = AddressedEnvelope<ByteBuffer>\n\n    private let promise: EventLoopPromise<InboundIn>\n\n    init(promise: EventLoopPromise<InboundIn>) {\n        self.promise = promise\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.promise.succeed(Self.unwrapInboundIn(data))\n        context.pipeline.syncOperations.removeHandler(context: context, promise: nil)\n    }\n}\n\nfinal class MulticastTest: XCTestCase {\n    private var group: MultiThreadedEventLoopGroup!\n\n    override func setUp() {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.group.syncShutdownGracefully())\n    }\n\n    struct NoSuchInterfaceError: Error {}\n\n    struct MulticastInterfaceMismatchError: Error {}\n\n    struct ReceivedDatagramError: Error {}\n\n    @available(*, deprecated)\n    private func interfaceForAddress(address: String) throws -> NIONetworkInterface {\n        let targetAddress = try SocketAddress(ipAddress: address, port: 0)\n        guard let interface = try System.enumerateInterfaces().lazy.filter({ $0.address == targetAddress }).first else {\n            throw NoSuchInterfaceError()\n        }\n        return interface\n    }\n\n    private func deviceForAddress(address: String) throws -> NIONetworkDevice {\n        let targetAddress = try SocketAddress(ipAddress: address, port: 0)\n        guard let device = try System.enumerateDevices().lazy.filter({ $0.address == targetAddress }).first else {\n            throw NoSuchInterfaceError()\n        }\n        return device\n    }\n\n    @available(*, deprecated)\n    private func bindMulticastChannel(\n        host: String,\n        port: Int,\n        multicastAddress: String,\n        interface: NIONetworkInterface\n    ) -> EventLoopFuture<MulticastChannel> {\n        DatagramBootstrap(group: self.group)\n            .channelOption(.socketOption(.so_reuseaddr), value: 1)\n            .bind(host: host, port: port)\n            .flatMap { channel in\n                let channel = channel as! MulticastChannel\n\n                do {\n                    let multicastAddress = try SocketAddress(\n                        ipAddress: multicastAddress,\n                        port: channel.localAddress!.port!\n                    )\n                    return channel.joinGroup(multicastAddress, interface: interface).map { channel }\n                } catch {\n                    return channel.eventLoop.makeFailedFuture(error)\n                }\n            }.flatMap { (channel: MulticastChannel) -> EventLoopFuture<MulticastChannel> in\n                let provider = channel as! SocketOptionProvider\n\n                switch channel.localAddress! {\n                case .v4:\n                    return provider.setIPMulticastLoop(1).map { channel }\n                case .v6:\n                    return provider.setIPv6MulticastLoop(1).map { channel }\n                case .unixDomainSocket:\n                    preconditionFailure(\"Multicast is meaningless on unix domain sockets\")\n                }\n            }\n    }\n\n    private func bindMulticastChannel(\n        host: String,\n        port: Int,\n        multicastAddress: String,\n        device: NIONetworkDevice\n    ) -> EventLoopFuture<MulticastChannel> {\n        DatagramBootstrap(group: self.group)\n            .channelOption(.socketOption(.so_reuseaddr), value: 1)\n            .bind(host: host, port: port)\n            .flatMap { channel in\n                let channel = channel as! MulticastChannel\n\n                do {\n                    let multicastAddress = try SocketAddress(\n                        ipAddress: multicastAddress,\n                        port: channel.localAddress!.port!\n                    )\n                    return channel.joinGroup(multicastAddress, device: device).map { channel }\n                } catch {\n                    return channel.eventLoop.makeFailedFuture(error)\n                }\n            }.flatMap { (channel: MulticastChannel) -> EventLoopFuture<MulticastChannel> in\n                let provider = channel as! SocketOptionProvider\n\n                switch channel.localAddress! {\n                case .v4:\n                    return provider.setIPMulticastLoop(1).map { channel }\n                case .v6:\n                    return provider.setIPv6MulticastLoop(1).map { channel }\n                case .unixDomainSocket:\n                    preconditionFailure(\"Multicast is meaningless on unix domain sockets\")\n                }\n            }\n    }\n\n    @available(*, deprecated)\n    private func configureSenderMulticastIf(\n        sender: Channel,\n        multicastInterface: NIONetworkInterface\n    ) -> EventLoopFuture<Void> {\n        let provider = sender as! SocketOptionProvider\n\n        switch (sender.localAddress!, multicastInterface.address) {\n        case (.v4, .v4(let addr)):\n            return provider.setIPMulticastIF(addr.address.sin_addr)\n        case (.v6, .v6):\n            return provider.setIPv6MulticastIF(CUnsignedInt(multicastInterface.interfaceIndex))\n        default:\n            XCTFail(\n                \"Cannot join channel bound to \\(sender.localAddress!) to interface at \\(multicastInterface.address)\"\n            )\n            return sender.eventLoop.makeFailedFuture(MulticastInterfaceMismatchError())\n        }\n    }\n\n    private func configureSenderMulticastIf(sender: Channel, multicastDevice: NIONetworkDevice) -> EventLoopFuture<Void>\n    {\n        let provider = sender as! SocketOptionProvider\n\n        switch (sender.localAddress!, multicastDevice.address) {\n        case (.v4, .some(.v4(let addr))):\n            return provider.setIPMulticastIF(addr.address.sin_addr)\n        case (.v6, .some(.v6)):\n            return provider.setIPv6MulticastIF(CUnsignedInt(multicastDevice.interfaceIndex))\n        default:\n            XCTFail(\n                \"Cannot join channel bound to \\(sender.localAddress!) to interface at \\(String(describing: multicastDevice.address))\"\n            )\n            return sender.eventLoop.makeFailedFuture(MulticastInterfaceMismatchError())\n        }\n    }\n\n    @available(*, deprecated)\n    private func leaveMulticastGroup(\n        channel: Channel,\n        multicastAddress: String,\n        interface: NIONetworkInterface\n    ) -> EventLoopFuture<Void> {\n        let channel = channel as! MulticastChannel\n\n        do {\n            let multicastAddress = try SocketAddress(ipAddress: multicastAddress, port: channel.localAddress!.port!)\n            return channel.leaveGroup(multicastAddress, interface: interface)\n        } catch {\n            return channel.eventLoop.makeFailedFuture(error)\n        }\n    }\n\n    private func leaveMulticastGroup(\n        channel: Channel,\n        multicastAddress: String,\n        device: NIONetworkDevice\n    ) -> EventLoopFuture<Void> {\n        let channel = channel as! MulticastChannel\n\n        do {\n            let multicastAddress = try SocketAddress(ipAddress: multicastAddress, port: channel.localAddress!.port!)\n            return channel.leaveGroup(multicastAddress, device: device)\n        } catch {\n            return channel.eventLoop.makeFailedFuture(error)\n        }\n    }\n\n    private func assertDatagramReaches(\n        multicastChannel: Channel,\n        sender: Channel,\n        multicastAddress: SocketAddress,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        let receivedMulticastDatagram = multicastChannel.eventLoop.makePromise(of: AddressedEnvelope<ByteBuffer>.self)\n        XCTAssertNoThrow(\n            try multicastChannel.pipeline.addHandler(PromiseOnReadHandler(promise: receivedMulticastDatagram)).wait()\n        )\n\n        var messageBuffer = sender.allocator.buffer(capacity: 24)\n        messageBuffer.writeStaticString(\"hello, world!\")\n\n        XCTAssertNoThrow(\n            try sender.writeAndFlush(AddressedEnvelope(remoteAddress: multicastAddress, data: messageBuffer)).wait(),\n            file: (file),\n            line: line\n        )\n\n        let receivedDatagram = try assertNoThrowWithValue(\n            receivedMulticastDatagram.futureResult.wait(),\n            file: (file),\n            line: line\n        )\n        XCTAssertEqual(receivedDatagram.remoteAddress, sender.localAddress!)\n        XCTAssertEqual(receivedDatagram.data, messageBuffer)\n    }\n\n    private func assertDatagramDoesNotReach(\n        multicastChannel: Channel,\n        after timeout: TimeAmount,\n        sender: Channel,\n        multicastAddress: SocketAddress,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        let timeoutPromise = multicastChannel.eventLoop.makePromise(of: Void.self)\n        let receivedMulticastDatagram = multicastChannel.eventLoop.makePromise(of: AddressedEnvelope<ByteBuffer>.self)\n        XCTAssertNoThrow(\n            try multicastChannel.pipeline.addHandler(PromiseOnReadHandler(promise: receivedMulticastDatagram)).wait()\n        )\n\n        // If we receive a datagram, or the reader promise fails, we must fail the timeoutPromise.\n        receivedMulticastDatagram.futureResult.map { (_: AddressedEnvelope<ByteBuffer>) in\n            timeoutPromise.fail(ReceivedDatagramError())\n        }.cascadeFailure(to: timeoutPromise)\n\n        var messageBuffer = sender.allocator.buffer(capacity: 24)\n        messageBuffer.writeStaticString(\"hello, world!\")\n\n        XCTAssertNoThrow(\n            try sender.writeAndFlush(AddressedEnvelope(remoteAddress: multicastAddress, data: messageBuffer)).wait(),\n            file: (file),\n            line: line\n        )\n\n        _ = multicastChannel.eventLoop.scheduleTask(in: timeout) { timeoutPromise.succeed(()) }\n        XCTAssertNoThrow(try timeoutPromise.futureResult.wait(), file: (file), line: line)\n    }\n\n    @available(*, deprecated)\n    func testCanJoinBasicMulticastGroupIPv4() throws {\n        let multicastInterface = try assertNoThrowWithValue(self.interfaceForAddress(address: \"127.0.0.1\"))\n        guard multicastInterface.multicastSupported else {\n            // alas, we don't support multicast, let's skip but test the right error is thrown\n\n            XCTAssertThrowsError(\n                try self.bindMulticastChannel(\n                    host: \"0.0.0.0\",\n                    port: 0,\n                    multicastAddress: \"224.0.2.66\",\n                    interface: multicastInterface\n                ).wait()\n            ) { error in\n                if let error = error as? NIOMulticastNotSupportedError {\n                    XCTAssertEqual(NIONetworkDevice(multicastInterface), error.device)\n                } else {\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            }\n            return\n        }\n\n        // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n        // group on the loopback.\n        let listenerChannel: Channel\n        do {\n            listenerChannel = try assertNoThrowWithValue(\n                self.bindMulticastChannel(\n                    host: \"0.0.0.0\",\n                    port: 0,\n                    multicastAddress: \"224.0.2.66\",\n                    interface: multicastInterface\n                ).wait()\n            )\n            // no error, that's great\n        } catch {\n            if error is NIOMulticastNotSupportedError {\n                XCTFail(\"network interface (\\(multicastInterface))) claims we support multicast but: \\(error)\")\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n            return\n        }\n\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"224.0.2.66\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastInterface: multicastInterface).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    @available(*, deprecated)\n    func testCanJoinBasicMulticastGroupIPv6() throws {\n        guard System.supportsIPv6 else {\n            // Skip on non-IPv6 systems\n            return\n        }\n\n        let multicastInterface = try assertNoThrowWithValue(self.interfaceForAddress(address: \"::1\"))\n        guard multicastInterface.multicastSupported else {\n            // alas, we don't support multicast, let's skip but test the right error is thrown\n\n            XCTAssertThrowsError(\n                try self.bindMulticastChannel(\n                    host: \"::1\",\n                    port: 0,\n                    multicastAddress: \"ff12::beeb\",\n                    interface: multicastInterface\n                ).wait()\n            ) { error in\n                if let error = error as? NIOMulticastNotSupportedError {\n                    XCTAssertEqual(NIONetworkDevice(multicastInterface), error.device)\n                } else {\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            }\n            return\n        }\n\n        let listenerChannel: Channel\n        do {\n            // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n            // group on the loopback.\n            listenerChannel = try assertNoThrowWithValue(\n                self.bindMulticastChannel(\n                    host: \"::1\",\n                    port: 0,\n                    multicastAddress: \"ff12::beeb\",\n                    interface: multicastInterface\n                ).wait()\n            )\n        } catch {\n            if error is NIOMulticastNotSupportedError {\n                XCTFail(\"network interface (\\(multicastInterface))) claims we support multicast but: \\(error)\")\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n            return\n        }\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"ff12::beeb\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"::1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastInterface: multicastInterface).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    @available(*, deprecated)\n    func testCanLeaveAnIPv4MulticastGroup() throws {\n        let multicastInterface = try assertNoThrowWithValue(self.interfaceForAddress(address: \"127.0.0.1\"))\n        guard multicastInterface.multicastSupported else {\n            // alas, we don't support multicast, let's skip\n            return\n        }\n\n        // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n        // group on the loopback.\n        let listenerChannel = try assertNoThrowWithValue(\n            self.bindMulticastChannel(\n                host: \"0.0.0.0\",\n                port: 0,\n                multicastAddress: \"224.0.2.66\",\n                interface: multicastInterface\n            ).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"224.0.2.66\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastInterface: multicastInterface).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n\n        // Now we should *leave* the group.\n        XCTAssertNoThrow(\n            try leaveMulticastGroup(\n                channel: listenerChannel,\n                multicastAddress: \"224.0.2.66\",\n                interface: multicastInterface\n            ).wait()\n        )\n        try self.assertDatagramDoesNotReach(\n            multicastChannel: listenerChannel,\n            after: .milliseconds(500),\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    @available(*, deprecated)\n    func testCanLeaveAnIPv6MulticastGroup() throws {\n        guard System.supportsIPv6 else {\n            // Skip on non-IPv6 systems\n            return\n        }\n\n        let multicastInterface = try assertNoThrowWithValue(self.interfaceForAddress(address: \"::1\"))\n        guard multicastInterface.multicastSupported else {\n            // alas, we don't support multicast, let's skip\n            return\n        }\n\n        // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n        // group on the loopback.\n        let listenerChannel = try assertNoThrowWithValue(\n            self.bindMulticastChannel(\n                host: \"::1\",\n                port: 0,\n                multicastAddress: \"ff12::beeb\",\n                interface: multicastInterface\n            ).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"ff12::beeb\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"::1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastInterface: multicastInterface).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n\n        // Now we should *leave* the group.\n        XCTAssertNoThrow(\n            try leaveMulticastGroup(\n                channel: listenerChannel,\n                multicastAddress: \"ff12::beeb\",\n                interface: multicastInterface\n            ).wait()\n        )\n        try self.assertDatagramDoesNotReach(\n            multicastChannel: listenerChannel,\n            after: .milliseconds(500),\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    func testCanJoinBasicMulticastGroupIPv4WithDevice() throws {\n        let multicastDevice = try assertNoThrowWithValue(self.deviceForAddress(address: \"127.0.0.1\"))\n        guard multicastDevice.multicastSupported else {\n            // alas, we don't support multicast, let's skip but test the right error is thrown\n\n            XCTAssertThrowsError(\n                try self.bindMulticastChannel(\n                    host: \"0.0.0.0\",\n                    port: 0,\n                    multicastAddress: \"224.0.2.66\",\n                    device: multicastDevice\n                ).wait()\n            ) { error in\n                if let error = error as? NIOMulticastNotSupportedError {\n                    XCTAssertEqual(multicastDevice, error.device)\n                } else {\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            }\n            return\n        }\n\n        // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n        // group on the loopback.\n        let listenerChannel: Channel\n        do {\n            listenerChannel = try assertNoThrowWithValue(\n                self.bindMulticastChannel(\n                    host: \"0.0.0.0\",\n                    port: 0,\n                    multicastAddress: \"224.0.2.66\",\n                    device: multicastDevice\n                ).wait()\n            )\n            // no error, that's great\n        } catch {\n            if error is NIOMulticastNotSupportedError {\n                XCTFail(\"network interface (\\(multicastDevice)) claims we support multicast but: \\(error)\")\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n            return\n        }\n\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"224.0.2.66\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastDevice: multicastDevice).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    func testCanJoinBasicMulticastGroupIPv6WithDevice() throws {\n        guard System.supportsIPv6 else {\n            // Skip on non-IPv6 systems\n            return\n        }\n\n        let multicastDevice = try assertNoThrowWithValue(self.deviceForAddress(address: \"::1\"))\n        guard multicastDevice.multicastSupported else {\n            // alas, we don't support multicast, let's skip but test the right error is thrown\n\n            XCTAssertThrowsError(\n                try self.bindMulticastChannel(\n                    host: \"::1\",\n                    port: 0,\n                    multicastAddress: \"ff12::beeb\",\n                    device: multicastDevice\n                ).wait()\n            ) { error in\n                if let error = error as? NIOMulticastNotSupportedError {\n                    XCTAssertEqual(multicastDevice, error.device)\n                } else {\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            }\n            return\n        }\n\n        let listenerChannel: Channel\n        do {\n            // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n            // group on the loopback.\n            listenerChannel = try assertNoThrowWithValue(\n                self.bindMulticastChannel(\n                    host: \"::1\",\n                    port: 0,\n                    multicastAddress: \"ff12::beeb\",\n                    device: multicastDevice\n                ).wait()\n            )\n        } catch {\n            if error is NIOMulticastNotSupportedError {\n                XCTFail(\"network interface (\\(multicastDevice)) claims we support multicast but: \\(error)\")\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n            return\n        }\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"ff12::beeb\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"::1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastDevice: multicastDevice).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    func testCanLeaveAnIPv4MulticastGroupWithDevice() throws {\n        let multicastDevice = try assertNoThrowWithValue(self.deviceForAddress(address: \"127.0.0.1\"))\n        guard multicastDevice.multicastSupported else {\n            // alas, we don't support multicast, let's skip\n            return\n        }\n\n        // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n        // group on the loopback.\n        let listenerChannel = try assertNoThrowWithValue(\n            self.bindMulticastChannel(\n                host: \"0.0.0.0\",\n                port: 0,\n                multicastAddress: \"224.0.2.66\",\n                device: multicastDevice\n            ).wait()\n        )\n\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"224.0.2.66\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastDevice: multicastDevice).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n\n        // Now we should *leave* the group.\n        XCTAssertNoThrow(\n            try leaveMulticastGroup(channel: listenerChannel, multicastAddress: \"224.0.2.66\", device: multicastDevice)\n                .wait()\n        )\n        try self.assertDatagramDoesNotReach(\n            multicastChannel: listenerChannel,\n            after: .milliseconds(500),\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n\n    func testCanLeaveAnIPv6MulticastGroupWithDevice() throws {\n        guard System.supportsIPv6 else {\n            // Skip on non-IPv6 systems\n            return\n        }\n\n        let multicastDevice = try assertNoThrowWithValue(self.deviceForAddress(address: \"::1\"))\n        guard multicastDevice.multicastSupported else {\n            // alas, we don't support multicast, let's skip\n            return\n        }\n\n        // We avoid the risk of interference due to our all-addresses bind by only joining this multicast\n        // group on the loopback.\n        let listenerChannel = try assertNoThrowWithValue(\n            self.bindMulticastChannel(\n                host: \"::1\",\n                port: 0,\n                multicastAddress: \"ff12::beeb\",\n                device: multicastDevice\n            ).wait()\n        )\n        defer {\n            XCTAssertNoThrow(try listenerChannel.close().wait())\n        }\n\n        let multicastAddress = try assertNoThrowWithValue(\n            try SocketAddress(ipAddress: \"ff12::beeb\", port: listenerChannel.localAddress!.port!)\n        )\n\n        // Now that we've joined the group, let's send to it.\n        let sender = try assertNoThrowWithValue(\n            DatagramBootstrap(group: self.group)\n                .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                .bind(host: \"::1\", port: 0)\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try sender.close().wait())\n        }\n\n        XCTAssertNoThrow(try configureSenderMulticastIf(sender: sender, multicastDevice: multicastDevice).wait())\n        try self.assertDatagramReaches(\n            multicastChannel: listenerChannel,\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n\n        // Now we should *leave* the group.\n        XCTAssertNoThrow(\n            try leaveMulticastGroup(channel: listenerChannel, multicastAddress: \"ff12::beeb\", device: multicastDevice)\n                .wait()\n        )\n        try self.assertDatagramDoesNotReach(\n            multicastChannel: listenerChannel,\n            after: .milliseconds(500),\n            sender: sender,\n            multicastAddress: multicastAddress\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/NIOFileHandleTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOPosix\nimport XCTest\n\n@testable import NIOCore\n\nfinal class NIOFileHandleTest: XCTestCase {\n    func testOpenCloseWorks() throws {\n        let pipeFDs = try Self.makePipe()\n        let fh1 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: pipeFDs.0)\n        XCTAssertTrue(fh1.isOpen)\n        defer {\n            XCTAssertTrue(fh1.isOpen)\n            XCTAssertNoThrow(try fh1.close())\n            XCTAssertFalse(fh1.isOpen)\n        }\n        let fh2 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: pipeFDs.1)\n        XCTAssertTrue(fh2.isOpen)\n        defer {\n            XCTAssertTrue(fh2.isOpen)\n            XCTAssertNoThrow(try fh2.close())\n            XCTAssertFalse(fh2.isOpen)\n        }\n        XCTAssertTrue(fh1.isOpen)\n        XCTAssertTrue(fh2.isOpen)\n    }\n\n    func testCloseStorm() throws {\n        for _ in 0..<1000 {\n            let pipeFDs = try Self.makePipe()\n            let fh1 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: pipeFDs.0)\n            let fh2 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: pipeFDs.1)\n\n            let threads = 32\n            let threadReadySems = (0..<threads).map { _ in\n                DispatchSemaphore(value: 0)\n            }\n            let threadGoSems = (0..<threads).map { _ in\n                DispatchSemaphore(value: 0)\n            }\n            let allDoneGroup = DispatchGroup()\n\n            for threadID in 0..<threads {\n                DispatchQueue.global().async(group: allDoneGroup) {\n                    threadReadySems[threadID].signal()\n                    threadGoSems[threadID].wait()\n\n                    do {\n                        if threadID % 2 == 0 {\n                            try fh1.close()\n                        } else {\n                            try fh2.close()\n                        }\n                    } catch let error as IOError where error.errnoCode == EBADF {\n                        // expected\n                    } catch {\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                }\n            }\n\n            for threadReadySem in threadReadySems {\n                threadReadySem.wait()\n            }\n            for threadGoSem in threadGoSems {\n                threadGoSem.signal()\n            }\n            allDoneGroup.wait()\n            XCTAssertFalse(fh1.isOpen)\n            XCTAssertFalse(fh2.isOpen)\n        }\n    }\n\n    func testCloseVsUseRace() throws {\n        for _ in 0..<1000 {\n            let pipeFDs = try Self.makePipe()\n            let fh1 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: pipeFDs.0)\n            let fh2 = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: pipeFDs.1)\n\n            let threads = 32\n            let threadReadySems = (0..<threads).map { _ in\n                DispatchSemaphore(value: 0)\n            }\n            let threadGoSems = (0..<threads).map { _ in\n                DispatchSemaphore(value: 0)\n            }\n            let allDoneGroup = DispatchGroup()\n\n            for threadID in 0..<threads {\n                DispatchQueue.global().async(group: allDoneGroup) {\n                    threadReadySems[threadID].signal()\n                    threadGoSems[threadID].wait()\n\n                    do {\n                        switch threadID % 4 {\n                        case 0:\n                            try fh1.close()\n                        case 1:\n                            try fh2.close()\n                        case 2:\n                            try fh1.withUnsafeFileDescriptor { fd in\n                                precondition(fd >= 0)\n                                usleep(.random(in: 0..<10))\n                            }\n                        case 3:\n                            try fh2.withUnsafeFileDescriptor { fd in\n                                precondition(fd >= 0)\n                                usleep(.random(in: 0..<10))\n                            }\n                        default:\n                            fatalError(\"impossible\")\n                        }\n                    } catch let error as IOError where error.errnoCode == EBADF || error.errnoCode == EBUSY {\n                        // expected\n                    } catch {\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                }\n            }\n\n            for threadReadySem in threadReadySems {\n                threadReadySem.wait()\n            }\n            for threadGoSem in threadGoSems {\n                threadGoSem.signal()\n            }\n            allDoneGroup.wait()\n            for fh in [fh1, fh2] {\n                // They may or may not be closed, depends on races above.\n                do {\n                    try fh.close()\n                } catch let error as IOError where error.errnoCode == EBADF {\n                    // expected\n                }\n            }\n            XCTAssertFalse(fh1.isOpen)\n            XCTAssertFalse(fh2.isOpen)\n        }\n    }\n\n    // MARK: - Helpers\n    struct POSIXError: Error {\n        var what: String\n        var errnoCode: CInt\n    }\n\n    private static func makePipe() throws -> (CInt, CInt) {\n        var pipeFDs: [CInt] = [-1, -1]\n        let err = pipeFDs.withUnsafeMutableBufferPointer { pipePtr in\n            pipe(pipePtr.baseAddress!)\n        }\n        guard err == 0 else {\n            throw POSIXError(what: \"pipe\", errnoCode: errno)\n        }\n        return (pipeFDs[0], pipeFDs[1])\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/NIOLoopBoundTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOPosix\nimport XCTest\n\nfinal class NIOLoopBoundTests: XCTestCase {\n    private var loop: EmbeddedEventLoop!\n\n    func testLoopBoundIsSendableWithNonSendableValue() {\n        let nonSendable = NotSendable()\n        let sendable = NIOLoopBound(nonSendable, eventLoop: self.loop)\n        let sendableBox = NIOLoopBoundBox(nonSendable, eventLoop: self.loop)\n\n        XCTAssert(sendable.value === nonSendable)\n        XCTAssert(sendableBox.value === nonSendable)\n\n        sendableBlackhole(sendable)\n        sendableBlackhole(sendableBox)\n    }\n\n    func testLoopBoundBoxCanBeInitialisedWithNilOffLoopAndLaterSetToValue() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let loop = group.any()\n\n        let sendableBox = NIOLoopBoundBox.makeEmptyBox(valueType: NotSendable.self, eventLoop: loop)\n        XCTAssertNoThrow(\n            try loop.submit {\n                sendableBox.value = NotSendable()\n            }.wait()\n        )\n        XCTAssertNoThrow(\n            try loop.submit {\n                XCTAssertNotNil(sendableBox.value)\n            }.wait()\n        )\n    }\n\n    func testLoopBoundBoxCanBeInitialisedWithSendableValueOffLoopAndLaterSetToValue() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let loop = group.any()\n\n        let sendableBox = NIOLoopBoundBox.makeBoxSendingValue(15, as: Int.self, eventLoop: loop)\n        for _ in 0..<(100 - 15) {\n            loop.execute {\n                sendableBox.value += 1\n            }\n        }\n        XCTAssertEqual(\n            100,\n            try loop.submit {\n                sendableBox.value\n            }.wait()\n        )\n    }\n\n    func testLoopBoundBoxCanBeInitialisedWithTakingValueOffLoopAndLaterSetToValue() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        let loop = group.any()\n\n        class NonSendableIntBox {\n            var value: Int\n\n            init(value: Int) {\n                self.value = value\n            }\n        }\n\n        let instance = NonSendableIntBox(value: 15)\n        let sendableBox = NIOLoopBoundBox.makeBoxSendingValue(instance, as: NonSendableIntBox.self, eventLoop: loop)\n        for _ in 0..<(100 - 15) {\n            loop.execute {\n                sendableBox.value.value += 1\n            }\n        }\n        XCTAssertEqual(\n            100,\n            try loop.submit {\n                sendableBox.value.value\n            }.wait()\n        )\n    }\n\n    func testInPlaceMutation() {\n        var loopBound = NIOLoopBound(CoWValue(), eventLoop: loop)\n        XCTAssertTrue(loopBound.value.mutateInPlace())\n\n        let loopBoundBox = NIOLoopBoundBox(CoWValue(), eventLoop: loop)\n        XCTAssertTrue(loopBoundBox.value.mutateInPlace())\n    }\n\n    func testWithValue() {\n        var expectedValue = 0\n        let loopBound = NIOLoopBoundBox(expectedValue, eventLoop: loop)\n        for value in 1...100 {\n            loopBound.withValue { boundValue in\n                XCTAssertEqual(boundValue, expectedValue)\n                boundValue = value\n                expectedValue = value\n            }\n        }\n        XCTAssertEqual(100, loopBound.value)\n    }\n\n    func testWithValueRethrows() {\n        struct TestError: Error {}\n\n        let loopBound = NIOLoopBoundBox(0, eventLoop: loop)\n        XCTAssertThrowsError(\n            try loopBound.withValue { boundValue in\n                XCTAssertEqual(0, boundValue)\n                boundValue = 10\n                throw TestError()\n            }\n        )\n\n        XCTAssertEqual(10, loopBound.value, \"Ensure value is set even if we throw\")\n    }\n\n    // MARK: - Helpers\n    func sendableBlackhole<S: Sendable>(_ sendableThing: S) {}\n\n    // MARK: - Setup/teardown\n    override func setUp() {\n        self.loop = EmbeddedEventLoop()\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.loop?.syncShutdownGracefully())\n        self.loop = nil\n    }\n}\n\nfinal class NotSendable {}\n\n@available(*, unavailable)\nextension NotSendable: Sendable {}\n"
  },
  {
    "path": "Tests/NIOPosixTests/NIOScheduledCallbackTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOCore\nimport NIOEmbedded\nimport NIOPosix\nimport XCTest\n\nprotocol ScheduledCallbackTestRequirements {\n    // Some ELs are backed by an ELG.\n    var loop: (any EventLoop) { get }\n\n    // Some ELs have a manual time ratchet.\n    func advanceTime(by amount: TimeAmount) async throws\n\n    // ELG-backed ELs need to be shutdown via the ELG.\n    func shutdownEventLoop() async throws\n\n    func waitForLoopTick() async throws\n}\n\nfinal class MTELGScheduledCallbackTests: _BaseScheduledCallbackTests {\n    struct Requirements: ScheduledCallbackTestRequirements {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        var loop: (any EventLoop) { self.group.next() }\n\n        func advanceTime(by amount: TimeAmount) async throws {\n            try await Task.sleep(nanoseconds: UInt64(amount.nanoseconds))\n        }\n\n        func shutdownEventLoop() async throws {\n            try await self.group.shutdownGracefully()\n        }\n\n        func waitForLoopTick() async throws {\n            try await self.loop.submit {}.get()\n        }\n    }\n\n    override func setUp() async throws {\n        self.requirements = Requirements()\n    }\n}\n\nfinal class NIOAsyncTestingEventLoopScheduledCallbackTests: _BaseScheduledCallbackTests {\n    struct Requirements: ScheduledCallbackTestRequirements {\n        let _loop = NIOAsyncTestingEventLoop()\n        var loop: (any EventLoop) { self._loop }\n\n        func advanceTime(by amount: TimeAmount) async throws {\n            await self._loop.advanceTime(by: amount)\n        }\n\n        func shutdownEventLoop() async throws {\n            await self._loop.shutdownGracefully()\n        }\n\n        func waitForLoopTick() async throws {\n            try await self._loop.executeInContext {}\n        }\n    }\n\n    override func setUp() async throws {\n        self.requirements = Requirements()\n    }\n}\n\nfinal class IsolatedEventLoopScheduledCallbackTests: XCTestCase {\n    struct Requirements: ScheduledCallbackTestRequirements {\n        let _loop = EmbeddedEventLoop()\n        var loop: (any EventLoop) { self._loop }\n\n        func advanceTime(by amount: TimeAmount) {\n            self._loop.advanceTime(by: amount)\n        }\n\n        func shutdownEventLoop() {\n            try! self._loop.syncShutdownGracefully()\n        }\n\n        func waitForLoopTick() {}\n    }\n\n    var requirements: Requirements! = nil\n    var loop: (any EventLoop) { self.requirements.loop }\n\n    func advanceTime(by amount: TimeAmount) {\n        self.requirements.advanceTime(by: amount)\n    }\n\n    func shutdownEventLoop() {\n        self.requirements.shutdownEventLoop()\n    }\n\n    override func setUp() {\n        self.requirements = Requirements()\n    }\n\n    func testScheduledCallbackNotExecutedBeforeDeadline() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        handler.assert(callbackCount: 0, cancelCount: 0)\n\n        self.advanceTime(by: .microseconds(1))\n        handler.assert(callbackCount: 0, cancelCount: 0)\n    }\n\n    func testScheduledCallbackExecutedAtDeadline() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        self.advanceTime(by: .milliseconds(1))\n        handler.assert(callbackCount: 1, cancelCount: 0)\n    }\n\n    func testMultipleScheduledCallbacksUsingSameHandler() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n\n        self.advanceTime(by: .milliseconds(1))\n        handler.assert(callbackCount: 2, cancelCount: 0)\n\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(2), handler: handler)\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(3), handler: handler)\n\n        self.advanceTime(by: .milliseconds(3))\n        handler.assert(callbackCount: 4, cancelCount: 0)\n    }\n\n    func testCancelExecutesCancellationCallback() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        scheduledCallback.cancel()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testCancelAfterDeadlineDoesNotExecutesCancellationCallback() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        self.advanceTime(by: .milliseconds(1))\n        scheduledCallback.cancel()\n        self.requirements.waitForLoopTick()\n        handler.assert(callbackCount: 1, cancelCount: 0)\n    }\n\n    func testCancelAfterCancelDoesNotCallCancellationCallbackAgain() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        scheduledCallback.cancel()\n        scheduledCallback.cancel()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testCancelAfterShutdownDoesNotCallCancellationCallbackAgain() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        self.shutdownEventLoop()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n\n        scheduledCallback.cancel()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testShutdownCancelsOutstandingScheduledCallbacks() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .hours(1), handler: handler)\n        self.shutdownEventLoop()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testShutdownDoesNotCancelCancelledCallbacksAgain() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        let handle = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        handle.cancel()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n\n        self.shutdownEventLoop()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testShutdownDoesNotCancelPastCallbacks() throws {\n        let handler = NonSendableMockScheduledCallbackHandler()\n\n        _ = try self.loop.assumeIsolated().scheduleCallback(in: .milliseconds(1), handler: handler)\n        self.advanceTime(by: .milliseconds(1))\n        handler.assert(callbackCount: 1, cancelCount: 0)\n\n        self.shutdownEventLoop()\n        handler.assert(callbackCount: 1, cancelCount: 0)\n    }\n}\n\nclass _BaseScheduledCallbackTests: XCTestCase {\n    // EL-specific test requirements.\n    var requirements: (any ScheduledCallbackTestRequirements)! = nil\n\n    override func setUp() async throws {\n        try XCTSkipIf(type(of: self) == _BaseScheduledCallbackTests.self, \"This is the abstract base class\")\n        preconditionFailure(\"Subclass should implement setup and initialise EL-specific `self.requirements`\")\n    }\n}\n\n// Provide pass through computed properties to the EL-specific test requirements.\nextension _BaseScheduledCallbackTests {\n    var loop: (any EventLoop) { self.requirements.loop }\n\n    func advanceTime(by amount: TimeAmount) async throws {\n        try await self.requirements.advanceTime(by: amount)\n        try await self.requirements.waitForLoopTick()\n    }\n\n    func shutdownEventLoop() async throws {\n        try await self.requirements.shutdownEventLoop()\n    }\n}\n\n// The tests, abstracted over any of the event loops.\nextension _BaseScheduledCallbackTests {\n\n    func testScheduledCallbackNotExecutedBeforeDeadline() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        // Use a long deadline so that even if the short sleep overshoots on a loaded CI machine,\n        // it cannot reach the callback deadline.\n        _ = try self.loop.scheduleCallback(in: .hours(1), handler: handler)\n        handler.assert(callbackCount: 0, cancelCount: 0)\n\n        try await self.advanceTime(by: .microseconds(1))\n        handler.assert(callbackCount: 0, cancelCount: 0)\n    }\n\n    func testScheduledCallbackExecutedAtDeadline() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        _ = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handler)\n        try await self.advanceTime(by: .milliseconds(1))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        handler.assert(callbackCount: 1, cancelCount: 0)\n    }\n\n    func testMultipleScheduledCallbacksUsingSameHandler() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        _ = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handler)\n        _ = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handler)\n\n        try await self.advanceTime(by: .milliseconds(1))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        handler.assert(callbackCount: 2, cancelCount: 0)\n\n        _ = try self.loop.scheduleCallback(in: .milliseconds(2), handler: handler)\n        _ = try self.loop.scheduleCallback(in: .milliseconds(3), handler: handler)\n\n        try await self.advanceTime(by: .milliseconds(3))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        handler.assert(callbackCount: 4, cancelCount: 0)\n    }\n\n    func testMultipleScheduledCallbacksUsingDifferentHandlers() async throws {\n        let handlerA = MockScheduledCallbackHandler()\n        let handlerB = MockScheduledCallbackHandler()\n\n        _ = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handlerA)\n        _ = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handlerB)\n\n        try await self.advanceTime(by: .milliseconds(1))\n        try await handlerA.waitForCallback(timeout: .seconds(1))\n        try await handlerB.waitForCallback(timeout: .seconds(1))\n        handlerA.assert(callbackCount: 1, cancelCount: 0)\n        handlerB.assert(callbackCount: 1, cancelCount: 0)\n    }\n\n    func testCancelExecutesCancellationCallback() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.scheduleCallback(in: .hours(1), handler: handler)\n        scheduledCallback.cancel()\n        try await self.requirements.waitForLoopTick()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testCancelAfterDeadlineDoesNotExecutesCancellationCallback() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handler)\n        try await self.advanceTime(by: .milliseconds(1))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        scheduledCallback.cancel()\n        try await self.requirements.waitForLoopTick()\n        handler.assert(callbackCount: 1, cancelCount: 0)\n    }\n\n    func testCancelAfterCancelDoesNotCallCancellationCallbackAgain() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.scheduleCallback(in: .hours(1), handler: handler)\n        scheduledCallback.cancel()\n        try await self.requirements.waitForLoopTick()\n        scheduledCallback.cancel()\n        try await self.requirements.waitForLoopTick()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testCancelAfterShutdownDoesNotCallCancellationCallbackAgain() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        let scheduledCallback = try self.loop.scheduleCallback(in: .hours(1), handler: handler)\n        try await self.shutdownEventLoop()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n\n        scheduledCallback.cancel()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testShutdownCancelsOutstandingScheduledCallbacks() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        _ = try self.loop.scheduleCallback(in: .hours(1), handler: handler)\n        try await self.shutdownEventLoop()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testShutdownDoesNotCancelCancelledCallbacksAgain() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        let handle = try self.loop.scheduleCallback(in: .hours(1), handler: handler)\n        handle.cancel()\n        try await self.requirements.waitForLoopTick()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n\n        try await self.shutdownEventLoop()\n        handler.assert(callbackCount: 0, cancelCount: 1)\n    }\n\n    func testShutdownDoesNotCancelPastCallbacks() async throws {\n        let handler = MockScheduledCallbackHandler()\n\n        _ = try self.loop.scheduleCallback(in: .milliseconds(1), handler: handler)\n        try await self.advanceTime(by: .milliseconds(1))\n        try await handler.waitForCallback(timeout: .seconds(1))\n        handler.assert(callbackCount: 1, cancelCount: 0)\n\n        try await self.shutdownEventLoop()\n        handler.assert(callbackCount: 1, cancelCount: 0)\n    }\n}\n\nprivate final class MockScheduledCallbackHandler: NIOScheduledCallbackHandler, Sendable {\n    let callbackCount = ManagedAtomic(0)\n    let cancelCount = ManagedAtomic(0)\n\n    let callbackStream: AsyncStream<Void>\n    private let callbackStreamContinuation: AsyncStream<Void>.Continuation\n\n    init() {\n        (self.callbackStream, self.callbackStreamContinuation) = AsyncStream.makeStream(of: Void.self)\n    }\n\n    deinit {\n        self.callbackStreamContinuation.finish()\n    }\n\n    func handleScheduledCallback(eventLoop: some EventLoop) {\n        self.callbackCount.wrappingIncrement(by: 1, ordering: .sequentiallyConsistent)\n        self.callbackStreamContinuation.yield()\n    }\n\n    func didCancelScheduledCallback(eventLoop: some EventLoop) {\n        self.cancelCount.wrappingIncrement(by: 1, ordering: .sequentiallyConsistent)\n    }\n\n    func assert(callbackCount: Int, cancelCount: Int, file: StaticString = #filePath, line: UInt = #line) {\n        XCTAssertEqual(\n            self.callbackCount.load(ordering: .sequentiallyConsistent),\n            callbackCount,\n            \"Unexpected callback count\",\n            file: file,\n            line: line\n        )\n        XCTAssertEqual(\n            self.cancelCount.load(ordering: .sequentiallyConsistent),\n            cancelCount,\n            \"Unexpected cancel count\",\n            file: file,\n            line: line\n        )\n    }\n\n    func waitForCallback(timeout: TimeAmount, file: StaticString = #filePath, line: UInt = #line) async throws {\n        try await XCTWithTimeout(timeout, file: file, line: line) { await self.callbackStream.first { _ in true } }\n    }\n}\n\nprivate final class NonSendableMockScheduledCallbackHandler: NIOScheduledCallbackHandler {\n    private(set) var callbackCount = 0\n    private(set) var cancelCount = 0\n\n    func handleScheduledCallback(eventLoop: some EventLoop) {\n        self.callbackCount += 1\n    }\n\n    func didCancelScheduledCallback(eventLoop: some EventLoop) {\n        self.cancelCount += 1\n    }\n\n    func assert(callbackCount: Int, cancelCount: Int, file: StaticString = #filePath, line: UInt = #line) {\n        XCTAssertEqual(\n            self.callbackCount,\n            callbackCount,\n            \"Unexpected callback count\",\n            file: file,\n            line: line\n        )\n        XCTAssertEqual(\n            self.cancelCount,\n            cancelCount,\n            \"Unexpected cancel count\",\n            file: file,\n            line: line\n        )\n    }\n}\n\n/// This function exists because there's no nice way of waiting in tests for something to happen in the handler\n/// without an arbitrary sleep.\n///\n/// Other options include setting `XCTestCase.allowedExecutionTime` in `setup()` but this doesn't work well because\n/// (1), it rounds up to the nearest minute; and (2), it doesn't seem to work reliably.\n///\n/// Another option is to install a timebomb in `XCTestCase.setup()` that will fail the test. This works, but you\n/// don't get any information on where the test was when it fails.\n///\n/// Alternatively, one can use expectations, but these cannot be awaited more than once so won't work for tests where\n/// the same handler is used to schedule multiple callbacks.\n///\n/// This function is probably a good balance of pragmatism and clarity.\nfunc XCTWithTimeout<Result>(\n    _ timeout: TimeAmount,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    operation: @escaping @Sendable () async throws -> Result\n) async throws -> Result where Result: Sendable {\n    do {\n        return try await withTimeout(timeout, operation: operation)\n    } catch is CancellationError {\n        XCTFail(\"Timed out after \\(timeout)\", file: file, line: line)\n        throw CancellationError()\n    }\n}\n\nfunc withTimeout<Result>(\n    _ timeout: TimeAmount,\n    operation: @escaping @Sendable () async throws -> Result\n) async throws -> Result where Result: Sendable {\n    try await withThrowingTaskGroup(of: Result.self) { group in\n        group.addTask {\n            try await Task.sleep(nanoseconds: UInt64(timeout.nanoseconds))\n            throw CancellationError()\n        }\n        group.addTask(operation: operation)\n        let result = try await group.next()!\n        group.cancelAll()\n        return result\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/NIOThreadPoolTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOEmbedded\nimport Testing\n\n@testable import NIOPosix\n\n@Suite(\"NIOThreadPoolTest\")\nclass NIOThreadPoolTest {\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testThreadNamesAreSetUp() {\n        let numberOfThreads = 11\n        let pool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        pool.start()\n        defer {\n            #expect(throws: Never.self) {\n                try pool.syncShutdownGracefully()\n            }\n        }\n\n        let allThreadNames = NIOLockedValueBox<Set<String>>([])\n        let threadNameCollectionSem = DispatchSemaphore(value: 0)\n        let threadBlockingSem = DispatchSemaphore(value: 0)\n\n        // let's use up all the threads\n        for i in (0..<numberOfThreads) {\n            pool.submit { s in\n                switch s {\n                case .cancelled:\n                    Issue.record(\"work item \\(i) cancelled\")\n                case .active:\n                    allThreadNames.withLockedValue {\n                        $0.formUnion([NIOThread.currentThreadName ?? \"n/a\"])\n                    }\n                    threadNameCollectionSem.signal()\n                }\n                threadBlockingSem.wait()\n            }\n        }\n\n        // now, let's wait for all the threads to have done their work\n        for _ in (0..<numberOfThreads) {\n            threadNameCollectionSem.wait()\n        }\n        // and finally, let them exit\n        for _ in (0..<numberOfThreads) {\n            threadBlockingSem.signal()\n        }\n\n        let localAllThreads = allThreadNames.withLockedValue { $0 }\n        for threadNumber in (0..<numberOfThreads) {\n            #expect(localAllThreads.contains(\"TP-#\\(threadNumber)\"), Comment(rawValue: \"\\(localAllThreads)\"))\n        }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testThreadPoolStartsMultipleTimes() async throws {\n        let numberOfThreads = 1\n        let pool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        pool.start()\n\n        await withTaskGroup(of: Void.self) { group in\n            // The lock here is arguably redundant with the dispatchgroup, but let's make\n            // this test thread-safe even if something unexpected happens\n            let threadOne: NIOLockedValueBox<UInt?> = NIOLockedValueBox(UInt?.none)\n            let threadTwo: NIOLockedValueBox<UInt?> = NIOLockedValueBox(UInt?.none)\n\n            group.addTask {\n                await withCheckedContinuation { continuation in\n                    pool.submit { s in\n                        precondition(s == .active)\n                        threadOne.withLockedValue { threadOne in\n                            #expect(threadOne == nil)\n                            threadOne = NIOThread.currentThreadID\n                        }\n                        continuation.resume()\n                    }\n                }\n            }\n\n            // Now start the thread pool again. This must not destroy existing threads, so our thread should be the same.\n            pool.start()\n            group.addTask {\n                await withCheckedContinuation { continuation in\n                    pool.submit { s in\n                        precondition(s == .active)\n                        threadTwo.withLockedValue { threadTwo in\n                            #expect(threadTwo == nil)\n                            threadTwo = NIOThread.currentThreadID\n                        }\n                        continuation.resume()\n                    }\n                }\n            }\n\n            await group.waitForAll()\n\n            #expect(threadOne.withLockedValue { $0 } != nil)\n            #expect(threadTwo.withLockedValue { $0 } != nil)\n            #expect(threadOne.withLockedValue { $0 } == threadTwo.withLockedValue { $0 })\n        }\n\n        await #expect(throws: Never.self) { try await pool.shutdownGracefully() }\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAsyncThreadPool() async throws {\n        let numberOfThreads = 1\n        let pool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        pool.start()\n        do {\n            let hitCount = ManagedAtomic(false)\n            try await pool.runIfActive {\n                hitCount.store(true, ordering: .relaxed)\n            }\n            #expect(hitCount.load(ordering: .relaxed) == true)\n        } catch {}\n        try await pool.shutdownGracefully()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAsyncThreadPoolErrorPropagation() async throws {\n        struct ThreadPoolError: Error {}\n        let numberOfThreads = 1\n        let pool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        pool.start()\n        do {\n            try await pool.runIfActive {\n                throw ThreadPoolError()\n            }\n            Issue.record(\"Should not get here as closure sent to runIfActive threw an error\")\n        } catch {\n            #expect(error as? ThreadPoolError != nil, \"Error thrown should be of type ThreadPoolError\")\n        }\n        try await pool.shutdownGracefully()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAsyncThreadPoolNotActiveError() async throws {\n        struct ThreadPoolError: Error {}\n        let numberOfThreads = 1\n        let pool = NIOThreadPool(numberOfThreads: numberOfThreads)\n        do {\n            try await pool.runIfActive {\n                throw ThreadPoolError()\n            }\n            Issue.record(\"Should not get here as thread pool isn't active\")\n        } catch {\n            #expect(\n                error as? CancellationError != nil,\n                \"Error thrown should be of type CancellationError\"\n            )\n        }\n        try await pool.shutdownGracefully()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAsyncThreadPoolCancellation() async throws {\n        let pool = NIOThreadPool(numberOfThreads: 1)\n        pool.start()\n\n        await withThrowingTaskGroup(of: Void.self) { group in\n            group.cancelAll()\n            group.addTask {\n                try await pool.runIfActive {\n                    _ = Issue.record(\"Should be cancelled before executed\")\n                }\n            }\n\n            do {\n                try await group.waitForAll()\n                Issue.record(\"Expected CancellationError to be thrown\")\n            } catch {\n                #expect(error is CancellationError)\n            }\n        }\n\n        try await pool.shutdownGracefully()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test\n    func testAsyncShutdownWorks() async throws {\n        let threadPool = NIOThreadPool(numberOfThreads: 17)\n        let eventLoop = NIOAsyncTestingEventLoop()\n\n        threadPool.start()\n        try await threadPool.shutdownGracefully()\n\n        let future: EventLoopFuture = threadPool.runIfActive(eventLoop: eventLoop) {\n            Issue.record(\"This shouldn't run because the pool is shutdown.\")\n        }\n\n        await #expect(throws: (any Error).self) {\n            try await future.get()\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/NIOTransportAccessibleChannelCoreTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2026 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore  // NOTE: Not @testable import here -- testing public API surface.\nimport NIOEmbedded\nimport NIOPosix  // NOTE: Not @testable import here -- testing public API surface.\nimport Testing\n\n@Suite struct NIOTransportAccessibleChannelCoreTests {\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test func testUnderlyingSocketAccessForSocketBasedChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { #expect(throws: Never.self) { try group.syncShutdownGracefully() } }\n        let channel = try DatagramBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).wait()\n        defer { #expect(throws: Never.self) { try channel.close().wait() } }\n\n        // We don't expect users to do this runtime check, but test the channel we got back from bootstrap conforms.\n        #expect(channel is any NIOTransportAccessibleChannelCore)\n        #expect(channel is any NIOTransportAccessibleChannelCore<NIOBSDSocket.Handle>)\n        #expect(channel is any NIOTransportAccessibleChannelCore<Any> == false)\n\n        // Here we try the public API use, in various flavours.\n        try channel.eventLoop.submit {\n            let syncOps = channel.pipeline.syncOperations\n\n            // Calling without explicit transport type runs closure if body inefers correct transport type.\n            try #expect(syncOps.withUnsafeTransportIfAvailable { fd in fd != NIOBSDSocket.invalidHandle } == true)\n            try #expect(syncOps.withUnsafeTransportIfAvailable { $0 != NIOBSDSocket.invalidHandle } == true)\n\n            // Calling with explicit correct transport type runs closure.\n            try #expect(syncOps.withUnsafeTransportIfAvailable(of: NIOBSDSocket.Handle.self) { _ in 42 } == 42)\n            try #expect(syncOps.withUnsafeTransportIfAvailable { (_: NIOBSDSocket.Handle) in 42 } == 42)\n\n            // Calling with explicit incorrect transport type does not run closure.\n            try #expect(syncOps.withUnsafeTransportIfAvailable(of: String.self) { _ in 42 } == nil)\n            try #expect(syncOps.withUnsafeTransportIfAvailable { (_: String) in 42 } == nil)\n\n            // Calling with explicit Any transport type does not run closure.\n            try #expect(syncOps.withUnsafeTransportIfAvailable(of: Any.self) { _ in 42 } == nil)\n            try #expect(syncOps.withUnsafeTransportIfAvailable { (_: Any) in 42 } == nil)\n\n            // Calling without explicit transport type does not run closure, even if body doesn't use transport.\n            try #expect(syncOps.withUnsafeTransportIfAvailable { 42 } == nil)\n\n            // Fun aside: What is the resolved type of the above function and why does it allow ignoring closure param?\n            // Even more fun: This test crashes when compiled in release mode, but only in Swift 6.2.\n            #if !(swift(>=6.2) && swift(<6.3))\n            try #expect(syncOps.withUnsafeTransportIfAvailable { $0.self } == nil)\n            #endif\n            // Answer: `$0: any (~Copyable & ~Escapable).Type`\n\n            // Calling without explicit transport type does not run closure, even if body uses compatible literal value.\n            try #expect(syncOps.withUnsafeTransportIfAvailable { transport in transport != -1 } == nil)\n        }.wait()\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test func testUnderlyingTransportForUnsupportedChannels() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { #expect(throws: Never.self) { try group.syncShutdownGracefully() } }\n        let channel = EmbeddedChannel()\n        defer { #expect(throws: Never.self) { try channel.close().wait() } }\n\n        #expect(channel is any NIOTransportAccessibleChannelCore == false)\n\n        // Calling the public API will never run the closure -- we cannot specify a type to pass the runtime check.\n        let syncOps = channel.pipeline.syncOperations\n        try #expect(syncOps.withUnsafeTransportIfAvailable { 42 } == nil)\n        try #expect(syncOps.withUnsafeTransportIfAvailable(of: Any.self) { _ in 42 } == nil)\n        try #expect(syncOps.withUnsafeTransportIfAvailable(of: CInt.self) { _ in 42 } == nil)\n        try #expect(syncOps.withUnsafeTransportIfAvailable(of: type(of: STDOUT_FILENO).self) { _ in 42 } == nil)\n    }\n\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    @Test func testUnderlyingTransportConformanceForExpectedChannels() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { #expect(throws: Never.self) { try group.syncShutdownGracefully() } }\n\n        // SeverSocketChannel -- yep.\n        let serverChannel = try ServerBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).wait()\n        defer { #expect(throws: Never.self) { try serverChannel.close().wait() } }\n        #expect(serverChannel is any NIOTransportAccessibleChannelCore)\n        #expect(serverChannel is any NIOTransportAccessibleChannelCore<NIOBSDSocket.Handle>)\n\n        // SocketChannel -- yep.\n        let clientChannel = try ClientBootstrap(group: group).connect(to: serverChannel.localAddress!).wait()\n        defer { #expect(throws: Never.self) { try clientChannel.close().wait() } }\n        #expect(clientChannel is any NIOTransportAccessibleChannelCore)\n        #expect(clientChannel is any NIOTransportAccessibleChannelCore<NIOBSDSocket.Handle>)\n\n        // DatagramChannel -- yep.\n        let datagramChannel = try DatagramBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).wait()\n        defer { #expect(throws: Never.self) { try datagramChannel.close().wait() } }\n        #expect(datagramChannel is any NIOTransportAccessibleChannelCore)\n        #expect(datagramChannel is any NIOTransportAccessibleChannelCore<NIOBSDSocket.Handle>)\n\n        // PipeChannel -- yep.\n        let pipeChannel = try NIOPipeBootstrap(group: group).takingOwnershipOfDescriptor(output: STDOUT_FILENO).wait()\n        defer { #expect(throws: Never.self) { try pipeChannel.close().wait() } }\n        #expect(pipeChannel is any NIOTransportAccessibleChannelCore)\n        #expect(pipeChannel is any NIOTransportAccessibleChannelCore<NIOBSDSocket.PipeHandle>)\n\n        // EmbeddedChannel -- nope.\n        let embeddedChannel = EmbeddedChannel()\n        defer { #expect(throws: Never.self) { try embeddedChannel.close().wait() } }\n        #expect(embeddedChannel is any NIOTransportAccessibleChannelCore == false)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/NonBlockingFileIOTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass NonBlockingFileIOTest: XCTestCase {\n    private var group: EventLoopGroup!\n    private var eventLoop: EventLoop!\n    private var allocator: ByteBufferAllocator!\n    private var fileIO: NonBlockingFileIO!\n    private var threadPool: NIOThreadPool!\n\n    override func setUp() {\n        super.setUp()\n        self.allocator = ByteBufferAllocator()\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        self.threadPool = NIOThreadPool(numberOfThreads: 6)\n        self.threadPool.start()\n        self.fileIO = NonBlockingFileIO(threadPool: threadPool)\n        self.eventLoop = self.group.next()\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.group?.syncShutdownGracefully())\n        XCTAssertNoThrow(try self.threadPool?.syncShutdownGracefully())\n        self.group = nil\n        self.eventLoop = nil\n        self.allocator = nil\n        self.threadPool = nil\n        self.fileIO = nil\n        super.tearDown()\n    }\n\n    struct Counter: Sendable {\n        private let _value: NIOLockedValueBox<Int>\n\n        init(_ initialValue: Int) {\n            self._value = NIOLockedValueBox(initialValue)\n        }\n\n        var value: Int {\n            get {\n                self._value.withLockedValue { $0 }\n            }\n            nonmutating set {\n                self._value.withLockedValue { $0 = newValue }\n            }\n        }\n\n        func increment(by delta: Int = 1) {\n            self._value.withLockedValue { $0 += delta }\n        }\n    }\n\n    func testBasicFileIOWorks() throws {\n        let content = \"hello\"\n        try withTemporaryFile(content: content) { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 5)\n            var buf = try self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(content.utf8.count, buf.readableBytes)\n            XCTAssertEqual(content, buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testOffsetWorks() throws {\n        let content = \"hello\"\n        try withTemporaryFile(content: content) { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 3, endIndex: 5)\n            var buf = try self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(2, buf.readableBytes)\n            XCTAssertEqual(\"lo\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testOffsetBeyondEOF() throws {\n        let content = \"hello\"\n        try withTemporaryFile(content: content) { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 3000, endIndex: 3001)\n            var buf = try self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(0, buf.readableBytes)\n            XCTAssertEqual(\"\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testEmptyReadWorks() throws {\n        try withTemporaryFile { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 0)\n            let buf = try self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(0, buf.readableBytes)\n        }\n    }\n\n    func testReadingShortWorks() throws {\n        let content = \"hello\"\n        try withTemporaryFile(content: \"hello\") { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 10)\n            var buf = try self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(content.utf8.count, buf.readableBytes)\n            XCTAssertEqual(content, buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testDoesNotBlockTheThreadOrEventLoop() throws {\n        var innerError: Error? = nil\n        try withPipe { readFH, writeFH in\n            let bufferFuture = self.fileIO.read(\n                fileHandle: readFH,\n                byteCount: 10,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            )\n\n            do {\n                try self.eventLoop.submit {\n                    try writeFH.withUnsafeFileDescriptor { writeFD in\n                        _ = try Posix.write(descriptor: writeFD, pointer: \"X\", size: 1)\n                    }\n                    try writeFH.close()\n                }.wait()\n                var buf = try bufferFuture.wait()\n                XCTAssertEqual(1, buf.readableBytes)\n                XCTAssertEqual(\"X\", buf.readString(length: buf.readableBytes))\n            } catch {\n                innerError = error\n            }\n            return [readFH]\n        }\n        XCTAssertNil(innerError)\n    }\n\n    func testGettingErrorWhenEventLoopGroupIsShutdown() throws {\n        self.threadPool.shutdownGracefully(queue: .global()) { err in\n            XCTAssertNil(err)\n        }\n\n        try withPipe { readFH, writeFH in\n            XCTAssertThrowsError(\n                try self.fileIO.read(\n                    fileHandle: readFH,\n                    byteCount: 1,\n                    allocator: self.allocator,\n                    eventLoop: self.eventLoop\n                ).wait()\n            ) { error in\n                XCTAssertTrue(error is NIOThreadPoolError.ThreadPoolInactive)\n            }\n            return [readFH, writeFH]\n        }\n    }\n\n    func testChunkReadingWorks() throws {\n        let content = \"hello\"\n        let contentBytes = Array(content.utf8)\n        let numCalls = Counter(0)\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 5)\n            try self.fileIO.readChunked(\n                fileRegion: fr,\n                chunkSize: 1,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                XCTAssertEqual(1, buf.readableBytes)\n                XCTAssertEqual(contentBytes[numCalls.value], buf.readBytes(length: 1)?.first!)\n                numCalls.increment()\n                return eventLoop!.makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(content.utf8.count, numCalls.value)\n    }\n\n    func testChunkReadingCanBeAborted() throws {\n        enum DummyError: Error { case dummy }\n        let content = \"hello\"\n        let contentBytes = Array(content.utf8)\n        let numCalls = Counter(0)\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 5)\n            XCTAssertThrowsError(\n                try self.fileIO.readChunked(\n                    fileRegion: fr,\n                    chunkSize: 1,\n                    allocator: self.allocator,\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buf in\n                    var buf = buf\n                    XCTAssertTrue(eventLoop!.inEventLoop)\n                    XCTAssertEqual(1, buf.readableBytes)\n                    XCTAssertEqual(contentBytes[numCalls.value], buf.readBytes(length: 1)?.first!)\n                    numCalls.increment()\n                    return eventLoop!.makeFailedFuture(DummyError.dummy)\n                }.wait()\n            ) { error in\n                XCTAssertEqual(.dummy, error as? DummyError)\n            }\n        }\n        XCTAssertEqual(1, numCalls.value)\n    }\n\n    func testChunkReadingWorksForIncrediblyLongChain() throws {\n        let content = String(repeating: \"X\", count: 20 * 1024)\n        let numCalls = Counter(0)\n        let expectedByte = content.utf8.first!\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            try self.fileIO.readChunked(\n                fileHandle: fileHandle,\n                fromOffset: 0,\n                byteCount: content.utf8.count,\n                chunkSize: 1,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                XCTAssertEqual(1, buf.readableBytes)\n                XCTAssertEqual(expectedByte, buf.readableBytesView.first)\n                numCalls.increment()\n                return eventLoop!.makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(content.utf8.count, numCalls.value)\n    }\n\n    func testReadingDifferentChunkSize() throws {\n        let content = \"0123456789\"\n        let numCalls = Counter(0)\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: content.utf8.count)\n            try self.fileIO.readChunked(\n                fileRegion: fr,\n                chunkSize: 2,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                XCTAssertEqual(2, buf.readableBytes)\n                let calls = numCalls.value\n                XCTAssertEqual(Array(\"\\(calls*2)\\(calls*2 + 1)\".utf8), buf.readBytes(length: 2)!)\n                numCalls.increment()\n                return eventLoop!.makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(content.utf8.count / 2, numCalls.value)\n    }\n\n    func testReadDoesNotReadShort() throws {\n        var innerError: Error? = nil\n        try withPipe { readFH, writeFH in\n            let bufferFuture = self.fileIO.read(\n                fileHandle: readFH,\n                byteCount: 10,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            )\n            do {\n                for i in 0..<10 {\n                    // this construction will cause 'read' to repeatedly return with 1 byte read\n                    try self.eventLoop.scheduleTask(in: .milliseconds(50)) {\n                        try writeFH.withUnsafeFileDescriptor { writeFD in\n                            _ = try Posix.write(descriptor: writeFD, pointer: \"\\(i)\", size: 1)\n                        }\n                    }.futureResult.wait()\n                }\n                try writeFH.close()\n\n                var buf = try bufferFuture.wait()\n                XCTAssertEqual(10, buf.readableBytes)\n                XCTAssertEqual(\"0123456789\", buf.readString(length: buf.readableBytes))\n            } catch {\n                innerError = error\n            }\n            return [readFH]\n        }\n        XCTAssertNil(innerError)\n    }\n\n    func testChunkReadingWhereByteCountIsNotAChunkSizeMultiplier() throws {\n        let content = \"prefix-12345-suffix\"\n        let allBytesActual = NIOLockedValueBox(\"\")\n        let allBytesExpected = String(content.dropFirst(7).dropLast(7))\n        let numCalls = Counter(0)\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 7, endIndex: 12)\n            try self.fileIO.readChunked(\n                fileRegion: fr,\n                chunkSize: 3,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                allBytesActual.withLockedValue {\n                    $0 += buf.readString(length: buf.readableBytes) ?? \"WRONG\"\n                }\n                numCalls.increment()\n                return eventLoop!.makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(allBytesExpected, allBytesActual.withLockedValue { $0 })\n        XCTAssertEqual(2, numCalls.value)\n    }\n\n    func testReadMoreThanIntMaxBytesDoesntThrow() throws {\n        try XCTSkipIf(MemoryLayout<size_t>.size == MemoryLayout<UInt32>.size)\n        // here we try to read way more data back from the file than it contains but it serves the purpose\n        // even on a small file the OS will return EINVAL if you try to read > INT_MAX bytes\n        try withTemporaryFile(\n            content: \"some-dummy-content\",\n            { (filehandle, path) -> Void in\n                let content = try self.fileIO.read(\n                    fileHandle: filehandle,\n                    // There's a runtime check above, use overflow addition to stop the compilation\n                    // from failing on 32-bit platforms.\n                    byteCount: Int(Int32.max) &+ 10,\n                    allocator: .init(),\n                    eventLoop: self.eventLoop\n                ).wait()\n                XCTAssertEqual(String(buffer: content), \"some-dummy-content\")\n            }\n        )\n    }\n\n    func testChunkedReadDoesNotReadShort() throws {\n        var innerError: Error? = nil\n        try withPipe { readFH, writeFH in\n            let allBytes = NIOLockedValueBox(\"\")\n            let f = self.fileIO.readChunked(\n                fileHandle: readFH,\n                byteCount: 10,\n                chunkSize: 3,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                let byteCount = allBytes.withLockedValue { $0.utf8.count }\n                if byteCount == 9 {\n                    XCTAssertEqual(1, buf.readableBytes)\n                } else {\n                    XCTAssertEqual(3, buf.readableBytes)\n                }\n                allBytes.withLockedValue {\n                    $0.append(buf.readString(length: buf.readableBytes) ?? \"THIS IS WRONG\")\n                }\n                return eventLoop!.makeSucceededFuture(())\n            }\n\n            do {\n                for i in 0..<10 {\n                    // this construction will cause 'read' to repeatedly return with 1 byte read\n                    try self.eventLoop.scheduleTask(in: .milliseconds(50)) {\n                        try writeFH.withUnsafeFileDescriptor { writeFD in\n                            _ = try Posix.write(descriptor: writeFD, pointer: \"\\(i)\", size: 1)\n                        }\n                    }.futureResult.wait()\n                }\n                try writeFH.close()\n\n                try f.wait()\n                XCTAssertEqual(\"0123456789\", allBytes.withLockedValue { $0 })\n            } catch {\n                innerError = error\n            }\n            return [readFH]\n        }\n        XCTAssertNil(innerError)\n    }\n\n    func testChunkSizeMoreThanTotal() throws {\n        let content = \"0123456789\"\n        let numCalls = Counter(0)\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 5)\n            try self.fileIO.readChunked(\n                fileRegion: fr,\n                chunkSize: 10,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                XCTAssertEqual(5, buf.readableBytes)\n                XCTAssertEqual(\"01234\", buf.readString(length: buf.readableBytes) ?? \"bad\")\n                numCalls.increment()\n                return eventLoop!.makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(1, numCalls.value)\n    }\n\n    func testFileRegionReadFromPipeFails() throws {\n        try withPipe { readFH, writeFH in\n            try! writeFH.withUnsafeFileDescriptor { writeFD in\n                _ = try! Posix.write(descriptor: writeFD, pointer: \"ABC\", size: 3)\n            }\n            let fr = FileRegion(fileHandle: readFH, readerIndex: 1, endIndex: 2)\n            XCTAssertThrowsError(\n                try self.fileIO.readChunked(\n                    fileRegion: fr,\n                    chunkSize: 10,\n                    allocator: self.allocator,\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buf in\n                    XCTFail(\"this shouldn't have been called\")\n                    return eventLoop!.makeSucceededFuture(())\n                }.wait()\n            ) { error in\n                XCTAssertEqual(ESPIPE, (error as? IOError)?.errnoCode)\n            }\n            return [readFH, writeFH]\n        }\n    }\n\n    func testReadFromNonBlockingPipeFails() throws {\n        try withPipe { readFH, writeFH in\n            do {\n                try readFH.withUnsafeFileDescriptor { readFD in\n                    let flags = try Posix.fcntl(descriptor: readFD, command: F_GETFL, value: 0)\n                    let ret = try Posix.fcntl(descriptor: readFD, command: F_SETFL, value: flags | O_NONBLOCK)\n                    assert(ret == 0, \"unexpectedly, fcntl(\\(readFD), F_SETFL, O_NONBLOCK) returned \\(ret)\")\n                }\n                try self.fileIO.readChunked(\n                    fileHandle: readFH,\n                    byteCount: 10,\n                    chunkSize: 10,\n                    allocator: self.allocator,\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buf in\n                    XCTFail(\"this shouldn't have been called\")\n                    return eventLoop!.makeSucceededFuture(())\n                }.wait()\n                XCTFail(\"succeeded and shouldn't have\")\n            } catch let e as NonBlockingFileIO.Error where e == NonBlockingFileIO.Error.descriptorSetToNonBlocking {\n                // OK\n            } catch {\n                XCTFail(\"wrong error \\(error) caught\")\n            }\n            return [readFH, writeFH]\n        }\n    }\n\n    func testSeekPointerIsSetToFront() throws {\n        let content = \"0123456789\"\n        let numCalls = Counter(0)\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            try self.fileIO.readChunked(\n                fileHandle: fileHandle,\n                byteCount: content.utf8.count,\n                chunkSize: 9,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                numCalls.increment()\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                if numCalls.value == 1 {\n                    XCTAssertEqual(9, buf.readableBytes)\n                    XCTAssertEqual(\"012345678\", buf.readString(length: buf.readableBytes) ?? \"bad\")\n                } else {\n                    XCTAssertEqual(1, buf.readableBytes)\n                    XCTAssertEqual(\"9\", buf.readString(length: buf.readableBytes) ?? \"bad\")\n                }\n                return eventLoop!.makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(2, numCalls.value)\n    }\n\n    func testReadingFileSize() throws {\n        try withTemporaryFile(content: \"0123456789\") { (fileHandle, _) -> Void in\n            let size = try self.fileIO.readFileSize(\n                fileHandle: fileHandle,\n                eventLoop: eventLoop\n            ).wait()\n            XCTAssertEqual(size, 10)\n        }\n    }\n\n    func testChangeFileSizeShrink() throws {\n        try withTemporaryFile(content: \"0123456789\") { (fileHandle, _) -> Void in\n            try self.fileIO.changeFileSize(\n                fileHandle: fileHandle,\n                size: 1,\n                eventLoop: eventLoop\n            ).wait()\n            let fileRegion = try FileRegion(fileHandle: fileHandle)\n            var buf = try self.fileIO.read(\n                fileRegion: fileRegion,\n                allocator: allocator,\n                eventLoop: eventLoop\n            ).wait()\n            XCTAssertEqual(\"0\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testChangeFileSizeGrow() throws {\n        try withTemporaryFile(content: \"0123456789\") { (fileHandle, _) -> Void in\n            try self.fileIO.changeFileSize(\n                fileHandle: fileHandle,\n                size: 100,\n                eventLoop: eventLoop\n            ).wait()\n            let fileRegion = try FileRegion(fileHandle: fileHandle)\n            var buf = try self.fileIO.read(\n                fileRegion: fileRegion,\n                allocator: allocator,\n                eventLoop: eventLoop\n            ).wait()\n            let zeros = (1...90).map { _ in UInt8(0) }\n            guard let bytes = buf.readBytes(length: buf.readableBytes)?.suffix(from: 10) else {\n                XCTFail(\"readBytes(length:) should not be nil\")\n                return\n            }\n            XCTAssertEqual(zeros, Array(bytes))\n        }\n    }\n\n    func testWriting() throws {\n        var buffer = allocator.buffer(capacity: 3)\n        buffer.writeStaticString(\"123\")\n\n        try withTemporaryFile(content: \"\") { (fileHandle, path) in\n            try self.fileIO.write(\n                fileHandle: fileHandle,\n                buffer: buffer,\n                eventLoop: self.eventLoop\n            ).wait()\n            let offset = try fileHandle.withUnsafeFileDescriptor {\n                try Posix.lseek(descriptor: $0, offset: 0, whence: SEEK_SET)\n            }\n            XCTAssertEqual(offset, 0)\n\n            let readBuffer = try self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: 3,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(readBuffer.getString(at: 0, length: 3), \"123\")\n        }\n    }\n\n    func testWriteMultipleTimes() throws {\n        var buffer = allocator.buffer(capacity: 3)\n        buffer.writeStaticString(\"xxx\")\n\n        try withTemporaryFile(content: \"AAA\") { (fileHandle, path) in\n            for i in 0..<3 {\n                buffer.writeString(\"\\(i)\")\n                try self.fileIO.write(\n                    fileHandle: fileHandle,\n                    buffer: buffer,\n                    eventLoop: self.eventLoop\n                ).wait()\n            }\n            let offset = try fileHandle.withUnsafeFileDescriptor {\n                try Posix.lseek(descriptor: $0, offset: 0, whence: SEEK_SET)\n            }\n            XCTAssertEqual(offset, 0)\n\n            let expectedOutput = \"xxx0xxx01xxx012\"\n            let readBuffer = try self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: expectedOutput.utf8.count,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(expectedOutput, String(decoding: readBuffer.readableBytesView, as: Unicode.UTF8.self))\n        }\n    }\n\n    func testWritingWithOffset() throws {\n        var buffer = allocator.buffer(capacity: 3)\n        buffer.writeStaticString(\"123\")\n\n        try withTemporaryFile(content: \"hello\") { (fileHandle, _) -> Void in\n            try self.fileIO.write(\n                fileHandle: fileHandle,\n                toOffset: 1,\n                buffer: buffer,\n                eventLoop: eventLoop\n            ).wait()\n            let offset = try fileHandle.withUnsafeFileDescriptor {\n                try Posix.lseek(descriptor: $0, offset: 0, whence: SEEK_SET)\n            }\n            XCTAssertEqual(offset, 0)\n\n            var readBuffer = try self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: 5,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(5, readBuffer.readableBytes)\n            XCTAssertEqual(\"h123o\", readBuffer.readString(length: readBuffer.readableBytes))\n        }\n    }\n\n    // This is undefined behavior and may cause different\n    // results on other platforms. Please add #if:s according\n    // to platform requirements.\n    func testWritingBeyondEOF() throws {\n        var buffer = allocator.buffer(capacity: 3)\n        buffer.writeStaticString(\"123\")\n\n        try withTemporaryFile(content: \"hello\") { (fileHandle, _) -> Void in\n            try self.fileIO.write(\n                fileHandle: fileHandle,\n                toOffset: 6,\n                buffer: buffer,\n                eventLoop: eventLoop\n            ).wait()\n\n            let fileRegion = try FileRegion(fileHandle: fileHandle)\n            var buf = try self.fileIO.read(\n                fileRegion: fileRegion,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ).wait()\n            XCTAssertEqual(9, buf.readableBytes)\n            XCTAssertEqual(\"hello\", buf.readString(length: 5))\n            XCTAssertEqual([UInt8(0)], buf.readBytes(length: 1))\n            XCTAssertEqual(\"123\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testFileOpenWorks() throws {\n        let content = \"123\"\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            try self.fileIO.openFile(_deprecatedPath: path, eventLoop: self.eventLoop).flatMapThrowing { vals in\n                let (fh, fr) = vals\n                try fh.withUnsafeFileDescriptor { fd in\n                    XCTAssertGreaterThanOrEqual(fd, 0)\n                }\n                XCTAssertTrue(fh.isOpen)\n                XCTAssertEqual(0, fr.readerIndex)\n                XCTAssertEqual(3, fr.endIndex)\n                try fh.close()\n            }.wait()\n        }\n    }\n\n    func testFileOpenWorksWithEmptyFile() throws {\n        let content = \"\"\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            try self.fileIO.openFile(_deprecatedPath: path, eventLoop: self.eventLoop).flatMapThrowing { vals in\n                let (fh, fr) = vals\n                try fh.withUnsafeFileDescriptor { fd in\n                    XCTAssertGreaterThanOrEqual(fd, 0)\n                }\n                XCTAssertTrue(fh.isOpen)\n                XCTAssertEqual(0, fr.readerIndex)\n                XCTAssertEqual(0, fr.endIndex)\n                try fh.close()\n            }.wait()\n        }\n    }\n\n    func testFileOpenFails() throws {\n        do {\n            try self.fileIO.openFile(\n                _deprecatedPath: \"/dev/null/this/does/not/exist\",\n                eventLoop: self.eventLoop\n            ).map { _ in }.wait()\n            XCTFail(\"should've thrown\")\n        } catch let e as IOError where e.errnoCode == ENOTDIR {\n            // OK\n        } catch {\n            XCTFail(\"wrong error: \\(error)\")\n        }\n    }\n\n    func testOpeningFilesForWriting() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { dir in\n                try self.fileIO!.openFile(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: .write,\n                    flags: .allowFileCreation(),\n                    eventLoop: self.eventLoop\n                ).wait().close()\n            }\n        )\n    }\n\n    func testOpeningFilesForWritingFailsIfWeDontAllowItExplicitly() {\n        XCTAssertThrowsError(\n            try withTemporaryDirectory { dir in\n                try self.fileIO!.openFile(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: .write,\n                    flags: .default,\n                    eventLoop: self.eventLoop\n                ).wait().close()\n            }\n        ) { error in\n            XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n        }\n    }\n\n    func testOpeningFilesForWritingDoesNotAllowReading() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { dir in\n                let fileHandle = try self.fileIO!.openFile(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: .write,\n                    flags: .allowFileCreation(),\n                    eventLoop: self.eventLoop\n                ).wait()\n                defer {\n                    try! fileHandle.close()\n                }\n                XCTAssertEqual(\n                    -1,  // read must fail\n                    try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                        var data: UInt8 = 0\n                        return withUnsafeMutableBytes(of: &data) { ptr in\n                            read(fd, ptr.baseAddress, ptr.count)\n                        }\n                    }\n                )\n            }\n        )\n    }\n\n    func testOpeningFilesForWritingAndReading() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { dir in\n                let fileHandle = try self.fileIO!.openFile(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: [.write, .read],\n                    flags: .allowFileCreation(),\n                    eventLoop: self.eventLoop\n                ).wait()\n                defer {\n                    try! fileHandle.close()\n                }\n                XCTAssertEqual(\n                    0,  // read should read EOF\n                    try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                        var data: UInt8 = 0\n                        return withUnsafeMutableBytes(of: &data) { ptr in\n                            read(fd, ptr.baseAddress, ptr.count)\n                        }\n                    }\n                )\n            }\n        )\n    }\n\n    func testOpeningFilesForWritingDoesNotImplyTruncation() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { dir in\n                // open 1 + write\n                try {\n                    let fileHandle = try self.fileIO!.openFile(\n                        _deprecatedPath: \"\\(dir)/file\",\n                        mode: [.write, .read],\n                        flags: .allowFileCreation(),\n                        eventLoop: self.eventLoop\n                    ).wait()\n                    defer {\n                        try! fileHandle.close()\n                    }\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        var data = UInt8(ascii: \"X\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                }()\n                // open 2 + write again + read\n                try {\n                    let fileHandle = try self.fileIO!.openFile(\n                        _deprecatedPath: \"\\(dir)/file\",\n                        mode: [.write, .read],\n                        flags: .default,\n                        eventLoop: self.eventLoop\n                    ).wait()\n                    defer {\n                        try! fileHandle.close()\n                    }\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_END)\n                        var data = UInt8(ascii: \"Y\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                    XCTAssertEqual(\n                        2,  // both bytes\n                        try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                            var data: UInt16 = 0\n                            try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_SET)\n                            let readReturn = withUnsafeMutableBytes(of: &data) { ptr in\n                                read(fd, ptr.baseAddress, ptr.count)\n                            }\n                            XCTAssertEqual(\n                                UInt16(bigEndian: (UInt16(UInt8(ascii: \"X\")) << 8) | UInt16(UInt8(ascii: \"Y\"))),\n                                data\n                            )\n                            return readReturn\n                        }\n                    )\n                }()\n            }\n        )\n    }\n\n    func testOpeningFilesForWritingCanUseTruncation() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { dir in\n                // open 1 + write\n                try {\n                    let fileHandle = try self.fileIO!.openFile(\n                        _deprecatedPath: \"\\(dir)/file\",\n                        mode: [.write, .read],\n                        flags: .allowFileCreation(),\n                        eventLoop: self.eventLoop\n                    ).wait()\n                    defer {\n                        try! fileHandle.close()\n                    }\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        var data = UInt8(ascii: \"X\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                }()\n                // open 2 (with truncation) + write again + read\n                try {\n                    let fileHandle = try self.fileIO!.openFile(\n                        _deprecatedPath: \"\\(dir)/file\",\n                        mode: [.write, .read],\n                        flags: .posix(flags: O_TRUNC, mode: 0),\n                        eventLoop: self.eventLoop\n                    ).wait()\n                    defer {\n                        try! fileHandle.close()\n                    }\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_END)\n                        var data = UInt8(ascii: \"Y\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                    XCTAssertEqual(\n                        1,  // read should read just one byte because we truncated the file\n                        try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                            var data: UInt16 = 0\n                            try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_SET)\n                            let readReturn = withUnsafeMutableBytes(of: &data) { ptr in\n                                read(fd, ptr.baseAddress, ptr.count)\n                            }\n                            XCTAssertEqual(UInt16(bigEndian: UInt16(UInt8(ascii: \"Y\")) << 8), data)\n                            return readReturn\n                        }\n                    )\n                }()\n            }\n        )\n    }\n\n    func testReadFromOffset() {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n                let buffer = self.fileIO.read(\n                    fileHandle: fileHandle,\n                    fromOffset: 6,\n                    byteCount: 5,\n                    allocator: ByteBufferAllocator(),\n                    eventLoop: self.eventLoop\n                )\n                XCTAssertNoThrow(\n                    try XCTAssertEqual(\n                        \"world\",\n                        String(\n                            decoding: buffer.wait().readableBytesView,\n                            as: Unicode.UTF8.self\n                        )\n                    )\n                )\n            }\n        )\n    }\n\n    func testReadChunkedFromOffset() {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n                let numberOfCalls = Counter(0)\n                try self.fileIO.readChunked(\n                    fileHandle: fileHandle,\n                    fromOffset: 6,\n                    byteCount: 5,\n                    chunkSize: 2,\n                    allocator: .init(),\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buffer in\n                    numberOfCalls.increment()\n                    switch numberOfCalls.value {\n                    case 1:\n                        XCTAssertEqual(\"wo\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                    case 2:\n                        XCTAssertEqual(\"rl\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                    case 3:\n                        XCTAssertEqual(\"d\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                    default:\n                        XCTFail()\n                    }\n                    return eventLoop!.makeSucceededFuture(())\n                }.wait()\n            }\n        )\n    }\n\n    func testReadChunkedFromOffsetAfterEOFDeliversExactlyOneChunk() {\n        let numberOfCalls = Counter(0)\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n                try self.fileIO.readChunked(\n                    fileHandle: fileHandle,\n                    fromOffset: 100,\n                    byteCount: 5,\n                    chunkSize: 2,\n                    allocator: .init(),\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buffer in\n                    numberOfCalls.increment()\n                    XCTAssertEqual(1, numberOfCalls.value)\n                    XCTAssertEqual(0, buffer.readableBytes)\n                    return eventLoop!.makeSucceededFuture(())\n                }.wait()\n            }\n        )\n    }\n\n    func testReadChunkedFromEOFDeliversExactlyOneChunk() {\n        let numberOfCalls = Counter(0)\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"\") { (fileHandle, path) in\n                try self.fileIO.readChunked(\n                    fileHandle: fileHandle,\n                    byteCount: 5,\n                    chunkSize: 2,\n                    allocator: .init(),\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buffer in\n                    numberOfCalls.increment()\n                    XCTAssertEqual(1, numberOfCalls.value)\n                    XCTAssertEqual(0, buffer.readableBytes)\n                    return eventLoop!.makeSucceededFuture(())\n                }.wait()\n            }\n        )\n    }\n\n    func testReadFromOffsetAfterEOFDeliversExactlyOneChunk() {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n                XCTAssertEqual(\n                    0,\n                    try self.fileIO.read(\n                        fileHandle: fileHandle,\n                        fromOffset: 100,\n                        byteCount: 5,\n                        allocator: .init(),\n                        eventLoop: self.eventLoop\n                    ).wait().readableBytes\n                )\n            }\n        )\n    }\n\n    func testReadFromEOFDeliversExactlyOneChunk() {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"\") { (fileHandle, path) in\n                XCTAssertEqual(\n                    0,\n                    try self.fileIO.read(\n                        fileHandle: fileHandle,\n                        byteCount: 5,\n                        allocator: .init(),\n                        eventLoop: self.eventLoop\n                    ).wait().readableBytes\n                )\n            }\n        )\n    }\n\n    func testReadChunkedFromOffsetFileRegion() {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n                let numberOfCalls = Counter(0)\n                let fileRegion = FileRegion(fileHandle: fileHandle, readerIndex: 6, endIndex: 11)\n                try self.fileIO.readChunked(\n                    fileRegion: fileRegion,\n                    chunkSize: 2,\n                    allocator: .init(),\n                    eventLoop: self.eventLoop\n                ) { [eventLoop = self.eventLoop] buffer in\n                    numberOfCalls.increment()\n                    switch numberOfCalls.value {\n                    case 1:\n                        XCTAssertEqual(\"wo\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                    case 2:\n                        XCTAssertEqual(\"rl\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                    case 3:\n                        XCTAssertEqual(\"d\", String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self))\n                    default:\n                        XCTFail()\n                    }\n                    return eventLoop!.makeSucceededFuture(())\n                }.wait()\n            }\n        )\n    }\n\n    func testReadManyChunks() {\n        let numberOfChunks = 2_000\n        XCTAssertNoThrow(\n            try withTemporaryFile(\n                content: String(\n                    repeating: \"X\",\n                    count: numberOfChunks\n                )\n            ) { (fileHandle, path) in\n                let numberOfCalls = ManagedAtomic(0)\n                XCTAssertNoThrow(\n                    try self.fileIO.readChunked(\n                        fileHandle: fileHandle,\n                        fromOffset: 0,\n                        byteCount: numberOfChunks,\n                        chunkSize: 1,\n                        allocator: self.allocator,\n                        eventLoop: self.eventLoop\n                    ) { [eventLoop = self.eventLoop] buffer in\n                        numberOfCalls.wrappingIncrement(ordering: .relaxed)\n                        XCTAssertEqual(1, buffer.readableBytes)\n                        XCTAssertEqual(UInt8(ascii: \"X\"), buffer.readableBytesView.first)\n                        return eventLoop!.makeSucceededFuture(())\n                    }.wait()\n                )\n                XCTAssertEqual(numberOfChunks, numberOfCalls.load(ordering: .relaxed))\n            }\n        )\n    }\n\n    func testThrowsErrorOnUnstartedPool() throws {\n        withTemporaryFile(content: \"hello, world\") { fileHandle, path in\n            let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n            defer {\n                XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully())\n            }\n\n            let expectation = XCTestExpectation(description: \"Opened file\")\n            let threadPool = NIOThreadPool(numberOfThreads: 1)\n            let fileIO = NonBlockingFileIO(threadPool: threadPool)\n            fileIO.openFile(_deprecatedPath: path, eventLoop: eventLoopGroup.next()).whenFailure { (error) in\n                XCTAssertTrue(error is NIOThreadPoolError.ThreadPoolInactive)\n                expectation.fulfill()\n            }\n\n            self.wait(for: [expectation], timeout: 1.0)\n        }\n    }\n\n    func testLStat() throws {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello, world\") { _, path in\n                let stat = try self.fileIO.lstat(path: path, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(12, stat.st_size)\n                XCTAssertEqual(S_IFREG, S_IFMT & stat.st_mode)\n            }\n        )\n\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { path in\n                let stat = try self.fileIO.lstat(path: path, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFDIR, S_IFMT & stat.st_mode)\n            }\n        )\n    }\n\n    func testSymlink() {\n        XCTAssertNoThrow(\n            try withTemporaryFile(content: \"hello, world\") { _, path in\n                let symlink = \"\\(path).symlink\"\n                XCTAssertNoThrow(try self.fileIO.symlink(path: symlink, to: path, eventLoop: self.eventLoop).wait())\n\n                XCTAssertEqual(path, try self.fileIO.readlink(path: symlink, eventLoop: self.eventLoop).wait())\n                let stat = try self.fileIO.lstat(path: symlink, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFLNK, S_IFMT & stat.st_mode)\n\n                XCTAssertNoThrow(try self.fileIO.unlink(path: symlink, eventLoop: self.eventLoop).wait())\n                XCTAssertThrowsError(try self.fileIO.lstat(path: symlink, eventLoop: self.eventLoop).wait()) { error in\n                    XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n                }\n            }\n        )\n    }\n\n    func testCreateDirectory() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { path in\n                let dir = \"\\(path)/f1/f2///f3\"\n                XCTAssertNoThrow(\n                    try self.fileIO.createDirectory(\n                        path: dir,\n                        withIntermediateDirectories: true,\n                        mode: S_IRWXU,\n                        eventLoop: self.eventLoop\n                    ).wait()\n                )\n\n                let stat = try self.fileIO.lstat(path: dir, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFDIR, S_IFMT & stat.st_mode)\n\n                XCTAssertNoThrow(\n                    try self.fileIO.createDirectory(\n                        path: \"\\(dir)/f4\",\n                        withIntermediateDirectories: false,\n                        mode: S_IRWXU,\n                        eventLoop: self.eventLoop\n                    ).wait()\n                )\n\n                let stat2 = try self.fileIO.lstat(path: dir, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFDIR, S_IFMT & stat2.st_mode)\n\n                let dir3 = \"\\(path)/f4/.\"\n                XCTAssertNoThrow(\n                    try self.fileIO.createDirectory(\n                        path: dir3,\n                        withIntermediateDirectories: true,\n                        mode: S_IRWXU,\n                        eventLoop: self.eventLoop\n                    ).wait()\n                )\n            }\n        )\n    }\n\n    func testListDirectory() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { path in\n                let file = \"\\(path)/file\"\n                let handle = try self.fileIO.openFile(\n                    _deprecatedPath: file,\n                    mode: .write,\n                    flags: .allowFileCreation(),\n                    eventLoop: self.eventLoop\n                ).wait()\n                defer {\n                    try? handle.close()\n                }\n\n                let list = try self.fileIO.listDirectory(path: path, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual([\".\", \"..\", \"file\"], list.sorted(by: { $0.name < $1.name }).map(\\.name))\n            }\n        )\n    }\n\n    func testRename() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { path in\n                let file = \"\\(path)/file\"\n                let handle = try self.fileIO.openFile(\n                    _deprecatedPath: file,\n                    mode: .write,\n                    flags: .allowFileCreation(),\n                    eventLoop: self.eventLoop\n                ).wait()\n                defer {\n                    try? handle.close()\n                }\n\n                let stat = try self.fileIO.lstat(path: file, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFREG, S_IFMT & stat.st_mode)\n\n                let new = \"\\(path).new\"\n                XCTAssertNoThrow(try self.fileIO.rename(path: file, newName: new, eventLoop: self.eventLoop).wait())\n\n                let stat2 = try self.fileIO.lstat(path: new, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFREG, S_IFMT & stat2.st_mode)\n\n                XCTAssertThrowsError(try self.fileIO.lstat(path: file, eventLoop: self.eventLoop).wait()) { error in\n                    XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n                }\n            }\n        )\n    }\n\n    func testRemove() {\n        XCTAssertNoThrow(\n            try withTemporaryDirectory { path in\n                let file = \"\\(path)/file\"\n                let handle = try self.fileIO.openFile(\n                    _deprecatedPath: file,\n                    mode: .write,\n                    flags: .allowFileCreation(),\n                    eventLoop: self.eventLoop\n                ).wait()\n                defer {\n                    try? handle.close()\n                }\n\n                let stat = try self.fileIO.lstat(path: file, eventLoop: self.eventLoop).wait()\n                XCTAssertEqual(S_IFREG, S_IFMT & stat.st_mode)\n\n                XCTAssertNoThrow(try self.fileIO.remove(path: file, eventLoop: self.eventLoop).wait())\n                XCTAssertThrowsError(try self.fileIO.lstat(path: file, eventLoop: self.eventLoop).wait()) { error in\n                    XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n                }\n            }\n        )\n    }\n\n    func testChunkedReadingToleratesChunkHandlersWithForeignEventLoops() throws {\n        let content = \"hello\"\n        let contentBytes = Array(content.utf8)\n        let numCalls = Counter(0)\n        let otherGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            try! otherGroup.syncShutdownGracefully()\n        }\n        try withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 5)\n            try self.fileIO.readChunked(\n                fileRegion: fr,\n                chunkSize: 1,\n                allocator: self.allocator,\n                eventLoop: self.eventLoop\n            ) { [eventLoop = self.eventLoop] buf in\n                var buf = buf\n                XCTAssertTrue(eventLoop!.inEventLoop)\n                XCTAssertEqual(1, buf.readableBytes)\n                XCTAssertEqual(contentBytes[numCalls.value], buf.readBytes(length: 1)?.first!)\n                numCalls.increment()\n                return otherGroup.next().makeSucceededFuture(())\n            }.wait()\n        }\n        XCTAssertEqual(content.utf8.count, numCalls.value)\n    }\n\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NonBlockingFileIOTest {\n    func testAsyncBasicFileIOWorks() async throws {\n        let content = \"hello\"\n        try await withTemporaryFile(content: content) { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 5)\n            var buf = try await self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(content.utf8.count, buf.readableBytes)\n            XCTAssertEqual(content, buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testAsyncOffsetWorks() async throws {\n        let content = \"hello\"\n        try await withTemporaryFile(content: content) { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 3, endIndex: 5)\n            var buf = try await self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(2, buf.readableBytes)\n            XCTAssertEqual(\"lo\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testAsyncOffsetBeyondEOF() async throws {\n        let content = \"hello\"\n        try await withTemporaryFile(content: content) { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 3000, endIndex: 3001)\n            var buf = try await self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(0, buf.readableBytes)\n            XCTAssertEqual(\"\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testAsyncEmptyReadWorks() async throws {\n        try await withTemporaryFile { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 0)\n            let buf = try await self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(0, buf.readableBytes)\n        }\n    }\n\n    func testAsyncReadingShortWorks() async throws {\n        let content = \"hello\"\n        try await withTemporaryFile(content: \"hello\") { (fileHandle, _) -> Void in\n            let fr = FileRegion(fileHandle: fileHandle, readerIndex: 0, endIndex: 10)\n            var buf = try await self.fileIO.read(\n                fileRegion: fr,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(content.utf8.count, buf.readableBytes)\n            XCTAssertEqual(content, buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testAsyncDoesNotBlockTheThreadOrEventLoop() async throws {\n        try await withPipe { [fileIO, allocator] readFH, writeFH in\n            async let byteBufferTask = try await fileIO!.read(\n                fileHandle: readFH,\n                byteCount: 10,\n                allocator: allocator!\n            )\n            do {\n                try await self.threadPool.runIfActive {\n                    try writeFH.withUnsafeFileDescriptor { writeFD in\n                        _ = try Posix.write(descriptor: writeFD, pointer: \"X\", size: 1)\n                    }\n                    try writeFH.close()\n                }\n                var buf = try await byteBufferTask\n                XCTAssertEqual(1, buf.readableBytes)\n                XCTAssertEqual(\"X\", buf.readString(length: buf.readableBytes))\n            }\n            return [readFH]\n        }\n    }\n\n    func testAsyncGettingErrorWhenThreadPoolIsShutdown() async throws {\n        try await self.threadPool.shutdownGracefully()\n\n        try await withPipe { readFH, writeFH in\n            do {\n                _ = try await self.fileIO.read(\n                    fileHandle: readFH,\n                    byteCount: 1,\n                    allocator: self.allocator\n                )\n                XCTFail(\"testAsyncGettingErrorWhenThreadPoolIsShutdown: fileIO.read should throw an error\")\n            } catch {\n                XCTAssertTrue(error is CancellationError)\n            }\n            return [readFH, writeFH]\n        }\n    }\n\n    func testAsyncReadDoesNotReadShort() async throws {\n        try await withPipe { [fileIO, allocator] readFH, writeFH in\n            async let bufferTask = try await fileIO!.read(\n                fileHandle: readFH,\n                byteCount: 10,\n                allocator: allocator!\n            )\n            for i in 0..<10 {\n                try await Task.sleep(nanoseconds: 5_000_000)\n                try await self.threadPool.runIfActive {\n                    try writeFH.withUnsafeFileDescriptor { writeFD in\n                        _ = try Posix.write(descriptor: writeFD, pointer: \"\\(i)\", size: 1)\n                    }\n                }\n            }\n            try writeFH.close()\n\n            var buf = try await bufferTask\n            XCTAssertEqual(10, buf.readableBytes)\n            XCTAssertEqual(\"0123456789\", buf.readString(length: buf.readableBytes))\n            return [readFH]\n        }\n    }\n\n    func testAsyncReadMoreThanIntMaxBytesDoesntThrow() async throws {\n        try XCTSkipIf(MemoryLayout<size_t>.size == MemoryLayout<UInt32>.size)\n        // here we try to read way more data back from the file than it contains but it serves the purpose\n        // even on a small file the OS will return EINVAL if you try to read > INT_MAX bytes\n        try await withTemporaryFile(\n            content: \"some-dummy-content\",\n            { (filehandle, path) -> Void in\n                let content = try await self.fileIO.read(\n                    fileHandle: filehandle,\n                    // There's a runtime check above, use overflow addition to stop the compilation\n                    // from failing on 32-bit platforms.\n                    byteCount: Int(Int32.max) &+ 10,\n                    allocator: .init()\n                )\n                XCTAssertEqual(String(buffer: content), \"some-dummy-content\")\n            }\n        )\n    }\n\n    func testAsyncReadingFileSize() async throws {\n        try await withTemporaryFile(content: \"0123456789\") { (fileHandle, _) -> Void in\n            let size = try await self.fileIO.readFileSize(fileHandle: fileHandle)\n            XCTAssertEqual(size, 10)\n        }\n    }\n\n    func testAsyncChangeFileSizeShrink() async throws {\n        try await withTemporaryFile(content: \"0123456789\") { (fileHandle, _) -> Void in\n            try await self.fileIO.changeFileSize(\n                fileHandle: fileHandle,\n                size: 1\n            )\n            let fileRegion = try FileRegion(fileHandle: fileHandle)\n            var buf = try await self.fileIO.read(\n                fileRegion: fileRegion,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(\"0\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testAsyncChangeFileSizeGrow() async throws {\n        try await withTemporaryFile(content: \"0123456789\") { (fileHandle, _) -> Void in\n            try await self.fileIO.changeFileSize(\n                fileHandle: fileHandle,\n                size: 100\n            )\n            let fileRegion = try FileRegion(fileHandle: fileHandle)\n            var buf = try await self.fileIO.read(\n                fileRegion: fileRegion,\n                allocator: self.allocator\n            )\n            let zeros = (1...90).map { _ in UInt8(0) }\n            guard let bytes = buf.readBytes(length: buf.readableBytes)?.suffix(from: 10) else {\n                XCTFail(\"readBytes(length:) should not be nil\")\n                return\n            }\n            XCTAssertEqual(zeros, Array(bytes))\n        }\n    }\n\n    func testAsyncWriting() async throws {\n        try await withTemporaryFile(content: \"\") { (fileHandle, path) in\n            var buffer = self.allocator.buffer(capacity: 3)\n            buffer.writeStaticString(\"123\")\n\n            try await self.fileIO.write(\n                fileHandle: fileHandle,\n                buffer: buffer\n            )\n            let offset = try fileHandle.withUnsafeFileDescriptor {\n                try Posix.lseek(descriptor: $0, offset: 0, whence: SEEK_SET)\n            }\n            XCTAssertEqual(offset, 0)\n\n            let readBuffer = try await self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: 3,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(readBuffer.getString(at: 0, length: 3), \"123\")\n        }\n    }\n\n    func testAsyncWriteMultipleTimes() async throws {\n        try await withTemporaryFile(content: \"AAA\") { (fileHandle, path) in\n            var buffer = self.allocator.buffer(capacity: 3)\n            buffer.writeStaticString(\"xxx\")\n\n            for i in 0..<3 {\n                buffer.writeString(\"\\(i)\")\n                try await self.fileIO.write(\n                    fileHandle: fileHandle,\n                    buffer: buffer\n                )\n            }\n            let offset = try fileHandle.withUnsafeFileDescriptor {\n                try Posix.lseek(descriptor: $0, offset: 0, whence: SEEK_SET)\n            }\n            XCTAssertEqual(offset, 0)\n\n            let expectedOutput = \"xxx0xxx01xxx012\"\n            let readBuffer = try await self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: expectedOutput.utf8.count,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(expectedOutput, String(decoding: readBuffer.readableBytesView, as: Unicode.UTF8.self))\n        }\n    }\n\n    func testAsyncWritingWithOffset() async throws {\n        try await withTemporaryFile(content: \"hello\") { (fileHandle, _) -> Void in\n            var buffer = self.allocator.buffer(capacity: 3)\n            buffer.writeStaticString(\"123\")\n\n            try await self.fileIO.write(\n                fileHandle: fileHandle,\n                toOffset: 1,\n                buffer: buffer\n            )\n            let offset = try fileHandle.withUnsafeFileDescriptor {\n                try Posix.lseek(descriptor: $0, offset: 0, whence: SEEK_SET)\n            }\n            XCTAssertEqual(offset, 0)\n\n            var readBuffer = try await self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: 5,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(5, readBuffer.readableBytes)\n            XCTAssertEqual(\"h123o\", readBuffer.readString(length: readBuffer.readableBytes))\n        }\n    }\n\n    // This is undefined behavior and may cause different\n    // results on other platforms. Please add #if:s according\n    // to platform requirements.\n    func testAsyncWritingBeyondEOF() async throws {\n        try await withTemporaryFile(content: \"hello\") { (fileHandle, _) -> Void in\n            var buffer = self.allocator.buffer(capacity: 3)\n            buffer.writeStaticString(\"123\")\n\n            try await self.fileIO.write(\n                fileHandle: fileHandle,\n                toOffset: 6,\n                buffer: buffer\n            )\n\n            let fileRegion = try FileRegion(fileHandle: fileHandle)\n            var buf = try await self.fileIO.read(\n                fileRegion: fileRegion,\n                allocator: self.allocator\n            )\n            XCTAssertEqual(9, buf.readableBytes)\n            XCTAssertEqual(\"hello\", buf.readString(length: 5))\n            XCTAssertEqual([UInt8(0)], buf.readBytes(length: 1))\n            XCTAssertEqual(\"123\", buf.readString(length: buf.readableBytes))\n        }\n    }\n\n    func testAsyncFileOpenWorks() async throws {\n        let content = \"123\"\n        try await withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            try await self.fileIO.withFileRegion(_deprecatedPath: path) { fr in\n                try fr.fileHandle.withUnsafeFileDescriptor { fd in\n                    XCTAssertGreaterThanOrEqual(fd, 0)\n                }\n                XCTAssertTrue(fr.fileHandle.isOpen)\n                XCTAssertEqual(0, fr.readerIndex)\n                XCTAssertEqual(3, fr.endIndex)\n            }\n        }\n    }\n\n    func testAsyncFileOpenWorksWithEmptyFile() async throws {\n        let content = \"\"\n        try await withTemporaryFile(content: content) { (fileHandle, path) -> Void in\n            try await self.fileIO.withFileRegion(_deprecatedPath: path) { fr in\n                try fr.fileHandle.withUnsafeFileDescriptor { fd in\n                    XCTAssertGreaterThanOrEqual(fd, 0)\n                }\n                XCTAssertTrue(fr.fileHandle.isOpen)\n                XCTAssertEqual(0, fr.readerIndex)\n                XCTAssertEqual(0, fr.endIndex)\n            }\n        }\n    }\n\n    func testAsyncFileOpenFails() async throws {\n        do {\n            _ = try await self.fileIO.withFileRegion(_deprecatedPath: \"/dev/null/this/does/not/exist\") { _ in }\n            XCTFail(\"should've thrown\")\n        } catch let e as IOError where e.errnoCode == ENOTDIR {\n            // OK\n        } catch {\n            XCTFail(\"wrong error: \\(error)\")\n        }\n    }\n\n    func testAsyncOpeningFilesForWriting() async throws {\n        try await withTemporaryDirectory { dir in\n            try await self.fileIO!.withFileHandle(\n                _deprecatedPath: \"\\(dir)/file\",\n                mode: .write,\n                flags: .allowFileCreation()\n            ) { _ in }\n        }\n    }\n\n    func testAsyncOpeningFilesForWritingFailsIfWeDontAllowItExplicitly() async throws {\n        do {\n            try await withTemporaryDirectory { dir in\n                try await self.fileIO!.withFileHandle(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: .write,\n                    flags: .default\n                ) { _ in }\n            }\n            XCTFail(\"testAsyncOpeningFilesForWritingFailsIfWeDontAllowItExplicitly: openFile should fail\")\n        } catch {\n            XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n        }\n    }\n\n    func testAsyncOpeningFilesForWritingDoesNotAllowReading() async throws {\n        try await withTemporaryDirectory { dir in\n            try await self.fileIO!.withFileHandle(\n                _deprecatedPath: \"\\(dir)/file\",\n                mode: .write,\n                flags: .allowFileCreation()\n            ) { fileHandle in\n                XCTAssertEqual(\n                    -1,  // read must fail\n                    try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                        var data: UInt8 = 0\n                        return withUnsafeMutableBytes(of: &data) { ptr in\n                            read(fd, ptr.baseAddress, ptr.count)\n                        }\n                    }\n                )\n            }\n        }\n    }\n\n    func testAsyncOpeningFilesForWritingAndReading() async throws {\n        try await withTemporaryDirectory { dir in\n            try await self.fileIO!.withFileHandle(\n                _deprecatedPath: \"\\(dir)/file\",\n                mode: [.write, .read],\n                flags: .allowFileCreation()\n            ) { fileHandle in\n                XCTAssertEqual(\n                    0,  // read should read EOF\n                    try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                        var data: UInt8 = 0\n                        return withUnsafeMutableBytes(of: &data) { ptr in\n                            read(fd, ptr.baseAddress, ptr.count)\n                        }\n                    }\n                )\n            }\n        }\n    }\n\n    func testAsyncOpeningFilesForWritingDoesNotImplyTruncation() async throws {\n        try await withTemporaryDirectory { dir in\n            // open 1 + write\n            do {\n                try await self.fileIO.withFileHandle(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: [.write, .read],\n                    flags: .allowFileCreation()\n                ) { fileHandle in\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        var data = UInt8(ascii: \"X\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                }\n            }\n\n            // open 2 + write again + read\n            do {\n                try await self.fileIO!.withFileHandle(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: [.write, .read],\n                    flags: .default\n                ) { fileHandle in\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_END)\n                        var data = UInt8(ascii: \"Y\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                    XCTAssertEqual(\n                        2,  // both bytes\n                        try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                            var data: UInt16 = 0\n                            try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_SET)\n                            let readReturn = withUnsafeMutableBytes(of: &data) { ptr in\n                                read(fd, ptr.baseAddress, ptr.count)\n                            }\n                            XCTAssertEqual(\n                                UInt16(bigEndian: (UInt16(UInt8(ascii: \"X\")) << 8) | UInt16(UInt8(ascii: \"Y\"))),\n                                data\n                            )\n                            return readReturn\n                        }\n                    )\n                }\n            }\n        }\n    }\n\n    func testAsyncOpeningFilesForWritingCanUseTruncation() async throws {\n        try await withTemporaryDirectory { dir in\n            // open 1 + write\n            do {\n                try await self.fileIO!.withFileHandle(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: [.write, .read],\n                    flags: .allowFileCreation()\n                ) { fileHandle in\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        var data = UInt8(ascii: \"X\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                }\n            }\n            // open 2 (with truncation) + write again + read\n            do {\n                try await self.fileIO!.withFileHandle(\n                    _deprecatedPath: \"\\(dir)/file\",\n                    mode: [.write, .read],\n                    flags: .posix(flags: O_TRUNC, mode: 0)\n                ) { fileHandle in\n                    try fileHandle.withUnsafeFileDescriptor { fd in\n                        try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_END)\n                        var data = UInt8(ascii: \"Y\")\n                        XCTAssertEqual(\n                            IOResult<Int>.processed(1),\n                            try withUnsafeBytes(of: &data) { ptr in\n                                try Posix.write(descriptor: fd, pointer: ptr.baseAddress!, size: ptr.count)\n                            }\n                        )\n                    }\n                    XCTAssertEqual(\n                        1,  // read should read just one byte because we truncated the file\n                        try fileHandle.withUnsafeFileDescriptor { fd -> ssize_t in\n                            var data: UInt16 = 0\n                            try Posix.lseek(descriptor: fd, offset: 0, whence: SEEK_SET)\n                            let readReturn = withUnsafeMutableBytes(of: &data) { ptr in\n                                read(fd, ptr.baseAddress, ptr.count)\n                            }\n                            XCTAssertEqual(UInt16(bigEndian: UInt16(UInt8(ascii: \"Y\")) << 8), data)\n                            return readReturn\n                        }\n                    )\n                }\n            }\n        }\n    }\n\n    func testAsyncReadFromOffset() async throws {\n        try await withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n            let buffer = try await self.fileIO.read(\n                fileHandle: fileHandle,\n                fromOffset: 6,\n                byteCount: 5,\n                allocator: ByteBufferAllocator()\n            )\n            let string = String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self)\n            XCTAssertEqual(\"world\", string)\n        }\n    }\n\n    func testAsyncReadFromOffsetAfterEOFDeliversExactlyOneChunk() async throws {\n        try await withTemporaryFile(content: \"hello world\") { (fileHandle, path) in\n            let readableBytes = try await self.fileIO.read(\n                fileHandle: fileHandle,\n                fromOffset: 100,\n                byteCount: 5,\n                allocator: .init()\n            ).readableBytes\n            XCTAssertEqual(0, readableBytes)\n        }\n    }\n\n    func testAsyncReadFromEOFDeliversExactlyOneChunk() async throws {\n        try await withTemporaryFile(content: \"\") { (fileHandle, path) in\n            let readableBytes = try await self.fileIO.read(\n                fileHandle: fileHandle,\n                byteCount: 5,\n                allocator: .init()\n            ).readableBytes\n            XCTAssertEqual(0, readableBytes)\n        }\n    }\n\n    func testAsyncThrowsErrorOnUnstartedPool() async throws {\n        await withTemporaryFile(content: \"hello, world\") { fileHandle, path in\n            let threadPool = NIOThreadPool(numberOfThreads: 1)\n            let fileIO = NonBlockingFileIO(threadPool: threadPool)\n            do {\n                try await fileIO.withFileRegion(_deprecatedPath: path) { _ in }\n                XCTFail(\"testAsyncThrowsErrorOnUnstartedPool: openFile should throw an error\")\n            } catch {\n            }\n        }\n    }\n\n    func testAsyncLStat() async throws {\n        try await withTemporaryFile(content: \"hello, world\") { _, path in\n            let stat = try await self.fileIO.lstat(path: path)\n            XCTAssertEqual(12, stat.st_size)\n            XCTAssertEqual(S_IFREG, S_IFMT & stat.st_mode)\n        }\n\n        try await withTemporaryDirectory { path in\n            let stat = try await self.fileIO.lstat(path: path)\n            XCTAssertEqual(S_IFDIR, S_IFMT & stat.st_mode)\n        }\n    }\n\n    func testAsyncSymlink() async throws {\n        try await withTemporaryFile(content: \"hello, world\") { _, path in\n            let symlink = \"\\(path).symlink\"\n            try await self.fileIO.symlink(path: symlink, to: path)\n\n            let link = try await self.fileIO.readlink(path: symlink)\n            XCTAssertEqual(path, link)\n            let stat = try await self.fileIO.lstat(path: symlink)\n            XCTAssertEqual(S_IFLNK, S_IFMT & stat.st_mode)\n\n            try await self.fileIO.unlink(path: symlink)\n            do {\n                _ = try await self.fileIO.lstat(path: symlink)\n                XCTFail(\"testAsyncSymlink: lstat should throw an error after unlink\")\n            } catch {\n                XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n            }\n        }\n    }\n\n    func testAsyncCreateDirectory() async throws {\n        try await withTemporaryDirectory { path in\n            let dir = \"\\(path)/f1/f2///f3\"\n            try await self.fileIO.createDirectory(path: dir, withIntermediateDirectories: true, mode: S_IRWXU)\n\n            let stat = try await self.fileIO.lstat(path: dir)\n            XCTAssertEqual(S_IFDIR, S_IFMT & stat.st_mode)\n\n            try await self.fileIO.createDirectory(path: \"\\(dir)/f4\", withIntermediateDirectories: false, mode: S_IRWXU)\n\n            let stat2 = try await self.fileIO.lstat(path: dir)\n            XCTAssertEqual(S_IFDIR, S_IFMT & stat2.st_mode)\n\n            let dir3 = \"\\(path)/f4/.\"\n            try await self.fileIO.createDirectory(path: dir3, withIntermediateDirectories: true, mode: S_IRWXU)\n        }\n    }\n\n    func testAsyncListDirectory() async throws {\n        try await withTemporaryDirectory { path in\n            let file = \"\\(path)/file\"\n            try await self.fileIO.withFileHandle(\n                _deprecatedPath: file,\n                mode: .write,\n                flags: .allowFileCreation()\n            ) { handle in\n                let list = try await self.fileIO.listDirectory(path: path)\n                XCTAssertEqual([\".\", \"..\", \"file\"], list.sorted(by: { $0.name < $1.name }).map(\\.name))\n            }\n        }\n    }\n\n    func testAsyncRename() async throws {\n        try await withTemporaryDirectory { path in\n            let file = \"\\(path)/file\"\n            try await self.fileIO.withFileHandle(\n                _deprecatedPath: file,\n                mode: .write,\n                flags: .allowFileCreation()\n            ) { handle in\n                let stat = try await self.fileIO.lstat(path: file)\n                XCTAssertEqual(S_IFREG, S_IFMT & stat.st_mode)\n\n                let new = \"\\(path).new\"\n                try await self.fileIO.rename(path: file, newName: new)\n\n                let stat2 = try await self.fileIO.lstat(path: new)\n                XCTAssertEqual(S_IFREG, S_IFMT & stat2.st_mode)\n\n                do {\n                    _ = try await self.fileIO.lstat(path: file)\n                    XCTFail(\"testAsyncRename: lstat should throw an error after file renamed\")\n                } catch {\n                    XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n                }\n            }\n        }\n    }\n\n    func testAsyncRemove() async throws {\n        try await withTemporaryDirectory { path in\n            let file = \"\\(path)/file\"\n            try await self.fileIO.withFileHandle(\n                _deprecatedPath: file,\n                mode: .write,\n                flags: .allowFileCreation()\n            ) { handle in\n                let stat = try await self.fileIO.lstat(path: file)\n                XCTAssertEqual(S_IFREG, S_IFMT & stat.st_mode)\n\n                try await self.fileIO.remove(path: file)\n                do {\n                    _ = try await self.fileIO.lstat(path: file)\n                    XCTFail(\"testAsyncRemove: lstat should throw an error after file removed\")\n                } catch {\n                    XCTAssertEqual(ENOENT, (error as? IOError)?.errnoCode)\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/PendingDatagramWritesManagerTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIODarwin\nimport CNIOLinux\n@_spi(CustomByteBufferAllocator) @testable import NIOCore\nimport NIOEmbedded\nimport XCTest\n\n@testable import NIOPosix\n\nextension SocketAddress {\n    fileprivate init(_ addr: UnsafePointer<sockaddr>) {\n        let erased = UnsafeRawPointer(addr)\n\n        switch NIOBSDSocket.AddressFamily(rawValue: CInt(addr.pointee.sa_family)) {\n        case .unix:\n            self = SocketAddress(erased.load(as: sockaddr_un.self))\n        case .inet:\n            self = SocketAddress(erased.load(as: sockaddr_in.self))\n        case .inet6:\n            self = SocketAddress(erased.load(as: sockaddr_in6.self))\n        default:\n            fatalError(\"Unexpected family type\")\n        }\n    }\n\n    fileprivate var expectedSize: socklen_t {\n        switch self {\n        case .v4:\n            return socklen_t(MemoryLayout<sockaddr_in>.size)\n        case .v6:\n            return socklen_t(MemoryLayout<sockaddr_in6>.size)\n        case .unixDomainSocket:\n            return socklen_t(MemoryLayout<sockaddr_un>.size)\n        }\n    }\n}\n\nclass PendingDatagramWritesManagerTests: XCTestCase {\n    private func withPendingDatagramWritesManager(_ body: (PendingDatagramWritesManager) throws -> Void) rethrows {\n        let bufferPool = Pool<PooledBuffer>(maxSize: 16)\n        let msgBufferPool = Pool<PooledMsgBuffer>(maxSize: 16)\n        let pwm = NIOPosix.PendingDatagramWritesManager(bufferPool: bufferPool, msgBufferPool: msgBufferPool)\n\n        XCTAssertTrue(pwm.isEmpty)\n        XCTAssertTrue(pwm.isOpen)\n        XCTAssertFalse(pwm.isFlushPending)\n        XCTAssertTrue(pwm.isWritable)\n\n        try body(pwm)\n\n        XCTAssertTrue(pwm.isEmpty)\n        XCTAssertFalse(pwm.isFlushPending)\n    }\n\n    /// A frankenstein testing monster. It asserts that for `PendingDatagramWritesManager` `pwm` and `EventLoopPromises` `promises`\n    /// the following conditions hold:\n    ///  - The 'single write operation' is called `exepectedSingleWritabilities.count` number of times with the respective buffer lengths in the array.\n    ///  - The 'vector write operation' is called `exepectedVectorWritabilities.count` number of times with the respective buffer lengths in the array.\n    ///  - after calling the write operations, the promises have the states in `promiseStates`\n    ///\n    /// The write operations will all be faked and return the return values provided in `returns`.\n    ///\n    /// - Parameters:\n    ///   - pwm: The `PendingStreamWritesManager` to test.\n    ///   - promises: The promises for the writes issued.\n    ///   - expectedSingleWritabilities: The expected buffer lengths and addresses for the calls to the single write operation.\n    ///   - expectedVectorWritabilities: The expected buffer lengths and addresses for the calls to the vector write operation.\n    ///   - returns: The return values of the fakes write operations (both single and vector).\n    ///   - promiseStates: The states of the promises _after_ the write operations are done.\n    private func assertExpectedWritability(\n        pendingWritesManager pwm: PendingDatagramWritesManager,\n        promises: [EventLoopPromise<Void>],\n        expectedSingleWritabilities: [(Int, SocketAddress)]?,\n        expectedVectorWritabilities: [[(Int, SocketAddress)]]?,\n        returns: [Result<NIOPosix.IOResult<Int>, Error>],\n        promiseStates: [[Bool]],\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> OverallWriteResult {\n        var everythingState = 0\n        var singleState = 0\n        var multiState = 0\n        var err: Error? = nil\n        var result: OverallWriteResult? = nil\n\n        do {\n            let r = try pwm.triggerAppropriateWriteOperations(\n                scalarWriteOperation: { (buf, addr, len, metadata) in\n                    defer {\n                        singleState += 1\n                        everythingState += 1\n                    }\n                    if let expected = expectedSingleWritabilities {\n                        if expected.count > singleState {\n                            XCTAssertGreaterThan(returns.count, everythingState)\n                            XCTAssertEqual(\n                                expected[singleState].0,\n                                buf.count,\n                                \"in single write \\(singleState) (overall \\(everythingState)), \\(expected[singleState].0) bytes expected but \\(buf.count) actual\",\n                                file: (file),\n                                line: line\n                            )\n                            XCTAssertEqual(\n                                expected[singleState].1,\n                                addr.map(SocketAddress.init),\n                                \"in single write \\(singleState) (overall \\(everythingState)), \\(expected[singleState].1) address expected but \\(String(describing: addr.map(SocketAddress.init))) received\",\n                                file: (file),\n                                line: line\n                            )\n                            XCTAssertEqual(\n                                expected[singleState].1.expectedSize,\n                                len,\n                                \"in single write \\(singleState) (overall \\(everythingState)), \\(expected[singleState].1.expectedSize) socklen expected but \\(len) received\",\n                                file: (file),\n                                line: line\n                            )\n\n                            switch returns[everythingState] {\n                            case .success(let r):\n                                return r\n                            case .failure(let e):\n                                throw e\n                            }\n                        } else {\n                            XCTFail(\n                                \"single write call \\(singleState) but less than \\(expected.count) expected\",\n                                file: (file),\n                                line: line\n                            )\n                            return IOResult.wouldBlock(-1 * (everythingState + 1))\n                        }\n                    } else {\n                        XCTFail(\"single write called on \\(buf) but no single writes expected\", file: (file), line: line)\n                        return IOResult.wouldBlock(-1 * (everythingState + 1))\n                    }\n                },\n                vectorWriteOperation: { ptrs in\n                    defer {\n                        multiState += 1\n                        everythingState += 1\n                    }\n                    if let expected = expectedVectorWritabilities {\n                        if expected.count > multiState {\n                            XCTAssertGreaterThan(returns.count, everythingState)\n                            XCTAssertEqual(\n                                ptrs.map { $0.msg_hdr.msg_iovlen },\n                                Array(repeating: 1, count: ptrs.count),\n                                \"mustn't write more than one iovec element per datagram\",\n                                file: (file),\n                                line: line\n                            )\n                            XCTAssertEqual(\n                                expected[multiState].map { numericCast($0.0) },\n                                ptrs.map { $0.msg_hdr.msg_iov.pointee.iov_len },\n                                \"in vector write \\(multiState) (overall \\(everythingState)), \\(expected[multiState]) byte counts expected but \\(ptrs.map { $0.msg_hdr.msg_iov.pointee.iov_len }) actual\",\n                                file: (file),\n                                line: line\n                            )\n                            XCTAssertEqual(\n                                ptrs.map { Int($0.msg_len) },\n                                Array(repeating: 0, count: ptrs.count),\n                                \"in vector write \\(multiState) (overall \\(everythingState)), \\(expected[multiState]) byte counts expected but \\(ptrs.map { $0.msg_len }) actual\",\n                                file: (file),\n                                line: line\n                            )\n                            XCTAssertEqual(\n                                expected[multiState].map { $0.1 },\n                                ptrs.map { SocketAddress($0.msg_hdr.msg_name.assumingMemoryBound(to: sockaddr.self)) },\n                                \"in vector write \\(multiState) (overall \\(everythingState)), \\(expected[multiState].map { $0.1 }) addresses expected but \\(ptrs.map { SocketAddress($0.msg_hdr.msg_name.assumingMemoryBound(to: sockaddr.self)) }) actual\",\n                                file: (file),\n                                line: line\n                            )\n                            XCTAssertEqual(\n                                expected[multiState].map { $0.1.expectedSize },\n                                ptrs.map { $0.msg_hdr.msg_namelen },\n                                \"in vector write \\(multiState) (overall \\(everythingState)), \\(expected[multiState].map { $0.1.expectedSize }) address lengths expected but \\(ptrs.map { $0.msg_hdr.msg_namelen }) actual\",\n                                file: (file),\n                                line: line\n                            )\n\n                            switch returns[everythingState] {\n                            case .success(let r):\n                                return r\n                            case .failure(let e):\n                                throw e\n                            }\n                        } else {\n                            XCTFail(\n                                \"vector write call \\(multiState) but less than \\(expected.count) expected\",\n                                file: (file),\n                                line: line\n                            )\n                            return IOResult.wouldBlock(-1 * (everythingState + 1))\n                        }\n                    } else {\n                        XCTFail(\n                            \"vector write called on \\(ptrs) but no vector writes expected\",\n                            file: (file),\n                            line: line\n                        )\n                        return IOResult.wouldBlock(-1 * (everythingState + 1))\n                    }\n                }\n            )\n            result = r\n        } catch {\n            err = error\n        }\n\n        if everythingState > 0 {\n            XCTAssertEqual(\n                promises.count,\n                promiseStates[everythingState - 1].count,\n                \"number of promises (\\(promises.count)) != number of promise states (\\(promiseStates[everythingState - 1].count))\",\n                file: (file),\n                line: line\n            )\n            _ = zip(promises, promiseStates[everythingState - 1]).map { p, pState in\n                XCTAssertEqual(\n                    p.futureResult.isFulfilled,\n                    pState,\n                    \"promise states incorrect (\\(everythingState) callbacks)\",\n                    file: (file),\n                    line: line\n                )\n            }\n\n            XCTAssertEqual(\n                everythingState,\n                singleState + multiState,\n                \"odd, calls the single/vector writes: \\(singleState)/\\(multiState)/ but overall \\(everythingState+1)\",\n                file: (file),\n                line: line\n            )\n\n            if singleState == 0 {\n                XCTAssertNil(\n                    expectedSingleWritabilities,\n                    \"no single writes have been done but we expected some\",\n                    file: (file),\n                    line: line\n                )\n            } else {\n                XCTAssertEqual(\n                    singleState,\n                    (expectedSingleWritabilities?.count ?? Int.min),\n                    \"different number of single writes than expected\",\n                    file: (file),\n                    line: line\n                )\n            }\n            if multiState == 0 {\n                XCTAssertNil(expectedVectorWritabilities, \"no vector writes have been done but we expected some\")\n            } else {\n                XCTAssertEqual(\n                    multiState,\n                    (expectedVectorWritabilities?.count ?? Int.min),\n                    \"different number of vector writes than expected\",\n                    file: (file),\n                    line: line\n                )\n            }\n        } else {\n            XCTAssertEqual(\n                0,\n                returns.count,\n                \"no callbacks called but apparently \\(returns.count) expected\",\n                file: (file),\n                line: line\n            )\n            XCTAssertNil(\n                expectedSingleWritabilities,\n                \"no callbacks called but apparently some single writes expected\",\n                file: (file),\n                line: line\n            )\n            XCTAssertNil(\n                expectedVectorWritabilities,\n                \"no callbacks calles but apparently some vector writes expected\",\n                file: (file),\n                line: line\n            )\n\n            _ = zip(promises, promiseStates[0]).map { p, pState in\n                XCTAssertEqual(\n                    p.futureResult.isFulfilled,\n                    pState,\n                    \"promise states incorrect (no callbacks)\",\n                    file: (file),\n                    line: line\n                )\n            }\n        }\n\n        if let error = err {\n            throw error\n        }\n        return result!\n    }\n\n    /// Tests that writes of empty buffers work correctly and that we don't accidentally write buffers that haven't been flushed.\n    func testPendingWritesEmptyWritesWorkAndWeDontWriteUnflushedThings() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 65535)\n        var buffer = alloc.buffer(capacity: 12)\n\n        try withPendingDatagramWritesManager { pwm in\n            buffer.clear()\n            let ps: [EventLoopPromise<Void>] = (0..<2).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[0])\n\n            XCTAssertFalse(pwm.isEmpty)\n            XCTAssertFalse(pwm.isFlushPending)\n\n            pwm.markFlushCheckpoint()\n\n            XCTAssertFalse(pwm.isEmpty)\n            XCTAssertTrue(pwm.isFlushPending)\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[1])\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(0, address)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(0))],\n                promiseStates: [[true, false]]\n            )\n\n            XCTAssertFalse(pwm.isEmpty)\n            XCTAssertFalse(pwm.isFlushPending)\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: nil,\n                returns: [],\n                promiseStates: [[true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(0, address)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(0))],\n                promiseStates: [[true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n        }\n    }\n\n    /// This tests that we do use the vector write operation if we have more than one flushed and still doesn't write unflushed buffers\n    func testPendingWritesUsesVectorWriteOperationAndDoesntWriteTooMuch() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let firstAddress = try SocketAddress(ipAddress: \"127.0.0.1\", port: 65535)\n        let secondAddress = try SocketAddress(ipAddress: \"127.0.0.2\", port: 65535)\n        var buffer = alloc.buffer(capacity: 12)\n        let emptyBuffer = buffer\n        _ = buffer.writeString(\"1234\")\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: firstAddress, data: buffer), promise: ps[0])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: secondAddress, data: buffer), promise: ps[1])\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: firstAddress, data: emptyBuffer), promise: ps[2])\n\n            XCTAssertEqual(8, pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[(4, firstAddress), (4, secondAddress)]],\n                returns: [.success(.processed(2))],\n                promiseStates: [[true, true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(0, firstAddress)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(0))],\n                promiseStates: [[true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Tests that we can handle partial writes correctly.\n    func testPendingWritesWorkWithPartialWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let firstAddress = try SocketAddress(ipAddress: \"fe80::1\", port: 65535)\n        let secondAddress = try SocketAddress(ipAddress: \"fe80::2\", port: 65535)\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<4).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: firstAddress, data: buffer), promise: ps[0])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: secondAddress, data: buffer), promise: ps[1])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: firstAddress, data: buffer), promise: ps[2])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: secondAddress, data: buffer), promise: ps[3])\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(16, pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [\n                    [(4, firstAddress), (4, secondAddress), (4, firstAddress), (4, secondAddress)],\n                    [(4, secondAddress), (4, firstAddress), (4, secondAddress)],\n                ],\n                returns: [.success(.processed(1)), .success(.wouldBlock(0))],\n                promiseStates: [[true, false, false, false], [true, false, false, false]]\n            )\n\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(12, pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(4, secondAddress)],\n                expectedVectorWritabilities: [\n                    [(4, secondAddress), (4, firstAddress), (4, secondAddress)]\n                ],\n                returns: [.success(.processed(2)), .success(.wouldBlock(0))],\n                promiseStates: [[true, true, true, false], [true, true, true, false]]\n\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(4, pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(4, secondAddress)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(4))],\n                promiseStates: [[true, true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Tests that the spin count works for many buffers if each is written one by one.\n    func testPendingWritesSpinCountWorksForSingleWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 65535)\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeBytes([UInt8](repeating: 0xff, count: 12))\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0...pwm.writeSpinCount + 1).map { (_: UInt) in el.makePromise() }\n            for promise in ps {\n                _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: promise)\n            }\n            let totalBytes = ps.count * buffer.readableBytes\n            let maxVectorWritabilities = ps.map { (_: EventLoopPromise<Void>) in (buffer.readableBytes, address) }\n            let actualVectorWritabilities = maxVectorWritabilities.indices.dropLast().map {\n                Array(maxVectorWritabilities[$0...])\n            }\n            let actualPromiseStates = ps.indices.dropFirst().map {\n                Array(repeating: true, count: $0) + Array(repeating: false, count: ps.count - $0)\n            }\n\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(Int64(totalBytes), pwm.bufferedBytes)\n\n            // below, we'll write 1 datagram at a time. So the number of datagrams offered should decrease by one.\n            // The write operation should be repeated until we did it 1 + spin count times and then return `.couldNotWriteEverything`.\n            // After that, one datagram will remain\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: Array(actualVectorWritabilities),\n                returns: Array(repeating: .success(.processed(1)), count: ps.count - 1),\n                promiseStates: actualPromiseStates\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n\n            // we'll now write the one last datagram and assert that all the writes are complete\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(12, address)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(12))],\n                promiseStates: [Array(repeating: true, count: ps.count - 1) + [true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Test that cancellation of the Channel writes works correctly.\n    func testPendingWritesCancellationWorksCorrectly() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 65535)\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[0])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[1])\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[2])\n\n            XCTAssertEqual(12, pwm.bufferedBytes)\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[(4, address), (4, address)]],\n                returns: [.success(.wouldBlock(0))],\n                promiseStates: [[false, false, false], [false, false, false]]\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(12, pwm.bufferedBytes)\n\n            pwm.failAll(error: ChannelError.operationUnsupported, close: true)\n\n            XCTAssertTrue(ps.map { $0.futureResult.isFulfilled }.allSatisfy { $0 })\n        }\n    }\n\n    /// Test that with a few massive buffers, we don't offer more than we should to `writev` if the individual chunks fit.\n    func testPendingWritesNoMoreThanWritevLimitIsWritten() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator(\n            allocate: { _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            reallocate: { _, _, _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            deallocate: { _ in },\n            copy: { _, _, _ in }\n        )\n        // each buffer is half the writev limit\n        let halfTheWriteVLimit = Socket.writevLimitBytes / 2\n        var buffer = alloc.buffer(capacity: halfTheWriteVLimit)\n        buffer.moveReaderIndex(to: 0)\n        buffer.moveWriterIndex(to: halfTheWriteVLimit)\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 65535)\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            // add 1.5x the writev limit\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[0])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[1])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[2])\n            pwm.markFlushCheckpoint()\n\n            XCTAssertEqual(Int64(3 * halfTheWriteVLimit), pwm.bufferedBytes)\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(halfTheWriteVLimit, address)],\n                expectedVectorWritabilities: [[(halfTheWriteVLimit, address), (halfTheWriteVLimit, address)]],\n                returns: [.success(.processed(2)), .success(.processed(1))],\n                promiseStates: [[true, true, false], [true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    /// Test that with a massive buffers (bigger than writev size), we fall back to linear processing.\n    func testPendingWritesNoMoreThanWritevLimitIsWrittenInOneMassiveChunk() throws {\n        if MemoryLayout<Int>.size == MemoryLayout<Int32>.size {  // skip this test on 32bit system\n            return\n        }\n\n        let el = EmbeddedEventLoop()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 65535)\n        let alloc = ByteBufferAllocator(\n            allocate: { _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            reallocate: { _, _, _ in UnsafeMutableRawPointer(bitPattern: 0xdeadbee)! },\n            deallocate: { _ in },\n            copy: { _, _, _ in }\n        )\n\n        let biggerThanWriteV = Socket.writevLimitBytes + 23\n        var buffer = alloc.buffer(capacity: biggerThanWriteV)\n        buffer.moveReaderIndex(to: 0)\n        buffer.moveWriterIndex(to: biggerThanWriteV)\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            // add 1.5x the writev limit\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[0])\n            XCTAssertEqual(Int64(biggerThanWriteV), pwm.bufferedBytes)\n            buffer.moveReaderIndex(to: 100)\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[1])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[2])\n            XCTAssertEqual(Int64(biggerThanWriteV * 3 - 100 * 2), pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [\n                    (Socket.writevLimitBytes + 23, address),\n                    (Socket.writevLimitBytes - 77, address),\n                ],\n                expectedVectorWritabilities: [[(Socket.writevLimitBytes - 77, address)]],\n                returns: [\n                    .failure(IOError(errnoCode: EMSGSIZE, reason: \"\")),\n                    .success(.processed(1)),\n                    .success(.processed(1)),\n                ],\n                promiseStates: [[true, false, false], [true, true, false], [true, true, true]]\n            )\n\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            XCTAssertNoThrow(try ps[1].futureResult.wait())\n            XCTAssertNoThrow(try ps[2].futureResult.wait())\n\n            do {\n                try ps[0].futureResult.wait()\n                XCTFail(\"Did not throw\")\n            } catch ChannelError.writeMessageTooLarge {\n                // Ok\n            } catch {\n                XCTFail(\"Unexpected error \\(error)\")\n            }\n        }\n    }\n\n    func testPendingWritesWorksWithManyEmptyWrites() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let emptyBuffer = alloc.buffer(capacity: 12)\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: emptyBuffer), promise: ps[0])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: emptyBuffer), promise: ps[1])\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: emptyBuffer), promise: ps[2])\n\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[(0, address), (0, address)]],\n                returns: [.success(.processed(2))],\n                promiseStates: [[true, true, false]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n\n            pwm.markFlushCheckpoint()\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(0, address)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(0))],\n                promiseStates: [[true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    func testPendingWritesCloseDuringVectorWrite() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0..<3).map { (_: Int) in el.makePromise() }\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[0])\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[1])\n            XCTAssertEqual(Int64(buffer.readableBytes * 2), pwm.bufferedBytes)\n            pwm.markFlushCheckpoint()\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[2])\n            XCTAssertEqual(Int64(buffer.readableBytes * 3), pwm.bufferedBytes)\n\n            ps[0].futureResult.assumeIsolated().whenComplete { (res: Result<Void, Error>) in\n                pwm.failAll(error: ChannelError.inputClosed, close: true)\n            }\n\n            let result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: nil,\n                expectedVectorWritabilities: [[(4, address), (4, address)]],\n                returns: [.success(.processed(1))],\n                promiseStates: [[true, true, true]]\n            )\n            XCTAssertEqual(.writtenCompletely(.closed(nil)), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n            XCTAssertNoThrow(try ps[0].futureResult.wait())\n            XCTAssertThrowsError(try ps[1].futureResult.wait())\n            XCTAssertThrowsError(try ps[2].futureResult.wait())\n        }\n    }\n\n    func testPendingWritesMoreThanWritevIOVectorLimit() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"1234\")\n\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0...Socket.writevLimitIOVectors).map { (_: Int) in el.makePromise() }\n            for promise in ps {\n                _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: promise)\n            }\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(Int64(buffer.readableBytes * ps.count), pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(4, address)],\n                expectedVectorWritabilities: [Array(repeating: (4, address), count: Socket.writevLimitIOVectors)],\n                returns: [.success(.processed(Socket.writevLimitIOVectors)), .success(.wouldBlock(0))],\n                promiseStates: [\n                    Array(repeating: true, count: Socket.writevLimitIOVectors) + [false],\n                    Array(repeating: true, count: Socket.writevLimitIOVectors) + [false],\n                ]\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(Int64(buffer.readableBytes), pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(4, address)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(4))],\n                promiseStates: [Array(repeating: true, count: Socket.writevLimitIOVectors + 1)]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n\n    func testReadBufferedWritableBytesWithConsecutiveWritesAndWouldBlock() throws {\n        let el = EmbeddedEventLoop()\n        let alloc = ByteBufferAllocator()\n        let address = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        var buffer = alloc.buffer(capacity: 12)\n        buffer.writeString(\"12\")\n        let bufferSize = buffer.readableBytes\n        try withPendingDatagramWritesManager { pwm in\n            let ps: [EventLoopPromise<Void>] = (0...4).map { (_: Int) in el.makePromise() }\n            for idx in 0..<4 {\n                _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps[idx])\n            }\n\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(Int64(bufferSize * (ps.count - 1)), pwm.bufferedBytes)\n\n            var result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(bufferSize, address)],\n                expectedVectorWritabilities: [Array(repeating: (bufferSize, address), count: 4)],\n                returns: [.success(.processed(3)), .success(.wouldBlock(0))],\n                promiseStates: [\n                    Array(repeating: true, count: 3) + [false, false],\n                    Array(repeating: true, count: 3) + [false, false],\n                ]\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(Int64(bufferSize), pwm.bufferedBytes)\n\n            _ = pwm.add(envelope: AddressedEnvelope(remoteAddress: address, data: buffer), promise: ps.last!)\n            pwm.markFlushCheckpoint()\n            XCTAssertEqual(Int64(bufferSize * 2), pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(bufferSize, address)],\n                expectedVectorWritabilities: [[(bufferSize, address), (bufferSize, address)]],\n                returns: [.success(.processed(1)), .success(.wouldBlock(0))],\n                promiseStates: [\n                    Array(repeating: true, count: 4) + [false],\n                    Array(repeating: true, count: 4) + [false],\n                ]\n            )\n            XCTAssertEqual(.couldNotWriteEverything, result.writeResult)\n            XCTAssertEqual(Int64(bufferSize), pwm.bufferedBytes)\n\n            result = try assertExpectedWritability(\n                pendingWritesManager: pwm,\n                promises: ps,\n                expectedSingleWritabilities: [(bufferSize, address)],\n                expectedVectorWritabilities: nil,\n                returns: [.success(.processed(1))],\n                promiseStates: [Array(repeating: true, count: 5)]\n            )\n            XCTAssertEqual(.writtenCompletely(.open), result.writeResult)\n            XCTAssertEqual(0, pwm.bufferedBytes)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/PipeChannelTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOPosix\n\nfinal class PipeChannelTest: XCTestCase {\n    var group: MultiThreadedEventLoopGroup! = nil\n    var channel: Channel! = nil\n    var toChannel: FileHandle! = nil\n    var fromChannel: FileHandle! = nil\n    var buffer: ByteBuffer! = nil\n\n    var eventLoop: SelectableEventLoop {\n        self.group.next() as! SelectableEventLoop\n    }\n\n    override func setUp() {\n        self.group = .init(numberOfThreads: 1)\n\n        XCTAssertNoThrow(\n            try withPipe { pipe1Read, pipe1Write in\n                try withPipe { pipe2Read, pipe2Write in\n                    self.toChannel = try pipe1Write.withUnsafeFileDescriptor { fd in\n                        FileHandle(fileDescriptor: fd, closeOnDealloc: false)\n                    }\n                    self.fromChannel = try pipe2Read.withUnsafeFileDescriptor { fd in\n                        FileHandle(fileDescriptor: fd, closeOnDealloc: false)\n                    }\n                    try pipe1Read.withUnsafeFileDescriptor { channelIn in\n                        try pipe2Write.withUnsafeFileDescriptor { channelOut in\n                            let channel = NIOPipeBootstrap(group: self.group)\n                                .takingOwnershipOfDescriptors(\n                                    input: channelIn,\n                                    output: channelOut\n                                )\n                            XCTAssertNoThrow(self.channel = try channel.wait())\n                        }\n                    }\n                    for pipe in [pipe1Read, pipe1Write, pipe2Read, pipe2Write] {\n                        XCTAssertNoThrow(try pipe.takeDescriptorOwnership())\n                    }\n                    return []  // we may leak the file handles because we take care of closing\n                }\n                return []  // we may leak the file handles because we take care of closing\n            }\n        )\n        self.buffer = self.channel.allocator.buffer(capacity: 128)\n    }\n\n    override func tearDown() {\n        self.buffer = nil\n        self.toChannel.closeFile()\n        self.fromChannel.closeFile()\n        self.toChannel = nil\n        self.fromChannel = nil\n        XCTAssertNoThrow(try self.channel.syncCloseAcceptingAlreadyClosed())\n        XCTAssertNoThrow(try self.group.syncShutdownGracefully())\n    }\n\n    func testBasicIO() throws {\n        final class Handler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.writeAndFlush(data).whenFailure { error in\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            }\n        }\n\n        XCTAssertTrue(self.channel.isActive)\n        XCTAssertNoThrow(try self.channel.pipeline.addHandler(Handler()).wait())\n        let longArray = Array(repeating: UInt8(ascii: \"x\"), count: 200_000)\n        for length in [1, 10_000, 100_000, 200_000] {\n            let fromChannel = self.fromChannel!\n\n            XCTAssertNoThrow(try self.toChannel.writeBytes(longArray[0..<length]))\n            let data = try? fromChannel.readBytes(ofExactLength: length)\n            XCTAssertEqual(Array(longArray[0..<length]), data)\n        }\n        XCTAssertNoThrow(try self.channel.close().wait())\n    }\n\n    func testWriteErrorsCloseChannel() {\n        XCTAssertNoThrow(try self.channel.setOption(.allowRemoteHalfClosure, value: true).wait())\n\n        // We need to wedge the EL open here to make sure that the close of `fromChannel` does\n        // not potentially cause us to handle writeEOF before we attempt to make the write. We\n        // want the _write_ to discover the issue first, not writeEOF.\n        let writeFuture = self.channel.eventLoop.flatSubmit { [fromChannel, channel] in\n            fromChannel!.closeFile()\n            var buffer = channel!.allocator.buffer(capacity: 1)\n            buffer.writeString(\"X\")\n            return channel!.writeAndFlush(buffer)\n        }\n        XCTAssertThrowsError(try writeFuture.wait()) { error in\n            if let error = error as? IOError {\n                XCTAssert([EPIPE, EBADF].contains(error.errnoCode), \"unexpected errno: \\(error)\")\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n        XCTAssertNoThrow(try self.channel.closeFuture.wait())\n    }\n\n    func testWeDontAcceptRegularFiles() throws {\n        try withPipe { pipeIn, pipeOut in\n            try withTemporaryFile { fileFH, path in\n                try fileFH.withUnsafeFileDescriptor { fileFHDescriptor in\n                    try pipeIn.withUnsafeFileDescriptor { pipeInDescriptor in\n                        try pipeOut.withUnsafeFileDescriptor { pipeOutDescriptor in\n                            XCTAssertThrowsError(\n                                try NIOPipeBootstrap(group: self.group)\n                                    .takingOwnershipOfDescriptors(\n                                        input: fileFHDescriptor,\n                                        output: pipeOutDescriptor\n                                    ).wait()\n                            ) { error in\n                                XCTAssertEqual(ChannelError.operationUnsupported, error as? ChannelError)\n                            }\n                            XCTAssertThrowsError(\n                                try NIOPipeBootstrap(group: self.group)\n                                    .takingOwnershipOfDescriptors(\n                                        input: pipeInDescriptor,\n                                        output: fileFHDescriptor\n                                    ).wait()\n                            ) { error in\n                                XCTAssertEqual(ChannelError.operationUnsupported, error as? ChannelError)\n                            }\n                        }\n                    }\n                }\n            }\n            return [pipeIn, pipeOut]\n        }\n    }\n\n    func testWeWorkFineWithASingleFileDescriptor() throws {\n        final class EchoHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.writeAndFlush(data).whenFailure { error in\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            }\n        }\n        // We're using a socketpair here and not say a serial line because it's much harder to get a serial line :).\n        var socketPair: [CInt] = [-1, -1]\n        XCTAssertNoThrow(\n            try socketPair.withUnsafeMutableBufferPointer { socketPairPtr in\n                precondition(socketPairPtr.count == 2)\n                try Posix.socketpair(\n                    domain: .local,\n                    type: .stream,\n                    protocolSubtype: .default,\n                    socketVector: socketPairPtr.baseAddress\n                )\n            }\n        )\n        defer {\n            XCTAssertNoThrow(try socketPair.filter { $0 > 0 }.forEach(Posix.close(descriptor:)))\n        }\n\n        XCTAssertNoThrow(\n            try \"X\".withCString { xPtr in\n                try Posix.write(descriptor: socketPair[1], pointer: xPtr, size: 1)\n            }\n        )\n\n        var maybeChannel: Channel? = nil\n        XCTAssertNoThrow(\n            maybeChannel = try NIOPipeBootstrap(group: self.group)\n                .channelInitializer { channel in\n                    channel.pipeline.addHandler(EchoHandler())\n                }\n                .takingOwnershipOfDescriptor(inputOutput: dup(socketPair[0]))\n                .wait()\n        )\n        defer {\n            XCTAssertNoThrow(try maybeChannel?.close().wait())\n        }\n\n        var spaceForX: UInt8 = 0\n        XCTAssertNoThrow(\n            try withUnsafeMutableBytes(of: &spaceForX) { xPtr in\n                try Posix.read(descriptor: socketPair[1], pointer: xPtr.baseAddress!, size: xPtr.count)\n            }\n        )\n        XCTAssertEqual(UInt8(ascii: \"X\"), spaceForX)\n    }\n\n    func testWriteEndGoingAway() throws {\n        try withPipe { readHandle, writeHandle in\n            let chan = try NIOPipeBootstrap(group: self.group)\n                .takingOwnershipOfDescriptor(output: try writeHandle.takeDescriptorOwnership())\n                .wait()\n\n            let writeResult = chan.writeAndFlush(ByteBuffer(repeating: 0x41, count: 32 * 1024 * 1024))\n            try chan.eventLoop.submit {}.wait()  // wait for write to be enqueued\n\n            try readHandle.close()\n\n            XCTAssertThrowsError(try writeResult.wait()) { error in\n                XCTAssertTrue(error is IOError, \"Expected IOError but got \\(type(of: error))\")\n                if let ioError = error as? IOError {\n                    XCTAssertEqual(ioError.errnoCode, EPIPE, \"Expected EPIPE but got \\(ioError.errnoCode)\")\n                }\n            }\n\n            // Channel should be closed after the write error\n            XCTAssertNoThrow(try chan.closeFuture.wait())\n\n            return []\n        }\n    }\n\n    func testReadEndGoingAway() throws {\n        try withPipe { readHandle, writeHandle in\n            let chan = try NIOPipeBootstrap(group: self.group)\n                .channelOption(ChannelOptions.allowRemoteHalfClosure, value: true)\n                .takingOwnershipOfDescriptor(input: try readHandle.takeDescriptorOwnership())\n                .wait()\n\n            try writeHandle.close()\n\n            // Channel should be closed because the read side is dead.\n            XCTAssertNoThrow(try chan.closeFuture.wait())\n\n            return []\n        }\n    }\n}\n\nextension FileHandle {\n    func writeBytes(_ bytes: ByteBuffer) throws {\n        try self.writeBytes(Array(bytes.readableBytesView))\n    }\n\n    func writeBytes(_ bytes: ArraySlice<UInt8>) throws {\n        bytes.withUnsafeBytes {\n            self.write(Data(bytesNoCopy: .init(mutating: $0.baseAddress!), count: $0.count, deallocator: .none))\n        }\n    }\n\n    func writeBytes(_ bytes: [UInt8]) throws {\n        try self.writeBytes(bytes[...])\n    }\n\n    func readBytes(ofExactLength completeLength: Int) throws -> [UInt8] {\n        var buffer: [UInt8] = []\n        buffer.reserveCapacity(completeLength)\n        var remaining = completeLength\n        while remaining > 0 {\n            buffer.append(contentsOf: self.readData(ofLength: remaining))\n            remaining = completeLength - buffer.count\n        }\n        return buffer\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/RawSocketBootstrapTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nextension NIOIPProtocol {\n    static let reservedForTesting = Self(rawValue: 253)\n}\n\n// lazily try's to create a raw socket and caches the error if it fails\nprivate let cachedRawSocketAPICheck = Result<Void, Error> {\n    let socket = try Socket(\n        protocolFamily: .inet,\n        type: .raw,\n        protocolSubtype: .init(NIOIPProtocol.reservedForTesting),\n        setNonBlocking: true\n    )\n    try socket.close()\n}\n\nfunc XCTSkipIfUserHasNotEnoughRightsForRawSocketAPI(file: StaticString = #filePath, line: UInt = #line) throws {\n    do {\n        try cachedRawSocketAPICheck.get()\n    } catch let error as IOError where error.errnoCode == EPERM {\n        throw XCTSkip(\"Raw Socket API requires higher privileges: \\(error)\", file: file, line: line)\n    }\n}\n\nfinal class RawSocketBootstrapTests: XCTestCase {\n    func testBindWithRecevMmsg() throws {\n        try XCTSkipIfUserHasNotEnoughRightsForRawSocketAPI()\n\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try elg.syncShutdownGracefully()) }\n        let channel = try NIORawSocketBootstrap(group: elg)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: \"127.0.0.1\", ipProtocol: .reservedForTesting).wait()\n        defer { XCTAssertNoThrow(try channel.close().wait()) }\n        try channel.configureForRecvMmsg(messageCount: 10)\n        let expectedMessages = (1...10).map { \"Hello World \\($0)\" }\n        for message in expectedMessages {\n            _ = try channel.write(\n                AddressedEnvelope(\n                    remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0),\n                    data: ByteBuffer(string: message)\n                )\n            )\n        }\n        channel.flush()\n\n        let receivedMessages = Set(\n            try channel.waitForDatagrams(count: 10).map { envelop -> String in\n                var data = envelop.data\n                let header = try XCTUnwrap(data.readIPv4HeaderFromOSRawSocket())\n                XCTAssertEqual(header.version, 4)\n                XCTAssertEqual(header.protocol, .reservedForTesting)\n                XCTAssertEqual(\n                    Int(header.platformIndependentTotalLengthForReceivedPacketFromRawSocket),\n                    IPv4Header.size + data.readableBytes\n                )\n                XCTAssertTrue(\n                    header.isValidChecksum(header.platformIndependentChecksumForReceivedPacketFromRawSocket),\n                    \"\\(header)\"\n                )\n                XCTAssertEqual(header.sourceIpAddress, .init(127, 0, 0, 1))\n                XCTAssertEqual(header.destinationIpAddress, .init(127, 0, 0, 1))\n                return String(buffer: data)\n            }\n        )\n\n        XCTAssertEqual(receivedMessages, Set(expectedMessages))\n    }\n\n    func testConnect() throws {\n        try XCTSkipIfUserHasNotEnoughRightsForRawSocketAPI()\n\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try elg.syncShutdownGracefully()) }\n        let readChannel = try NIORawSocketBootstrap(group: elg)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: \"127.0.0.1\", ipProtocol: .reservedForTesting).wait()\n        defer { XCTAssertNoThrow(try readChannel.close().wait()) }\n\n        let writeChannel = try NIORawSocketBootstrap(group: elg)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: \"127.0.0.1\", ipProtocol: .reservedForTesting).wait()\n        defer { XCTAssertNoThrow(try writeChannel.close().wait()) }\n\n        let expectedMessages = (1...10).map { \"Hello World \\($0)\" }\n        for message in expectedMessages {\n            _ = try writeChannel.write(\n                AddressedEnvelope(\n                    remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0),\n                    data: ByteBuffer(string: message)\n                )\n            )\n        }\n        writeChannel.flush()\n\n        let receivedMessages = Set(\n            try readChannel.waitForDatagrams(count: 10).map { envelop -> String in\n                var data = envelop.data\n                let header = try XCTUnwrap(data.readIPv4HeaderFromOSRawSocket())\n                XCTAssertEqual(header.version, 4)\n                XCTAssertEqual(header.protocol, .reservedForTesting)\n                XCTAssertEqual(\n                    Int(header.platformIndependentTotalLengthForReceivedPacketFromRawSocket),\n                    IPv4Header.size + data.readableBytes\n                )\n                XCTAssertTrue(\n                    header.isValidChecksum(header.platformIndependentChecksumForReceivedPacketFromRawSocket),\n                    \"\\(header)\"\n                )\n                XCTAssertEqual(header.sourceIpAddress, .init(127, 0, 0, 1))\n                XCTAssertEqual(header.destinationIpAddress, .init(127, 0, 0, 1))\n                return String(buffer: data)\n            }\n        )\n\n        XCTAssertEqual(receivedMessages, Set(expectedMessages))\n    }\n\n    func testIpHdrincl() throws {\n        try XCTSkipIfUserHasNotEnoughRightsForRawSocketAPI()\n\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try elg.syncShutdownGracefully()) }\n        let channel = try NIORawSocketBootstrap(group: elg)\n            .channelOption(.ipOption(.ip_hdrincl), value: 1)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(\n                        DatagramReadRecorder<ByteBuffer>(),\n                        name: \"ByteReadRecorder\"\n                    )\n                }\n            }\n            .bind(host: \"127.0.0.1\", ipProtocol: .reservedForTesting).wait()\n        defer { XCTAssertNoThrow(try channel.close().wait()) }\n        try channel.configureForRecvMmsg(messageCount: 10)\n        let expectedMessages = (1...10).map { \"Hello World \\($0)\" }\n        for message in expectedMessages.map(ByteBuffer.init(string:)) {\n            var packet = ByteBuffer()\n            var header = IPv4Header()\n            header.version = 4\n            header.internetHeaderLength = 5\n            header.totalLength = UInt16(IPv4Header.size + message.readableBytes)\n            header.protocol = .reservedForTesting\n            header.timeToLive = 64\n            header.destinationIpAddress = .init(127, 0, 0, 1)\n            header.sourceIpAddress = .init(127, 0, 0, 1)\n            header.setChecksum()\n            packet.writeIPv4HeaderToOSRawSocket(header)\n            packet.writeImmutableBuffer(message)\n            try channel.writeAndFlush(\n                AddressedEnvelope(\n                    remoteAddress: SocketAddress(ipAddress: \"127.0.0.1\", port: 0),\n                    data: packet\n                )\n            ).wait()\n        }\n\n        let receivedMessages = Set(\n            try channel.waitForDatagrams(count: 10).map { envelop -> String in\n                var data = envelop.data\n                let header = try XCTUnwrap(data.readIPv4HeaderFromOSRawSocket())\n                XCTAssertEqual(header.version, 4)\n                XCTAssertEqual(header.protocol, .reservedForTesting)\n                XCTAssertEqual(\n                    Int(header.platformIndependentTotalLengthForReceivedPacketFromRawSocket),\n                    IPv4Header.size + data.readableBytes\n                )\n                XCTAssertTrue(\n                    header.isValidChecksum(header.platformIndependentChecksumForReceivedPacketFromRawSocket),\n                    \"\\(header)\"\n                )\n                XCTAssertEqual(header.sourceIpAddress, .init(127, 0, 0, 1))\n                XCTAssertEqual(header.destinationIpAddress, .init(127, 0, 0, 1))\n                return String(buffer: data)\n            }\n        )\n\n        XCTAssertEqual(receivedMessages, Set(expectedMessages))\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SALChannelTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nfinal class SALChannelTest: XCTestCase {\n    func testBasicConnectedChannel() throws {\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"0.1.2.3\", port: 4)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let buffer = ByteBuffer(string: \"xxx\")\n\n            let channel = try context.makeConnectedSocketChannel(\n                localAddress: localAddress,\n                remoteAddress: serverAddress\n            )\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                channel.writeAndFlush(buffer).flatMap {\n                    channel.write(buffer, promise: nil)\n                    return channel.writeAndFlush(buffer)\n                }.flatMap {\n                    channel.close()\n                }\n            } syscallAssertions: { assertions in\n                try assertions.assertWrite(\n                    expectedFD: .max,\n                    expectedBytes: buffer,\n                    return: .processed(buffer.readableBytes)\n                )\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [buffer, buffer],\n                    return: .processed(2 * buffer.readableBytes)\n                )\n                try assertions.assertDeregister { selectable in\n                    try selectable.withUnsafeHandle {\n                        XCTAssertEqual(.max, $0)\n                    }\n                    return true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testWritesFromWritabilityNotificationsDoNotGetLostIfWePreviouslyWroteEverything() throws {\n        // This is a unit test, doing what\n        //     testWriteAndFlushFromReentrantFlushNowTriggeredOutOfWritabilityWhereOuterSaysAllWrittenAndInnerDoesNot\n        // does but in a deterministic way, without having to send actual bytes.\n\n        let localAddress = try! SocketAddress(ipAddress: \"0.1.2.3\", port: 4)\n        let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n        let buffer = ByteBuffer(string: \"12\")\n\n        let writableNotificationStepExpectation = ManagedAtomic(0)\n\n        final class DoWriteFromWritabilityChangedNotification: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            var numberOfCalls = 0\n\n            var writableNotificationStepExpectation: ManagedAtomic<Int>\n\n            init(writableNotificationStepExpectation: ManagedAtomic<Int>) {\n                self.writableNotificationStepExpectation = writableNotificationStepExpectation\n            }\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                self.numberOfCalls += 1\n\n                XCTAssertEqual(\n                    self.writableNotificationStepExpectation.load(ordering: .relaxed),\n                    numberOfCalls\n                )\n                switch self.numberOfCalls {\n                case 1:\n                    // First, we should see a `false` here because 2 bytes is above the high watermark.\n                    XCTAssertFalse(context.channel.isWritable)\n                case 2:\n                    // Then, we should go back to `true` from a `writable` notification. Now, let's write 3 bytes which\n                    // will exhaust the high watermark. We'll also set up (further down) that we only partially write\n                    // those 3 bytes.\n                    XCTAssertTrue(context.channel.isWritable)\n                    var buffer = context.channel.allocator.buffer(capacity: 3)\n                    buffer.writeString(\"ABC\")\n\n                    // We expect another channelWritabilityChanged notification\n                    XCTAssertTrue(\n                        self.writableNotificationStepExpectation.compareExchange(\n                            expected: 2,\n                            desired: 3,\n                            ordering: .relaxed\n                        ).exchanged\n                    )\n                    context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n                case 3:\n                    // Next, we should go to false because we never send all the bytes.\n                    XCTAssertFalse(context.channel.isWritable)\n                case 4:\n                    // And finally, back to `true` because eventually, we'll write enough.\n                    XCTAssertTrue(context.channel.isWritable)\n                default:\n                    XCTFail(\"call \\(self.numberOfCalls) unexpected (\\(context.channel.isWritable))\")\n                }\n            }\n        }\n\n        try withSALContext { context in\n            let channel = try context.makeConnectedSocketChannel(\n                localAddress: localAddress,\n                remoteAddress: serverAddress\n            )\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                channel.setOption(.writeSpin, value: 0).flatMap {\n                    channel.setOption(.writeBufferWaterMark, value: .init(low: 1, high: 1))\n                }.flatMapThrowing {\n                    let sync = channel.pipeline.syncOperations\n                    try sync.addHandler(\n                        DoWriteFromWritabilityChangedNotification(\n                            writableNotificationStepExpectation: writableNotificationStepExpectation\n                        )\n                    )\n                }.flatMap {\n                    // This write should cause a Channel writability change.\n                    XCTAssertTrue(\n                        writableNotificationStepExpectation.compareExchange(expected: 0, desired: 1, ordering: .relaxed)\n                            .exchanged\n                    )\n                    return channel.writeAndFlush(buffer)\n                }\n            } syscallAssertions: { assertions in\n                // We get in a write of 2 bytes, and we claim we wrote 1 bytes of that.\n                try assertions.assertWrite(expectedFD: .max, expectedBytes: buffer, return: .processed(1))\n\n                // Next, we expect a reregistration which adds the `.write` notification\n                try assertions.assertReregister { selectable, eventSet in\n                    XCTAssert(selectable as? Socket === channel.socket)\n                    XCTAssertEqual([.read, .reset, .error, .readEOF, .write], eventSet)\n                    return true\n                }\n\n                // Before sending back the writable notification, we know that that'll trigger a Channel writability change\n                XCTAssertTrue(\n                    writableNotificationStepExpectation.compareExchange(expected: 1, desired: 2, ordering: .relaxed)\n                        .exchanged\n                )\n                let writableEvent = SelectorEvent(\n                    io: [.write],\n                    registration: NIORegistration(\n                        channel: .socketChannel(channel),\n                        interested: [.write],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: writableEvent)\n                try assertions.assertWrite(\n                    expectedFD: .max,\n                    expectedBytes: buffer.getSlice(at: 1, length: 1)!,\n                    return: .processed(1)\n                )\n                var buffer = buffer\n                buffer.clear()\n                buffer.writeString(\"ABC\")  // expected\n\n                // This time, the write again, just writes one byte, so we should remain registered for writable.\n                try assertions.assertWrite(\n                    expectedFD: .max,\n                    expectedBytes: buffer,\n                    return: .processed(1)\n                )\n                buffer.moveReaderIndex(forwardBy: 1)\n\n                // Let's send them another 'writable' notification:\n                try assertions.assertWaitingForNotification(result: writableEvent)\n\n                // This time, we'll make the write write everything which should also lead to a final channelWritability\n                // change.\n                XCTAssertTrue(\n                    writableNotificationStepExpectation.compareExchange(expected: 3, desired: 4, ordering: .relaxed)\n                        .exchanged\n                )\n                try assertions.assertWrite(\n                    expectedFD: .max,\n                    expectedBytes: buffer,\n                    return: .processed(2)\n                )\n\n                // And lastly, after having written everything, we'd expect to unregister for write\n                try assertions.assertReregister { selectable, eventSet in\n                    XCTAssert(selectable as? Socket === channel.socket)\n                    XCTAssertEqual([.read, .reset, .error, .readEOF], eventSet)\n                    return true\n                }\n\n                try assertions.assertParkedRightNow()\n            }\n        }\n    }\n\n    func testWeSurviveIfIgnoringSIGPIPEFails() throws {\n        try withSALContext { context in\n            // We know this sometimes happens on Darwin, so let's test it.\n            let expectedError = IOError(errnoCode: EINVAL, reason: \"bad\")\n            XCTAssertThrowsError(try context.makeSocketChannelInjectingFailures(disableSIGPIPEFailure: expectedError)) {\n                error in\n                XCTAssertEqual(expectedError.errnoCode, (error as? IOError)?.errnoCode)\n            }\n        }\n    }\n\n    func testBasicRead() throws {\n        final class SignalGroupOnRead: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private let group: DispatchGroup\n            private var numberOfCalls = 0\n\n            init(group: DispatchGroup) {\n                self.group = group\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                self.numberOfCalls += 1\n                XCTAssertEqual(\n                    \"hello\",\n                    String(decoding: Self.unwrapInboundIn(data).readableBytesView, as: Unicode.UTF8.self)\n                )\n                if self.numberOfCalls == 1 {\n                    self.group.leave()\n                }\n            }\n        }\n\n        let g = DispatchGroup()\n        g.enter()\n\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"0.1.2.3\", port: 4)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let buffer = ByteBuffer(string: \"hello\")\n\n            let channel = try context.makeConnectedSocketChannel(\n                localAddress: localAddress,\n                remoteAddress: serverAddress\n            )\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(SignalGroupOnRead(group: g))\n                }\n            } syscallAssertions: { assertions in\n                let readEvent = SelectorEvent(\n                    io: [.read],\n                    registration: NIORegistration(\n                        channel: .socketChannel(channel),\n                        interested: [.read],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: readEvent)\n                try assertions.assertRead(expectedFD: .max, expectedBufferSpace: 2048, return: buffer)\n            }\n        }\n\n        g.wait()\n    }\n\n    func testBasicConnectWithClientBootstrap() throws {\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.autoRead, value: false)\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap { channel in\n                        channel.close()\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                try assertions.assertConnect(expectedAddress: serverAddress, result: true)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: localAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testClientBootstrapBindIsDoneAfterSocketOptions() throws {\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.socketOption(.so_reuseaddr), value: 1)\n                    .channelOption(.autoRead, value: false)\n                    .bind(to: localAddress)\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap { channel in\n                        channel.close()\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                // This is the important bit: We need to apply the socket options _before_ ...\n                try assertions.assertSetOption(expectedLevel: .socket, expectedOption: .so_reuseaddr) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                // ... we call bind.\n                try assertions.assertBind(expectedAddress: localAddress)\n                try assertions.assertLocalAddress(address: nil)  // this is an inefficiency in `bind0`.\n                try assertions.assertConnect(expectedAddress: serverAddress, result: true)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: localAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testAcceptingInboundConnections() throws {\n        final class ConnectionRecorder: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n\n            let readCount = ManagedAtomic(0)\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                readCount.wrappingIncrement(ordering: .sequentiallyConsistent)\n                context.fireChannelRead(data)\n            }\n        }\n\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let remoteAddress = try! SocketAddress(ipAddress: \"5.6.7.8\", port: 10)\n            let channel = try context.makeBoundServerSocketChannel(localAddress: localAddress)\n            let unsafeTransferSocket = try context.makeSocket()\n\n            let readRecorder = ConnectionRecorder()\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                channel.pipeline.addHandler(readRecorder)\n            } syscallAssertions: { assertions in\n                let readEvent = SelectorEvent(\n                    io: [.read],\n                    registration: NIORegistration(\n                        channel: .serverSocketChannel(channel),\n                        interested: [.read],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: readEvent)\n                try assertions.assertAccept(\n                    expectedFD: .max,\n                    expectedNonBlocking: true,\n                    return: unsafeTransferSocket.wrappedValue\n                )\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: remoteAddress)\n\n                // This accept is expected: we delay inbound channel registration by one EL tick.\n                try assertions.assertAccept(expectedFD: .max, expectedNonBlocking: true, return: nil)\n\n                // Then we register the inbound channel.\n                try assertions.assertRegister { selectable, eventSet, registration in\n                    if case (.socketChannel(let channel), let registrationEventSet) =\n                        (registration.channel, registration.interested)\n                    {\n\n                        XCTAssertEqual(localAddress, channel.localAddress)\n                        XCTAssertEqual(remoteAddress, channel.remoteAddress)\n                        XCTAssertEqual(eventSet, registrationEventSet)\n                        XCTAssertEqual([.reset, .error], eventSet)\n                        return true\n                    } else {\n                        return false\n                    }\n                }\n                try assertions.assertReregister { selectable, eventSet in\n                    XCTAssertEqual([.reset, .error, .readEOF], eventSet)\n                    return true\n                }\n                // because autoRead is on by default\n                try assertions.assertReregister { selectable, eventSet in\n                    XCTAssertEqual([.reset, .error, .readEOF, .read], eventSet)\n                    return true\n                }\n\n                try assertions.assertParkedRightNow()\n            }\n\n            XCTAssertEqual(readRecorder.readCount.load(ordering: .sequentiallyConsistent), 1)\n        }\n    }\n\n    func testAcceptingInboundConnectionsDoesntUnregisterForReadIfTheSecondAcceptErrors() throws {\n        final class ConnectionRecorder: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Any\n            typealias InboundOut = Any\n\n            let readCount = ManagedAtomic(0)\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                readCount.wrappingIncrement(ordering: .sequentiallyConsistent)\n                context.fireChannelRead(data)\n            }\n        }\n\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let remoteAddress = try! SocketAddress(ipAddress: \"5.6.7.8\", port: 10)\n            let channel = try context.makeBoundServerSocketChannel(localAddress: localAddress)\n            let unsafeTransferSocket = try context.makeSocket()\n\n            let readRecorder = ConnectionRecorder()\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                channel.pipeline.addHandler(readRecorder)\n            } syscallAssertions: { assertions in\n                let readEvent = SelectorEvent(\n                    io: [.read],\n                    registration: NIORegistration(\n                        channel: .serverSocketChannel(channel),\n                        interested: [.read],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: readEvent)\n                try assertions.assertAccept(\n                    expectedFD: .max,\n                    expectedNonBlocking: true,\n                    return: unsafeTransferSocket.wrappedValue\n                )\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: remoteAddress)\n\n                // This accept is expected: we delay inbound channel registration by one EL tick. This one throws.\n                // We throw a deliberate error here: this one hits the buggy codepath.\n                try assertions.assertAccept(\n                    expectedFD: .max,\n                    expectedNonBlocking: true,\n                    throwing: NIOFcntlFailedError()\n                )\n\n                // Then we register the inbound channel from the first accept.\n                try assertions.assertRegister { selectable, eventSet, registration in\n                    if case (.socketChannel(let channel), let registrationEventSet) =\n                        (registration.channel, registration.interested)\n                    {\n\n                        XCTAssertEqual(localAddress, channel.localAddress)\n                        XCTAssertEqual(remoteAddress, channel.remoteAddress)\n                        XCTAssertEqual(eventSet, registrationEventSet)\n                        XCTAssertEqual([.reset, .error], eventSet)\n                        return true\n                    } else {\n                        return false\n                    }\n                }\n                try assertions.assertReregister { selectable, eventSet in\n                    XCTAssertEqual([.reset, .error, .readEOF], eventSet)\n                    return true\n                }\n                // because autoRead is on by default\n                try assertions.assertReregister { selectable, eventSet in\n                    XCTAssertEqual([.reset, .error, .readEOF, .read], eventSet)\n                    return true\n                }\n\n                // Importantly, we should now be _parked_. This test is mostly testing in the absence:\n                // we expect not to see a reregister that removes readable.\n                try assertions.assertParkedRightNow()\n            }\n\n            XCTAssertEqual(readRecorder.readCount.load(ordering: .sequentiallyConsistent), 1)\n        }\n    }\n\n    func testWriteBeforeChannelActiveClientStreamDelayedConnect() throws {\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.autoRead, value: false)\n                    .channelInitializer { channel in\n                        channel.write(firstWrite, promise: nil)\n                        channel.write(secondWrite).whenComplete { _ in\n                            channel.close(promise: nil)\n                        }\n                        channel.flush()\n                        return channel.eventLoop.makeSucceededVoidFuture()\n                    }\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap {\n                        $0.closeFuture\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                try assertions.assertConnect(expectedAddress: serverAddress, result: false)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .write], event)\n                    return true\n                }\n\n                let writeEvent = SelectorEvent(\n                    io: [.write],\n                    registration: NIORegistration(\n                        channel: .socketChannel(channel),\n                        interested: [.reset, .write],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: writeEvent)\n                try assertions.assertGetOption(expectedLevel: .socket, expectedOption: .so_error, value: CInt(0))\n                try assertions.assertRemoteAddress(address: serverAddress)\n\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF, .write], event)\n                    return true\n                }\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(6)\n                )\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testWriteBeforeChannelActiveClientStreamInstantConnect() throws {\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.autoRead, value: false)\n                    .channelInitializer { channel in\n                        channel.write(firstWrite, promise: nil)\n                        channel.write(secondWrite).whenComplete { _ in\n                            channel.close(promise: nil)\n                        }\n                        channel.flush()\n                        return channel.eventLoop.makeSucceededVoidFuture()\n                    }\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap {\n                        $0.closeFuture\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                try assertions.assertConnect(expectedAddress: serverAddress, result: true)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: serverAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(6)\n                )\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testWriteBeforeChannelActiveClientStreamInstantConnect_shortWriteLeadsToWritable() throws {\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.autoRead, value: false)\n                    .channelOption(.writeSpin, value: 1)\n                    .channelInitializer { channel in\n                        channel.write(firstWrite).whenComplete { _ in\n                            // An extra EL spin here to ensure that the close doesn't\n                            // beat the writable\n                            channel.eventLoop.execute {\n                                channel.close(promise: nil)\n                            }\n                        }\n                        channel.write(secondWrite, promise: nil)\n                        channel.flush()\n                        return channel.eventLoop.makeSucceededVoidFuture()\n                    }\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap {\n                        $0.closeFuture\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                try assertions.assertConnect(expectedAddress: serverAddress, result: true)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: serverAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(3)\n                )\n                try assertions.assertWrite(expectedFD: .max, expectedBytes: secondWrite, return: .wouldBlock(0))\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF, .write], event)\n                    return true\n                }\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testWriteBeforeChannelActiveClientStreamInstantConnect_shortWriteLeadsToWritable_instantClose() throws {\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.autoRead, value: false)\n                    .channelOption(.writeSpin, value: 1)\n                    .channelInitializer { channel in\n                        channel.write(firstWrite).whenComplete { _ in\n                            // No EL spin here so the close happens in the middle of the write spin.\n                            channel.close(promise: nil)\n                        }\n                        channel.write(secondWrite, promise: nil)\n                        channel.flush()\n                        return channel.eventLoop.makeSucceededVoidFuture()\n                    }\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap {\n                        $0.closeFuture\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                try assertions.assertConnect(expectedAddress: serverAddress, result: true)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: serverAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(3)\n                )\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n\n    func testWriteBeforeChannelActiveServerStream() throws {\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let remoteAddress = try! SocketAddress(ipAddress: \"5.6.7.8\", port: 10)\n            let channel = try context.makeBoundServerSocketChannel(localAddress: localAddress)\n\n            let unsafeTransferSocket = try context.makeSocket()\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n\n            try context.runSALOnEventLoop { _, _, _ in\n                try channel.pipeline.syncOperations.addHandler(\n                    ServerBootstrap.AcceptHandler(\n                        childChannelInitializer: { channel in\n                            channel.write(firstWrite, promise: nil)\n                            channel.write(secondWrite).whenComplete { _ in\n                                channel.close(promise: nil)\n                            }\n                            channel.flush()\n                            return channel.eventLoop.makeSucceededVoidFuture()\n                        },\n                        childChannelOptions: .init()\n                    )\n                )\n            } syscallAssertions: { assertions in\n                let readEvent = SelectorEvent(\n                    io: [.read],\n                    registration: NIORegistration(\n                        channel: .serverSocketChannel(channel),\n                        interested: [.read],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: readEvent)\n                try assertions.assertAccept(\n                    expectedFD: .max,\n                    expectedNonBlocking: true,\n                    return: unsafeTransferSocket.wrappedValue\n                )\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: remoteAddress)\n\n                // This accept is expected: we delay inbound channel registration by one EL tick.\n                try assertions.assertAccept(expectedFD: .max, expectedNonBlocking: true, return: nil)\n\n                // Then we register the inbound channel.\n                try assertions.assertRegister { selectable, eventSet, registration in\n                    if case (.socketChannel(let channel), let registrationEventSet) =\n                        (registration.channel, registration.interested)\n                    {\n\n                        XCTAssertEqual(localAddress, channel.localAddress)\n                        XCTAssertEqual(remoteAddress, channel.remoteAddress)\n                        XCTAssertEqual(eventSet, registrationEventSet)\n                        XCTAssertEqual([.reset, .error], eventSet)\n                        return true\n                    } else {\n                        return false\n                    }\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n\n                // We then get an immediate write which completes, then a close.\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(6)\n                )\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n\n                try assertions.assertParkedRightNow()\n            }\n        }\n    }\n\n    func testWriteBeforeChannelActiveServerStream_shortWriteLeadsToWritable() throws {\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let remoteAddress = try! SocketAddress(ipAddress: \"5.6.7.8\", port: 10)\n            let channel = try context.makeBoundServerSocketChannel(localAddress: localAddress)\n\n            let unsafeTransferSocket = try context.makeSocket()\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n            var childChannelOptions = ChannelOptions.Storage()\n            childChannelOptions.append(key: .autoRead, value: false)\n\n            try context.runSALOnEventLoop { [childChannelOptions] _, _, _ in\n                try channel.pipeline.syncOperations.addHandler(\n                    ServerBootstrap.AcceptHandler(\n                        childChannelInitializer: { channel in\n                            channel.write(firstWrite).whenComplete { _ in\n                                // An extra EL spin here to ensure that the close doesn't\n                                // beat the writable\n                                channel.eventLoop.execute {\n                                    channel.close(promise: nil)\n                                }\n                            }\n                            channel.write(secondWrite, promise: nil)\n                            channel.flush()\n                            return channel.eventLoop.makeSucceededVoidFuture()\n                        },\n                        childChannelOptions: childChannelOptions\n                    )\n                )\n            } syscallAssertions: { assertions in\n                let readEvent = SelectorEvent(\n                    io: [.read],\n                    registration: NIORegistration(\n                        channel: .serverSocketChannel(channel),\n                        interested: [.read],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: readEvent)\n                try assertions.assertAccept(\n                    expectedFD: .max,\n                    expectedNonBlocking: true,\n                    return: unsafeTransferSocket.wrappedValue\n                )\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: remoteAddress)\n\n                // This accept is expected: we delay inbound channel registration by one EL tick.\n                try assertions.assertAccept(expectedFD: .max, expectedNonBlocking: true, return: nil)\n\n                // Then we register the inbound channel.\n                try assertions.assertRegister { selectable, eventSet, registration in\n                    if case (.socketChannel(let channel), let registrationEventSet) =\n                        (registration.channel, registration.interested)\n                    {\n\n                        XCTAssertEqual(localAddress, channel.localAddress)\n                        XCTAssertEqual(remoteAddress, channel.remoteAddress)\n                        XCTAssertEqual(eventSet, registrationEventSet)\n                        XCTAssertEqual([.reset, .error], eventSet)\n                        return true\n                    } else {\n                        return false\n                    }\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(3)\n                )\n                try assertions.assertWrite(expectedFD: .max, expectedBytes: secondWrite, return: .wouldBlock(0))\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF, .write], event)\n                    return true\n                }\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n\n                try assertions.assertParkedRightNow()\n            }\n        }\n    }\n\n    func testWriteBeforeChannelActiveServerStream_shortWriteLeadsToWritable_instantClose() throws {\n        try withSALContext { context in\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let remoteAddress = try! SocketAddress(ipAddress: \"5.6.7.8\", port: 10)\n            let channel = try context.makeBoundServerSocketChannel(localAddress: localAddress)\n\n            let unsafeTransferSocket = try context.makeSocket()\n            let firstWrite = ByteBuffer(string: \"foo\")\n            let secondWrite = ByteBuffer(string: \"bar\")\n            var childChannelOptions = ChannelOptions.Storage()\n            childChannelOptions.append(key: .autoRead, value: false)\n\n            try context.runSALOnEventLoop { [childChannelOptions] _, _, _ in\n                try channel.pipeline.syncOperations.addHandler(\n                    ServerBootstrap.AcceptHandler(\n                        childChannelInitializer: { channel in\n                            channel.write(firstWrite).whenComplete { _ in\n                                channel.close(promise: nil)\n                            }\n                            channel.write(secondWrite, promise: nil)\n                            channel.flush()\n                            return channel.eventLoop.makeSucceededVoidFuture()\n                        },\n                        childChannelOptions: childChannelOptions\n                    )\n                )\n            } syscallAssertions: { assertions in\n                let readEvent = SelectorEvent(\n                    io: [.read],\n                    registration: NIORegistration(\n                        channel: .serverSocketChannel(channel),\n                        interested: [.read],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: readEvent)\n                try assertions.assertAccept(\n                    expectedFD: .max,\n                    expectedNonBlocking: true,\n                    return: unsafeTransferSocket.wrappedValue\n                )\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRemoteAddress(address: remoteAddress)\n\n                // This accept is expected: we delay inbound channel registration by one EL tick.\n                try assertions.assertAccept(expectedFD: .max, expectedNonBlocking: true, return: nil)\n\n                // Then we register the inbound channel.\n                try assertions.assertRegister { selectable, eventSet, registration in\n                    if case (.socketChannel(let channel), let registrationEventSet) =\n                        (registration.channel, registration.interested)\n                    {\n\n                        XCTAssertEqual(localAddress, channel.localAddress)\n                        XCTAssertEqual(remoteAddress, channel.remoteAddress)\n                        XCTAssertEqual(eventSet, registrationEventSet)\n                        XCTAssertEqual([.reset, .error], eventSet)\n                        return true\n                    } else {\n                        return false\n                    }\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF], event)\n                    return true\n                }\n\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [firstWrite, secondWrite],\n                    return: .processed(3)\n                )\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n\n                try assertions.assertParkedRightNow()\n            }\n        }\n    }\n\n    func testBaseSocketChannelFlushNowReentrancyCrash() throws {\n        final class TestHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n            typealias OutboundOut = ByteBuffer\n\n            private let buffer: ByteBuffer\n\n            init(_ buffer: ByteBuffer) {\n                self.buffer = buffer\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                context.write(self.wrapOutboundOut(buffer), promise: nil)\n                context.write(self.wrapOutboundOut(buffer), promise: nil)\n                context.flush()\n                context.fireChannelActive()\n            }\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                if context.channel.isWritable {\n                    context.close(promise: nil)\n                }\n                context.fireChannelWritabilityChanged()\n            }\n        }\n\n        try withSALContext { context in\n            let channel = try context.makeSocketChannel()\n            let localAddress = try! SocketAddress(ipAddress: \"1.2.3.4\", port: 5)\n            let serverAddress = try! SocketAddress(ipAddress: \"9.8.7.6\", port: 5)\n            let buffer = ByteBuffer(repeating: 0, count: 1024)\n\n            try context.runSALOnEventLoopAndWait { _, _, _ in\n                ClientBootstrap(group: channel.eventLoop)\n                    .channelOption(.autoRead, value: false)\n                    .channelOption(.writeSpin, value: 0)\n                    .channelOption(\n                        .writeBufferWaterMark,\n                        value: .init(low: buffer.readableBytes + 1, high: buffer.readableBytes + 1)\n                    )\n                    .channelInitializer { channel in\n                        try! channel.pipeline.syncOperations.addHandler(TestHandler(buffer))\n                        return channel.eventLoop.makeSucceededVoidFuture()\n                    }\n                    .testOnly_connect(injectedChannel: channel, to: serverAddress)\n                    .flatMap {\n                        $0.closeFuture\n                    }\n            } syscallAssertions: { assertions in\n                try assertions.assertSetOption(expectedLevel: .tcp, expectedOption: .tcp_nodelay) { value in\n                    (value as? SocketOptionValue) == 1\n                }\n                try assertions.assertConnect(expectedAddress: serverAddress, result: false)\n                try assertions.assertLocalAddress(address: localAddress)\n                try assertions.assertRegister { selectable, event, Registration in\n                    XCTAssertEqual([.reset, .error], event)\n                    return true\n                }\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .write], event)\n                    return true\n                }\n\n                let writeEvent = SelectorEvent(\n                    io: [.write],\n                    registration: NIORegistration(\n                        channel: .socketChannel(channel),\n                        interested: [.reset, .write],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: writeEvent)\n                try assertions.assertGetOption(expectedLevel: .socket, expectedOption: .so_error, value: CInt(0))\n                try assertions.assertRemoteAddress(address: serverAddress)\n\n                try assertions.assertReregister { selectable, event in\n                    XCTAssertEqual([.reset, .error, .readEOF, .write], event)\n                    return true\n                }\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [buffer, buffer],\n                    return: .wouldBlock(0)\n                )\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [buffer, buffer],\n                    return: .wouldBlock(0)\n                )\n\n                let canWriteEvent = SelectorEvent(\n                    io: [.write],\n                    registration: NIORegistration(\n                        channel: .socketChannel(channel),\n                        interested: [.reset, .readEOF, .write],\n                        registrationID: .initialRegistrationID\n                    )\n                )\n                try assertions.assertWaitingForNotification(result: canWriteEvent)\n                try assertions.assertWritev(\n                    expectedFD: .max,\n                    expectedBytes: [buffer, buffer],\n                    return: .processed(buffer.readableBytes)\n                )\n\n                try assertions.assertDeregister { selectable in\n                    true\n                }\n                try assertions.assertClose(expectedFD: .max)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SALEventLoopTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport XCTest\n\nfinal class SALEventLoopTests: XCTestCase {\n    func testSchedulingTaskOnSleepingLoopWakesUpOnce() throws {\n        try withSALContext { context in\n            try context.runSALOnEventLoopAndWait { thisLoop, _, _ in\n                // We're going to execute some tasks on the loop. This will force a single wakeup, as the first task will wedge the loop open.\n                // However, we're currently _on_ the loop so the first thing we have to do is give it up.\n                let promise = thisLoop.makePromise(of: Void.self)\n\n                DispatchQueue(label: \"background\").asyncAfter(deadline: .now() + .milliseconds(100)) {\n                    let semaphore = DispatchSemaphore(value: 0)\n\n                    thisLoop.execute {\n                        // Wedge the loop open. This will also _wake_ the loop.\n                        XCTAssertEqual(semaphore.wait(timeout: .now() + .milliseconds(500)), .success)\n                    }\n\n                    // Now execute 10 tasks.\n                    for _ in 0..<10 {\n                        thisLoop.execute {}\n                    }\n\n                    // Now enqueue a \"last\" task.\n                    thisLoop.execute {\n                        promise.succeed(())\n                    }\n\n                    // Now we can unblock the semaphore.\n                    semaphore.signal()\n                }\n\n                return promise.futureResult\n            } syscallAssertions: { assertions in\n                try assertions.assertParkedRightNow()\n                try assertions.assertWakeup()\n\n                // We actually need to wait for the inner code to exit, as the optimisation we're testing here will remove a signal that the\n                // SAL is actually going to wait for in salWait().\n                try assertions.assertParkedRightNow()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SelectorTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass SelectorTest: XCTestCase {\n\n    func testDeregisterWhileProcessingEvents() throws {\n        try assertDeregisterWhileProcessingEvents(closeAfterDeregister: false)\n    }\n\n    func testDeregisterAndCloseWhileProcessingEvents() throws {\n        try assertDeregisterWhileProcessingEvents(closeAfterDeregister: true)\n    }\n\n    private func assertDeregisterWhileProcessingEvents(closeAfterDeregister: Bool) throws {\n        struct TestRegistration: Registration {\n\n            let socket: Socket\n            var interested: SelectorEventSet\n            var registrationID: SelectorRegistrationID\n        }\n\n        let thread = NIOThread(handle: .init(handle: pthread_self()), desiredName: nil)\n        let selector = try NIOPosix.Selector<TestRegistration>(thread: thread)\n        defer {\n            XCTAssertNoThrow(try selector.close())\n            thread.takeOwnership()\n        }\n\n        let socket1 = try Socket(protocolFamily: .inet, type: .stream, protocolSubtype: .default)\n        defer {\n            if socket1.isOpen {\n                XCTAssertNoThrow(try socket1.close())\n            }\n        }\n        try socket1.setNonBlocking()\n\n        let socket2 = try Socket(protocolFamily: .inet, type: .stream, protocolSubtype: .default)\n        defer {\n            if socket2.isOpen {\n                XCTAssertNoThrow(try socket2.close())\n            }\n        }\n        try socket2.setNonBlocking()\n\n        let serverSocket = try assertNoThrowWithValue(\n            ServerSocket.bootstrap(\n                protocolFamily: .inet,\n                host: \"127.0.0.1\",\n                port: 0\n            )\n        )\n        defer {\n            XCTAssertNoThrow(try serverSocket.close())\n        }\n        _ = try socket1.connect(to: serverSocket.localAddress())\n        _ = try socket2.connect(to: serverSocket.localAddress())\n\n        let accepted1 = try serverSocket.accept()!\n        defer {\n            XCTAssertNoThrow(try accepted1.close())\n        }\n        let accepted2 = try serverSocket.accept()!\n        defer {\n            XCTAssertNoThrow(try accepted2.close())\n        }\n\n        // Register both sockets with .write. This will ensure both are ready when calling selector.whenReady.\n        try selector.register(\n            selectable: socket1,\n            interested: [.reset, .error, .write],\n            makeRegistration: { ev, regID in\n                TestRegistration(socket: socket1, interested: ev, registrationID: regID)\n            }\n        )\n\n        try selector.register(\n            selectable: socket2,\n            interested: [.reset, .error, .write],\n            makeRegistration: { ev, regID in\n                TestRegistration(socket: socket2, interested: ev, registrationID: regID)\n            }\n        )\n\n        var readyCount = 0\n        try selector.whenReady(strategy: .block) {\n        } _: { ev in\n            readyCount += 1\n            if socket1 === ev.registration.socket {\n                try selector.deregister(selectable: socket2)\n                if closeAfterDeregister {\n                    try socket2.close()\n                }\n            } else if socket2 === ev.registration.socket {\n                try selector.deregister(selectable: socket1)\n                if closeAfterDeregister {\n                    try socket1.close()\n                }\n            } else {\n                XCTFail(\"ev.registration.socket was neither \\(socket1) or \\(socket2) but \\(ev.registration.socket)\")\n            }\n        }\n\n        XCTAssertEqual(1, readyCount)\n    }\n\n    private static let testWeDoNotDeliverEventsForPreviouslyClosedChannels_numberOfChannelsToUse = 10\n    func testWeDoNotDeliverEventsForPreviouslyClosedChannels() throws {\n        enum DidNotReadError: Error {\n            case didNotReadGotInactive\n            case didNotReadGotReadComplete\n        }\n\n        /// This handler is inserted in the `ChannelPipeline` that are re-connected. So we're closing a bunch of\n        /// channels and (in the same event loop tick) we then connect the same number for which I'm using the\n        /// terminology 're-connect' here.\n        /// These re-connected channels will re-use the fd numbers of the just closed channels. The interesting thing\n        /// is that the `Selector` will still have events buffered for the _closed fds_. Note: the re-connected ones\n        /// will end up using the _same_ fds and this test ensures that we're not getting the outdated events. In this\n        /// case the outdated events are all `.readEOF`s which manifest as `channelReadComplete`s. If we're delivering\n        /// outdated events, they will also happen in the _same event loop tick_ and therefore we do quite a few\n        /// assertions that we're either in or not in that interesting event loop tick.\n        class HappyWhenReadHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private let didReadPromise: EventLoopPromise<Void>\n            private let hasReConnectEventLoopTickFinished: NIOLoopBoundBox<Bool>\n            private var didRead: Bool = false\n\n            init(hasReConnectEventLoopTickFinished: NIOLoopBoundBox<Bool>, didReadPromise: EventLoopPromise<Void>) {\n                self.didReadPromise = didReadPromise\n                self.hasReConnectEventLoopTickFinished = hasReConnectEventLoopTickFinished\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                // we expect these channels to be connected within the re-connect event loop tick\n                XCTAssertFalse(self.hasReConnectEventLoopTickFinished.value)\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                // we expect these channels to be close a while after the re-connect event loop tick\n                XCTAssertTrue(self.hasReConnectEventLoopTickFinished.value)\n                XCTAssertTrue(self.didRead)\n                if !self.didRead {\n                    self.didReadPromise.fail(DidNotReadError.didNotReadGotInactive)\n                    context.close(promise: nil)\n                }\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                // we expect these channels to get data only a while after the re-connect event loop tick as it's\n                // impossible to get a read notification in the very same event loop tick that you got registered\n                XCTAssertTrue(self.hasReConnectEventLoopTickFinished.value)\n\n                XCTAssertFalse(self.didRead)\n                var buf = Self.unwrapInboundIn(data)\n                XCTAssertEqual(1, buf.readableBytes)\n                XCTAssertEqual(\"H\", buf.readString(length: 1)!)\n                self.didRead = true\n                self.didReadPromise.succeed(())\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                // we expect these channels to get data only a while after the re-connect event loop tick as it's\n                // impossible to get a read notification in the very same event loop tick that you got registered\n                XCTAssertTrue(self.hasReConnectEventLoopTickFinished.value)\n                XCTAssertTrue(self.didRead)\n                if !self.didRead {\n                    self.didReadPromise.fail(DidNotReadError.didNotReadGotReadComplete)\n                    context.close(promise: nil)\n                }\n            }\n        }\n\n        /// This handler will wait for all client channels to have come up and for one of them to have received EOF.\n        /// (We will see the EOF as they're set to support half-closure). Then, it'll close half of those file\n        /// descriptors and open the same number of new ones. The new ones (called re-connected) will share the same\n        /// fd numbers as the recently closed ones. That brings us in an interesting situation: There will (very likely)\n        /// be `.readEOF` events enqueued for the just closed ones and because the re-connected channels share the same\n        /// fd numbers danger looms. The `HappyWhenReadHandler` above makes sure nothing bad happens.\n        class CloseEveryOtherAndOpenNewOnesHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private let allChannels: NIOLoopBoundBox<[Channel]>\n            private let serverAddress: SocketAddress\n            private let everythingWasReadPromise: EventLoopPromise<Void>\n            private let hasReConnectEventLoopTickFinished: NIOLoopBoundBox<Bool>\n\n            init(\n                allChannels: NIOLoopBoundBox<[Channel]>,\n                hasReConnectEventLoopTickFinished: NIOLoopBoundBox<Bool>,\n                serverAddress: SocketAddress,\n                everythingWasReadPromise: EventLoopPromise<Void>\n            ) {\n                self.allChannels = allChannels\n                self.serverAddress = serverAddress\n                self.everythingWasReadPromise = everythingWasReadPromise\n                self.hasReConnectEventLoopTickFinished = hasReConnectEventLoopTickFinished\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                // collect all the channels\n                context.channel.getOption(.allowRemoteHalfClosure).whenSuccess { halfClosureAllowed in\n                    precondition(\n                        halfClosureAllowed,\n                        \"the test configuration is bogus: half-closure is dis-allowed which breaks the setup of this test\"\n                    )\n                }\n                self.allChannels.value.append(context.channel)\n            }\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                // this is the `.readEOF` that is triggered by the `ServerHandler`'s `close` calls because our channel\n                // supports half-closure\n                guard\n                    self.allChannels.value.count\n                        == SelectorTest.testWeDoNotDeliverEventsForPreviouslyClosedChannels_numberOfChannelsToUse\n                else {\n                    return\n                }\n                // all channels are up, so let's construct the situation we want to be in:\n                // 1. let's close half the channels\n                // 2. then re-connect (must be synchronous) the same number of channels and we'll get fd number re-use\n\n                context.channel.eventLoop.execute { [hasReConnectEventLoopTickFinished] in\n                    // this will be run immediately after we processed all `Selector` events so when\n                    // `self.hasReConnectEventLoopTickFinished.value` becomes true, we're out of the event loop\n                    // tick that is interesting.\n                    XCTAssertFalse(hasReConnectEventLoopTickFinished.value)\n                    hasReConnectEventLoopTickFinished.value = true\n                }\n                XCTAssertFalse(self.hasReConnectEventLoopTickFinished.value)\n\n                let everyOtherIndex = stride(\n                    from: 0,\n                    to: SelectorTest.testWeDoNotDeliverEventsForPreviouslyClosedChannels_numberOfChannelsToUse,\n                    by: 2\n                )\n                for f in everyOtherIndex {\n                    XCTAssertTrue(self.allChannels.value[f].isActive)\n                    // close will succeed synchronously as we're on the right event loop.\n                    self.allChannels.value[f].close(promise: nil)\n                    XCTAssertFalse(self.allChannels.value[f].isActive)\n                }\n\n                // now we have completed stage 1: we freed up a bunch of file descriptor numbers, so let's open\n                // some new ones\n                var reconnectedChannelsHaveRead: [EventLoopFuture<Void>] = []\n                for _ in everyOtherIndex {\n                    let hasBeenAdded = NIOLockedValueBox(false)\n                    let p = context.channel.eventLoop.makePromise(of: Void.self)\n                    reconnectedChannelsHaveRead.append(p.futureResult)\n                    let newChannel = ClientBootstrap(group: context.eventLoop)\n                        .channelInitializer { [hasReConnectEventLoopTickFinished] channel in\n                            channel.eventLoop.assumeIsolated().makeCompletedFuture {\n                                let sync = channel.pipeline.syncOperations\n                                try sync.addHandler(\n                                    HappyWhenReadHandler(\n                                        hasReConnectEventLoopTickFinished: hasReConnectEventLoopTickFinished,\n                                        didReadPromise: p\n                                    )\n                                )\n                                hasBeenAdded.withLockedValue { $0 = true }\n                            }\n                        }\n                        .connect(to: self.serverAddress)\n                        .map { [hasReConnectEventLoopTickFinished] (channel: Channel) -> Void in\n                            XCTAssertFalse(\n                                hasReConnectEventLoopTickFinished.value,\n                                \"\"\"\n                                This is bad: the connect of the channels to be re-connected has not\n                                completed synchronously.\n                                We assumed that on all platform a UNIX Domain Socket connect is\n                                synchronous but we must be wrong :(.\n                                The good news is: Not everything is lost, this test should also work\n                                if you instead open a regular file (in O_RDWR) and just use this file's\n                                fd with `ClientBootstrap(group: group).withConnectedSocket(fileFD)`.\n                                Sure, a file is not a socket but it's always readable and writable and\n                                that fulfills the requirements we have here.\n                                I still hope this change will never have to be done.\n                                Note: if you changed anything about the pipeline's handler adding/removal\n                                you might also have a bug there.\n                                \"\"\"\n                            )\n                        }\n                    // just to make sure we got `newChannel` synchronously and we could add our handler to the\n                    // pipeline synchronously too.\n                    XCTAssertTrue(newChannel.isFulfilled)\n                    XCTAssertTrue(hasBeenAdded.withLockedValue { $0 })\n                }\n\n                // if all the new re-connected channels have read, then we're happy here.\n                EventLoopFuture.andAllSucceed(reconnectedChannelsHaveRead, on: context.eventLoop)\n                    .cascade(to: self.everythingWasReadPromise)\n                // let's also remove all the channels so this code will not be triggered again.\n                self.allChannels.value.removeAll()\n            }\n\n        }\n\n        /// This spawns a server, always send a character immediately and after the first\n        /// `SelectorTest.numberOfChannelsToUse` have been established, we'll close them all. That will trigger\n        /// an `.readEOF` in the connected client channels which will then trigger other interesting things (see above).\n        class ServerHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private var number: Int = 0\n            private let allServerChannels: NIOLoopBoundBox<[Channel]>\n            private let numberOfConnectedChannels: NIOLoopBoundBox<Int>\n\n            init(allServerChannels: NIOLoopBoundBox<[Channel]>, numberOfConnectedChannels: NIOLoopBoundBox<Int>) {\n                self.allServerChannels = allServerChannels\n                self.numberOfConnectedChannels = numberOfConnectedChannels\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                var buf = context.channel.allocator.buffer(capacity: 1)\n                buf.writeString(\"H\")\n                context.channel.writeAndFlush(buf, promise: nil)\n                self.number += 1\n                self.allServerChannels.value.append(context.channel)\n                if self.allServerChannels.value.count\n                    == SelectorTest.testWeDoNotDeliverEventsForPreviouslyClosedChannels_numberOfChannelsToUse\n                {\n                    // just to be sure all of the client channels have connected\n                    XCTAssertEqual(\n                        SelectorTest.testWeDoNotDeliverEventsForPreviouslyClosedChannels_numberOfChannelsToUse,\n                        numberOfConnectedChannels.value\n                    )\n                    for channel in self.allServerChannels.value {\n                        channel.close(promise: nil)\n                    }\n                }\n            }\n        }\n\n        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let el = elg.next()\n        defer {\n            XCTAssertNoThrow(try elg.syncShutdownGracefully())\n        }\n\n        // all of the following are boxed as we need mutable references to them, they can only be read/written on the\n        // event loop `el`.\n        let loopBounds = try el.submit {\n            let allServerChannels = NIOLoopBoundBox([Channel](), eventLoop: el)\n            let allChannels = NIOLoopBoundBox([Channel](), eventLoop: el)\n            let hasReConnectEventLoopTickFinished = NIOLoopBoundBox(false, eventLoop: el)\n            let numberOfConnectedChannels = NIOLoopBoundBox(0, eventLoop: el)\n            return (allServerChannels, allChannels, hasReConnectEventLoopTickFinished, numberOfConnectedChannels)\n        }.wait()\n        let allServerChannels = loopBounds.0\n        let allChannels = loopBounds.1\n        let hasReConnectEventLoopTickFinished = loopBounds.2\n        let numberOfConnectedChannels = loopBounds.3\n\n        XCTAssertNoThrow(\n            try withTemporaryUnixDomainSocketPathName { udsPath in\n                let secondServerChannel = try! ServerBootstrap(group: el)\n                    .childChannelInitializer { channel in\n                        channel.eventLoop.makeCompletedFuture {\n                            try channel.pipeline.syncOperations.addHandler(\n                                ServerHandler(\n                                    allServerChannels: allServerChannels,\n                                    numberOfConnectedChannels: numberOfConnectedChannels\n                                )\n                            )\n                        }\n                    }\n                    .bind(to: SocketAddress(unixDomainSocketPath: udsPath))\n                    .wait()\n\n                let everythingWasReadPromise = el.makePromise(of: Void.self)\n                let futures = try el.submit { () -> [EventLoopFuture<Channel>] in\n                    (0..<SelectorTest.testWeDoNotDeliverEventsForPreviouslyClosedChannels_numberOfChannelsToUse).map {\n                        (_: Int) in\n                        ClientBootstrap(group: el)\n                            .channelOption(.allowRemoteHalfClosure, value: true)\n                            .channelInitializer { channel in\n                                channel.eventLoop.makeCompletedFuture {\n                                    try channel.pipeline.syncOperations.addHandler(\n                                        CloseEveryOtherAndOpenNewOnesHandler(\n                                            allChannels: allChannels,\n                                            hasReConnectEventLoopTickFinished: hasReConnectEventLoopTickFinished,\n                                            serverAddress: secondServerChannel.localAddress!,\n                                            everythingWasReadPromise: everythingWasReadPromise\n                                        )\n                                    )\n                                }\n                            }\n                            .connect(to: secondServerChannel.localAddress!)\n                            .map { channel in\n                                numberOfConnectedChannels.value += 1\n                                return channel\n                            }\n                    }\n                }.wait()\n                for future in futures {\n                    XCTAssertNoThrow(try future.wait())\n                }\n\n                XCTAssertNoThrow(try everythingWasReadPromise.futureResult.wait())\n            }\n        )\n    }\n\n    func testTimerFDIsLevelTriggered() throws {\n        // this is a regression test for https://github.com/apple/swift-nio/issues/872\n        let delayToUseInMicroSeconds: Int64 = 100_000  // needs to be much greater than time it takes to EL.execute\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        class FakeSocket: Socket {\n            private let hasBeenClosedPromise: EventLoopPromise<Void>\n            init(hasBeenClosedPromise: EventLoopPromise<Void>, socket: NIOBSDSocket.Handle) throws {\n                self.hasBeenClosedPromise = hasBeenClosedPromise\n                try super.init(socket: socket)\n            }\n            override func close() throws {\n                self.hasBeenClosedPromise.succeed(())\n                try super.close()\n            }\n        }\n        var socketFDs: [CInt] = [-1, -1]\n        XCTAssertNoThrow(\n            try Posix.socketpair(\n                domain: .local,\n                type: .stream,\n                protocolSubtype: .default,\n                socketVector: &socketFDs\n            )\n        )\n\n        let numberFires = ManagedAtomic(0)\n        let el = group.next() as! SelectableEventLoop\n        let channelHasBeenClosedPromise = el.makePromise(of: Void.self)\n        let channel = try SocketChannel(\n            socket: FakeSocket(\n                hasBeenClosedPromise: channelHasBeenClosedPromise,\n                socket: socketFDs[0]\n            ),\n            eventLoop: el\n        )\n        let sched = el.scheduleRepeatedTask(\n            initialDelay: .microseconds(delayToUseInMicroSeconds),\n            delay: .microseconds(delayToUseInMicroSeconds)\n        ) { (_: RepeatedTask) in\n            numberFires.wrappingIncrement(ordering: .relaxed)\n        }\n        XCTAssertNoThrow(\n            try el.submit {\n                // EL tick 1: this is used to\n                //   - actually arm the timer (timerfd_settime)\n                //   - set the channel registration up\n                if numberFires.load(ordering: .relaxed) > 0 {\n                    print(\n                        \"WARNING: This test hit a race and this result doesn't mean it actually worked.\"\n                            + \" This should really only ever happen in very bizarre conditions.\"\n                    )\n                }\n                channel.interestedEvent = [.readEOF, .reset, .error]\n                func workaroundSR9815() {\n                    channel.registerAlreadyConfigured0(promise: nil)\n                }\n                workaroundSR9815()\n            }.wait()\n        )\n        usleep(10_000)  // this makes this repro very stable\n        el.execute {\n            // EL tick 2: this is used to\n            //   - close one end of the socketpair so that in EL tick 3, we'll see a EPOLLHUP\n            //   - sleep `delayToUseInMicroSeconds + 10` so in EL tick 3, we'll also see timerfd fire\n            close(socketFDs[1])\n            usleep(.init(delayToUseInMicroSeconds))\n        }\n\n        // EL tick 3: happens in the background here. We will likely lose the timer signal because of the\n        // `deregistrationsHappened` workaround in `Selector.swift` and we expect to pick it up again when we enter\n        // `epoll_wait`/`kevent` next. This however only works if the timer event is level triggered.\n        assert(\n            numberFires.load(ordering: .relaxed) > 5,\n            within: .seconds(1),\n            \"timer only fired \\(numberFires.load(ordering: .relaxed)) times\"\n        )\n        sched.cancel()\n        XCTAssertNoThrow(try channelHasBeenClosedPromise.futureResult.wait())\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SerialExecutorTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport NIOCore\nimport NIOEmbedded\nimport NIOPosix\nimport XCTest\n\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\nactor EventLoopBoundActor {\n    nonisolated let unownedExecutor: UnownedSerialExecutor\n\n    var counter: Int = 0\n\n    init(loop: EventLoop) {\n        self.unownedExecutor = loop.executor.asUnownedSerialExecutor()\n    }\n\n    func assertInLoop(_ loop: EventLoop) {\n        loop.assertInEventLoop()\n        XCTAssertTrue(loop.inEventLoop)\n    }\n\n    func assertNotInLoop(_ loop: EventLoop) {\n        loop.assertNotInEventLoop()\n        XCTAssertFalse(loop.inEventLoop)\n    }\n\n    nonisolated func assumeInLoop() -> Int {\n        self.assumeIsolated { actor in\n            actor.counter\n        }\n    }\n}\n\n@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)\nfinal class SerialExecutorTests: XCTestCase {\n    var group: MultiThreadedEventLoopGroup!\n\n    private func _testBasicExecutorFitsOnEventLoop(loop1: EventLoop, loop2: EventLoop) async throws {\n        let testActor = EventLoopBoundActor(loop: loop1)\n        await testActor.assertInLoop(loop1)\n        await testActor.assertNotInLoop(loop2)\n    }\n\n    func testBasicExecutorFitsOnEventLoop_MTELG() async throws {\n        let loops = Array(self.group.makeIterator())\n        try await self._testBasicExecutorFitsOnEventLoop(loop1: loops[0], loop2: loops[1])\n    }\n\n    func testBasicExecutorFitsOnEventLoop_AsyncTestingEventLoop() async throws {\n        let loop1 = NIOAsyncTestingEventLoop()\n        let loop2 = NIOAsyncTestingEventLoop()\n        func shutdown() async {\n            await loop1.shutdownGracefully()\n            await loop2.shutdownGracefully()\n        }\n\n        do {\n            try await self._testBasicExecutorFitsOnEventLoop(loop1: loop1, loop2: loop2)\n            await shutdown()\n        } catch {\n            await shutdown()\n            throw error\n        }\n    }\n\n    func testAssumeIsolation() async throws {\n        let el = self.group.next()\n\n        let testActor = EventLoopBoundActor(loop: el)\n        let result = try await el.submit {\n            testActor.assumeInLoop()\n        }.get()\n        XCTAssertEqual(result, 0)\n    }\n\n    override func setUp() {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 3)\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.group.syncShutdownGracefully())\n        self.group = nil\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SocketAddressTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOPosix\n\nclass SocketAddressTest: XCTestCase {\n\n    func testDescriptionWorks() throws {\n        var ipv4SocketAddress = sockaddr_in()\n        let res = \"10.0.0.1\".withCString { p in\n            inet_pton(NIOBSDSocket.AddressFamily.inet.rawValue, p, &ipv4SocketAddress.sin_addr)\n        }\n        XCTAssertEqual(res, 1)\n        ipv4SocketAddress.sin_port = (12345 as in_port_t).bigEndian\n        let sa = SocketAddress(ipv4SocketAddress, host: \"foobar.com\")\n        XCTAssertEqual(\"[IPv4]foobar.com/10.0.0.1:12345\", sa.description)\n    }\n\n    func testDescriptionWorksWithoutIP() throws {\n        var ipv4SocketAddress = sockaddr_in()\n        ipv4SocketAddress.sin_port = (12345 as in_port_t).bigEndian\n        let sa = SocketAddress(ipv4SocketAddress, host: \"foobar.com\")\n        XCTAssertEqual(\"[IPv4]foobar.com/0.0.0.0:12345\", sa.description)\n    }\n\n    func testDescriptionWorksWithIPOnly() throws {\n        let sa = try! SocketAddress(ipAddress: \"10.0.0.2\", port: 12345)\n        XCTAssertEqual(\"[IPv4]10.0.0.2:12345\", sa.description)\n    }\n\n    func testDescriptionWorksWithByteBufferIPv4IP() throws {\n        let IPv4: [UInt8] = [0x7F, 0x00, 0x00, 0x01]\n        let ipv4Address: ByteBuffer = ByteBuffer.init(bytes: IPv4)\n        let sa = try! SocketAddress(packedIPAddress: ipv4Address, port: 12345)\n        XCTAssertEqual(\"[IPv4]127.0.0.1:12345\", sa.description)\n    }\n\n    func testDescriptionWorksWithByteBufferIPv6IP() throws {\n        let IPv6: [UInt8] = [\n            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,\n        ]\n        let ipv6Address: ByteBuffer = ByteBuffer.init(bytes: IPv6)\n        let sa = try! SocketAddress(packedIPAddress: ipv6Address, port: 12345)\n        XCTAssertEqual(\"[IPv6]fe80::5:12345\", sa.description)\n    }\n\n    func testRejectsWrongIPByteBufferLength() {\n        let wrongIP: [UInt8] = [0x01, 0x7F, 0x00]\n        let ipAddress: ByteBuffer = ByteBuffer.init(bytes: wrongIP)\n        XCTAssertThrowsError(try SocketAddress(packedIPAddress: ipAddress, port: 12345)) { error in\n            switch error {\n            case is SocketAddressError.FailedToParseIPByteBuffer:\n                XCTAssertEqual(ipAddress, (error as! SocketAddressError.FailedToParseIPByteBuffer).address)\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testIn6AddrDescriptionWorks() throws {\n        let sampleString = \"::1\"\n        let sampleIn6Addr: [UInt8] = [  // ::1\n            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n            0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x54,\n            0xc2, 0xb5, 0x58, 0xff, 0x7f, 0x0, 0x0, 0x7,\n            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1, 0x1, 0x0,\n        ]\n\n        var address = sockaddr_in6()\n        #if os(Linux) || os(Android)  // no sin6_len on Linux/Android\n        #else\n        address.sin6_len = UInt8(MemoryLayout<sockaddr_in6>.size)\n        #endif\n        address.sin6_family = sa_family_t(NIOBSDSocket.AddressFamily.inet6.rawValue)\n        address.sin6_addr = sampleIn6Addr.withUnsafeBytes {\n            $0.baseAddress!.bindMemory(to: in6_addr.self, capacity: 1).pointee\n        }\n\n        let s = __testOnly_addressDescription(address)\n        XCTAssertEqual(\n            s.count,\n            sampleString.count,\n            \"Address description has unexpected length 😱\"\n        )\n        XCTAssertEqual(\n            s,\n            sampleString,\n            \"Address description is way below our expectations 😱\"\n        )\n    }\n\n    func testIPAddressWorks() throws {\n        let sa = try! SocketAddress(ipAddress: \"127.0.0.1\", port: 12345)\n        XCTAssertEqual(\"127.0.0.1\", sa.ipAddress)\n        let sa6 = try! SocketAddress(ipAddress: \"::1\", port: 12345)\n        XCTAssertEqual(\"::1\", sa6.ipAddress)\n        let unix = try! SocketAddress(unixDomainSocketPath: \"/definitely/a/path\")\n        XCTAssertEqual(nil, unix.ipAddress)\n    }\n\n    func testCanCreateIPv4AddressFromString() throws {\n        let sa = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        let expectedAddress: [UInt8] = [0x7F, 0x00, 0x00, 0x01]\n        if case .v4(let address) = sa {\n            var addr = address.address\n            let host = address.host\n            XCTAssertEqual(host, \"\")\n            XCTAssertEqual(addr.sin_family, sa_family_t(NIOBSDSocket.AddressFamily.inet.rawValue))\n            XCTAssertEqual(addr.sin_port, in_port_t(80).bigEndian)\n            expectedAddress.withUnsafeBytes { expectedPtr in\n                withUnsafeBytes(of: &addr.sin_addr) { actualPtr in\n                    let rc = memcmp(actualPtr.baseAddress!, expectedPtr.baseAddress!, MemoryLayout<in_addr>.size)\n                    XCTAssertEqual(rc, 0)\n                }\n            }\n        } else {\n            XCTFail(\"Invalid address: \\(sa)\")\n        }\n    }\n\n    func testCanCreateIPv6AddressFromString() throws {\n        let sa = try SocketAddress(ipAddress: \"fe80::5\", port: 443)\n        let expectedAddress: [UInt8] = [\n            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,\n        ]\n        if case .v6(let address) = sa {\n            var addr = address.address\n            let host = address.host\n            XCTAssertEqual(host, \"\")\n            XCTAssertEqual(addr.sin6_family, sa_family_t(NIOBSDSocket.AddressFamily.inet6.rawValue))\n            XCTAssertEqual(addr.sin6_port, in_port_t(443).bigEndian)\n            XCTAssertEqual(addr.sin6_scope_id, 0)\n            XCTAssertEqual(addr.sin6_flowinfo, 0)\n            expectedAddress.withUnsafeBytes { expectedPtr in\n                withUnsafeBytes(of: &addr.sin6_addr) { actualPtr in\n                    let rc = memcmp(actualPtr.baseAddress!, expectedPtr.baseAddress!, MemoryLayout<in6_addr>.size)\n                    XCTAssertEqual(rc, 0)\n                }\n            }\n        } else {\n            XCTFail(\"Invalid address: \\(sa)\")\n        }\n    }\n\n    func testCanCreateScopedIPv6AddressFromString() throws {\n        #if os(Windows) || os(WASI)\n        // Scoped IPv6 parsing uses getaddrinfo, not available on these platforms.\n        #else\n        let loopback: String\n        #if canImport(Darwin)\n        loopback = \"lo0\"\n        #else\n        loopback = \"lo\"\n        #endif\n\n        let expectedIndex = if_nametoindex(loopback)\n        guard expectedIndex != 0 else { return }\n\n        let sa = try SocketAddress(ipAddress: \"fe80::1%\\(loopback)\", port: 443)\n        if case .v6(let address) = sa {\n            XCTAssertEqual(address.address.sin6_family, sa_family_t(NIOBSDSocket.AddressFamily.inet6.rawValue))\n            XCTAssertEqual(address.address.sin6_port, in_port_t(443).bigEndian)\n            XCTAssertEqual(address.address.sin6_flowinfo, 0)\n            XCTAssertEqual(address.address.sin6_scope_id, expectedIndex)\n            XCTAssertEqual(address.host, \"fe80::1%\\(loopback)\")\n        } else {\n            XCTFail(\"Invalid address: \\(sa)\")\n        }\n        #endif\n    }\n\n    func testCanCreateScopedIPv6WithNumericIndex() throws {\n        #if os(Windows) || os(WASI)\n        // Scoped IPv6 parsing uses getaddrinfo, not available on these platforms.\n        #else\n        // Use the loopback interface index so the test isn't fragile on systems\n        // where index 1 might not exist.\n        let loopback: String\n        #if canImport(Darwin)\n        loopback = \"lo0\"\n        #else\n        loopback = \"lo\"\n        #endif\n        let expectedIndex = if_nametoindex(loopback)\n        guard expectedIndex != 0 else { return }\n\n        // getaddrinfo accepts both interface names (%lo) and numeric indices (%1).\n        let sa = try SocketAddress(ipAddress: \"fe80::1%\\(expectedIndex)\", port: 80)\n        if case .v6(let address) = sa {\n            XCTAssertEqual(address.address.sin6_flowinfo, 0)\n            XCTAssertEqual(address.address.sin6_scope_id, expectedIndex)\n            XCTAssertEqual(address.address.sin6_port, in_port_t(80).bigEndian)\n        } else {\n            XCTFail(\"Invalid address: \\(sa)\")\n        }\n        #endif\n    }\n\n    func testScopedAndNonScopedIPv6AreNotEqual() throws {\n        #if os(Windows) || os(WASI)\n        #else\n        let loopback: String\n        #if canImport(Darwin)\n        loopback = \"lo0\"\n        #else\n        loopback = \"lo\"\n        #endif\n        guard if_nametoindex(loopback) != 0 else { return }\n\n        let scoped = try SocketAddress(ipAddress: \"fe80::1%\\(loopback)\", port: 80)\n        let nonScoped = try SocketAddress(ipAddress: \"fe80::1\", port: 80)\n        // sin6_scope_id differs, so these should not be equal.\n        XCTAssertNotEqual(scoped, nonScoped)\n        #endif\n    }\n\n    func testRejectsInvalidScopedIPv6() {\n        #if os(Windows) || os(WASI)\n        #else\n        // Empty scope after %\n        XCTAssertThrowsError(try SocketAddress(ipAddress: \"fe80::1%\", port: 80)) { error in\n            switch error as? SocketAddressError {\n            case .some(.failedToParseIPString(\"fe80::1%\")):\n                ()  // ok\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n        // Nonexistent interface name\n        XCTAssertThrowsError(try SocketAddress(ipAddress: \"fe80::1%doesnotexist999\", port: 80)) { error in\n            switch error as? SocketAddressError {\n            case .some(.failedToParseIPString(\"fe80::1%doesnotexist999\")):\n                ()  // ok\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n        #endif\n    }\n\n    func testCanCreateNonScopedIPv6AfterScopedIPv6Support() throws {\n        // Regression: ensure non-scoped IPv6 still works after adding scoped support.\n        let sa = try SocketAddress(ipAddress: \"::1\", port: 80)\n        if case .v6(let address) = sa {\n            XCTAssertEqual(address.address.sin6_scope_id, 0)\n            XCTAssertEqual(address.address.sin6_port, in_port_t(80).bigEndian)\n        } else {\n            XCTFail(\"Invalid address: \\(sa)\")\n        }\n    }\n\n    func testRejectsNonIPStrings() {\n        XCTAssertThrowsError(try SocketAddress(ipAddress: \"definitelynotanip\", port: 800)) { error in\n            switch error as? SocketAddressError {\n            case .some(.failedToParseIPString(\"definitelynotanip\")):\n                ()  // ok\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testConvertingStorage() throws {\n        let first = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let third = try SocketAddress(unixDomainSocketPath: \"/definitely/a/path\")\n\n        guard case .v4(let firstAddress) = first else {\n            XCTFail(\"Unable to extract IPv4 address\")\n            return\n        }\n        guard case .v6(let secondAddress) = second else {\n            XCTFail(\"Unable to extract IPv6 address\")\n            return\n        }\n        guard case .unixDomainSocket(let thirdAddress) = third else {\n            XCTFail(\"Unable to extract UDS address\")\n            return\n        }\n\n        var storage = sockaddr_storage()\n        var firstIPAddress = firstAddress.address\n        var secondIPAddress = secondAddress.address\n        var thirdIPAddress = thirdAddress.address\n\n        var firstCopy: sockaddr_in = withUnsafeBytes(of: &firstIPAddress) { outer in\n            _ = withUnsafeMutableBytes(of: &storage) { temp in\n                memcpy(temp.baseAddress!, outer.baseAddress!, MemoryLayout<sockaddr_in>.size)\n            }\n            return __testOnly_convertSockAddr(storage)\n        }\n        var secondCopy: sockaddr_in6 = withUnsafeBytes(of: &secondIPAddress) { outer in\n            _ = withUnsafeMutableBytes(of: &storage) { temp in\n                memcpy(temp.baseAddress!, outer.baseAddress!, MemoryLayout<sockaddr_in6>.size)\n            }\n            return __testOnly_convertSockAddr(storage)\n        }\n        var thirdCopy: sockaddr_un = withUnsafeBytes(of: &thirdIPAddress) { outer in\n            _ = withUnsafeMutableBytes(of: &storage) { temp in\n                memcpy(temp.baseAddress!, outer.baseAddress!, MemoryLayout<sockaddr_un>.size)\n            }\n            return __testOnly_convertSockAddr(storage)\n        }\n\n        XCTAssertEqual(memcmp(&firstIPAddress, &firstCopy, MemoryLayout<sockaddr_in>.size), 0)\n        XCTAssertEqual(memcmp(&secondIPAddress, &secondCopy, MemoryLayout<sockaddr_in6>.size), 0)\n        XCTAssertEqual(memcmp(&thirdIPAddress, &thirdCopy, MemoryLayout<sockaddr_un>.size), 0)\n\n        // Test unsupported socket address family.\n        var unspecAddr = sockaddr_storage()\n        unspecAddr.ss_family = sa_family_t(AF_UNSPEC)\n        XCTAssertThrowsError(try __testOnly_convertSockAddr(unspecAddr) as SocketAddress) { error in\n            guard case .unsupported = error as? SocketAddressError else {\n                XCTFail(\"Expected error \\(SocketAddressError.unsupported), got error \\(error).\")\n                return\n            }\n        }\n    }\n\n    func testComparingSockaddrs() throws {\n        let first = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let third = try SocketAddress(unixDomainSocketPath: \"/definitely/a/path\")\n\n        guard case .v4(let firstAddress) = first else {\n            XCTFail(\"Unable to extract IPv4 address\")\n            return\n        }\n        guard case .v6(let secondAddress) = second else {\n            XCTFail(\"Unable to extract IPv6 address\")\n            return\n        }\n        guard case .unixDomainSocket(let thirdAddress) = third else {\n            XCTFail(\"Unable to extract UDS address\")\n            return\n        }\n\n        let firstIPAddress = firstAddress.address\n        let secondIPAddress = secondAddress.address\n        let thirdIPAddress = thirdAddress.address\n\n        first.withSockAddr { outerAddr, outerSize in\n            __testOnly_withSockAddr(firstIPAddress) { innerAddr, innerSize in\n                XCTAssertEqual(outerSize, innerSize)\n                XCTAssertEqual(memcmp(innerAddr, outerAddr, min(outerSize, innerSize)), 0)\n                XCTAssertNotEqual(outerAddr, innerAddr)\n            }\n        }\n        second.withSockAddr { outerAddr, outerSize in\n            __testOnly_withSockAddr(secondIPAddress) { innerAddr, innerSize in\n                XCTAssertEqual(outerSize, innerSize)\n                XCTAssertEqual(memcmp(innerAddr, outerAddr, min(outerSize, innerSize)), 0)\n                XCTAssertNotEqual(outerAddr, innerAddr)\n            }\n        }\n        third.withSockAddr { outerAddr, outerSize in\n            thirdIPAddress.withSockAddr { innerAddr, innerSize in\n                XCTAssertEqual(outerSize, innerSize)\n                XCTAssertEqual(memcmp(innerAddr, outerAddr, min(outerSize, innerSize)), 0)\n                XCTAssertNotEqual(outerAddr, innerAddr)\n            }\n        }\n    }\n\n    func testEqualSocketAddresses() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"00:00::1\", port: 80)\n        let third = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n        let fourth = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n        let fifth = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n        let sixth = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n\n        XCTAssertEqual(first, second)\n        XCTAssertEqual(third, fourth)\n        XCTAssertEqual(fifth, sixth)\n    }\n\n    func testUnequalAddressesOnPort() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"::1\", port: 443)\n        let third = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        let fourth = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n\n        XCTAssertNotEqual(first, second)\n        XCTAssertNotEqual(third, fourth)\n    }\n\n    func testUnequalOnAddress() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"::2\", port: 80)\n        let third = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n        let fourth = try SocketAddress(ipAddress: \"127.0.0.2\", port: 443)\n        let fifth = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n        let sixth = try SocketAddress(unixDomainSocketPath: \"/var/tmq\")\n\n        XCTAssertNotEqual(first, second)\n        XCTAssertNotEqual(third, fourth)\n        XCTAssertNotEqual(fifth, sixth)\n    }\n\n    func testHashEqualSocketAddresses() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"00:00::1\", port: 80)\n        let third = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n        let fourth = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n        let fifth = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n        let sixth = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n\n        let set: Set<SocketAddress> = [first, second, third, fourth, fifth, sixth]\n        XCTAssertEqual(set.count, 3)\n        XCTAssertEqual(set, [first, third, fifth])\n        XCTAssertEqual(set, [second, fourth, sixth])\n    }\n\n    func testHashUnequalAddressesOnPort() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"::1\", port: 443)\n        let third = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        let fourth = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n\n        let set: Set<SocketAddress> = [first, second, third, fourth]\n        XCTAssertEqual(set.count, 4)\n    }\n\n    func testHashUnequalOnAddress() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"::2\", port: 80)\n        let third = try SocketAddress(ipAddress: \"127.0.0.1\", port: 443)\n        let fourth = try SocketAddress(ipAddress: \"127.0.0.2\", port: 443)\n        let fifth = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n        let sixth = try SocketAddress(unixDomainSocketPath: \"/var/tmq\")\n\n        let set: Set<SocketAddress> = [first, second, third, fourth, fifth, sixth]\n        XCTAssertEqual(set.count, 6)\n    }\n\n    func testUnequalAcrossFamilies() throws {\n        let first = try SocketAddress(ipAddress: \"::1\", port: 80)\n        let second = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        let third = try SocketAddress(unixDomainSocketPath: \"/var/tmp\")\n\n        XCTAssertNotEqual(first, second)\n        XCTAssertNotEqual(second, third)\n        // By the transitive property first != third, but let's protect against me being an idiot\n        XCTAssertNotEqual(third, first)\n    }\n\n    func testUnixSocketAddressIgnoresTrailingJunk() throws {\n        var addr = sockaddr_un()\n        addr.sun_family = sa_family_t(NIOBSDSocket.AddressFamily.unix.rawValue)\n        let pathBytes: [UInt8] = \"/var/tmp\".utf8 + [0]\n\n        pathBytes.withUnsafeBufferPointer { srcPtr in\n            withUnsafeMutablePointer(to: &addr.sun_path) { dstPtr in\n                dstPtr.withMemoryRebound(to: UInt8.self, capacity: srcPtr.count) { dstPtr in\n                    dstPtr.update(from: srcPtr.baseAddress!, count: srcPtr.count)\n                }\n            }\n        }\n\n        let first = SocketAddress(addr)\n\n        // Now poke a random byte at the end. This should be ignored, as that's uninitialized memory.\n        addr.sun_path.100 = 60\n        let second = SocketAddress(addr)\n\n        XCTAssertEqual(first, second)\n        XCTAssertEqual(first.hashValue, second.hashValue)\n    }\n\n    func testPortAccessor() throws {\n        XCTAssertEqual(try SocketAddress(ipAddress: \"127.0.0.1\", port: 80).port, 80)\n        XCTAssertEqual(try SocketAddress(ipAddress: \"::1\", port: 80).port, 80)\n        XCTAssertEqual(try SocketAddress(unixDomainSocketPath: \"/definitely/a/path\").port, nil)\n    }\n\n    func testCanMutateSockaddrStorage() throws {\n        var storage = sockaddr_storage()\n        XCTAssertEqual(storage.ss_family, 0)\n        __testOnly_withMutableSockAddr(&storage) { (addr, _) in\n            addr.pointee.sa_family = sa_family_t(NIOBSDSocket.AddressFamily.unix.rawValue)\n        }\n        XCTAssertEqual(storage.ss_family, sa_family_t(NIOBSDSocket.AddressFamily.unix.rawValue))\n    }\n\n    func testPortIsMutable() throws {\n        var ipV4 = try SocketAddress(ipAddress: \"127.0.0.1\", port: 80)\n        var ipV6 = try SocketAddress(ipAddress: \"::1\", port: 80)\n        var unix = try SocketAddress(unixDomainSocketPath: \"/definitely/a/path\")\n\n        ipV4.port = 81\n        ipV6.port = 81\n\n        XCTAssertEqual(ipV4.port, 81)\n        XCTAssertEqual(ipV6.port, 81)\n\n        ipV4.port = nil\n        ipV6.port = nil\n        unix.port = nil\n\n        XCTAssertEqual(ipV4.port, 0)\n        XCTAssertEqual(ipV6.port, 0)\n        XCTAssertNil(unix.port)\n    }\n\n    func testCanCreateIPv4MaskFromPrefix() throws {\n        // This function is simple enough that we can simply test it for all valid inputs.\n        let vectors: [(Int, SocketAddress)] = [\n            (0, try SocketAddress(ipAddress: \"0.0.0.0\", port: 0)),\n            (1, try SocketAddress(ipAddress: \"128.0.0.0\", port: 0)),\n            (2, try SocketAddress(ipAddress: \"192.0.0.0\", port: 0)),\n            (3, try SocketAddress(ipAddress: \"224.0.0.0\", port: 0)),\n            (4, try SocketAddress(ipAddress: \"240.0.0.0\", port: 0)),\n            (5, try SocketAddress(ipAddress: \"248.0.0.0\", port: 0)),\n            (6, try SocketAddress(ipAddress: \"252.0.0.0\", port: 0)),\n            (7, try SocketAddress(ipAddress: \"254.0.0.0\", port: 0)),\n            (8, try SocketAddress(ipAddress: \"255.0.0.0\", port: 0)),\n            (9, try SocketAddress(ipAddress: \"255.128.0.0\", port: 0)),\n            (10, try SocketAddress(ipAddress: \"255.192.0.0\", port: 0)),\n            (11, try SocketAddress(ipAddress: \"255.224.0.0\", port: 0)),\n            (12, try SocketAddress(ipAddress: \"255.240.0.0\", port: 0)),\n            (13, try SocketAddress(ipAddress: \"255.248.0.0\", port: 0)),\n            (14, try SocketAddress(ipAddress: \"255.252.0.0\", port: 0)),\n            (15, try SocketAddress(ipAddress: \"255.254.0.0\", port: 0)),\n            (16, try SocketAddress(ipAddress: \"255.255.0.0\", port: 0)),\n            (17, try SocketAddress(ipAddress: \"255.255.128.0\", port: 0)),\n            (18, try SocketAddress(ipAddress: \"255.255.192.0\", port: 0)),\n            (19, try SocketAddress(ipAddress: \"255.255.224.0\", port: 0)),\n            (20, try SocketAddress(ipAddress: \"255.255.240.0\", port: 0)),\n            (21, try SocketAddress(ipAddress: \"255.255.248.0\", port: 0)),\n            (22, try SocketAddress(ipAddress: \"255.255.252.0\", port: 0)),\n            (23, try SocketAddress(ipAddress: \"255.255.254.0\", port: 0)),\n            (24, try SocketAddress(ipAddress: \"255.255.255.0\", port: 0)),\n            (25, try SocketAddress(ipAddress: \"255.255.255.128\", port: 0)),\n            (26, try SocketAddress(ipAddress: \"255.255.255.192\", port: 0)),\n            (27, try SocketAddress(ipAddress: \"255.255.255.224\", port: 0)),\n            (28, try SocketAddress(ipAddress: \"255.255.255.240\", port: 0)),\n            (29, try SocketAddress(ipAddress: \"255.255.255.248\", port: 0)),\n            (30, try SocketAddress(ipAddress: \"255.255.255.252\", port: 0)),\n            (31, try SocketAddress(ipAddress: \"255.255.255.254\", port: 0)),\n            (32, try SocketAddress(ipAddress: \"255.255.255.255\", port: 0)),\n        ]\n\n        for vector in vectors {\n            XCTAssertEqual(SocketAddress(ipv4MaskForPrefix: vector.0), vector.1)\n        }\n    }\n\n    func testCanCreateIPv6MaskFromPrefix() throws {\n        // This function is simple enough that we can simply test it for all valid inputs.\n        let vectors: [(Int, SocketAddress)] = [\n            (0, try SocketAddress(ipAddress: \"0000::\", port: 0)),\n            (1, try SocketAddress(ipAddress: \"8000::\", port: 0)),\n            (2, try SocketAddress(ipAddress: \"c000::\", port: 0)),\n            (3, try SocketAddress(ipAddress: \"e000::\", port: 0)),\n            (4, try SocketAddress(ipAddress: \"f000::\", port: 0)),\n            (5, try SocketAddress(ipAddress: \"f800::\", port: 0)),\n            (6, try SocketAddress(ipAddress: \"fc00::\", port: 0)),\n            (7, try SocketAddress(ipAddress: \"fe00::\", port: 0)),\n            (8, try SocketAddress(ipAddress: \"ff00::\", port: 0)),\n            (9, try SocketAddress(ipAddress: \"ff80::\", port: 0)),\n            (10, try SocketAddress(ipAddress: \"ffc0::\", port: 0)),\n            (11, try SocketAddress(ipAddress: \"ffe0::\", port: 0)),\n            (12, try SocketAddress(ipAddress: \"fff0::\", port: 0)),\n            (13, try SocketAddress(ipAddress: \"fff8::\", port: 0)),\n            (14, try SocketAddress(ipAddress: \"fffc::\", port: 0)),\n            (15, try SocketAddress(ipAddress: \"fffe::\", port: 0)),\n            (16, try SocketAddress(ipAddress: \"ffff::\", port: 0)),\n            (17, try SocketAddress(ipAddress: \"ffff:8000::\", port: 0)),\n            (18, try SocketAddress(ipAddress: \"ffff:c000::\", port: 0)),\n            (19, try SocketAddress(ipAddress: \"ffff:e000::\", port: 0)),\n            (20, try SocketAddress(ipAddress: \"ffff:f000::\", port: 0)),\n            (21, try SocketAddress(ipAddress: \"ffff:f800::\", port: 0)),\n            (22, try SocketAddress(ipAddress: \"ffff:fc00::\", port: 0)),\n            (23, try SocketAddress(ipAddress: \"ffff:fe00::\", port: 0)),\n            (24, try SocketAddress(ipAddress: \"ffff:ff00::\", port: 0)),\n            (25, try SocketAddress(ipAddress: \"ffff:ff80::\", port: 0)),\n            (26, try SocketAddress(ipAddress: \"ffff:ffc0::\", port: 0)),\n            (27, try SocketAddress(ipAddress: \"ffff:ffe0::\", port: 0)),\n            (28, try SocketAddress(ipAddress: \"ffff:fff0::\", port: 0)),\n            (29, try SocketAddress(ipAddress: \"ffff:fff8::\", port: 0)),\n            (30, try SocketAddress(ipAddress: \"ffff:fffc::\", port: 0)),\n            (31, try SocketAddress(ipAddress: \"ffff:fffe::\", port: 0)),\n            (32, try SocketAddress(ipAddress: \"ffff:ffff::\", port: 0)),\n            (33, try SocketAddress(ipAddress: \"ffff:ffff:8000::\", port: 0)),\n            (34, try SocketAddress(ipAddress: \"ffff:ffff:c000::\", port: 0)),\n            (35, try SocketAddress(ipAddress: \"ffff:ffff:e000::\", port: 0)),\n            (36, try SocketAddress(ipAddress: \"ffff:ffff:f000::\", port: 0)),\n            (37, try SocketAddress(ipAddress: \"ffff:ffff:f800::\", port: 0)),\n            (38, try SocketAddress(ipAddress: \"ffff:ffff:fc00::\", port: 0)),\n            (39, try SocketAddress(ipAddress: \"ffff:ffff:fe00::\", port: 0)),\n            (40, try SocketAddress(ipAddress: \"ffff:ffff:ff00::\", port: 0)),\n            (41, try SocketAddress(ipAddress: \"ffff:ffff:ff80::\", port: 0)),\n            (42, try SocketAddress(ipAddress: \"ffff:ffff:ffc0::\", port: 0)),\n            (43, try SocketAddress(ipAddress: \"ffff:ffff:ffe0::\", port: 0)),\n            (44, try SocketAddress(ipAddress: \"ffff:ffff:fff0::\", port: 0)),\n            (45, try SocketAddress(ipAddress: \"ffff:ffff:fff8::\", port: 0)),\n            (46, try SocketAddress(ipAddress: \"ffff:ffff:fffc::\", port: 0)),\n            (47, try SocketAddress(ipAddress: \"ffff:ffff:fffe::\", port: 0)),\n            (48, try SocketAddress(ipAddress: \"ffff:ffff:ffff::\", port: 0)),\n            (49, try SocketAddress(ipAddress: \"ffff:ffff:ffff:8000::\", port: 0)),\n            (50, try SocketAddress(ipAddress: \"ffff:ffff:ffff:c000::\", port: 0)),\n            (51, try SocketAddress(ipAddress: \"ffff:ffff:ffff:e000::\", port: 0)),\n            (52, try SocketAddress(ipAddress: \"ffff:ffff:ffff:f000::\", port: 0)),\n            (53, try SocketAddress(ipAddress: \"ffff:ffff:ffff:f800::\", port: 0)),\n            (54, try SocketAddress(ipAddress: \"ffff:ffff:ffff:fc00::\", port: 0)),\n            (55, try SocketAddress(ipAddress: \"ffff:ffff:ffff:fe00::\", port: 0)),\n            (56, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ff00::\", port: 0)),\n            (57, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ff80::\", port: 0)),\n            (58, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffc0::\", port: 0)),\n            (59, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffe0::\", port: 0)),\n            (60, try SocketAddress(ipAddress: \"ffff:ffff:ffff:fff0::\", port: 0)),\n            (61, try SocketAddress(ipAddress: \"ffff:ffff:ffff:fff8::\", port: 0)),\n            (62, try SocketAddress(ipAddress: \"ffff:ffff:ffff:fffc::\", port: 0)),\n            (63, try SocketAddress(ipAddress: \"ffff:ffff:ffff:fffe::\", port: 0)),\n            (64, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff::\", port: 0)),\n            (65, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:8000::\", port: 0)),\n            (66, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:c000::\", port: 0)),\n            (67, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:e000::\", port: 0)),\n            (68, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:f000::\", port: 0)),\n            (69, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:f800::\", port: 0)),\n            (70, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:fc00::\", port: 0)),\n            (71, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:fe00::\", port: 0)),\n            (72, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ff00::\", port: 0)),\n            (73, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ff80::\", port: 0)),\n            (74, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffc0::\", port: 0)),\n            (75, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffe0::\", port: 0)),\n            (76, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:fff0::\", port: 0)),\n            (77, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:fff8::\", port: 0)),\n            (78, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:fffc::\", port: 0)),\n            (79, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:fffe::\", port: 0)),\n            (80, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff::\", port: 0)),\n            (81, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:8000::\", port: 0)),\n            (82, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:c000::\", port: 0)),\n            (83, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:e000::\", port: 0)),\n            (84, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:f000::\", port: 0)),\n            (85, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:f800::\", port: 0)),\n            (86, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:fc00::\", port: 0)),\n            (87, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:fe00::\", port: 0)),\n            (88, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ff00::\", port: 0)),\n            (89, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ff80::\", port: 0)),\n            (90, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffc0::\", port: 0)),\n            (91, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffe0::\", port: 0)),\n            (92, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:fff0::\", port: 0)),\n            (93, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:fff8::\", port: 0)),\n            (94, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:fffc::\", port: 0)),\n            (95, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:fffe::\", port: 0)),\n            (96, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff::\", port: 0)),\n            (97, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:8000::\", port: 0)),\n            (98, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:c000::\", port: 0)),\n            (99, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:e000::\", port: 0)),\n            (100, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:f000::\", port: 0)),\n            (101, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:f800::\", port: 0)),\n            (102, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:fc00::\", port: 0)),\n            (103, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:fe00::\", port: 0)),\n            (104, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ff00::\", port: 0)),\n            (105, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ff80::\", port: 0)),\n            (106, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffc0::\", port: 0)),\n            (107, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffe0::\", port: 0)),\n            (108, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:fff0::\", port: 0)),\n            (109, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:fff8::\", port: 0)),\n            (110, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:fffc::\", port: 0)),\n            (111, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:fffe::\", port: 0)),\n            (112, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff::\", port: 0)),\n            (113, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000\", port: 0)),\n            (114, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:c000\", port: 0)),\n            (115, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:e000\", port: 0)),\n            (116, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:f000\", port: 0)),\n            (117, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:f800\", port: 0)),\n            (118, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fc00\", port: 0)),\n            (119, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fe00\", port: 0)),\n            (120, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00\", port: 0)),\n            (121, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80\", port: 0)),\n            (122, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0\", port: 0)),\n            (123, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0\", port: 0)),\n            (124, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0\", port: 0)),\n            (125, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8\", port: 0)),\n            (126, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc\", port: 0)),\n            (127, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe\", port: 0)),\n            (128, try SocketAddress(ipAddress: \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\", port: 0)),\n        ]\n\n        for vector in vectors {\n            XCTAssertEqual(SocketAddress(ipv6MaskForPrefix: vector.0), vector.1)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SocketChannelTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOPosix\n\nextension Array {\n    /// A helper function that asserts that a predicate is true for all elements.\n    fileprivate func assertAll(_ predicate: (Element) -> Bool) {\n        for (index, element) in self.enumerated() {\n            if !predicate(element) {\n                XCTFail(\"Entry \\(index) failed predicate, contents: \\(element)\")\n            }\n        }\n    }\n}\n\nfinal class SocketChannelTest: XCTestCase {\n    /// Validate that channel options are applied asynchronously.\n    public func testAsyncSetOption() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        // Create two channels with different event loops.\n        let channelA = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        let channelB: Channel = try {\n            while true {\n                let channel = try assertNoThrowWithValue(\n                    ServerBootstrap(group: group)\n                        .bind(host: \"127.0.0.1\", port: 0)\n                        .wait()\n                )\n                if channel.eventLoop !== channelA.eventLoop {\n                    return channel\n                }\n            }\n        }()\n        XCTAssert(channelA.eventLoop !== channelB.eventLoop)\n\n        // Ensure we can dispatch two concurrent set option's on each others\n        // event loops.\n        let condition = ManagedAtomic(0)\n        let futureA = channelA.eventLoop.submit {\n            condition.wrappingIncrement(ordering: .relaxed)\n            while condition.load(ordering: .relaxed) < 2 {}\n            _ = channelB.setOption(.backlog, value: 1)\n        }\n        let futureB = channelB.eventLoop.submit {\n            condition.wrappingIncrement(ordering: .relaxed)\n            while condition.load(ordering: .relaxed) < 2 {}\n            _ = channelA.setOption(.backlog, value: 1)\n        }\n        try futureA.wait()\n        try futureB.wait()\n    }\n\n    public func testDelayedConnectSetsUpRemotePeerAddress() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .serverChannelOption(.backlog, value: 256)\n                .bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n\n        // The goal of this test is to try to trigger at least one channel to have connection setup that is not\n        // instantaneous. Due to the design of NIO this is not really observable to us, and due to the complex\n        // overlapping interactions between SYN queues and loopback interfaces in modern kernels it's not\n        // trivial to trigger this behaviour. The easiest thing we can do here is to try to slow the kernel down\n        // enough that a connection eventually is delayed. To do this we're going to submit 50 connections more\n        // or less at once.\n        var clientConnectionFutures: [EventLoopFuture<Channel>] = []\n        clientConnectionFutures.reserveCapacity(50)\n        let clientBootstrap = ClientBootstrap(group: group)\n\n        for _ in 0..<50 {\n            let conn = clientBootstrap.connect(to: serverChannel.localAddress!)\n            clientConnectionFutures.append(conn)\n        }\n\n        let remoteAddresses = try clientConnectionFutures.map { try $0.wait() }.map { $0.remoteAddress }\n\n        // Now we want to check that they're all the same. The bug we're catching here is one where delayed connection\n        // setup causes us to get nil as the remote address, even though we connected (and we did, as these are all\n        // up right now).\n        remoteAddresses.assertAll { $0 != nil }\n    }\n\n    public func testAcceptFailsWithECONNABORTED() throws {\n        try assertAcceptFails(error: ECONNABORTED, active: true)\n    }\n\n    public func testAcceptFailsWithEMFILE() throws {\n        try assertAcceptFails(error: EMFILE, active: true)\n    }\n\n    public func testAcceptFailsWithENFILE() throws {\n        try assertAcceptFails(error: ENFILE, active: true)\n    }\n\n    public func testAcceptFailsWithENOBUFS() throws {\n        try assertAcceptFails(error: ENOBUFS, active: true)\n    }\n\n    public func testAcceptFailsWithENOMEM() throws {\n        try assertAcceptFails(error: ENOMEM, active: true)\n    }\n\n    public func testAcceptFailsWithEFAULT() throws {\n        try assertAcceptFails(error: EFAULT, active: false)\n    }\n\n    private func assertAcceptFails(error: Int32, active: Bool) throws {\n        final class AcceptHandler: ChannelInboundHandler {\n            typealias InboundIn = Channel\n            typealias InboundOut = Channel\n\n            private let promise: EventLoopPromise<IOError>\n\n            init(_ promise: EventLoopPromise<IOError>) {\n                self.promise = promise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTFail(\"Should not accept a Channel but got \\(Self.unwrapInboundIn(data))\")\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                if let ioError = error as? IOError {\n                    self.promise.succeed(ioError)\n                }\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let socket = try NonAcceptingServerSocket(errors: [error])\n        let serverChannel = try assertNoThrowWithValue(\n            ServerSocketChannel(\n                serverSocket: socket,\n                eventLoop: group.next() as! SelectableEventLoop,\n                group: group\n            )\n        )\n        let promise = serverChannel.eventLoop.makePromise(of: IOError.self)\n\n        XCTAssertNoThrow(\n            try serverChannel.eventLoop.flatSubmit {\n                serverChannel.eventLoop.makeCompletedFuture {\n                    try serverChannel.pipeline.syncOperations.addHandler(AcceptHandler(promise))\n                }.flatMap {\n                    serverChannel.register()\n                }.flatMap {\n                    serverChannel.bind(to: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n                }\n            }.wait() as Void\n        )\n\n        XCTAssertEqual(\n            active,\n            try serverChannel.eventLoop.submit {\n                serverChannel.readable()\n                return serverChannel.isActive\n            }.wait()\n        )\n\n        if active {\n            XCTAssertNoThrow(try serverChannel.close().wait())\n        }\n\n        let ioError = try promise.futureResult.wait()\n        XCTAssertEqual(error, ioError.errnoCode)\n    }\n\n    public func testSetGetOptionClosedServerSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        // Create two channels with different event loops.\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        XCTAssertNoThrow(\n            try assertSetGetOptionOnOpenAndClosed(\n                channel: clientChannel,\n                option: .allowRemoteHalfClosure,\n                value: true\n            )\n        )\n        XCTAssertNoThrow(\n            try assertSetGetOptionOnOpenAndClosed(\n                channel: serverChannel,\n                option: .backlog,\n                value: 100\n            )\n        )\n    }\n\n    public func testConnect() throws {\n        final class ActiveVerificationHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias InboundOut = ByteBuffer\n\n            private let promise: EventLoopPromise<Void>\n\n            init(_ promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                promise.succeed(())\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class ConnectSocket: Socket {\n            private let promise: EventLoopPromise<Void>\n            init(promise: EventLoopPromise<Void>) throws {\n                self.promise = promise\n                try super.init(protocolFamily: .inet, type: .stream)\n            }\n\n            override func connect(to address: SocketAddress) throws -> Bool {\n                self.promise.succeed(())\n                return true\n            }\n        }\n\n        let eventLoop = group.next()\n        let connectPromise = eventLoop.makePromise(of: Void.self)\n\n        let channel = try assertNoThrowWithValue(\n            SocketChannel(\n                socket: ConnectSocket(promise: connectPromise),\n                parent: nil,\n                eventLoop: eventLoop as! SelectableEventLoop\n            )\n        )\n        let promise = channel.eventLoop.makePromise(of: Void.self)\n\n        XCTAssertNoThrow(\n            try channel.eventLoop.flatSubmit {\n                // We need to hop to the EventLoop here to make sure that we don't get an ECONNRESET before we manage\n                // to close.\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(ActiveVerificationHandler(promise))\n                }.flatMap {\n                    channel.register()\n                }.flatMap {\n                    channel.connect(to: try! SocketAddress(ipAddress: \"127.0.0.1\", port: 9999))\n                }.flatMap {\n                    channel.close()\n                }\n            }.wait()\n        )\n\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n        XCTAssertNoThrow(try promise.futureResult.wait())\n        XCTAssertNoThrow(try connectPromise.futureResult.wait())\n    }\n\n    public func testWriteServerSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        XCTAssertThrowsError(try serverChannel.writeAndFlush(\"test\").wait()) { error in\n            XCTAssertEqual(.operationUnsupported, error as? ChannelError)\n        }\n        try serverChannel.close().wait()\n    }\n\n    public func testWriteAndFlushServerSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        XCTAssertThrowsError(try serverChannel.writeAndFlush(\"test\").wait()) { error in\n            XCTAssertEqual(.operationUnsupported, error as? ChannelError)\n        }\n        try serverChannel.close().wait()\n    }\n\n    public func testConnectServerSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        XCTAssertThrowsError(try serverChannel.writeAndFlush(\"test\").wait()) { error in\n            XCTAssertEqual(.operationUnsupported, error as? ChannelError)\n        }\n    }\n\n    public func testCloseDuringWriteFailure() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        // Put a write in the channel but don't flush it. We're then going to\n        // close the channel. This should trigger an error callback that will\n        // re-close the channel, which should fail with `alreadyClosed`.\n        var buffer = clientChannel.allocator.buffer(capacity: 12)\n        buffer.writeStaticString(\"hello\")\n        let writeFut = clientChannel.write(buffer).map {\n            XCTFail(\"Must not succeed\")\n        }.flatMapError { error in\n            XCTAssertEqual(error as? ChannelError, ChannelError.ioOnClosedChannel)\n            return clientChannel.close()\n        }\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        XCTAssertThrowsError(try writeFut.wait()) { error in\n            XCTAssertEqual(.alreadyClosed, error as? ChannelError)\n        }\n    }\n\n    public func testWithConfiguredStreamSocket() throws {\n        let didAccept = ConditionLock<Int>(value: 0)\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverSock = try Socket(protocolFamily: .inet, type: .stream)\n        try serverSock.bind(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n        let serverChannelFuture = try serverSock.withUnsafeHandle {\n            ServerBootstrap(group: group)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let acquiredLock = didAccept.lock(whenValue: 0, timeoutSeconds: 1)\n                        XCTAssertTrue(acquiredLock)\n                        didAccept.unlock(withValue: 1)\n                    }\n                }\n                .withBoundSocket(dup($0))\n        }\n        try serverSock.close()\n        let serverChannel = try serverChannelFuture.wait()\n\n        let clientSock = try Socket(protocolFamily: .inet, type: .stream)\n        let connected = try clientSock.connect(to: serverChannel.localAddress!)\n        XCTAssertEqual(connected, true)\n        let clientChannelFuture = try clientSock.withUnsafeHandle {\n            ClientBootstrap(group: group).withConnectedSocket(dup($0))\n        }\n        try clientSock.close()\n\n        // At this point we need to wait not just for the client connection to be created\n        // but also for the server connection to come in. Otherwise we risk a race where the\n        // client connection has come up but the server connection hasn't yet, leading to the\n        // server channel close below causing the server to never accept the inbound channel\n        // and leading to an unexpected error on close.\n        let clientChannel = try clientChannelFuture.wait()\n        XCTAssertEqual(true, clientChannel.isActive)\n\n        let acquiredLock = didAccept.lock(whenValue: 1, timeoutSeconds: 1)\n        XCTAssertTrue(acquiredLock)\n        didAccept.unlock()\n\n        try serverChannel.close().wait()\n        try clientChannel.close().wait()\n    }\n\n    public func testWithConfiguredDatagramSocket() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverSock = try Socket(protocolFamily: .inet, type: .datagram)\n        try serverSock.bind(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n        let serverChannelFuture = try serverSock.withUnsafeHandle {\n            DatagramBootstrap(group: group).withBoundSocket(dup($0))\n        }\n        try serverSock.close()\n        let serverChannel = try serverChannelFuture.wait()\n\n        XCTAssertEqual(true, serverChannel.isActive)\n\n        try serverChannel.close().wait()\n    }\n\n    public func testPendingConnectNotificationOrder() throws {\n\n        class NotificationOrderHandler: ChannelDuplexHandler {\n            typealias InboundIn = Never\n            typealias OutboundIn = Never\n\n            private var connectPromise: EventLoopPromise<Void>?\n\n            public func channelInactive(context: ChannelHandlerContext) {\n                if let connectPromise = self.connectPromise {\n                    XCTAssertTrue(connectPromise.futureResult.isFulfilled)\n                } else {\n                    XCTFail(\"connect(...) not called before\")\n                }\n            }\n\n            public func connect(\n                context: ChannelHandlerContext,\n                to address: SocketAddress,\n                promise: EventLoopPromise<Void>?\n            ) {\n                XCTAssertNil(self.connectPromise)\n                self.connectPromise = promise\n                context.connect(to: address, promise: promise)\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                XCTAssertNil(self.connectPromise)\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                if let connectPromise = self.connectPromise {\n                    XCTAssertTrue(connectPromise.futureResult.isFulfilled)\n                } else {\n                    XCTFail(\"connect(...) not called before\")\n                }\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer { XCTAssertNoThrow(try serverChannel.close().wait()) }\n\n        let eventLoop = group.next()\n        let promise = eventLoop.makePromise(of: Void.self)\n\n        class ConnectPendingSocket: Socket {\n            let promise: EventLoopPromise<Void>\n            init(promise: EventLoopPromise<Void>) throws {\n                self.promise = promise\n                try super.init(protocolFamily: .inet, type: .stream)\n            }\n\n            override func connect(to address: SocketAddress) throws -> Bool {\n                // We want to return false here to have a pending connect.\n                _ = try super.connect(to: address)\n                self.promise.succeed(())\n                return false\n            }\n        }\n\n        let channel = try SocketChannel(\n            socket: ConnectPendingSocket(promise: promise),\n            parent: nil,\n            eventLoop: eventLoop as! SelectableEventLoop\n        )\n        let connectPromise = channel.eventLoop.makePromise(of: Void.self)\n        let closePromise = channel.eventLoop.makePromise(of: Void.self)\n\n        closePromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            XCTAssertTrue(connectPromise.futureResult.isFulfilled)\n        }\n        connectPromise.futureResult.whenComplete { (_: Result<Void, Error>) in\n            XCTAssertFalse(closePromise.futureResult.isFulfilled)\n        }\n\n        let added = channel.eventLoop.submit {\n            try channel.pipeline.syncOperations.addHandler(NotificationOrderHandler())\n        }\n\n        XCTAssertNoThrow(try added.wait())\n\n        // We need to call submit {...} here to ensure then {...} is called while on the EventLoop already to not have\n        // a ECONNRESET sneak in.\n        XCTAssertNoThrow(\n            try channel.eventLoop.flatSubmit {\n                channel.register().map { () -> Void in\n                    channel.connect(to: serverChannel.localAddress!, promise: connectPromise)\n                }.map { () -> Void in\n                    XCTAssertFalse(connectPromise.futureResult.isFulfilled)\n                    // The close needs to happen in the then { ... } block to ensure we close the channel\n                    // before we have the chance to register it for .write.\n                    channel.close(promise: closePromise)\n                }\n            }.wait() as Void\n        )\n\n        XCTAssertThrowsError(try connectPromise.futureResult.wait()) { error in\n            XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)\n        }\n        XCTAssertNoThrow(try closePromise.futureResult.wait())\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n        XCTAssertNoThrow(try promise.futureResult.wait())\n    }\n\n    public func testLocalAndRemoteAddressNotNilInChannelInactiveAndHandlerRemoved() throws {\n\n        class AddressVerificationHandler: ChannelInboundHandler {\n            typealias InboundIn = Never\n            typealias OutboundIn = Never\n\n            enum HandlerState {\n                case created\n                case inactive\n                case removed\n            }\n\n            let promise: EventLoopPromise<Void>\n            var state = HandlerState.created\n\n            init(promise: EventLoopPromise<Void>) {\n                self.promise = promise\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                XCTAssertNotNil(context.localAddress)\n                XCTAssertNotNil(context.remoteAddress)\n                XCTAssertEqual(.created, state)\n                state = .inactive\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertNotNil(context.localAddress)\n                XCTAssertNotNil(context.remoteAddress)\n                XCTAssertEqual(.inactive, state)\n                state = .removed\n\n                let loopBoundContext = context.loopBound\n                context.channel.closeFuture.assumeIsolated().whenComplete { (_: Result<Void, Error>) in\n                    let context = loopBoundContext.value\n                    XCTAssertNil(context.localAddress)\n                    XCTAssertNil(context.remoteAddress)\n\n                    self.promise.succeed(())\n                }\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let promise = group.next().makePromise(of: Void.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .childChannelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        let handler = AddressVerificationHandler(promise: promise)\n                        return try channel.pipeline.syncOperations.addHandler(handler)\n                    }\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n        defer { XCTAssertNoThrow(try serverChannel.close().wait()) }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        XCTAssertNoThrow(try clientChannel.close().wait())\n        XCTAssertNoThrow(try promise.futureResult.wait())\n    }\n\n    func testSocketFlagNONBLOCKWorks() throws {\n        var socket = try assertNoThrowWithValue(try ServerSocket(protocolFamily: .inet, setNonBlocking: true))\n        XCTAssertNoThrow(\n            try socket.withUnsafeHandle { fd in\n                let flags = try assertNoThrowWithValue(Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0))\n                XCTAssertEqual(O_NONBLOCK, flags & O_NONBLOCK)\n            }\n        )\n        XCTAssertNoThrow(try socket.close())\n\n        socket = try assertNoThrowWithValue(ServerSocket(protocolFamily: .inet, setNonBlocking: false))\n        XCTAssertNoThrow(\n            try socket.withUnsafeHandle { fd in\n                var flags = try assertNoThrowWithValue(Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0))\n                XCTAssertEqual(0, flags & O_NONBLOCK)\n                let ret = try assertNoThrowWithValue(\n                    Posix.fcntl(descriptor: fd, command: F_SETFL, value: flags | O_NONBLOCK)\n                )\n                XCTAssertEqual(0, ret)\n                flags = try assertNoThrowWithValue(Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0))\n                XCTAssertEqual(O_NONBLOCK, flags & O_NONBLOCK)\n            }\n        )\n        XCTAssertNoThrow(try socket.close())\n    }\n\n    func testInstantTCPConnectionResetThrowsError() throws {\n        #if !os(Linux) && !os(Android)\n        // This test checks that we correctly fail with an error rather than\n        // asserting or silently ignoring if a client aborts the connection\n        // early with a RST before accept(). The behaviour is the same as closing the socket\n        // during the accept. But it is easier to test closing the socket before the accept, than during it.\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        // Handler that checks for the expected error.\n        final class ErrorHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Channel\n            typealias InboundOut = Channel\n\n            private let promise: EventLoopPromise<IOError>\n\n            init(_ promise: EventLoopPromise<IOError>) {\n                self.promise = promise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                XCTFail(\"Should not accept a Channel but got \\(self.unwrapInboundIn(data))\")\n                self.promise.fail(ChannelError.inappropriateOperationForState)  // any old error will do\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                if let ioError = error as? IOError, ioError.errnoCode == EINVAL {\n                    self.promise.succeed(ioError)\n                } else {\n                    self.promise.fail(error)\n                }\n            }\n        }\n\n        // Build server channel; after this point the server called listen()\n        let serverPromise = group.next().makePromise(of: IOError.self)\n        let serverChannel = try assertNoThrowWithValue(\n            ServerBootstrap(group: group)\n                .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n                .serverChannelOption(.backlog, value: 256)\n                .serverChannelOption(.autoRead, value: false)\n                .serverChannelInitializer {\n                    channel in channel.pipeline.addHandler(ErrorHandler(serverPromise))\n                }\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        )\n\n        // Make a client socket to mess with the server. Setting SO_LINGER forces RST instead of FIN.\n        let clientSocket = try assertNoThrowWithValue(Socket(protocolFamily: .inet, type: .stream))\n        XCTAssertNoThrow(\n            try clientSocket.setOption(level: .socket, name: .so_linger, value: linger(l_onoff: 1, l_linger: 0))\n        )\n        XCTAssertNoThrow(try clientSocket.connect(to: serverChannel.localAddress!))\n        XCTAssertNoThrow(try clientSocket.close())\n\n        // We wait here to allow slow machines to close the socket\n        // We want to ensure the socket is closed before we trigger accept\n        // That will trigger the error that we want to test for\n        group.any().scheduleTask(in: .seconds(1)) {\n            // Trigger accept() in the server\n            serverChannel.read()\n        }\n\n        // Wait for the server to have something\n        XCTAssertThrowsError(try serverPromise.futureResult.wait()) { error in\n            XCTAssert(error is NIOFcntlFailedError)\n        }\n        #endif\n    }\n\n    func testUnprocessedOutboundUserEventFailsOnServerSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let channel = try ServerSocketChannel(\n            eventLoop: group.next() as! SelectableEventLoop,\n            group: group,\n            protocolFamily: .inet\n        )\n        XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"event\").wait()) { (error: Error) in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.operationUnsupported, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testUnprocessedOutboundUserEventFailsOnSocketChannel() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let channel = try SocketChannel(\n            eventLoop: group.next() as! SelectableEventLoop,\n            protocolFamily: .inet\n        )\n        XCTAssertThrowsError(try channel.triggerUserOutboundEvent(\"event\").wait()) { (error: Error) in\n            if let error = error as? ChannelError {\n                XCTAssertEqual(ChannelError.operationUnsupported, error)\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testSetSockOptDoesNotOverrideExistingFlags() throws {\n        let s = try assertNoThrowWithValue(\n            Socket(\n                protocolFamily: .inet,\n                type: .stream,\n                setNonBlocking: false\n            )\n        )\n        // check initial flags\n        XCTAssertNoThrow(\n            try s.withUnsafeHandle { fd in\n                let flags = try Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0)\n                XCTAssertEqual(0, flags & O_NONBLOCK)\n            }\n        )\n\n        // set other random flag\n        XCTAssertNoThrow(\n            try s.withUnsafeHandle { fd in\n                let oldFlags = try Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0)\n                let ret = try Posix.fcntl(descriptor: fd, command: F_SETFL, value: oldFlags | O_ASYNC)\n                XCTAssertEqual(0, ret)\n                let newFlags = try Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0)\n                XCTAssertEqual(O_ASYNC, newFlags & O_ASYNC)\n            }\n        )\n\n        // enable non-blocking\n        XCTAssertNoThrow(try s.setNonBlocking())\n\n        // check both are enabled\n        XCTAssertNoThrow(\n            try s.withUnsafeHandle { fd in\n                let flags = try Posix.fcntl(descriptor: fd, command: F_GETFL, value: 0)\n                XCTAssertEqual(O_ASYNC, flags & O_ASYNC)\n                XCTAssertEqual(O_NONBLOCK, flags & O_NONBLOCK)\n            }\n        )\n\n        XCTAssertNoThrow(try s.close())\n    }\n\n    func testServerChannelDoesNotBreakIfAcceptingFailsWithEINVAL() throws {\n        // regression test for:\n        // - https://github.com/apple/swift-nio/issues/1030\n        // - https://github.com/apple/swift-nio/issues/1598\n        class HandsOutMoodySocketsServerSocket: ServerSocket {\n            let shouldAcceptsFail = ManagedAtomic(true)\n            override func accept(setNonBlocking: Bool = false) throws -> Socket? {\n                XCTAssertTrue(setNonBlocking)\n                if self.shouldAcceptsFail.load(ordering: .relaxed) {\n                    throw NIOFcntlFailedError()\n                } else {\n                    return try Socket(\n                        protocolFamily: .inet,\n                        type: .stream,\n                        setNonBlocking: false\n                    )\n                }\n            }\n        }\n\n        final class CloseAcceptedSocketsHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Channel\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                Self.unwrapInboundIn(data).close(promise: nil)\n            }\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                XCTAssert(error is NIOFcntlFailedError, \"unexpected error: \\(error)\")\n            }\n        }\n\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n        let serverSock = try assertNoThrowWithValue(\n            HandsOutMoodySocketsServerSocket(\n                protocolFamily: .inet,\n                setNonBlocking: true\n            )\n        )\n        let serverChan = try assertNoThrowWithValue(\n            ServerSocketChannel(\n                serverSocket: serverSock,\n                eventLoop: group.next() as! SelectableEventLoop,\n                group: group\n            )\n        )\n        XCTAssertNoThrow(try serverChan.setOption(.maxMessagesPerRead, value: 1).wait())\n        XCTAssertNoThrow(try serverChan.setOption(.autoRead, value: false).wait())\n        XCTAssertNoThrow(try serverChan.register().wait())\n        XCTAssertNoThrow(try serverChan.bind(to: .init(ipAddress: \"127.0.0.1\", port: 0)).wait())\n\n        let eventCounter = EventCounterHandler()\n        XCTAssertNoThrow(try serverChan.pipeline.addHandler(eventCounter).wait())\n        XCTAssertNoThrow(try serverChan.pipeline.addHandler(CloseAcceptedSocketsHandler()).wait())\n\n        XCTAssertEqual([], eventCounter.allTriggeredEvents())\n        XCTAssertNoThrow(\n            try serverChan.eventLoop.submit {\n                serverChan.readable()\n            }.wait()\n        )\n        XCTAssertEqual([\"channelReadComplete\", \"errorCaught\"], eventCounter.allTriggeredEvents())\n        XCTAssertEqual(1, eventCounter.channelReadCompleteCalls)\n        XCTAssertEqual(1, eventCounter.errorCaughtCalls)\n\n        serverSock.shouldAcceptsFail.store(false, ordering: .relaxed)\n\n        XCTAssertNoThrow(\n            try serverChan.eventLoop.submit {\n                serverChan.readable()\n            }.wait()\n        )\n        XCTAssertEqual(\n            [\"errorCaught\", \"channelRead\", \"channelReadComplete\"],\n            eventCounter.allTriggeredEvents()\n        )\n        XCTAssertEqual(1, eventCounter.errorCaughtCalls)\n        XCTAssertEqual(1, eventCounter.channelReadCalls)\n        XCTAssertEqual(2, eventCounter.channelReadCompleteCalls)\n    }\n\n    func testWeAreInterestedInReadEOFWhenChannelIsConnectedOnTheServerSide() throws {\n        guard isEarlyEOFDeliveryWorkingOnThisOS else {\n            #if os(Linux) || os(Android)\n            preconditionFailure(\"this should only ever be entered on Darwin.\")\n            #else\n            return\n            #endif\n        }\n        // This test makes sure that we notice EOFs early, even if we never register for read (by dropping all the reads\n        // on the floor. This is the same test as below but this one is for TCP servers.\n        for mode in [DropAllReadsOnTheFloorHandler.Mode.halfClosureEnabled, .halfClosureDisabled] {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n            defer {\n                XCTAssertNoThrow(try group.syncShutdownGracefully())\n            }\n\n            let channelInactivePromise = group.next().makePromise(of: Void.self)\n            let channelHalfClosedPromise = group.next().makePromise(of: Void.self)\n            let waitUntilWriteFailedPromise = group.next().makePromise(of: Void.self)\n            let channelActivePromise = group.next().makePromise(of: Void.self)\n            if mode == .halfClosureDisabled {\n                // if we don't support half-closure these two promises would otherwise never be fulfilled\n                channelInactivePromise.futureResult.cascade(to: waitUntilWriteFailedPromise)\n                channelInactivePromise.futureResult.cascade(to: channelHalfClosedPromise)\n            }\n            let eventCounter = EventCounterHandler()\n            let numberOfAcceptedChannels = NIOLockedValueBox(0)\n            let server = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .childChannelOption(.allowRemoteHalfClosure, value: mode == .halfClosureEnabled)\n                    .childChannelInitializer { channel in\n                        numberOfAcceptedChannels.withLockedValue { $0 += 1 }\n                        XCTAssertEqual(1, numberOfAcceptedChannels.withLockedValue { $0 })\n                        let drop = DropAllReadsOnTheFloorHandler(\n                            mode: mode,\n                            channelInactivePromise: channelInactivePromise,\n                            channelHalfClosedPromise: channelHalfClosedPromise,\n                            waitUntilWriteFailedPromise: waitUntilWriteFailedPromise,\n                            channelActivePromise: channelActivePromise\n                        )\n                        return channel.pipeline.addHandlers([eventCounter, drop])\n                    }\n                    .bind(to: .init(ipAddress: \"127.0.0.1\", port: 0)).wait()\n            )\n            let client = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .connect(to: server.localAddress!).wait()\n            )\n            XCTAssertNoThrow(\n                try channelActivePromise.futureResult.flatMap { () -> EventLoopFuture<Void> in\n                    XCTAssertTrue(client.isActive)\n                    XCTAssertEqual(\n                        [\"register\", \"channelActive\", \"channelRegistered\"],\n                        eventCounter.allTriggeredEvents()\n                    )\n                    XCTAssertEqual(1, eventCounter.channelActiveCalls)\n                    XCTAssertEqual(1, eventCounter.channelRegisteredCalls)\n                    return client.close()\n                }.wait()\n            )\n\n            XCTAssertNoThrow(try channelHalfClosedPromise.futureResult.wait())\n            XCTAssertNoThrow(try channelInactivePromise.futureResult.wait())\n            XCTAssertNoThrow(try waitUntilWriteFailedPromise.futureResult.wait())\n        }\n    }\n\n    func testWeAreInterestedInReadEOFWhenChannelIsConnectedOnTheClientSide() throws {\n        guard isEarlyEOFDeliveryWorkingOnThisOS else {\n            #if os(Linux) || os(Android)\n            preconditionFailure(\"this should only ever be entered on Darwin.\")\n            #else\n            return\n            #endif\n        }\n        // This test makes sure that we notice EOFs early, even if we never register for read (by dropping all the reads\n        // on the floor. This is the same test as above but this one is for TCP clients.\n        enum Mode {\n            case halfClosureEnabled\n            case halfClosureDisabled\n        }\n        for mode in [DropAllReadsOnTheFloorHandler.Mode.halfClosureEnabled, .halfClosureDisabled] {\n            let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n            defer {\n                XCTAssertNoThrow(try group.syncShutdownGracefully())\n            }\n\n            let acceptedServerChannel: EventLoopPromise<Channel> = group.next().makePromise()\n            let channelInactivePromise = group.next().makePromise(of: Void.self)\n            let channelHalfClosedPromise = group.next().makePromise(of: Void.self)\n            let waitUntilWriteFailedPromise = group.next().makePromise(of: Void.self)\n            if mode == .halfClosureDisabled {\n                // if we don't support half-closure these two promises would otherwise never be fulfilled\n                channelInactivePromise.futureResult.cascade(to: waitUntilWriteFailedPromise)\n                channelInactivePromise.futureResult.cascade(to: channelHalfClosedPromise)\n            }\n            let eventCounter = EventCounterHandler()\n            let server = try assertNoThrowWithValue(\n                ServerBootstrap(group: group)\n                    .childChannelInitializer { channel in\n                        acceptedServerChannel.succeed(channel)\n                        return channel.eventLoop.makeSucceededFuture(())\n                    }\n                    .bind(to: .init(ipAddress: \"127.0.0.1\", port: 0))\n                    .wait()\n            )\n            let client = try assertNoThrowWithValue(\n                ClientBootstrap(group: group)\n                    .channelOption(.allowRemoteHalfClosure, value: mode == .halfClosureEnabled)\n                    .channelInitializer { channel in\n                        channel.pipeline.addHandlers([\n                            eventCounter,\n                            DropAllReadsOnTheFloorHandler(\n                                mode: mode,\n                                channelInactivePromise: channelInactivePromise,\n                                channelHalfClosedPromise: channelHalfClosedPromise,\n                                waitUntilWriteFailedPromise: waitUntilWriteFailedPromise\n                            ),\n                        ])\n                    }\n                    .connect(to: server.localAddress!).wait()\n            )\n            XCTAssertNoThrow(\n                try acceptedServerChannel.futureResult.flatMap { channel -> EventLoopFuture<Void> in\n                    XCTAssertEqual(\n                        [\"register\", \"channelActive\", \"channelRegistered\", \"connect\"],\n                        eventCounter.allTriggeredEvents()\n                    )\n                    XCTAssertEqual(1, eventCounter.channelActiveCalls)\n                    XCTAssertEqual(1, eventCounter.channelRegisteredCalls)\n                    return channel.close()\n                }.wait()\n            )\n\n            XCTAssertNoThrow(try channelHalfClosedPromise.futureResult.wait())\n            XCTAssertNoThrow(try channelInactivePromise.futureResult.wait())\n            XCTAssertNoThrow(try client.closeFuture.wait())\n            XCTAssertNoThrow(try waitUntilWriteFailedPromise.futureResult.wait())\n        }\n    }\n\n    func testServerClosesTheConnectionImmediately() throws {\n        // This is a regression test for a problem that the grpc-swift compatibility tests hit where everything would\n        // get stuck on a server that just insta-closes every accepted connection.\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        class WaitForChannelInactiveHandler: ChannelInboundHandler {\n            typealias InboundIn = Never\n            typealias OutboundOut = ByteBuffer\n\n            let channelInactivePromise: EventLoopPromise<Void>\n\n            init(channelInactivePromise: EventLoopPromise<Void>) {\n                self.channelInactivePromise = channelInactivePromise\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                var buffer = context.channel.allocator.buffer(capacity: 128)\n                buffer.writeString(String(repeating: \"x\", count: 517))\n                context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n            }\n\n            func channelInactive(context: ChannelHandlerContext) {\n                self.channelInactivePromise.succeed(())\n                context.fireChannelInactive()\n            }\n        }\n\n        let serverSocket = try assertNoThrowWithValue(ServerSocket(protocolFamily: .inet))\n        XCTAssertNoThrow(try serverSocket.bind(to: .init(ipAddress: \"127.0.0.1\", port: 0)))\n        XCTAssertNoThrow(try serverSocket.listen())\n        let serverAddress = try serverSocket.localAddress()\n        let g = DispatchGroup()\n        // Transfer the socket to the dispatch queue. It's not used on this thread after this point.\n        let unsafeServerSocket = UnsafeTransfer(serverSocket)\n        DispatchQueue(label: \"accept one client\").async(group: g) {\n            if let socket = try! unsafeServerSocket.wrappedValue.accept() {\n                try! socket.close()\n            }\n        }\n        let channelInactivePromise = group.next().makePromise(of: Void.self)\n        let eventCounter = EventCounterHandler()\n        let client = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .channelInitializer { channel in\n                    channel.eventLoop.makeCompletedFuture {\n                        try channel.pipeline.syncOperations.addHandlers([\n                            eventCounter,\n                            WaitForChannelInactiveHandler(channelInactivePromise: channelInactivePromise),\n                        ])\n                    }\n                }\n                .connect(to: serverAddress)\n                .wait()\n        )\n        XCTAssertNoThrow(\n            try channelInactivePromise.futureResult.map { _ in\n                XCTAssertEqual(1, eventCounter.channelInactiveCalls)\n            }.wait()\n        )\n        XCTAssertNoThrow(try client.closeFuture.wait())\n        g.wait()\n        XCTAssertNoThrow(try serverSocket.close())\n    }\n\n    func testSimpleMPTCP() throws {\n        #if os(Linux)\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n\n        let serverChannel: Channel\n\n        do {\n            serverChannel = try ServerBootstrap(group: group)\n                .enableMPTCP(true)\n                .bind(host: \"127.0.0.1\", port: 0)\n                .wait()\n        } catch let error as IOError {\n            // Older Linux kernel versions don't support MPTCP, which is fine.\n            if error.errnoCode != EINVAL && error.errnoCode != EPROTONOSUPPORT && error.errnoCode != ENOPROTOOPT {\n                XCTFail(\"Unexpected error: \\(error)\")\n            }\n            return\n        }\n\n        let clientChannel = try assertNoThrowWithValue(\n            ClientBootstrap(group: group)\n                .enableMPTCP(true)\n                .connect(to: serverChannel.localAddress!)\n                .wait()\n        )\n\n        do {\n            let serverInfo = try (serverChannel as? SocketOptionProvider)?.getMPTCPInfo().wait()\n            let clientInfo = try (clientChannel as? SocketOptionProvider)?.getMPTCPInfo().wait()\n\n            XCTAssertNotNil(serverInfo)\n            XCTAssertNotNil(clientInfo)\n        } catch let error as IOError {\n            // Some Linux kernel versions do support MPTCP but don't support the MPTCP_INFO\n            // option.\n            XCTAssertEqual(error.errnoCode, EOPNOTSUPP, \"Unexpected error: \\(error)\")\n            return\n        }\n\n        #endif\n    }\n\n    func testBaseSocketChannelWithUnderlyingTransport() throws {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }\n        let socket = try Socket.SocketType(protocolFamily: .inet, type: .datagram)\n        let channel = try BaseSocketChannel(\n            socket: socket,\n            parent: nil,\n            eventLoop: group.next() as! SelectableEventLoop,\n            recvAllocator: FixedSizeRecvByteBufferAllocator(capacity: 1024),\n            supportReconnect: false\n        )\n\n        try channel.socket.withUnsafeHandle { fd in\n            XCTAssertNotEqual(fd, NIOBSDSocket.invalidHandle)\n            try channel.withUnsafeTransport { XCTAssertEqual($0, fd) }\n        }\n    }\n}\n\nfinal class DropAllReadsOnTheFloorHandler: ChannelDuplexHandler, Sendable {\n    typealias InboundIn = Never\n    typealias OutboundIn = Never\n    typealias OutboundOut = ByteBuffer\n\n    enum Mode {\n        case halfClosureEnabled\n        case halfClosureDisabled\n    }\n\n    let channelInactivePromise: EventLoopPromise<Void>\n    let channelHalfClosedPromise: EventLoopPromise<Void>\n    let waitUntilWriteFailedPromise: EventLoopPromise<Void>\n    let channelActivePromise: EventLoopPromise<Void>?\n    let mode: Mode\n\n    init(\n        mode: Mode,\n        channelInactivePromise: EventLoopPromise<Void>,\n        channelHalfClosedPromise: EventLoopPromise<Void>,\n        waitUntilWriteFailedPromise: EventLoopPromise<Void>,\n        channelActivePromise: EventLoopPromise<Void>? = nil\n    ) {\n        self.mode = mode\n        self.channelInactivePromise = channelInactivePromise\n        self.channelHalfClosedPromise = channelHalfClosedPromise\n        self.waitUntilWriteFailedPromise = waitUntilWriteFailedPromise\n        self.channelActivePromise = channelActivePromise\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        self.channelActivePromise?.succeed(())\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        if let event = event as? ChannelEvent, event == .inputClosed {\n            XCTAssertEqual(.halfClosureEnabled, self.mode)\n            self.channelHalfClosedPromise.succeed(())\n            var buffer = context.channel.allocator.buffer(capacity: 1_000_000)\n            buffer.writeBytes(\n                Array(\n                    repeating: UInt8(ascii: \"x\"),\n                    count: 1_000_000\n                )\n            )\n\n            // What we're trying to do here is forcing a close without calling `close`. We know that the other side of\n            // the connection is fully closed but because we support half-closure, we need to write to 'learn' that the\n            // other side has actually fully closed the socket.\n            let promise = self.waitUntilWriteFailedPromise\n            func writeUntilError() {\n                context.writeAndFlush(Self.wrapOutboundOut(buffer)).assumeIsolated().map {\n                    writeUntilError()\n                }.whenFailure { (_: Error) in\n                    promise.succeed(())\n                }\n            }\n            writeUntilError()\n        }\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    func channelInactive(context: ChannelHandlerContext) {\n        self.channelInactivePromise.succeed(())\n        context.fireChannelInactive()\n    }\n\n    func read(context: ChannelHandlerContext) {}\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SocketOptionProviderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\nimport NIOCore\nimport NIOPosix\nimport XCTest\n\nfinal class SocketOptionProviderTest: XCTestCase {\n    var group: MultiThreadedEventLoopGroup!\n    var serverChannel: Channel!\n    var clientChannel: Channel!\n    var ipv4DatagramChannel: Channel!\n    var ipv6DatagramChannel: Channel?\n\n    struct CastError: Error {}\n\n    private func convertedChannel(file: StaticString = #filePath, line: UInt = #line) throws -> SocketOptionProvider {\n        guard let provider = self.clientChannel as? SocketOptionProvider else {\n            XCTFail(\n                \"Unable to cast \\(String(describing: self.clientChannel)) to SocketOptionProvider\",\n                file: (file),\n                line: line\n            )\n            throw CastError()\n        }\n        return provider\n    }\n\n    private func ipv4MulticastProvider(\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> SocketOptionProvider {\n        guard let provider = self.ipv4DatagramChannel as? SocketOptionProvider else {\n            XCTFail(\n                \"Unable to cast \\(String(describing: self.ipv4DatagramChannel)) to SocketOptionProvider\",\n                file: (file),\n                line: line\n            )\n            throw CastError()\n        }\n        return provider\n    }\n\n    private func ipv6MulticastProvider(\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> SocketOptionProvider? {\n        guard let ipv6Channel = self.ipv6DatagramChannel else {\n            return nil\n        }\n\n        guard let provider = ipv6Channel as? SocketOptionProvider else {\n            XCTFail(\"Unable to cast \\(ipv6Channel)) to SocketOptionChannel\", file: (file), line: line)\n            throw CastError()\n        }\n\n        return provider\n    }\n\n    override func setUp() {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        self.serverChannel = try? assertNoThrowWithValue(\n            ServerBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).wait()\n        )\n        self.clientChannel = try? assertNoThrowWithValue(\n            ClientBootstrap(group: group).connect(to: serverChannel.localAddress!).wait()\n        )\n\n        // We need to join these multicast groups on the loopback interface to work around issues with rapidly joining and leaving\n        // many multicast groups. On some OSes, if we do that on a public interface, we can build up a kernel backlog of IGMP\n        // joins/leaves that may eventually lead to an ENOMEM and a spurious test failure. As joining/leaving groups on loopback\n        // interfaces does not require IGMP joins/leaves, forcing these joins onto the loopback interface saves us from this\n        // risk.\n        let v4LoopbackAddress = try! assertNoThrowWithValue(SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n        let v6LoopbackAddress = try! assertNoThrowWithValue(SocketAddress(ipAddress: \"::1\", port: 0))\n        let v4LoopbackInterface = try! assertNoThrowWithValue(\n            System.enumerateDevices().filter {\n                $0.address == v4LoopbackAddress\n            }.first\n        )!\n\n        // Only run the setup if the loopback interface supports multicast\n        if v4LoopbackAddress.isMulticast {\n            self.ipv4DatagramChannel = try? assertNoThrowWithValue(\n                DatagramBootstrap(group: group).bind(host: \"127.0.0.1\", port: 0).flatMap { channel in\n                    (channel as! MulticastChannel).joinGroup(\n                        try! SocketAddress(ipAddress: \"224.0.2.66\", port: 0),\n                        device: v4LoopbackInterface\n                    ).map { channel }\n                }.wait()\n            )\n        }\n\n        // Only run the setup if the loopback interface supports multicast\n        if v6LoopbackAddress.isMulticast {\n            // The IPv6 setup is allowed to fail, some hosts don't have IPv6.\n            let v6LoopbackInterface = try? assertNoThrowWithValue(\n                System.enumerateDevices().filter { $0.address == v6LoopbackAddress }.first\n            )\n            self.ipv6DatagramChannel = try? DatagramBootstrap(group: group).bind(host: \"::1\", port: 0).flatMap {\n                channel in\n                (channel as! MulticastChannel).joinGroup(\n                    try! SocketAddress(ipAddress: \"ff12::beeb\", port: 0),\n                    device: v6LoopbackInterface\n                ).map { channel }\n            }.wait()\n        }\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try ipv6DatagramChannel?.close().wait())\n        XCTAssertNoThrow(try ipv4DatagramChannel?.close().wait())\n        XCTAssertNoThrow(try clientChannel.close().wait())\n        XCTAssertNoThrow(try serverChannel.close().wait())\n        XCTAssertNoThrow(try group.syncShutdownGracefully())\n    }\n\n    func testSettingAndGettingComplexSocketOption() throws {\n        let provider = try assertNoThrowWithValue(self.convertedChannel())\n\n        let newTimeout = timeval(tv_sec: 5, tv_usec: 0)\n        let retrievedTimeout = try assertNoThrowWithValue(\n            provider.unsafeSetSocketOption(level: .socket, name: .so_rcvtimeo, value: newTimeout).flatMap {\n                provider.unsafeGetSocketOption(level: .socket, name: .so_rcvtimeo) as EventLoopFuture<timeval>\n            }.wait()\n        )\n\n        XCTAssertEqual(retrievedTimeout.tv_sec, newTimeout.tv_sec)\n        XCTAssertEqual(retrievedTimeout.tv_usec, newTimeout.tv_usec)\n    }\n\n    func testObtainingDefaultValueOfComplexSocketOption() throws {\n        let provider = try assertNoThrowWithValue(self.convertedChannel())\n\n        let retrievedTimeout: timeval = try assertNoThrowWithValue(\n            provider.unsafeGetSocketOption(level: .socket, name: .so_rcvtimeo).wait()\n        )\n        XCTAssertEqual(retrievedTimeout.tv_sec, 0)\n        XCTAssertEqual(retrievedTimeout.tv_usec, 0)\n    }\n\n    func testSettingAndGettingSimpleSocketOption() throws {\n        let provider = try assertNoThrowWithValue(self.convertedChannel())\n\n        let newReuseAddr = 1 as CInt\n        let retrievedReuseAddr = try assertNoThrowWithValue(\n            provider.unsafeSetSocketOption(level: .socket, name: .so_reuseaddr, value: newReuseAddr).flatMap {\n                provider.unsafeGetSocketOption(level: .socket, name: .so_reuseaddr) as EventLoopFuture<CInt>\n            }.wait()\n        )\n\n        XCTAssertNotEqual(retrievedReuseAddr, 0)\n    }\n\n    func testObtainingDefaultValueOfSimpleSocketOption() throws {\n        let provider = try assertNoThrowWithValue(self.convertedChannel())\n\n        let reuseAddr: CInt = try assertNoThrowWithValue(\n            provider.unsafeGetSocketOption(level: .socket, name: .so_reuseaddr).wait()\n        )\n        XCTAssertEqual(reuseAddr, 0)\n    }\n\n    func testPassingInvalidSizeToSetComplexSocketOptionFails() throws {\n        // You'll notice that there are no other size mismatch tests in this file. The reason for that is that\n        // setsockopt is pretty dumb, and getsockopt is dumber. Specifically, setsockopt checks only that the length\n        // of the option value is *at least as large* as the expected struct (which is why this test will actually\n        // work), and getsockopt will happily return without error even in the buffer is too small. Either way,\n        // we just abandon the other tests: this is sufficient to prove that the error path works.\n        let provider = try assertNoThrowWithValue(self.convertedChannel())\n\n        XCTAssertThrowsError(try provider.unsafeSetSocketOption(level: .socket, name: .so_rcvtimeo, value: 1).wait()) {\n            error in\n            XCTAssertEqual(EINVAL, (error as? IOError)?.errnoCode)\n        }\n    }\n\n    // MARK: Tests for the safe helper functions.\n    func testLinger() throws {\n        let newLingerValue = linger(l_onoff: 1, l_linger: 64)\n\n        let provider = try self.convertedChannel()\n        XCTAssertNoThrow(\n            try provider.setSoLinger(newLingerValue).flatMap {\n                provider.getSoLinger()\n            }.map {\n                XCTAssertEqual($0.l_linger, newLingerValue.l_linger)\n                XCTAssertEqual($0.l_onoff, newLingerValue.l_onoff)\n            }.wait()\n        )\n    }\n\n    func testSoIpMulticastIf() throws {\n        guard let channel = self.ipv4DatagramChannel else {\n            // no multicast support\n            return\n        }\n        let provider = try assertNoThrowWithValue(self.ipv4MulticastProvider())\n\n        let address: in_addr\n        switch channel.localAddress {\n        case .some(.v4(let addr)):\n            address = addr.address.sin_addr\n        default:\n            XCTFail(\"Local address must be IPv4, but is \\(channel.localAddress.debugDescription)\")\n            return\n        }\n\n        XCTAssertNoThrow(\n            try provider.setIPMulticastIF(address).flatMap {\n                provider.getIPMulticastIF()\n            }.map {\n                XCTAssertEqual($0.s_addr, address.s_addr)\n            }.wait()\n        )\n    }\n\n    func testIpMulticastTtl() throws {\n        guard self.ipv4DatagramChannel != nil else {\n            // alas, no multicast, let's skip.\n            return\n        }\n        let provider = try assertNoThrowWithValue(self.ipv4MulticastProvider())\n        XCTAssertNoThrow(\n            try provider.setIPMulticastTTL(6).flatMap {\n                provider.getIPMulticastTTL()\n            }.map {\n                XCTAssertEqual($0, 6)\n            }.wait()\n        )\n    }\n\n    func testIpMulticastLoop() throws {\n        guard self.ipv4DatagramChannel != nil else {\n            // alas, no multicast, let's skip.\n            return\n        }\n        let provider = try assertNoThrowWithValue(self.ipv4MulticastProvider())\n        XCTAssertNoThrow(\n            try provider.setIPMulticastLoop(1).flatMap {\n                provider.getIPMulticastLoop()\n            }.map {\n                XCTAssertNotEqual($0, 0)\n            }.wait()\n        )\n    }\n\n    func testIpv6MulticastIf() throws {\n        guard let provider = try assertNoThrowWithValue(self.ipv6MulticastProvider()) else {\n            // Skip on systems without IPv6.\n            return\n        }\n        guard self.ipv6DatagramChannel != nil else {\n            // alas, no multicast, let's skip.\n            return\n        }\n\n        // TODO: test this when we know what the interface indices are.\n        let loopbackAddress = try assertNoThrowWithValue(SocketAddress(ipAddress: \"::1\", port: 0))\n        guard\n            let loopbackInterface = try assertNoThrowWithValue(\n                System.enumerateDevices().filter({ $0.address == loopbackAddress }).first\n            )\n        else {\n            XCTFail(\"Could not find index of loopback address\")\n            return\n        }\n\n        XCTAssertNoThrow(\n            try provider.setIPv6MulticastIF(CUnsignedInt(loopbackInterface.interfaceIndex)).flatMap {\n                provider.getIPv6MulticastIF()\n            }.map {\n                XCTAssertEqual($0, CUnsignedInt(loopbackInterface.interfaceIndex))\n            }.wait()\n        )\n    }\n\n    func testIPv6MulticastHops() throws {\n        guard let provider = try assertNoThrowWithValue(self.ipv6MulticastProvider()) else {\n            // Skip on systems without IPv6.\n            return\n        }\n        guard self.ipv6DatagramChannel != nil else {\n            // alas, no multicast, let's skip.\n            return\n        }\n\n        XCTAssertNoThrow(\n            try provider.setIPv6MulticastHops(6).flatMap {\n                provider.getIPv6MulticastHops()\n            }.map {\n                XCTAssertEqual($0, 6)\n            }.wait()\n        )\n    }\n\n    func testIPv6MulticastLoop() throws {\n        guard let provider = try assertNoThrowWithValue(self.ipv6MulticastProvider()) else {\n            // Skip on systems without IPv6.\n            return\n        }\n        guard self.ipv6DatagramChannel != nil else {\n            // alas, no multicast, let's skip.\n            return\n        }\n\n        XCTAssertNoThrow(\n            try provider.setIPv6MulticastLoop(1).flatMap {\n                provider.getIPv6MulticastLoop()\n            }.map {\n                XCTAssertNotEqual($0, 0)\n            }.wait()\n        )\n    }\n\n    func testTCPInfo() throws {\n        // This test only runs on Linux, FreeBSD, and Android.\n        #if os(Linux) || os(FreeBSD) || os(Android)\n        let channel = self.clientChannel! as! SocketOptionProvider\n        let tcpInfo = try assertNoThrowWithValue(channel.getTCPInfo().wait())\n\n        // We just need to soundness check something here to ensure that the data is vaguely reasonable.\n        XCTAssertEqual(tcpInfo.tcpi_state, UInt8(TCP_ESTABLISHED))\n        #endif\n    }\n\n    func testTCPConnectionInfo() throws {\n        // This test only runs on Darwin.\n        #if canImport(Darwin)\n        let channel = self.clientChannel! as! SocketOptionProvider\n        let tcpConnectionInfo = try assertNoThrowWithValue(channel.getTCPConnectionInfo().wait())\n\n        #if os(macOS)  // deliberately only on macOS\n        // We just need to soundness check something here to ensure that the data is vaguely reasonable.\n        XCTAssertEqual(tcpConnectionInfo.tcpi_state, UInt8(TSI_S_ESTABLISHED))\n        #endif\n        // Suppress the unused warning\n        _ = tcpConnectionInfo\n        #endif\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/StreamChannelsTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Atomics\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOPosix\n\nclass StreamChannelTest: XCTestCase {\n    var buffer: ByteBuffer! = nil\n\n    override func setUp() {\n        self.buffer = ByteBufferAllocator().buffer(capacity: 128)\n    }\n\n    override func tearDown() {\n        self.buffer = nil\n    }\n\n    func testEchoBasic() throws {\n        final class EchoHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                context.write(data, promise: nil)\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                context.flush()\n            }\n        }\n\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            var everythingBuffer = chan1.allocator.buffer(capacity: 300000)\n            let allDonePromise = chan1.eventLoop.makePromise(of: ByteBuffer.self)\n            XCTAssertNoThrow(try chan1.pipeline.addHandler(EchoHandler()).wait())\n\n            let configuredChannel2 = chan2.eventLoop.submit {\n                let handler = AccumulateAllReads(allDonePromise: allDonePromise)\n                try chan2.pipeline.syncOperations.addHandler(handler)\n            }\n            XCTAssertNoThrow(try configuredChannel2.wait())\n\n            for f in [1, 10, 100, 1_000, 10_000, 300_000] {\n                let from = everythingBuffer.writerIndex\n                everythingBuffer.writeString(\"\\(f)\")\n                everythingBuffer.writeBytes(repeatElement(UInt8(ascii: \"x\"), count: f))\n                XCTAssertNoThrow(\n                    chan2.writeAndFlush(\n                        everythingBuffer.getSlice(\n                            at: from,\n                            length: everythingBuffer.writerIndex - from\n                        )!\n                    )\n                )\n            }\n            let from = everythingBuffer.writerIndex\n            everythingBuffer.writeString(\"$\")  // magic end marker that will cause the channel to close\n            XCTAssertNoThrow(chan2.writeAndFlush(everythingBuffer.getSlice(at: from, length: 1)!))\n            XCTAssertNoThrow(XCTAssertEqual(everythingBuffer, try allDonePromise.futureResult.wait()))\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testSyncChannelOptions() throws {\n        final class GetAndSetAutoReadHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Any\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                guard let syncOptions = context.channel.syncOptions else {\n                    XCTFail(\"Sync options are not supported on \\(type(of: context.channel))\")\n                    return\n                }\n\n                XCTAssertTrue(try syncOptions.getOption(.autoRead))\n                XCTAssertNoThrow(try syncOptions.setOption(.autoRead, value: false))\n                XCTAssertFalse(try syncOptions.getOption(.autoRead))\n            }\n        }\n\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            XCTAssertNoThrow(try chan1.pipeline.addHandler(GetAndSetAutoReadHandler()).wait())\n            XCTAssertNoThrow(try chan2.pipeline.addHandler(GetAndSetAutoReadHandler()).wait())\n        }\n\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testChannelReturnsNilForDefaultSyncOptionsImplementation() throws {\n        final class TestChannel: Channel {\n            var allocator: ByteBufferAllocator { fatalError() }\n            var closeFuture: EventLoopFuture<Void> { fatalError() }\n            var pipeline: ChannelPipeline { fatalError() }\n            let localAddress: SocketAddress? = nil\n            let remoteAddress: SocketAddress? = nil\n            let parent: Channel? = nil\n            var _channelCore: ChannelCore { fatalError() }\n            var eventLoop: EventLoop { fatalError() }\n            let isWritable: Bool = false\n            let isActive: Bool = false\n\n            func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void> {\n                fatalError()\n            }\n\n            func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value> {\n                fatalError()\n            }\n\n            init() {\n            }\n        }\n\n        let channel = TestChannel()\n        XCTAssertNil(channel.syncOptions)\n    }\n\n    func testWritabilityStartsTrueGoesFalseAndBackToTrue() throws {\n        class WritabilityTrackerStateMachine: ChannelInboundHandler {\n            typealias InboundIn = Never\n            typealias OutboundOut = ByteBuffer\n\n            enum State: Int {\n                case beginsTrue = 0\n                case thenFalse = 1\n                case thenTrueAgain = 2\n            }\n\n            var channelWritabilityChangedCalls = 0\n            var state = State.beginsTrue\n            let writabilityNowFalsePromise: EventLoopPromise<Void>\n            let writeFullyDonePromise: EventLoopPromise<Void>\n\n            init(\n                writabilityNowFalsePromise: EventLoopPromise<Void>,\n                writeFullyDonePromise: EventLoopPromise<Void>\n            ) {\n                self.writabilityNowFalsePromise = writabilityNowFalsePromise\n                self.writeFullyDonePromise = writeFullyDonePromise\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                // 5 MB, this must be safely more than send buffer + receive buffer. The reason is that we don't want\n                // the overall write to complete before we make the other end of the channel readable.\n                let totalAmount = 5 * 1024 * 1024\n                let chunkSize = 10 * 1024\n                XCTAssertEqual(.beginsTrue, self.state)\n                self.state = .thenFalse\n                XCTAssertEqual(true, context.channel.isWritable)\n\n                var buffer = context.channel.allocator.buffer(capacity: chunkSize)\n                buffer.writeBytes(repeatElement(UInt8(ascii: \"x\"), count: chunkSize))\n                for _ in 0..<(totalAmount / chunkSize) {\n                    context.write(Self.wrapOutboundOut(buffer)).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                }\n                context.write(Self.wrapOutboundOut(buffer)).assumeIsolated().map {\n                    XCTAssertEqual(self.state, .thenTrueAgain)\n                }.recover { error in\n                    XCTFail(\"unexpected error \\(error)\")\n                }.nonisolated().cascade(to: self.writeFullyDonePromise)\n                context.flush()\n            }\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                self.channelWritabilityChangedCalls += 1\n                XCTAssertEqual(self.state.rawValue % 2 == 0, context.channel.isWritable)\n                XCTAssertEqual(State(rawValue: self.channelWritabilityChangedCalls), self.state)\n                if let newState = State(rawValue: self.channelWritabilityChangedCalls + 1) {\n                    if self.state == .thenFalse {\n                        context.eventLoop.assumeIsolated().scheduleTask(in: .microseconds(100)) {\n                            // Let's delay this a tiny little bit just so we get a higher chance to actually exhaust all\n                            // the buffers. The delay is not necessary for this test to work but it makes the tests a\n                            // little bit harder.\n                            self.writabilityNowFalsePromise.succeed(())\n                        }\n                    }\n                    self.state = newState\n                }\n            }\n        }\n\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            let allDonePromise = chan1.eventLoop.makePromise(of: ByteBuffer.self)\n            let writabilityFalsePromise = chan1.eventLoop.makePromise(of: Void.self)\n            let writeFullyDonePromise = chan1.eventLoop.makePromise(of: Void.self)\n            XCTAssertNoThrow(try chan2.setOption(.autoRead, value: false).wait())\n\n            let chan2Configured = chan2.eventLoop.submit {\n                try chan2.pipeline.syncOperations.addHandler(AccumulateAllReads(allDonePromise: allDonePromise))\n            }\n            XCTAssertNoThrow(try chan2Configured.wait())\n\n            let chan1Configured = chan1.eventLoop.submit {\n                try chan1.pipeline.syncOperations.addHandler(\n                    WritabilityTrackerStateMachine(\n                        writabilityNowFalsePromise: writabilityFalsePromise,\n                        writeFullyDonePromise: writeFullyDonePromise\n                    )\n                )\n            }\n            XCTAssertNoThrow(try chan1Configured.wait())\n\n            // Writability should turn false because we're writing lots of data and we aren't reading.\n            XCTAssertNoThrow(try writabilityFalsePromise.futureResult.wait())\n            // Ok, let's read.\n            XCTAssertNoThrow(try chan2.setOption(.autoRead, value: true).wait())\n            // Which should lead to the write to complete.\n            XCTAssertNoThrow(try writeFullyDonePromise.futureResult.wait())\n            // To finish up, let's just tear this down.\n            XCTAssertNoThrow(try chan2.close().wait())\n            XCTAssertNoThrow(try chan1.closeFuture.wait())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testHalfCloseOwnOutput() throws {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            let readPromise = chan2.eventLoop.makePromise(of: Void.self)\n            let eofPromise = chan1.eventLoop.makePromise(of: Void.self)\n\n            XCTAssertNoThrow(try chan1.setOption(.allowRemoteHalfClosure, value: true).wait())\n            XCTAssertNoThrow(\n                try chan1.pipeline.addHandler(FulfillOnFirstEventHandler(userInboundEventTriggeredPromise: eofPromise))\n                    .wait()\n            )\n\n            // let's close chan2's output\n            XCTAssertNoThrow(try chan2.close(mode: .output).wait())\n            XCTAssertNoThrow(try eofPromise.futureResult.wait())\n\n            self.buffer.writeString(\"X\")\n            XCTAssertNoThrow(\n                try chan2.pipeline.addHandler(FulfillOnFirstEventHandler(channelReadPromise: readPromise)).wait()\n            )\n\n            // let's write a byte from chan1 to chan2.\n            XCTAssertNoThrow(try chan1.writeAndFlush(self.buffer).wait(), \"write on \\(chan1) failed\")\n\n            // and wait for it to arrive\n            XCTAssertNoThrow(try readPromise.futureResult.wait())\n\n            XCTAssertNoThrow(try chan1.syncCloseAcceptingAlreadyClosed())\n            XCTAssertNoThrow(try chan2.syncCloseAcceptingAlreadyClosed())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testHalfCloseOwnOutputWithPopulatedBuffer() throws {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            let readPromise = chan2.eventLoop.makePromise(of: Void.self)\n\n            XCTAssertNoThrow(try chan1.setOption(.allowRemoteHalfClosure, value: true).wait())\n\n            self.buffer.writeString(\"X\")\n            XCTAssertNoThrow(\n                try chan2.pipeline.addHandler(FulfillOnFirstEventHandler(channelReadPromise: readPromise)).wait()\n            )\n\n            // let's write a byte from chan1 to chan2 which we leave in the buffer.\n            let writeFuture = chan1.write(self.buffer)\n\n            // close chan1's output, this shouldn't take effect until the buffer is empty\n            let closeFuture = chan1.close(mode: .output)\n\n            // flush chan1's output\n            chan1.flush()\n\n            // Attempt to write a byte from chan1 to chan2 which should be refused after the close.\n            // We expect `.outputClosed` from the half-close, but if the remote peer processes\n            // the FIN and closes before this write is processed, the channel may fully close\n            // and we get `.ioOnClosedChannel` instead.\n            XCTAssertThrowsError(try chan1.write(self.buffer).wait()) { error in\n                let channelError = error as? ChannelError\n                XCTAssertTrue(\n                    channelError == .outputClosed || channelError == .ioOnClosedChannel,\n                    \"Unexpected error \\(error) on \\(chan1)\"\n                )\n            }\n\n            // wait for the write to complete\n            XCTAssertNoThrow(try writeFuture.wait(), \"chan1 write failed\")\n\n            // and wait for it to arrive\n            XCTAssertNoThrow(try readPromise.futureResult.wait())\n\n            // wait for the close to complete\n            XCTAssertNoThrow(try closeFuture.wait(), \"chan1 close failed\")\n\n            XCTAssertNoThrow(try chan1.syncCloseAcceptingAlreadyClosed())\n            XCTAssertNoThrow(try chan2.syncCloseAcceptingAlreadyClosed())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testHalfCloseOwnOutputWithWritabilityChange() throws {\n        final class BytesReadCountingHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n\n            private let numBytes = NIOLockedValueBox<Int>(0)\n            private let numBytesReadAtInputClose = NIOLockedValueBox<Int>(0)\n\n            var bytesRead: Int {\n                self.numBytes.withLockedValue { $0 }\n            }\n            var bytesReadAtInputClose: Int {\n                self.numBytesReadAtInputClose.withLockedValue { $0 }\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let currentBuffer = Self.unwrapInboundIn(data)\n                self.numBytes.withLockedValue { numBytes in\n                    numBytes += currentBuffer.readableBytes\n                }\n                context.fireChannelRead(data)\n            }\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                if event as? ChannelEvent == .some(.inputClosed) {\n                    let numBytes = self.numBytes.withLockedValue { $0 }\n                    self.numBytesReadAtInputClose.withLockedValue { $0 = numBytes }\n                    context.close(mode: .all, promise: nil)\n                }\n                context.fireUserInboundEventTriggered(event)\n            }\n        }\n\n        final class BytesWrittenCountingHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n\n            public typealias OutboundIn = ByteBuffer\n            public typealias OutboundOut = ByteBuffer\n\n            private let numBytes = NIOLockedValueBox<Int>(0)\n            private let seenOutputClosed = NIOLockedValueBox<Bool>(false)\n\n            func setup(_ context: ChannelHandlerContext) {\n                let bufferLength = 1024\n                let bytesToWrite = ByteBuffer.init(repeating: 0x42, count: bufferLength)\n\n                // write until the kernel buffer and the pendingWrites buffer are full\n                while context.channel.isWritable {\n                    XCTAssertNoThrow(context.writeAndFlush(self.wrapOutboundOut(bytesToWrite), promise: nil))\n                    self.numBytes.withLockedValue { numBytes in\n                        numBytes += bufferLength\n                    }\n                }\n            }\n\n            var bytesWritten: Int {\n                self.numBytes.withLockedValue { $0 }\n            }\n\n            var seenOutputClosedEvent: Bool {\n                self.seenOutputClosed.withLockedValue { $0 }\n            }\n\n            func channelActive(context: ChannelHandlerContext) {\n                self.setup(context)\n                context.fireChannelActive()\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                self.setup(context)\n            }\n\n            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                if event as? ChannelEvent == .some(.outputClosed) {\n                    self.seenOutputClosed.withLockedValue { $0 = true }\n                }\n                context.fireUserInboundEventTriggered(event)\n            }\n        }\n\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            try chan1.setOption(.autoRead, value: false).wait()\n            try chan1.setOption(.allowRemoteHalfClosure, value: true).wait()\n\n            let bytesReadCountingHandler = BytesReadCountingHandler()\n            try chan1.pipeline.addHandler(bytesReadCountingHandler).wait()\n\n            let bytesWrittenCountingHandler = BytesWrittenCountingHandler()\n            try chan2.pipeline.addHandler(bytesWrittenCountingHandler).wait()\n\n            XCTAssertFalse(bytesWrittenCountingHandler.seenOutputClosedEvent)\n\n            // close the writing side\n            let chan2ClosePromise = chan2.eventLoop.makePromise(of: Void.self)\n            chan2.close(mode: .output, promise: chan2ClosePromise)\n\n            XCTAssertFalse(bytesWrittenCountingHandler.seenOutputClosedEvent)\n\n            // tell the read side to begin reading leading to the write buffers draining\n            try chan1.setOption(.autoRead, value: true).wait()\n\n            // wait for the reading-side close to complete\n            try chan1.closeFuture.wait()\n\n            XCTAssertTrue(bytesWrittenCountingHandler.seenOutputClosedEvent)\n\n            // now the dust has settled all the bytes should be accounted for\n            XCTAssertNotEqual(bytesWrittenCountingHandler.bytesWritten, 0)\n            XCTAssertEqual(bytesReadCountingHandler.bytesRead, bytesWrittenCountingHandler.bytesWritten)\n            XCTAssertEqual(bytesReadCountingHandler.bytesRead, bytesReadCountingHandler.bytesReadAtInputClose)\n\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(forceSeparateEventLoops: false, runTest))\n    }\n\n    func testHalfCloseAfterEOF() throws {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            let readPromise = chan2.eventLoop.makePromise(of: Void.self)\n\n            self.buffer.writeString(\"X\")\n            XCTAssertNoThrow(\n                try chan2.pipeline.addHandler(FulfillOnFirstEventHandler(channelReadPromise: readPromise)).wait()\n            )\n\n            // let's write a byte from chan1 to chan2 and wait for it to complete\n            XCTAssertNoThrow(try chan1.writeAndFlush(self.buffer).wait(), \"chan1 write failed\")\n\n            // and wait for it to arrive\n            XCTAssertNoThrow(try readPromise.futureResult.wait())\n\n            // the receiver has what it wants and closes the channel\n            try chan2.close(mode: .all).wait()\n\n            // the writer's logic says that it is done writing so it closes its output\n            // we're mostly making sure we don't panic here, if we do see an error then it should be a particular type\n            do {\n                try chan1.close(mode: .output).wait()\n            } catch ChannelError.alreadyClosed {\n                ()  // expected possibility depending on ordering\n            } catch {\n                if let err = error as? NIOCore.IOError {\n                    switch err.errnoCode {\n                    case EBADF, ENOTCONN:\n                        ()  // expected possibility depending on ordering\n                    default:\n                        XCTFail(\"Unexpected IO error encountered during close: \\(error)\")\n                    }\n                } else {\n                    XCTFail(\"Unexpected error encountered during close: \\(error)\")\n                }\n            }\n\n            XCTAssertNoThrow(try chan1.syncCloseAcceptingAlreadyClosed())\n            XCTAssertNoThrow(try chan2.syncCloseAcceptingAlreadyClosed())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testHalfCloseOwnInput() {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n\n            let readPromise = chan1.eventLoop.makePromise(of: Void.self)\n\n            XCTAssertNoThrow(try chan2.setOption(.allowRemoteHalfClosure, value: true).wait())\n            // let's close chan2's input\n            XCTAssertNoThrow(try chan2.close(mode: .input).wait())\n\n            self.buffer.writeString(\"X\")\n            XCTAssertNoThrow(\n                try chan1.pipeline.addHandler(FulfillOnFirstEventHandler(channelReadPromise: readPromise)).wait()\n            )\n\n            // let's write a byte from chan2 to chan1.\n            XCTAssertNoThrow(try chan2.writeAndFlush(self.buffer).wait())\n\n            // and wait for it to arrive\n            XCTAssertNoThrow(try readPromise.futureResult.wait())\n\n            XCTAssertNoThrow(try chan1.syncCloseAcceptingAlreadyClosed())\n            XCTAssertNoThrow(try chan2.syncCloseAcceptingAlreadyClosed())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testDoubleShutdownInput() {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            XCTAssertNoThrow(try chan1.setOption(.allowRemoteHalfClosure, value: true).wait())\n            XCTAssertNoThrow(try chan1.close(mode: .input).wait())\n            XCTAssertThrowsError(try chan1.close(mode: .input).wait()) { error in\n                XCTAssertEqual(ChannelError.inputClosed, error as? ChannelError, \"\\(chan1)\")\n            }\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testDoubleShutdownOutput() {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            XCTAssertNoThrow(try chan2.setOption(.allowRemoteHalfClosure, value: true).wait())\n            XCTAssertNoThrow(try chan1.close(mode: .output).wait())\n            XCTAssertThrowsError(try chan1.close(mode: .output).wait()) { error in\n                XCTAssertEqual(ChannelError.outputClosed, error as? ChannelError, \"\\(chan1)\")\n            }\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testWriteFailsAfterOutputClosed() {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            XCTAssertNoThrow(try chan2.setOption(.allowRemoteHalfClosure, value: true).wait())\n            XCTAssertNoThrow(try chan1.close(mode: .output).wait())\n            var buffer = chan1.allocator.buffer(capacity: 10)\n            buffer.writeString(\"helloworld\")\n            XCTAssertThrowsError(try chan1.writeAndFlush(buffer).wait()) { error in\n                XCTAssertEqual(ChannelError.outputClosed, error as? ChannelError, \"\\(chan1)\")\n            }\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testVectorWrites() {\n        func runTest(chan1: Channel, chan2: Channel) throws {\n            let readPromise = chan2.eventLoop.makePromise(of: Void.self)\n            XCTAssertNoThrow(chan2.pipeline.addHandler(FulfillOnFirstEventHandler(channelReadPromise: readPromise)))\n            var buffer = chan1.allocator.buffer(capacity: 1)\n            buffer.writeString(\"X\")\n            for _ in 0..<100 {\n                chan1.write(buffer, promise: nil)\n            }\n            chan1.flush()\n            XCTAssertNoThrow(try readPromise.futureResult.wait())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testLotsOfWritesWhilstOtherSideNotReading() {\n        // This is a regression test for a problem where we would spin on EVFILT_EXCEPT despite the fact that there\n        // was no EOF or any other exceptional event present. So this is a regression test for rdar://53656794 and https://github.com/apple/swift-nio/pull/526.\n        final class FailOnReadHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = ByteBuffer\n\n            let areReadsOkayNow: ManagedAtomic<Bool>\n\n            init(areReadOkayNow: ManagedAtomic<Bool>) {\n                self.areReadsOkayNow = areReadOkayNow\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                guard self.areReadsOkayNow.load(ordering: .relaxed) else {\n                    XCTFail(\"unexpected read of \\(Self.unwrapInboundIn(data))\")\n                    return\n                }\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                guard self.areReadsOkayNow.load(ordering: .relaxed) else {\n                    XCTFail(\"unexpected readComplete\")\n                    return\n                }\n            }\n        }\n\n        func runTest(receiver: Channel, sender: Channel) throws {\n            let sends = ManagedAtomic(0)\n            precondition(\n                receiver.eventLoop !== sender.eventLoop,\n                \"this test cannot run if sender and receiver live on the same EventLoop. \\(receiver)\"\n            )\n            XCTAssertNoThrow(try receiver.setOption(.autoRead, value: false).wait())\n            let areReadsOkayNow = ManagedAtomic(false)\n            XCTAssertNoThrow(\n                try receiver.pipeline.addHandler(FailOnReadHandler(areReadOkayNow: areReadsOkayNow)).wait()\n            )\n\n            // We will immediately send exactly the amount of data that fits in the receiver's receive buffer.\n            let receiveBufferSize = Int(\n                (try? receiver.getOption(ChannelOptions.socketOption(.so_rcvbuf)).wait()) ?? 8192\n            )\n\n            let buffer = sender.allocator.buffer(repeating: UInt8(ascii: \"X\"), count: receiveBufferSize)\n\n            XCTAssertNoThrow(\n                try sender.eventLoop.submit {\n                    @Sendable\n                    func send() {\n                        var allBuffer = buffer\n                        // When we run through this for the first time, we send exactly the receive buffer size, after that\n                        // we send one byte at a time. Sending the receive buffer will trigger the EVFILT_EXCEPT loop\n                        // (rdar://53656794) for UNIX Domain Sockets and the additional 1 byte send loop will also pretty\n                        // reliably trigger it for TCP sockets.\n                        let myBuffer = allBuffer.readSlice(\n                            length: sends.load(ordering: .relaxed) == 0 ? receiveBufferSize : 1\n                        )!\n                        sender.writeAndFlush(myBuffer).map {\n                            sends.wrappingIncrement(ordering: .relaxed)\n                            sender.eventLoop.scheduleTask(in: .microseconds(1)) {\n                                send()\n                            }\n                        }.whenFailure { error in\n                            XCTAssert(\n                                areReadsOkayNow.load(ordering: .relaxed),\n                                \"error before the channel should go down\"\n                            )\n                            guard case .some(.ioOnClosedChannel) = error as? ChannelError else {\n                                XCTFail(\"unexpected error: \\(error)\")\n                                return\n                            }\n                        }\n                    }\n                    send()\n                }.wait()\n            )\n\n            for _ in 0..<10 {\n                // We just spin here for a little while to check that there are no bogus events available on the\n                // selector.\n                let eventLoop = (receiver.eventLoop as! SelectableEventLoop)\n                XCTAssertNoThrow(\n                    try eventLoop._selector.testsOnly_withUnsafeSelectorFD { fd in\n                        try assertNoSelectorChanges(fd: fd, selector: eventLoop._selector)\n                    },\n                    \"after \\(sends.load(ordering: .relaxed)) sends, we got an unexpected selector event for \\(receiver)\"\n                )\n                usleep(10000)\n            }\n            // We'll soon close the channels, so reads are now acceptable (from the EOF that we may read).\n            XCTAssertTrue(areReadsOkayNow.compareExchange(expected: false, desired: true, ordering: .relaxed).exchanged)\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(forceSeparateEventLoops: true, runTest))\n    }\n\n    func testFlushInWritePromise() {\n        class WaitForTwoBytesHandler: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private let allDonePromise: EventLoopPromise<Void>\n            private var numberOfBytes = 0\n\n            init(allDonePromise: EventLoopPromise<Void>) {\n                self.allDonePromise = allDonePromise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                // The two writes could be coalesced, so we add up the bytes and not always the number of read calls.\n                self.numberOfBytes += Self.unwrapInboundIn(data).readableBytes\n                if self.numberOfBytes == 2 {\n                    self.allDonePromise.succeed(())\n                }\n            }\n        }\n\n        func runTest(receiver: Channel, sender: Channel) throws {\n            let allDonePromise = receiver.eventLoop.makePromise(of: Void.self)\n            XCTAssertNoThrow(try sender.setOption(.writeSpin, value: 0).wait())\n            let receiverConfigured = receiver.eventLoop.submit {\n                try receiver.pipeline.syncOperations.addHandler(\n                    WaitForTwoBytesHandler(allDonePromise: allDonePromise)\n                )\n            }\n            XCTAssertNoThrow(try receiverConfigured.wait())\n            let buffer = sender.allocator.buffer(string: \"X\")\n            XCTAssertNoThrow(\n                try sender.eventLoop.flatSubmit { () -> EventLoopFuture<Void> in\n                    let writePromise = sender.eventLoop.makePromise(of: Void.self)\n                    let bothWritesResult = writePromise.futureResult.flatMap {\n                        sender.writeAndFlush(buffer)\n                    }\n                    sender.writeAndFlush(buffer, promise: writePromise)\n                    return bothWritesResult\n                }.wait()\n            )\n            XCTAssertNoThrow(try allDonePromise.futureResult.wait())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testWriteAndFlushInChannelWritabilityChangedToTrue() {\n        // regression test for rdar://58571521\n        final class WriteWhenWritabilityGoesToTrue: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            private var numberOfCalls = 0\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                self.numberOfCalls += 1\n\n                switch self.numberOfCalls {\n                case 1:\n                    // This is us exceeding the high water mark\n                    XCTAssertFalse(context.channel.isWritable)\n                case 2:\n                    // This is after the two bytes have been written.\n                    XCTAssertTrue(context.channel.isWritable)\n\n                    // Now, let's trigger another write which should cause flushNow to be re-entered. But first, let's\n                    // raise the high water mark so we don't get another call straight away.\n                    let buffer = context.channel.allocator.buffer(string: \"hello\")\n                    let loopBoundContext = context.loopBound\n                    context.channel.setOption(.writeBufferWaterMark, value: .init(low: 1024, high: 1024))\n                        .flatMap {\n                            let context = loopBoundContext.value\n                            return context.writeAndFlush(Self.wrapOutboundOut(buffer))\n                        }.whenFailure { error in\n                            XCTFail(\"unexpected error: \\(error)\")\n                        }\n                default:\n                    XCTFail(\"call \\(self.numberOfCalls) to \\(#function) unexpected\")\n                }\n            }\n        }\n\n        final class WaitForNumberOfBytes: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n\n            private let allDonePromise: EventLoopPromise<Void>\n            private var numberOfReads = 0\n            private let expectedNumberOfBytes: Int\n\n            init(numberOfBytes: Int, allDonePromise: EventLoopPromise<Void>) {\n                self.expectedNumberOfBytes = numberOfBytes\n                self.allDonePromise = allDonePromise\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                // The two writes could be coalesced, so we add up the bytes and not always the number of read calls.\n                self.numberOfReads += Self.unwrapInboundIn(data).readableBytes\n                if self.numberOfReads >= self.expectedNumberOfBytes {\n                    self.allDonePromise.succeed(())\n                }\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                self.allDonePromise.fail(ChannelError.ioOnClosedChannel)\n            }\n        }\n\n        func runTest(receiver: Channel, sender: Channel) throws {\n            // Write spin might just disturb this test so let's switch it off\n            XCTAssertNoThrow(try sender.setOption(.writeSpin, value: 0).wait())\n            // Writing more than the high water mark will cause the channel to become unwritable very easily\n            XCTAssertNoThrow(\n                try sender.setOption(.writeBufferWaterMark, value: .init(low: 1, high: 1)).wait()\n            )\n\n            let sevenBytesReceived = receiver.eventLoop.makePromise(of: Void.self)\n            let receiverConfigured = receiver.eventLoop.submit {\n                let handler = WaitForNumberOfBytes(\n                    numberOfBytes: 7,\n                    allDonePromise: sevenBytesReceived\n                )\n                try receiver.pipeline.syncOperations.addHandler(handler)\n            }\n            XCTAssertNoThrow(try receiverConfigured.wait())\n\n            let eventCounterHandler = EventCounterHandler()\n            let senderConfigured = sender.eventLoop.submit {\n                let sync = sender.pipeline.syncOperations\n                try sync.addHandler(eventCounterHandler)\n                try sync.addHandler(WriteWhenWritabilityGoesToTrue())\n            }\n            XCTAssertNoThrow(try senderConfigured.wait())\n\n            var buffer = sender.allocator.buffer(capacity: 5)\n            buffer.writeString(\"XX\")  // 2 bytes, exceeds the high water mark\n\n            XCTAssertTrue(sender.isWritable)\n            XCTAssertEqual(0, eventCounterHandler.channelWritabilityChangedCalls)\n            XCTAssertNoThrow(try sender.writeAndFlush(buffer).wait())\n            XCTAssertNoThrow(try sevenBytesReceived.futureResult.wait())\n        }\n\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testWritabilityChangedDoesNotGetCalledOnSimpleWrite() {\n        func runTest(receiver: Channel, sender: Channel) throws {\n            let eventCounter = EventCounterHandler()\n            XCTAssertNoThrow(try sender.pipeline.addHandler(eventCounter).wait())\n            var buffer = sender.allocator.buffer(capacity: 1)\n            buffer.writeString(\"X\")\n            XCTAssertNoThrow(try sender.writeAndFlush(buffer).wait())\n            XCTAssertEqual(0, eventCounter.channelWritabilityChangedCalls)\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testWriteAndFlushFromReentrantFlushNowTriggeredOutOfWritabilityWhereOuterSaysAllWrittenAndInnerDoesNot() {\n        // regression test for rdar://58571521, harder version\n\n        //\n        // What we're doing here is to enter exactly the following scenario which used to be an issue.\n\n        // 1: writable()\n        // 2: --> flushNow (result: .writtenCompletely)\n        // 3:     --> writabilityChanged callout\n        // 4:         --> flushNow because user calls writeAndFlush (result: .couldNotWriteEverything)\n        // 5:         --> registerForWritable (because line 4 could not write everything and flushNow returned .register)\n        // 6: --> unregisterForWritable (because line 2 wrote everything and flushNow returned .unregister)\n        //\n        // line 6 undoes the registration in line 5. The fix makes sure that flushNow never re-enters and therefore the\n        // problem described above cannot happen anymore.\n        //\n        // Our match plan is the following:\n        // - receiver: switch off autoRead\n        // - sender: send 1k chunks of \"0\"s until we get a writabilityChange to false, then write a \"1\" sentinel\n        // - sender: should now be registered for writes\n        // - receiver: allocate a buffer big enough for the \"0....1\" and read it out as soon as possible\n        // - sender: the kernel should now call us with the `writable()` notification\n        // - sender: the remaining \"0...1\" should now go out of the door together, which means that `flushNow` decides\n        //           to `.unregister`\n        // - sender: because we now `.unregister` and also fall below the low watermark, we will send a writabilityChange\n        //           notification from which we will send a large 100MB chunk which certainly requires a new `writable()`\n        //           registration (which was previously lost)\n        // - receiver: just read off all the bytes\n        // - test: wait until the 100MB write completes which means that we didn't lost that `writable()` registration and\n        //         everybody should be happy :)\n\n        final class WriteUntilWriteDoesNotCompletelyInstantlyHandler: ChannelInboundHandler, RemovableChannelHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            enum State {\n                case writingUntilFull\n                case writeSentinel\n                case done\n            }\n\n            let chunkSize: Int\n            let wroteEnoughToBeStuckPromise: EventLoopPromise<Int>\n            var state = State.writingUntilFull\n            var bytesWritten = 0\n\n            init(chunkSize: Int, wroteEnoughToBeStuckPromise: EventLoopPromise<Int>) {\n                self.chunkSize = chunkSize\n                self.wroteEnoughToBeStuckPromise = wroteEnoughToBeStuckPromise\n            }\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                // We set the high watermark such that if we can't write something immediately, we'll get a\n                // writabilityChanged notification.\n                context.channel.setOption(\n                    .writeBufferWaterMark,\n                    value: .init(\n                        low: self.chunkSize,\n                        high: self.chunkSize + 1\n                    )\n                ).whenFailure { error in\n                    XCTFail(\"unexpected error \\(error)\")\n                }\n\n                // Write spin count would make the test less deterministic, so let's switch it off.\n                context.channel.setOption(.writeSpin, value: 0).whenFailure { error in\n                    XCTFail(\"unexpected error \\(error)\")\n                }\n\n                let loopBoundContext = context.loopBound\n                context.eventLoop.assumeIsolated().execute {\n                    let context = loopBoundContext.value\n                    self.kickOff(context: context)\n                }\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertEqual(.done, self.state)\n            }\n\n            func kickOff(context: ChannelHandlerContext) {\n                let buffer = NIOLoopBoundBox(\n                    context.channel.allocator.buffer(capacity: self.chunkSize),\n                    eventLoop: context.eventLoop\n                )\n                buffer.value.writeBytes(Array(repeating: UInt8(ascii: \"0\"), count: chunkSize))\n\n                let loopBoundContext = context.loopBound\n                let loopBoundSelf = NIOLoopBound(self, eventLoop: context.eventLoop)\n                func writeOneMore() {\n                    let context = loopBoundContext.value\n                    self.bytesWritten += buffer.value.readableBytes\n                    context.writeAndFlush(Self.wrapOutboundOut(buffer.value)).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                    context.eventLoop.assumeIsolated().scheduleTask(in: .microseconds(100)) {\n                        let context = loopBoundContext.value\n                        switch self.state {\n                        case .writingUntilFull:\n                            // We're just enqueuing another chunk.\n                            writeOneMore()\n                        case .writeSentinel:\n                            let `self` = loopBoundSelf.value\n                            // We've seen the notification that the channel is unwritable, let's write one more byte.\n                            buffer.value.clear()\n                            buffer.value.writeString(\"1\")\n                            self.state = .done\n                            self.bytesWritten += 1\n                            context.writeAndFlush(Self.wrapOutboundOut(buffer.value)).whenFailure { error in\n                                XCTFail(\"unexpected error \\(error)\")\n                            }\n                            self.wroteEnoughToBeStuckPromise.succeed(self.bytesWritten)\n                        case .done:\n                            ()  // let's ignore this.\n                        }\n                    }\n                }\n                context.eventLoop.assumeIsolated().execute {\n                    writeOneMore()  // this kicks everything off\n                }\n            }\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                switch self.state {\n                case .writingUntilFull:\n                    XCTAssert(!context.channel.isWritable)\n                    self.state = .writeSentinel\n                case .writeSentinel:\n                    XCTFail(\"we shouldn't see another notification here writable=\\(context.channel.isWritable)\")\n                case .done:\n                    ()  // ignored, we're done\n                }\n                context.fireChannelWritabilityChanged()\n                let loopBoundContext = context.loopBound\n                self.wroteEnoughToBeStuckPromise.futureResult.assumeIsolated().whenSuccess { _ in\n                    let context = loopBoundContext.value\n                    context.pipeline.syncOperations.removeHandler(self).whenFailure { error in\n                        XCTFail(\"unexpected error \\(error)\")\n                    }\n                }\n            }\n        }\n\n        final class WriteWhenChannelBecomesWritableAgain: ChannelInboundHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundOut = ByteBuffer\n\n            enum State {\n                case waitingForNotWritable\n                case waitingForWritableAgain\n                case done\n            }\n\n            var state = State.waitingForNotWritable\n            let beganBigWritePromise: EventLoopPromise<Void>\n            let finishedBigWritePromise: EventLoopPromise<Void>\n\n            init(beganBigWritePromise: EventLoopPromise<Void>, finishedBigWritePromise: EventLoopPromise<Void>) {\n                self.beganBigWritePromise = beganBigWritePromise\n                self.finishedBigWritePromise = finishedBigWritePromise\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertEqual(.done, self.state)\n            }\n\n            func channelWritabilityChanged(context: ChannelHandlerContext) {\n                switch self.state {\n                case .waitingForNotWritable:\n                    XCTAssert(!context.channel.isWritable)\n                    self.state = .waitingForWritableAgain\n                case .waitingForWritableAgain:\n                    XCTAssert(context.channel.isWritable)\n                    self.state = .done\n                    var buffer = context.channel.allocator.buffer(capacity: 10 * 1024 * 1024)\n                    buffer.writeBytes(Array(repeating: UInt8(ascii: \"X\"), count: buffer.capacity - 1))\n                    context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: self.finishedBigWritePromise)\n                    self.beganBigWritePromise.succeed(())\n                case .done:\n                    ()  // ignored\n                }\n            }\n        }\n\n        final class ReadChunksUntilWeSee1Handler: ChannelDuplexHandler {\n            typealias InboundIn = ByteBuffer\n            typealias OutboundIn = ByteBuffer\n\n            enum State {\n                case waitingForInitialOutsideReadCall\n                case waitingForZeroesTerminatedByOne\n                case done\n            }\n\n            var state: State = .waitingForInitialOutsideReadCall\n\n            func handlerAdded(context: ChannelHandlerContext) {\n                context.channel.setOption(.autoRead, value: false).whenFailure { error in\n                    XCTFail(\"unexpected error \\(error)\")\n                }\n            }\n\n            func handlerRemoved(context: ChannelHandlerContext) {\n                XCTAssertEqual(.done, self.state)\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let buffer = Self.unwrapInboundIn(data)\n                switch self.state {\n                case .waitingForInitialOutsideReadCall:\n                    XCTFail(\"unexpected \\(#function)\")\n                case .waitingForZeroesTerminatedByOne:\n                    buffer.withUnsafeReadableBytes { buffer in\n                        if buffer.first(where: { byte in byte == UInt8(ascii: \"1\") }) != nil {\n                            self.state = .done\n                        }\n                    }\n                case .done:\n                    ()  // let's ignore those reads, just 100 MB of Xs.\n                }\n            }\n\n            func channelReadComplete(context: ChannelHandlerContext) {\n                switch self.state {\n                case .waitingForInitialOutsideReadCall:\n                    XCTFail(\"unexpected \\(#function)\")\n                case .waitingForZeroesTerminatedByOne:\n                    context.read()  // read more\n                case .done:\n                    ()  // let's stop reading forever\n                }\n            }\n\n            func read(context: ChannelHandlerContext) {\n                switch self.state {\n                case .waitingForInitialOutsideReadCall:\n                    self.state = .waitingForZeroesTerminatedByOne\n                case .waitingForZeroesTerminatedByOne, .done:\n                    ()  // nothing else to do\n                }\n                context.read()\n            }\n        }\n\n        final class FailOnError: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Never\n\n            func errorCaught(context: ChannelHandlerContext, error: Error) {\n                XCTFail(\"unexpected error in \\(context.channel): \\(error)\")\n            }\n        }\n\n        func runTest(receiver: Channel, sender: Channel) throws {\n            // This promise will be fulfilled once we have exhausted all buffers and writes no longer worked for the\n            // sender. We can then start reading. The integer is the number of written bytes.\n            let wroteEnoughToBeStuckPromise: EventLoopPromise<Int> = sender.eventLoop.makePromise()\n\n            // This promise is fulfilled when we enqueue the big write on the sender side\n            let beganBigWritePromise: EventLoopPromise<Void> = sender.eventLoop.makePromise()\n\n            // This promise is fulfilled when we're done writing the big write, ie. all is done.\n            let finishedBigWritePromise: EventLoopPromise<Void> = sender.eventLoop.makePromise()\n\n            let chunkSize = 1024\n\n            // We need to not read automatically from the receiving end to be able to force writability notifications\n            // for the sender.\n            XCTAssertNoThrow(try receiver.setOption(.autoRead, value: false).wait())\n            let receiverConfigured = receiver.eventLoop.submit {\n                try receiver.pipeline.syncOperations.addHandler(ReadChunksUntilWeSee1Handler())\n            }\n            XCTAssertNoThrow(try receiverConfigured.wait())\n\n            let senderConfigured1 = sender.eventLoop.submit {\n                try sender.pipeline.syncOperations.addHandler(\n                    WriteWhenChannelBecomesWritableAgain(\n                        beganBigWritePromise: beganBigWritePromise,\n                        finishedBigWritePromise: finishedBigWritePromise\n                    )\n                )\n            }\n            XCTAssertNoThrow(try senderConfigured1.wait())\n\n            XCTAssertNoThrow(try sender.pipeline.addHandler(FailOnError()).wait())\n            XCTAssertNoThrow(try receiver.pipeline.addHandler(FailOnError()).wait())\n\n            let senderConfigured2 = sender.eventLoop.submit {\n                try sender.pipeline.syncOperations.addHandler(\n                    WriteUntilWriteDoesNotCompletelyInstantlyHandler(\n                        chunkSize: chunkSize,\n                        wroteEnoughToBeStuckPromise: wroteEnoughToBeStuckPromise\n                    ),\n                    position: .first\n                )\n            }\n            XCTAssertNoThrow(try senderConfigured2.wait())\n            var howManyBytes: Int? = nil\n\n            XCTAssertNoThrow(howManyBytes = try wroteEnoughToBeStuckPromise.futureResult.wait())\n            guard let bytes = howManyBytes else {\n                XCTFail(\"couldn't determine how much was written.\")\n                return\n            }\n\n            // Let's prepare the receiver's allocator to allocate exactly the right amount of bytes :), ...\n            XCTAssertNoThrow(\n                try receiver.setOption(\n                    .recvAllocator,\n                    value: FixedSizeRecvByteBufferAllocator(capacity: bytes)\n                ).wait()\n            )\n\n            // ... wait for the sender to not send any more, and ...\n            XCTAssertNoThrow(try wroteEnoughToBeStuckPromise.futureResult.wait())\n\n            // ... make the receiver read.\n            receiver.read()\n\n            // Now, we wait until the big write has been enqueued, that's when we should enter the main stage of this\n            // test.\n            XCTAssertNoThrow(try beganBigWritePromise.futureResult.wait())\n\n            // We now just set autoRead to true and let the receiver receive everything to tear everything down.\n            XCTAssertNoThrow(try receiver.setOption(.autoRead, value: true).wait())\n\n            XCTAssertNoThrow(try finishedBigWritePromise.futureResult.wait())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n\n    func testCloseInReEntrantFlushNowCall() {\n        func runTest(receiver: Channel, sender: Channel) throws {\n            final class CloseInWritabilityChanged: ChannelInboundHandler {\n                typealias InboundIn = Never\n                typealias OutboundOut = ByteBuffer\n\n                private let amount: Int\n                private var numberOfCalls = 0\n\n                init(amount: Int) {\n                    self.amount = amount\n                }\n\n                func channelWritabilityChanged(context: ChannelHandlerContext) {\n                    self.numberOfCalls += 1\n                    switch self.numberOfCalls {\n                    case 1:\n                        XCTAssertFalse(context.channel.isWritable)  // because we sent more than high water\n                    case 2:\n                        XCTAssertTrue(context.channel.isWritable)  // but actually only 2 bytes\n\n                        // Let's send another 2 bytes, ...\n                        var buffer = context.channel.allocator.buffer(capacity: amount)\n                        buffer.writeBytes(Array(repeating: UInt8(ascii: \"X\"), count: amount))\n                        context.writeAndFlush(Self.wrapOutboundOut(buffer), promise: nil)\n\n                        // ... and let's close\n                        context.close(promise: nil)\n                    case 3:\n                        XCTAssertFalse(context.channel.isWritable)  // 2 bytes > high water\n                    default:\n                        XCTFail(\"\\(self.numberOfCalls) calls to \\(#function) are unexpected\")\n                    }\n                }\n            }\n\n            let amount = 2\n            let senderConfigured = sender.eventLoop.submit {\n                try sender.pipeline.syncOperations.addHandler(CloseInWritabilityChanged(amount: amount))\n            }\n            XCTAssertNoThrow(try senderConfigured.wait())\n            XCTAssertNoThrow(\n                try sender.setOption(\n                    .writeBufferWaterMark,\n                    value: .init(\n                        low: amount - 1,\n                        high: amount - 1\n                    )\n                ).wait()\n            )\n            var buffer = sender.allocator.buffer(capacity: amount)\n            buffer.writeBytes(Array(repeating: UInt8(ascii: \"X\"), count: amount))\n            XCTAssertNoThrow(try sender.writeAndFlush(buffer).wait())\n        }\n        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))\n    }\n}\n\nfinal class AccumulateAllReads: ChannelInboundHandler {\n    typealias InboundIn = ByteBuffer\n\n    var accumulator: ByteBuffer!\n    let allDonePromise: EventLoopPromise<ByteBuffer>\n\n    init(allDonePromise: EventLoopPromise<ByteBuffer>) {\n        self.allDonePromise = allDonePromise\n    }\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        self.accumulator = context.channel.allocator.buffer(capacity: 1024)\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var buffer = Self.unwrapInboundIn(data)\n        let closeAfter = buffer.readableBytesView.last == UInt8(ascii: \"$\")\n        self.accumulator.writeBuffer(&buffer)\n        if closeAfter {\n            context.close(promise: nil)\n        }\n    }\n\n    func channelInactive(context: ChannelHandlerContext) {\n        self.allDonePromise.succeed(self.accumulator)\n        self.accumulator = nil\n    }\n}\n\nprivate func assertNoSelectorChanges(\n    fd: CInt,\n    selector: NIOPosix.Selector<NIORegistration>,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws {\n    struct UnexpectedSelectorChanges: Error, CustomStringConvertible {\n        let description: String\n    }\n\n    #if canImport(Darwin) || os(FreeBSD)\n    var ev: kevent = .init()\n    var nothing: timespec = .init()\n    let numberOfEvents = try KQueue.kevent(\n        kq: fd,\n        changelist: nil,\n        nchanges: 0,\n        eventlist: &ev,\n        nevents: 1,\n        timeout: &nothing\n    )\n    guard numberOfEvents == 0 else {\n        throw UnexpectedSelectorChanges(description: \"\\(ev)\")\n    }\n    #elseif os(Linux) || os(Android)\n    #if !SWIFTNIO_USE_IO_URING\n    var ev = Epoll.epoll_event()\n    let numberOfEvents = try Epoll.epoll_wait(epfd: fd, events: &ev, maxevents: 1, timeout: 0)\n    guard numberOfEvents == 0 else {\n        throw UnexpectedSelectorChanges(description: \"\\(ev) [userdata: \\(EPollUserData(rawValue: ev.data.u64))]\")\n    }\n    #else\n    let events: UnsafeMutablePointer<URingEvent> = UnsafeMutablePointer.allocate(capacity: 1)\n    events.initialize(to: URingEvent())\n    let numberOfEvents = try selector.ring.io_uring_wait_cqe_timeout(\n        events: events,\n        maxevents: 1,\n        timeout: TimeAmount.seconds(0)\n    )\n    events.deinitialize(count: 1)\n    events.deallocate()\n    guard numberOfEvents == 0 else {\n        throw UnexpectedSelectorChanges(description: \"\\(selector)\")\n    }\n    #endif\n    #else\n    #warning(\"assertNoSelectorChanges unsupported on this OS.\")\n    #endif\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SyscallAbstractionLayer.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// This file contains a syscall abstraction layer (SAL) which hooks the Selector and the Socket in a way that we can\n// play the kernel whilst NIO thinks it's running on a real OS.\n//\n// The SAL tests are pretty darn awkward with respect to sendability.\n//\n// Each SAL test is setup such that it can run some work on an event loop whose\n// selector has been hooked such that it signals various events to locked\n// containers. Another closure in each test can make assertions on the values of\n// these containers, waiting for them to happen. These run in lock step. It\n// means that various very much not sendable values must be transferred between\n// isoaltion domains (the event loop and the calling thread). In general this\n// isn't safe as non-sendable values could be escaped. These tests are quite\n// careful to avoid that. This does however, mean that annotating types\n// appropriately in order for the compiler to catch thread safety warnings is\n// difficult.\n//\n// The current setup requires a 'SALContext' which holds the hooked event\n// loop and various locked containers. It's also responsible for the lifecycle\n// of these objects.\n//\n// The context also provides you with various methods for running a SAL test on\n// the hooked event loop. Within that closure you're provided with the event\n// loop and the user-to-kernel and kernel-to-user locked boxes. Another closure\n// is also provided with an assertions object to wait for various events to\n// happen.\n//\n// There are some sendability holes here:\n//\n// - LockedBox is unconditionally Sendable. It should only be Sendable when the\n//   value it stores is Sendable.\n// - Instances of LockedBox hold KernelToUser and UserToKernel types which are\n//   *not* Sendable. These are shared between the event loop and the calling\n//   thread.\n// - HookedSocket isn't Sendable but is transferred between the EventLoop and\n//   the calling thread in an UnsafeTransfer.\n\nimport CNIOLinux\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\ninternal enum SAL {\n    fileprivate static let defaultTimeout: Double = 5\n    private static let debugTests: Bool = false\n    static func printIfDebug(_ item: Any) {\n        if debugTests {\n            print(item)\n        }\n    }\n}\n\nfinal class LockedBox<T>: @unchecked Sendable {\n    // @unchecked: _value is protected by a condition lock.\n    // TODO: a condition-locked-value-box could hide some of the unchecked-ness here.\n\n    struct TimeoutError: Error {\n        var description: String\n        init(_ description: String) {\n            self.description = description\n        }\n    }\n    struct ExpectedEmptyBox: Error {}\n\n    private let condition = ConditionLock(value: 0)\n    private let description: String\n    private let didSet: @Sendable (T?) -> Void\n    private var _value: T? {\n        didSet {\n            self.didSet(self._value)\n        }\n    }\n\n    init(\n        _ value: T? = nil,\n        description: String? = nil,\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        didSet: @escaping @Sendable (T?) -> Void = { _ in }\n    ) {\n        self._value = value\n        self.didSet = didSet\n        self.description = description ?? \"\\(file):\\(line)\"\n    }\n\n    internal var value: T? {\n        get {\n            self.condition.lock()\n            defer {\n                self.condition.unlock()\n            }\n            return self._value\n        }\n\n        set {\n            self.condition.lock()\n            if let value = newValue {\n                self._value = value\n                self.condition.unlock(withValue: 1)\n            } else {\n                self._value = nil\n                self.condition.unlock(withValue: 0)\n            }\n        }\n    }\n\n    func waitForEmptyAndSet(_ value: T) throws {\n        if self.condition.lock(whenValue: 0, timeoutSeconds: SAL.defaultTimeout) {\n            defer {\n                self.condition.unlock(withValue: 1)\n            }\n            self._value = value\n        } else {\n            throw TimeoutError(self.description)\n        }\n    }\n\n    func takeValue() throws -> T {\n        if self.condition.lock(whenValue: 1, timeoutSeconds: SAL.defaultTimeout) {\n            defer {\n                self.condition.unlock(withValue: 0)\n            }\n            let value = self._value!\n            self._value = nil\n            return value\n        } else {\n            throw TimeoutError(self.description)\n        }\n    }\n\n    func waitForLockedValue<R>(_ body: (T) throws -> R) throws -> R {\n        if self.condition.lock(whenValue: 1, timeoutSeconds: SAL.defaultTimeout) {\n            defer {\n                self.condition.unlock(withValue: 1)\n            }\n            return try body(self._value!)\n        } else {\n            throw TimeoutError(self.description)\n        }\n    }\n}\n\nextension LockedBox where T == UserToKernel {\n    func assertParkedRightNow(file: StaticString = #filePath, line: UInt = #line) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.waitForLockedValue { syscall in\n            if case .whenReady(.block) = syscall {\n                return\n            } else {\n                XCTFail(\"unexpected syscall \\(syscall)\", file: (file), line: line)\n            }\n        }\n    }\n}\n\nenum UserToKernel {\n    case localAddress\n    case remoteAddress\n    case connect(SocketAddress)\n    case read(Int)\n    case close(CInt)\n    case register(Selectable, SelectorEventSet, NIORegistration)\n    case reregister(Selectable, SelectorEventSet)\n    case deregister(Selectable)\n    case whenReady(SelectorStrategy)\n    case disableSIGPIPE(CInt)\n    case write(CInt, ByteBuffer)\n    case writev(CInt, [ByteBuffer])\n    case bind(SocketAddress)\n    case getOption(NIOBSDSocket.OptionLevel, NIOBSDSocket.Option)\n    case setOption(NIOBSDSocket.OptionLevel, NIOBSDSocket.Option, Any)\n    case listen(CInt, CInt)\n    case accept(CInt, Bool)\n}\n\nenum KernelToUser {\n    case returnSocketAddress(SocketAddress)\n    case returnBool(Bool)\n    case returnBytes(ByteBuffer)\n    case returnVoid\n    case returnSelectorEvent(SelectorEvent<NIORegistration>?)\n    case returnIOResultInt(IOResult<Int>)\n    case returnSocket(Socket?)\n    case error(Error)\n    case returnAny(Any)\n}\n\nstruct UnexpectedKernelReturn: Error {\n    private var ret: String\n\n    init(_ ret: KernelToUser) {\n        self.ret = String(describing: ret)\n    }\n}\n\nstruct UnexpectedSyscall: Error {\n    private var syscall: String\n\n    init(_ syscall: UserToKernel) {\n        self.syscall = String(describing: syscall)\n    }\n}\n\nprivate protocol UserKernelInterface {\n    var userToKernel: LockedBox<UserToKernel> { get }\n    var kernelToUser: LockedBox<KernelToUser> { get }\n}\n\nextension UserKernelInterface {\n    fileprivate func waitForKernelReturn() throws -> KernelToUser {\n        let value = try self.kernelToUser.takeValue()\n        if case .error(let error) = value {\n            throw error\n        } else {\n            return value\n        }\n    }\n}\n\ninternal class HookedSelector: NIOPosix.Selector<NIORegistration>, UserKernelInterface {\n    fileprivate let userToKernel: LockedBox<UserToKernel>\n    fileprivate let kernelToUser: LockedBox<KernelToUser>\n    fileprivate let wakeups: LockedBox<()>\n\n    init(\n        userToKernel: LockedBox<UserToKernel>,\n        kernelToUser: LockedBox<KernelToUser>,\n        wakeups: LockedBox<()>,\n        thread: NIOThread\n    ) throws {\n        self.userToKernel = userToKernel\n        self.kernelToUser = kernelToUser\n        self.wakeups = wakeups\n        try super.init(thread: thread)\n        self.lifecycleState = .open\n    }\n\n    override func register<S: Selectable>(\n        selectable: S,\n        interested: SelectorEventSet,\n        makeRegistration: (SelectorEventSet, SelectorRegistrationID) -> NIORegistration\n    ) throws {\n        try self.userToKernel.waitForEmptyAndSet(\n            .register(\n                selectable,\n                interested,\n                makeRegistration(\n                    interested,\n                    .initialRegistrationID\n                )\n            )\n        )\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func reregister<S: Selectable>(selectable: S, interested: SelectorEventSet) throws {\n        try self.userToKernel.waitForEmptyAndSet(.reregister(selectable, interested))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func whenReady(\n        strategy: SelectorStrategy,\n        onLoopBegin loopStart: () -> Void,\n        _ body: (SelectorEvent<NIORegistration>) throws -> Void\n    ) throws {\n        try self.userToKernel.waitForEmptyAndSet(.whenReady(strategy))\n        let ret = try self.waitForKernelReturn()\n        if case .returnSelectorEvent(let event) = ret {\n            loopStart()\n            if let event = event {\n                try body(event)\n            }\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func deregister<S: Selectable>(selectable: S) throws {\n        try self.userToKernel.waitForEmptyAndSet(.deregister(selectable))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func wakeup() throws {\n        SAL.printIfDebug(\"WAKEUP\")\n        try self.wakeups.waitForEmptyAndSet(())\n    }\n}\n\nclass HookedServerSocket: ServerSocket, UserKernelInterface {\n    fileprivate let userToKernel: LockedBox<UserToKernel>\n    fileprivate let kernelToUser: LockedBox<KernelToUser>\n\n    init(\n        userToKernel: LockedBox<UserToKernel>,\n        kernelToUser: LockedBox<KernelToUser>,\n        socket: NIOBSDSocket.Handle\n    ) throws {\n        self.userToKernel = userToKernel\n        self.kernelToUser = kernelToUser\n        try super.init(socket: socket)\n    }\n\n    override func ignoreSIGPIPE() throws {\n        try self.withUnsafeHandle { fd in\n            try self.userToKernel.waitForEmptyAndSet(.disableSIGPIPE(fd))\n            let ret = try self.waitForKernelReturn()\n            if case .returnVoid = ret {\n                return\n            } else {\n                throw UnexpectedKernelReturn(ret)\n            }\n        }\n    }\n\n    override func localAddress() throws -> SocketAddress {\n        try self.userToKernel.waitForEmptyAndSet(.localAddress)\n        let ret = try self.waitForKernelReturn()\n        if case .returnSocketAddress(let address) = ret {\n            return address\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func remoteAddress() throws -> SocketAddress {\n        try self.userToKernel.waitForEmptyAndSet(.remoteAddress)\n        let ret = try self.waitForKernelReturn()\n        if case .returnSocketAddress(let address) = ret {\n            return address\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func bind(to address: SocketAddress) throws {\n        try self.userToKernel.waitForEmptyAndSet(.bind(address))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func listen(backlog: Int32 = 128) throws {\n        try self.withUnsafeHandle { fd in\n            try self.userToKernel.waitForEmptyAndSet(.listen(fd, backlog))\n            let ret = try self.waitForKernelReturn()\n            if case .returnVoid = ret {\n                return\n            } else {\n                throw UnexpectedKernelReturn(ret)\n            }\n        }\n    }\n\n    override func accept(setNonBlocking: Bool = false) throws -> Socket? {\n        try self.withUnsafeHandle { fd in\n            try self.userToKernel.waitForEmptyAndSet(.accept(fd, setNonBlocking))\n            let ret = try self.waitForKernelReturn()\n            switch ret {\n            case .returnSocket(let socket):\n                return socket\n            case .error(let error):\n                throw error\n            default:\n                throw UnexpectedKernelReturn(ret)\n            }\n        }\n    }\n\n    override func close() throws {\n        let fd = try self.takeDescriptorOwnership()\n\n        try self.userToKernel.waitForEmptyAndSet(.close(fd))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n}\n\nfinal class HookedSocket: Socket, UserKernelInterface {\n    fileprivate let userToKernel: LockedBox<UserToKernel>\n    fileprivate let kernelToUser: LockedBox<KernelToUser>\n\n    init(\n        userToKernel: LockedBox<UserToKernel>,\n        kernelToUser: LockedBox<KernelToUser>,\n        socket: NIOBSDSocket.Handle\n    ) throws {\n        self.userToKernel = userToKernel\n        self.kernelToUser = kernelToUser\n        try super.init(socket: socket)\n    }\n\n    override func ignoreSIGPIPE() throws {\n        try self.withUnsafeHandle { fd in\n            try self.userToKernel.waitForEmptyAndSet(.disableSIGPIPE(fd))\n            let ret = try self.waitForKernelReturn()\n            if case .returnVoid = ret {\n                return\n            } else {\n                throw UnexpectedKernelReturn(ret)\n            }\n        }\n    }\n\n    override func localAddress() throws -> SocketAddress {\n        try self.userToKernel.waitForEmptyAndSet(.localAddress)\n        let ret = try self.waitForKernelReturn()\n        if case .returnSocketAddress(let address) = ret {\n            return address\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func remoteAddress() throws -> SocketAddress {\n        try self.userToKernel.waitForEmptyAndSet(.remoteAddress)\n        let ret = try self.waitForKernelReturn()\n        if case .returnSocketAddress(let address) = ret {\n            return address\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func connect(to address: SocketAddress) throws -> Bool {\n        try self.userToKernel.waitForEmptyAndSet(.connect(address))\n        let ret = try self.waitForKernelReturn()\n        if case .returnBool(let success) = ret {\n            return success\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func read(pointer: UnsafeMutableRawBufferPointer) throws -> IOResult<Int> {\n        try self.userToKernel.waitForEmptyAndSet(.read(pointer.count))\n        let ret = try self.waitForKernelReturn()\n        if case .returnBytes(let buffer) = ret {\n            assert(buffer.readableBytes <= pointer.count)\n            pointer.copyBytes(from: buffer.readableBytesView)\n            return .processed(buffer.readableBytes)\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func write(pointer: UnsafeRawBufferPointer) throws -> IOResult<Int> {\n        try self.withUnsafeHandle { fd in\n            var buffer = ByteBufferAllocator().buffer(capacity: pointer.count)\n            buffer.writeBytes(pointer)\n            try self.userToKernel.waitForEmptyAndSet(.write(fd, buffer))\n            let ret = try self.waitForKernelReturn()\n            if case .returnIOResultInt(let result) = ret {\n                return result\n            } else {\n                throw UnexpectedKernelReturn(ret)\n            }\n        }\n    }\n\n    override func writev(iovecs: UnsafeBufferPointer<IOVector>) throws -> IOResult<Int> {\n        try self.withUnsafeHandle { fd in\n            let buffers = iovecs.map { iovec -> ByteBuffer in\n                #if os(Android)\n                var buffer = ByteBufferAllocator().buffer(capacity: Int(iovec.iov_len))\n                buffer.writeBytes(UnsafeRawBufferPointer(start: iovec.iov_base, count: Int(iovec.iov_len)))\n                #else\n                var buffer = ByteBufferAllocator().buffer(capacity: iovec.iov_len)\n                buffer.writeBytes(UnsafeRawBufferPointer(start: iovec.iov_base, count: iovec.iov_len))\n                #endif\n                return buffer\n            }\n\n            try self.userToKernel.waitForEmptyAndSet(.writev(fd, buffers))\n            let ret = try self.waitForKernelReturn()\n            if case .returnIOResultInt(let result) = ret {\n                return result\n            } else {\n                throw UnexpectedKernelReturn(ret)\n            }\n        }\n    }\n\n    override func close() throws {\n        let fd = try self.takeDescriptorOwnership()\n\n        try self.userToKernel.waitForEmptyAndSet(.close(fd))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func getOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) throws -> T {\n        try self.userToKernel.waitForEmptyAndSet(.getOption(level, name))\n        let ret = try self.waitForKernelReturn()\n        if case .returnAny(let any) = ret {\n            return any as! T\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func setOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option, value: T) throws {\n        try self.userToKernel.waitForEmptyAndSet(.setOption(level, name, value))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n\n    override func bind(to address: SocketAddress) throws {\n        try self.userToKernel.waitForEmptyAndSet(.bind(address))\n        let ret = try self.waitForKernelReturn()\n        if case .returnVoid = ret {\n            return\n        } else {\n            throw UnexpectedKernelReturn(ret)\n        }\n    }\n}\n\nextension HookedSelector {\n    func assertSyscallAndReturn(\n        _ result: KernelToUser,\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        matcher: (UserToKernel) throws -> Bool\n    ) throws {\n        let syscall = try self.userToKernel.takeValue()\n        if try matcher(syscall) {\n            try self.kernelToUser.waitForEmptyAndSet(result)\n        } else {\n            XCTFail(\"unexpected syscall \\(syscall)\", file: (file), line: line)\n            throw UnexpectedSyscall(syscall)\n        }\n    }\n\n    /// This function will wait for an event loop wakeup until it unblocks. If the event loop\n    /// is currently executing then it will not be woken: as a result, consider using\n    /// `assertParkedRightNow` before the event that you want to trigger the wakeup, and before calling\n    /// this code.\n    func assertWakeup(file: StaticString = #filePath, line: UInt = #line) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.wakeups.takeValue()\n        try self.assertSyscallAndReturn(.returnSelectorEvent(nil), file: (file), line: line) { syscall in\n            if case .whenReady(.block) = syscall {\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertParkedRightNow(file: StaticString = #filePath, line: UInt = #line) throws {\n        try self.userToKernel.assertParkedRightNow(file: file, line: line)\n    }\n}\n\nextension EventLoopFuture where Value: Sendable {\n    /// This works like `EventLoopFuture.wait()` but can be used together with the SAL.\n    ///\n    /// Using a plain `EventLoopFuture.wait()` together with the SAL would require you to spin the `EventLoop` manually\n    /// which is error prone and hard.\n    func salWait(context: SALContext) throws -> Value {\n        precondition(context.eventLoop === self.eventLoop)\n        let box = LockedBox<Result<Value, Error>>()\n\n        XCTAssertNoThrow(\n            try context.runSALOnEventLoop { _, _, _ in\n                self.whenComplete { value in\n                    // We can bang this because the LockedBox is empty so it'll immediately succeed.\n                    try! box.waitForEmptyAndSet(value)\n                }\n            }\n        )\n\n        return try box.waitForLockedValue { try $0.get() }\n    }\n}\n\nextension SALContext {\n    private func makeSocketChannel(\n        eventLoop: SelectableEventLoop,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> SocketChannel {\n        let channel = try self.runSALOnEventLoop { eventLoop, kernelToUser, userToKernel in\n            try SocketChannel(\n                socket: HookedSocket(\n                    userToKernel: userToKernel,\n                    kernelToUser: kernelToUser,\n                    socket: .max\n                ),\n                eventLoop: eventLoop\n            )\n        } syscallAssertions: { assertions in\n            try assertions.assertdisableSIGPIPE(expectedFD: .max, result: .success(()))\n            try assertions.assertLocalAddress(address: nil)\n            try assertions.assertRemoteAddress(address: nil)\n            try assertions.assertParkedRightNow()\n        }\n\n        try self.selector.assertParkedRightNow()\n        return channel\n    }\n\n    private func makeServerSocketChannel(\n        eventLoop: SelectableEventLoop,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> ServerSocketChannel {\n        let channel = try self.runSALOnEventLoop { eventLoop, kernelToUser, userToKernel in\n            try ServerSocketChannel(\n                serverSocket: HookedServerSocket(\n                    userToKernel: userToKernel,\n                    kernelToUser: kernelToUser,\n                    socket: .max\n                ),\n                eventLoop: eventLoop,\n                group: eventLoop\n            )\n        } syscallAssertions: { assertions in\n            try assertions.assertdisableSIGPIPE(expectedFD: .max, result: .success(()))\n            try assertions.assertLocalAddress(address: nil)\n            try assertions.assertRemoteAddress(address: nil)\n        }\n\n        try self.selector.assertParkedRightNow()\n        return channel\n    }\n\n    func makeSocketChannelInjectingFailures(disableSIGPIPEFailure: IOError?) throws -> SocketChannel {\n        let channel = try self.runSALOnEventLoop { eventLoop, kernelToUser, userToKernel in\n            try SocketChannel(\n                socket: HookedSocket(\n                    userToKernel: userToKernel,\n                    kernelToUser: kernelToUser,\n                    socket: .max\n                ),\n                eventLoop: eventLoop\n            )\n        } syscallAssertions: { assertions in\n            try assertions.assertdisableSIGPIPE(\n                expectedFD: .max,\n                result: disableSIGPIPEFailure.map {\n                    Result<Void, IOError>.failure($0)\n                } ?? .success(())\n            )\n            guard disableSIGPIPEFailure == nil else {\n                // if F_NOSIGPIPE failed, we shouldn't see other syscalls.\n                return\n            }\n            try assertions.assertLocalAddress(address: nil)\n            try assertions.assertRemoteAddress(address: nil)\n        }\n\n        try self.selector.assertParkedRightNow()\n        return channel\n    }\n\n    func makeSocketChannel(file: StaticString = #filePath, line: UInt = #line) throws -> SocketChannel {\n        try self.makeSocketChannel(eventLoop: self.eventLoop, file: file, line: line)\n    }\n\n    func makeServerSocketChannel(file: StaticString = #filePath, line: UInt = #line) throws -> ServerSocketChannel {\n        try self.makeServerSocketChannel(eventLoop: self.eventLoop, file: file, line: line)\n    }\n\n    func makeConnectedSocketChannel(\n        localAddress: SocketAddress?,\n        remoteAddress: SocketAddress,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> SocketChannel {\n        let channel = try self.makeSocketChannel(eventLoop: self.eventLoop)\n        try self.runSALOnEventLoopAndWait { _, _, _ in\n            channel.register().flatMap {\n                channel.connect(to: remoteAddress)\n            }\n        } syscallAssertions: { assertions in\n            try assertions.assertConnect(expectedAddress: remoteAddress, result: true)\n            try assertions.assertLocalAddress(address: localAddress)\n            try assertions.assertRemoteAddress(address: remoteAddress)\n            try assertions.assertRegister { selectable, eventSet, registration in\n                if case (.socketChannel(let channel), let registrationEventSet) =\n                    (registration.channel, registration.interested)\n                {\n\n                    XCTAssertEqual(localAddress, channel.localAddress)\n                    XCTAssertEqual(remoteAddress, channel.remoteAddress)\n                    XCTAssertEqual(eventSet, registrationEventSet)\n                    XCTAssertEqual([.reset, .error], eventSet)\n                    return true\n                } else {\n                    return false\n                }\n            }\n            try assertions.assertReregister { selectable, eventSet in\n                XCTAssertEqual([.reset, .error, .readEOF], eventSet)\n                return true\n            }\n            // because autoRead is on by default\n            try assertions.assertReregister { selectable, eventSet in\n                XCTAssertEqual([.reset, .error, .readEOF, .read], eventSet)\n                return true\n            }\n        }\n        return channel\n    }\n\n    func makeBoundServerSocketChannel(\n        localAddress: SocketAddress,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws -> ServerSocketChannel {\n        let channel = try self.makeServerSocketChannel(eventLoop: self.eventLoop)\n        try self.runSALOnEventLoopAndWait { _, _, _ in\n            channel.register().flatMap {\n                channel.bind(to: localAddress)\n            }\n        } syscallAssertions: { assertions in\n            try assertions.assertBind(expectedAddress: localAddress)\n            try assertions.assertLocalAddress(address: localAddress)\n            try assertions.assertListen(expectedFD: .max, expectedBacklog: 128)\n            try assertions.assertRegister { selectable, eventSet, registration in\n                if case (.serverSocketChannel(let channel), let registrationEventSet) =\n                    (registration.channel, registration.interested)\n                {\n\n                    XCTAssertEqual(localAddress, channel.localAddress)\n                    XCTAssertEqual(nil, channel.remoteAddress)\n                    XCTAssertEqual(eventSet, registrationEventSet)\n                    XCTAssertEqual([.reset, .error], eventSet)\n                    return true\n                } else {\n                    return false\n                }\n            }\n            try assertions.assertReregister { selectable, eventSet in\n                XCTAssertEqual([.reset, .error, .readEOF], eventSet)\n                return true\n            }\n            // because autoRead is on by default\n            try assertions.assertReregister { selectable, eventSet in\n                XCTAssertEqual([.reset, .error, .readEOF, .read], eventSet)\n                return true\n            }\n        }\n        return channel\n    }\n\n    func makeSocket() throws -> UnsafeTransfer<HookedSocket> {\n        try self.runSALOnEventLoop { _, kernelToUser, userToKernel in\n            let socket = try HookedSocket(userToKernel: userToKernel, kernelToUser: kernelToUser, socket: .max)\n            return UnsafeTransfer(socket)\n        } syscallAssertions: { assertions in\n            try assertions.assertdisableSIGPIPE(expectedFD: .max, result: .success(()))\n        }\n    }\n\n}\n\nstruct SyscallAssertions: @unchecked Sendable {\n    // The HookedSelector _isn't_ Sendable and holds locked value boxes for types which also\n    // aren't Sendable. However, these assertions are safe; they effectively wait on a locked\n    // value and make assertions against them.\n    private let selector: HookedSelector\n\n    init(selector: HookedSelector) {\n        self.selector = selector\n    }\n\n    func assertWaitingForNotification(\n        result: SelectorEvent<NIORegistration>?,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)(result: \\(result.debugDescription))\")\n        try self.selector.assertSyscallAndReturn(\n            .returnSelectorEvent(result),\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .whenReady = syscall {\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertWakeup(file: StaticString = #filePath, line: UInt = #line) throws {\n        try self.selector.assertWakeup(file: (file), line: line)\n    }\n\n    func assertdisableSIGPIPE(\n        expectedFD: CInt,\n        result: Result<Void, IOError>,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        let ret: KernelToUser\n        switch result {\n        case .success:\n            ret = .returnVoid\n        case .failure(let error):\n            ret = .error(error)\n        }\n        try self.selector.assertSyscallAndReturn(ret, file: (file), line: line) { syscall in\n            if case .disableSIGPIPE(expectedFD) = syscall {\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertLocalAddress(address: SocketAddress?, file: StaticString = #filePath, line: UInt = #line) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(\n            address.map {\n                .returnSocketAddress($0)\n            } ?? .error(IOError(errnoCode: EOPNOTSUPP, reason: \"nil passed\")),\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .localAddress = syscall {\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertRemoteAddress(address: SocketAddress?, file: StaticString = #filePath, line: UInt = #line) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(\n            address.map { .returnSocketAddress($0) } ?? .error(IOError(errnoCode: EOPNOTSUPP, reason: \"nil passed\")),\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .remoteAddress = syscall {\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertConnect(\n        expectedAddress: SocketAddress,\n        result: Bool,\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        _ matcher: (SocketAddress) -> Bool = { _ in true }\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnBool(result), file: (file), line: line) { syscall in\n            if case .connect(let address) = syscall {\n                return address == expectedAddress\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertBind(expectedAddress: SocketAddress, file: StaticString = #filePath, line: UInt = #line) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnVoid, file: (file), line: line) { syscall in\n            if case .bind(let address) = syscall {\n                return address == expectedAddress\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertClose(expectedFD: CInt, file: StaticString = #filePath, line: UInt = #line) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnVoid, file: (file), line: line) { syscall in\n            if case .close(let fd) = syscall {\n                XCTAssertEqual(expectedFD, fd, file: (file), line: line)\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertGetOption<OptionValue>(\n        expectedLevel: NIOBSDSocket.OptionLevel,\n        expectedOption: NIOBSDSocket.Option,\n        value: OptionValue,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnAny(value), file: (file), line: line) { syscall in\n            if case .getOption(expectedLevel, expectedOption) = syscall {\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertSetOption(\n        expectedLevel: NIOBSDSocket.OptionLevel,\n        expectedOption: NIOBSDSocket.Option,\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        _ valueMatcher: (Any) -> Bool = { _ in true }\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnVoid, file: (file), line: line) { syscall in\n            if case .setOption(expectedLevel, expectedOption, let value) = syscall {\n                return valueMatcher(value)\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertRegister(\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        _ matcher: (Selectable, SelectorEventSet, NIORegistration) throws -> Bool\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnVoid, file: (file), line: line) { syscall in\n            if case .register(let selectable, let eventSet, let registration) = syscall {\n                return try matcher(selectable, eventSet, registration)\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertReregister(\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        _ matcher: (Selectable, SelectorEventSet) throws -> Bool\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnVoid, file: (file), line: line) { syscall in\n            if case .reregister(let selectable, let eventSet) = syscall {\n                return try matcher(selectable, eventSet)\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertDeregister(\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        _ matcher: (Selectable) throws -> Bool\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnVoid, file: (file), line: line) { syscall in\n            if case .deregister(let selectable) = syscall {\n                return try matcher(selectable)\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertWrite(\n        expectedFD: CInt,\n        expectedBytes: ByteBuffer,\n        return: IOResult<Int>,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnIOResultInt(`return`), file: (file), line: line) { syscall in\n            if case .write(let actualFD, let actualBytes) = syscall {\n                return expectedFD == actualFD && expectedBytes == actualBytes\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertWritev(\n        expectedFD: CInt,\n        expectedBytes: [ByteBuffer],\n        return: IOResult<Int>,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(.returnIOResultInt(`return`), file: (file), line: line) { syscall in\n            if case .writev(let actualFD, let actualBytes) = syscall {\n                return expectedFD == actualFD && expectedBytes == actualBytes\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertRead(\n        expectedFD: CInt,\n        expectedBufferSpace: Int,\n        return: ByteBuffer,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(\n            .returnBytes(`return`),\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .read(let amount) = syscall {\n                XCTAssertEqual(expectedBufferSpace, amount, file: (file), line: line)\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertListen(\n        expectedFD: CInt,\n        expectedBacklog: CInt,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(\n            .returnVoid,\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .listen(let fd, let backlog) = syscall {\n                XCTAssertEqual(fd, expectedFD, file: (file), line: line)\n                XCTAssertEqual(backlog, expectedBacklog, file: (file), line: line)\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertAccept(\n        expectedFD: CInt,\n        expectedNonBlocking: Bool,\n        return: Socket?,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(\n            .returnSocket(`return`),\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .accept(let fd, let nonBlocking) = syscall {\n                XCTAssertEqual(fd, expectedFD, file: (file), line: line)\n                XCTAssertEqual(nonBlocking, expectedNonBlocking, file: (file), line: line)\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertAccept(\n        expectedFD: CInt,\n        expectedNonBlocking: Bool,\n        throwing error: Error,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        SAL.printIfDebug(\"\\(#function)\")\n        try self.selector.assertSyscallAndReturn(\n            .error(error),\n            file: (file),\n            line: line\n        ) { syscall in\n            if case .accept(let fd, let nonBlocking) = syscall {\n                XCTAssertEqual(fd, expectedFD, file: (file), line: line)\n                XCTAssertEqual(nonBlocking, expectedNonBlocking, file: (file), line: line)\n                return true\n            } else {\n                return false\n            }\n        }\n    }\n\n    func assertSyscallAndReturn(\n        _ result: KernelToUser,\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        matcher: (UserToKernel) throws -> Bool\n    ) throws {\n        try self.selector.assertSyscallAndReturn(result, file: file, line: line, matcher: matcher)\n    }\n\n    func assertParkedRightNow(file: StaticString = #filePath, line: UInt = #line) throws {\n        try self.selector.assertParkedRightNow(file: file, line: line)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SyscallAbstractionLayerContext.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nstruct SALContext {\n    let eventLoop: SelectableEventLoop\n    private let wakeups: LockedBox<Void>\n    private let unchecked: Unchecked\n\n    // KernelToUser and UserToKernel are *not* Sendable but we need an escape hatch so that\n    // they can be moved from the testing thread to the event-loop and back.\n    struct Unchecked: @unchecked Sendable {\n        let kernelToUserBox: LockedBox<KernelToUser>\n        let userToKernelBox: LockedBox<UserToKernel>\n    }\n\n    var selector: HookedSelector {\n        self.eventLoop._selector as! HookedSelector\n    }\n\n    fileprivate init(\n        eventLoop: SelectableEventLoop,\n        wakeups: LockedBox<Void>,\n        unchecked: Unchecked\n    ) {\n        self.eventLoop = eventLoop\n        self.wakeups = wakeups\n        self.unchecked = unchecked\n    }\n\n    func runSALOnEventLoop<Result: Sendable>(\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        body:\n            @escaping @Sendable (\n                _ eventLoop: SelectableEventLoop,\n                _ kernelToUser: LockedBox<KernelToUser>,\n                _ userToKernal: LockedBox<UserToKernel>\n            ) throws -> Result,\n        syscallAssertions: (SyscallAssertions) throws -> Void\n    ) throws -> Result {\n        let box = LockedBox<Swift.Result<Result, Error>>()\n        let hookedSelector = self.eventLoop._selector as! HookedSelector\n\n        // To prevent races between the test driver thread (this thread) and the EventLoop (another thread), we need\n        // to wait for the EventLoop to finish its tick and park itself. That makes sure both threads are synchronised\n        // so we know exactly what the EventLoop thread is currently up to (nothing at all, waiting for a wakeup).\n        try self.unchecked.userToKernelBox.assertParkedRightNow()\n\n        self.eventLoop.execute {\n            do {\n                let result = try body(self.eventLoop, self.unchecked.kernelToUserBox, self.unchecked.userToKernelBox)\n                try box.waitForEmptyAndSet(.success(result))\n            } catch {\n                box.value = .failure(error)\n            }\n        }\n        try hookedSelector.assertWakeup(file: file, line: line)\n        try syscallAssertions(SyscallAssertions(selector: hookedSelector))\n\n        // Here as well, we need to synchronise and wait for the EventLoop to finish running its tick.\n        try self.unchecked.userToKernelBox.assertParkedRightNow()\n        return try box.takeValue().get()\n    }\n\n    func runSALOnEventLoopAndWait<Result: Sendable>(\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        body:\n            @escaping @Sendable (\n                _ eventLoop: SelectableEventLoop,\n                _ kernelToUser: LockedBox<KernelToUser>,\n                _ userToKernal: LockedBox<UserToKernel>\n            ) throws -> EventLoopFuture<Result>,\n        syscallAssertions: (SyscallAssertions) throws -> Void\n    ) throws -> Result {\n        let result = try self.runSALOnEventLoop(body: body, syscallAssertions: syscallAssertions)\n        return try result.salWait(context: self)\n    }\n\n    func runSALOnEventLoop<Result: Sendable>(\n        file: StaticString = #filePath,\n        line: UInt = #line,\n        body:\n            @escaping @Sendable (\n                _ eventLoop: SelectableEventLoop,\n                _ kernelToUser: LockedBox<KernelToUser>,\n                _ userToKernal: LockedBox<UserToKernel>\n            ) throws -> Result\n    ) throws -> Result {\n        try self.runSALOnEventLoop(file: file, line: line, body: body) { _ in }\n    }\n}\n\n@available(*, unavailable)\nextension SALContext: Sendable {}\n\nfunc withSALContext<R>(body: (SALContext) throws -> R) throws -> R {\n    let kernelToUserBox = LockedBox<KernelToUser>(description: \"k2u\") { newValue in\n        if let newValue = newValue {\n            SAL.printIfDebug(\"K --> U: \\(newValue)\")\n        }\n    }\n\n    let userToKernelBox = LockedBox<UserToKernel>(description: \"u2k\") { newValue in\n        if let newValue = newValue {\n            SAL.printIfDebug(\"U --> K: \\(newValue)\")\n        }\n    }\n\n    let wakeups = LockedBox<Void>(description: \"wakeups\")\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1, metricsDelegate: nil) { thread in\n        try HookedSelector(\n            userToKernel: userToKernelBox,\n            kernelToUser: kernelToUserBox,\n            wakeups: wakeups,\n            thread: thread\n        )\n    }\n    defer {\n        try! group.syncShutdownGracefully()\n    }\n\n    let context = SALContext(\n        eventLoop: group.next() as! SelectableEventLoop,\n        wakeups: wakeups,\n        unchecked: SALContext.Unchecked(\n            kernelToUserBox: kernelToUserBox,\n            userToKernelBox: userToKernelBox\n        )\n    )\n\n    defer {\n        SAL.printIfDebug(\"=== TEAR DOWN ===\")\n\n        let dispatchGroup = DispatchGroup()\n        dispatchGroup.enter()\n        XCTAssertNoThrow(\n            group.shutdownGracefully(queue: DispatchQueue.global()) { error in\n                XCTAssertNil(error, \"unexpected error: \\(error!)\")\n                dispatchGroup.leave()\n            }\n        )\n        // We're in a slightly tricky situation here. We don't know if the EventLoop thread enters `whenReady` again\n        // or not. If it has, we have to wake it up, so let's just put a return value in the 'kernel to user' box, just\n        // in case :)\n        XCTAssertNoThrow(try kernelToUserBox.waitForEmptyAndSet(.returnSelectorEvent(nil)))\n        dispatchGroup.wait()\n    }\n\n    let result = try body(context)\n    return result\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SystemCallWrapperHelpers.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\n\n#if !RUNNING_INTEGRATION_TESTS\n@testable import NIOPosix\n#endif\n\npublic func measureRunTime(_ body: () throws -> Int) rethrows -> TimeInterval {\n    func measureOne(_ body: () throws -> Int) rethrows -> TimeInterval {\n        let start = DispatchTime.now().uptimeNanoseconds\n        _ = try body()\n        let end = DispatchTime.now().uptimeNanoseconds\n        return Double(end - start) / 1_000_000\n    }\n\n    _ = try measureOne(body)\n    var measurements = Array(repeating: 0.0, count: 10)\n    for i in 0..<10 {\n        measurements[i] = try measureOne(body)\n    }\n\n    //return measurements.reduce(0, +) / 10.0\n    return measurements.min()!\n}\n\npublic func measureRunTimeAndPrint(desc: String, body: () throws -> Int) rethrows {\n    print(\"measuring: \\(desc)\")\n    print(\"\\(try measureRunTime(body))s\")\n}\n\nenum TestError: Error {\n    case writeFailed\n    case wouldBlock\n}\n\nfunc runStandalone() {\n    func assertFun(\n        condition: @autoclosure () -> Bool,\n        string: @autoclosure () -> String,\n        file: StaticString,\n        line: UInt\n    ) {\n        if !condition() {\n            fatalError(string(), file: (file), line: line)\n        }\n    }\n    do {\n        try runSystemCallWrapperPerformanceTest(testAssertFunction: assertFun, debugModeAllowed: false)\n    } catch let e {\n        fatalError(\"Error thrown: \\(e)\")\n    }\n}\n\nfunc runSystemCallWrapperPerformanceTest(\n    testAssertFunction: (@autoclosure () -> Bool, @autoclosure () -> String, StaticString, UInt) -> Void,\n    debugModeAllowed: Bool\n) throws {\n    let fd = open(\"/dev/null\", O_WRONLY)\n    precondition(fd >= 0, \"couldn't open /dev/null (\\(errno))\")\n    defer {\n        close(fd)\n    }\n\n    let isDebugMode = _isDebugAssertConfiguration()\n    if !debugModeAllowed && isDebugMode {\n        fatalError(\"running in debug mode, release mode required\")\n    }\n\n    let iterations = isDebugMode ? 100_000 : 1_000_000\n    let pointer = UnsafePointer<UInt8>(bitPattern: 0xdeadbee)!\n\n    let directCallTime = try measureRunTime { () -> Int in\n        // imitate what the system call wrappers do to have a fair comparison\n        var preventCompilerOptimisation: Int = 0\n        for _ in 0..<iterations {\n            while true {\n                let r = write(fd, pointer, 0)\n                if r < 0 {\n                    let saveErrno = errno\n                    switch saveErrno {\n                    case EINTR:\n                        continue\n                    case EWOULDBLOCK:\n                        throw TestError.wouldBlock\n                    case EBADF, EFAULT:\n                        fatalError()\n                    default:\n                        throw TestError.writeFailed\n                    }\n                } else {\n                    preventCompilerOptimisation += r\n                    break\n                }\n            }\n        }\n        return preventCompilerOptimisation\n    }\n\n    let withSystemCallWrappersTime = try measureRunTime { () -> Int in\n        var preventCompilerOptimisation: Int = 0\n        for _ in 0..<iterations {\n            switch try Posix.write(descriptor: fd, pointer: pointer, size: 0) {\n            case .processed(let v):\n                preventCompilerOptimisation += v\n            case .wouldBlock:\n                throw TestError.wouldBlock\n            }\n        }\n        return preventCompilerOptimisation\n    }\n\n    let allowedOverheadPercent: Int = isDebugMode ? 2000 : 20\n    if allowedOverheadPercent > 100 {\n        precondition(isDebugMode)\n        print(\n            \"WARNING: Syscall wrapper test: Over 100% overhead allowed. Running in debug assert configuration which allows \\(allowedOverheadPercent)% overhead :(. Consider running in Release mode.\"\n        )\n    }\n    testAssertFunction(\n        directCallTime * (1.0 + Double(allowedOverheadPercent) / 100) > withSystemCallWrappersTime,\n        \"Posix wrapper adds more than \\(allowedOverheadPercent)% overhead (with wrapper: \\(withSystemCallWrappersTime), without: \\(directCallTime)\",\n        #filePath,\n        #line\n    )\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/SystemTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport CNIOLinux\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass SystemTest: XCTestCase {\n    func testSystemCallWrapperPerformance() throws {\n        try runSystemCallWrapperPerformanceTest(\n            testAssertFunction: XCTAssert,\n            debugModeAllowed: true\n        )\n    }\n\n    func testErrorsWorkCorrectly() throws {\n        try withPipe { readFD, writeFD in\n            var randomBytes: UInt8 = 42\n            do {\n                _ = try withUnsafePointer(to: &randomBytes) { ptr in\n                    try readFD.withUnsafeFileDescriptor { readFD in\n                        try NIOBSDSocket.setsockopt(\n                            socket: readFD,\n                            level: NIOBSDSocket.OptionLevel(rawValue: -1),\n                            option_name: NIOBSDSocket.Option(rawValue: -1),\n                            option_value: ptr,\n                            option_len: 0\n                        )\n                    }\n                }\n                XCTFail(\"success even though the call was invalid\")\n            } catch let e as IOError {\n                // ENOTSOCK almost everything and ENOPROTOOPT in Qemu\n                XCTAssert([ENOTSOCK, ENOPROTOOPT].contains(e.errnoCode))\n                XCTAssert(e.description.contains(\"setsockopt\"))\n                XCTAssert(e.description.contains(\"\\(ENOTSOCK)\") || e.description.contains(\"\\(ENOPROTOOPT)\"))\n            } catch let e {\n                XCTFail(\"wrong error thrown: \\(e)\")\n            }\n            return [readFD, writeFD]\n        }\n    }\n\n    #if canImport(Darwin)\n    // Example twin data options captured on macOS\n    private static let cmsghdrExample: [UInt8] = [\n        0x10, 0x00, 0x00, 0x00,  // Length 16 including header\n        0x00, 0x00, 0x00, 0x00,  // IPPROTO_IP\n        0x07, 0x00, 0x00, 0x00,  // IP_RECVDSTADDR\n        0x7F, 0x00, 0x00, 0x01,  // 127.0.0.1\n        0x0D, 0x00, 0x00, 0x00,  // Length 13 including header\n        0x00, 0x00, 0x00, 0x00,  // IPPROTO_IP\n        0x1B, 0x00, 0x00, 0x00,  // IP_RECVTOS\n        0x01, 0x00, 0x00, 0x00,\n    ]  // ECT-1 (1 byte)\n    private static let cmsghdr_secondStartPosition = 16\n    private static let cmsghdr_firstDataStart = 12\n    private static let cmsghdr_firstDataCount = 4\n    private static let cmsghdr_secondDataCount = 1\n    private static let cmsghdr_firstType = IP_RECVDSTADDR\n    private static let cmsghdr_secondType = IP_RECVTOS\n    #elseif os(Android) && arch(arm)\n    private static let cmsghdrExample: [UInt8] = [\n        0x10, 0x00, 0x00, 0x00,  // Length 16 including header\n        0x00, 0x00, 0x00, 0x00,  // IPPROTO_IP\n        0x08, 0x00, 0x00, 0x00,  // IP_PKTINFO\n        0x7F, 0x00, 0x00, 0x01,  // 127.0.0.1\n        0x0D, 0x00, 0x00, 0x00,  // Length 13 including header\n        0x00, 0x00, 0x00, 0x00,  // IPPROTO_IP\n        0x01, 0x00, 0x00, 0x00,  // IP_TOS\n        0x01, 0x00, 0x00, 0x00,\n    ]  // ECT-1 (1 byte)\n    private static let cmsghdr_secondStartPosition = 16\n    private static let cmsghdr_firstDataStart = 12\n    private static let cmsghdr_firstDataCount = 4\n    private static let cmsghdr_secondDataCount = 1\n    private static let cmsghdr_firstType = IP_PKTINFO\n    private static let cmsghdr_secondType = IP_TOS\n    #elseif os(Linux) || os(Android)\n    // Example twin data options captured on Linux\n    private static let cmsghdrExample: [UInt8] = [\n        0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Length 28 including header.\n        0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,  // IPPROTO_IP, IP_PKTINFO\n        0x01, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01,  // interface number, 127.0.0.1 (local)\n        0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,  // 127.0.0.1 (destination), 4 bytes to align length\n        0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Length 17\n        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,  // IPPROTO_IP, IP_TOS\n        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ECT-1 (1 byte)\n    ]\n    private static let cmsghdr_secondStartPosition = 32\n    private static let cmsghdr_firstDataStart = 16\n    private static let cmsghdr_firstDataCount = 12\n    private static let cmsghdr_secondDataCount = 1\n    private static let cmsghdr_firstType = IP_PKTINFO\n    private static let cmsghdr_secondType = IP_TOS\n    #else\n    #error(\"No cmsg support on this platform.\")\n    #endif\n\n    func testCmsgFirstHeader() {\n        var exampleCmsgHdr = SystemTest.cmsghdrExample\n        exampleCmsgHdr.withUnsafeMutableBytes { pCmsgHdr in\n            var msgHdr = msghdr()\n            msgHdr.control_ptr = pCmsgHdr\n\n            withUnsafePointer(to: msgHdr) { pMsgHdr in\n                let result = NIOBSDSocketControlMessage.firstHeader(inside: pMsgHdr)\n                XCTAssertEqual(pCmsgHdr.baseAddress, result)\n            }\n        }\n    }\n\n    func testCMsgNextHeader() {\n        var exampleCmsgHdr = SystemTest.cmsghdrExample\n        exampleCmsgHdr.withUnsafeMutableBytes { pCmsgHdr in\n            var msgHdr = msghdr()\n            msgHdr.control_ptr = pCmsgHdr\n\n            withUnsafeMutablePointer(to: &msgHdr) { pMsgHdr in\n                let first = NIOBSDSocketControlMessage.firstHeader(inside: pMsgHdr)\n                let second = NIOBSDSocketControlMessage.nextHeader(inside: pMsgHdr, after: first!)\n                let expectedSecondStart = pCmsgHdr.baseAddress! + SystemTest.cmsghdr_secondStartPosition\n                XCTAssertEqual(expectedSecondStart, second!)\n                let third = NIOBSDSocketControlMessage.nextHeader(inside: pMsgHdr, after: second!)\n                XCTAssertEqual(third, nil)\n            }\n        }\n    }\n\n    func testCMsgData() {\n        var exampleCmsgHrd = SystemTest.cmsghdrExample\n        exampleCmsgHrd.withUnsafeMutableBytes { pCmsgHdr in\n            var msgHdr = msghdr()\n            msgHdr.control_ptr = pCmsgHdr\n\n            withUnsafePointer(to: msgHdr) { pMsgHdr in\n                let first = NIOBSDSocketControlMessage.firstHeader(inside: pMsgHdr)\n                let firstData = NIOBSDSocketControlMessage.data(for: first!)\n                let expecedFirstData = UnsafeRawBufferPointer(\n                    rebasing: pCmsgHdr[\n                        SystemTest\n                            .cmsghdr_firstDataStart..<(SystemTest.cmsghdr_firstDataStart\n                            + SystemTest.cmsghdr_firstDataCount)\n                    ]\n                )\n                XCTAssertEqual(expecedFirstData.baseAddress, firstData?.baseAddress)\n                XCTAssertEqual(expecedFirstData.count, firstData?.count)\n            }\n        }\n    }\n\n    func testCMsgCollection() {\n        var exampleCmsgHrd = SystemTest.cmsghdrExample\n        exampleCmsgHrd.withUnsafeMutableBytes { pCmsgHdr in\n            var msgHdr = msghdr()\n            msgHdr.control_ptr = pCmsgHdr\n            let collection = UnsafeControlMessageCollection(messageHeader: msgHdr)\n            var msgNum = 0\n            for cmsg in collection {\n                if msgNum == 0 {\n                    XCTAssertEqual(cmsg.level, .init(IPPROTO_IP))\n                    XCTAssertEqual(cmsg.type, .init(SystemTest.cmsghdr_firstType))\n                    XCTAssertEqual(cmsg.data?.count, SystemTest.cmsghdr_firstDataCount)\n                } else if msgNum == 1 {\n                    XCTAssertEqual(cmsg.level, .init(IPPROTO_IP))\n                    XCTAssertEqual(cmsg.type, .init(SystemTest.cmsghdr_secondType))\n                    XCTAssertEqual(cmsg.data?.count, SystemTest.cmsghdr_secondDataCount)\n                }\n                msgNum += 1\n            }\n            XCTAssertEqual(msgNum, 2)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/TestUtils.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\n\nimport NIOConcurrencyHelpers\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOPosix\n\nextension System {\n    static var supportsIPv6: Bool {\n        do {\n            let ipv6Loopback = try SocketAddress.makeAddressResolvingHost(\"::1\", port: 0)\n            return try System.enumerateDevices().filter { $0.address == ipv6Loopback }.first != nil\n        } catch {\n            return false\n        }\n    }\n\n    static var supportsVsockLoopback: Bool {\n        #if os(Linux) || os(Android)\n        guard let modules = try? String(contentsOf: URL(fileURLWithPath: \"/proc/modules\"), encoding: .utf8) else {\n            return false\n        }\n        return modules.split(separator: \"\\n\").compactMap({ $0.split(separator: \" \").first }).contains(\"vsock_loopback\")\n        #else\n        return false\n        #endif\n    }\n}\n\nfunc withPipe(_ body: (NIOCore.NIOFileHandle, NIOCore.NIOFileHandle) throws -> [NIOCore.NIOFileHandle]) throws {\n    var fds: [Int32] = [-1, -1]\n    fds.withUnsafeMutableBufferPointer { ptr in\n        XCTAssertEqual(0, pipe(ptr.baseAddress!))\n    }\n    let readFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[0])\n    let writeFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[1])\n    var toClose: [NIOFileHandle] = [readFH, writeFH]\n    var error: Error? = nil\n    do {\n        toClose = try body(readFH, writeFH)\n    } catch let err {\n        error = err\n    }\n    for fileHandle in toClose {\n        XCTAssertNoThrow(try fileHandle.close())\n    }\n    if let error = error {\n        throw error\n    }\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc withPipe(\n    _ body: (NIOCore.NIOFileHandle, NIOCore.NIOFileHandle) async throws -> [NIOCore.NIOFileHandle]\n) async throws {\n    var fds: [Int32] = [-1, -1]\n    fds.withUnsafeMutableBufferPointer { ptr in\n        XCTAssertEqual(0, pipe(ptr.baseAddress!))\n    }\n    let readFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[0])\n    let writeFH = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fds[1])\n    var toClose: [NIOFileHandle] = [readFH, writeFH]\n    var error: Error? = nil\n    do {\n        toClose = try await body(readFH, writeFH)\n    } catch let err {\n        error = err\n    }\n    for fileHandle in toClose {\n        try fileHandle.close()\n    }\n    if let error = error {\n        throw error\n    }\n}\n\n// swift-format-ignore: AmbiguousTrailingClosureOverload\nfunc withTemporaryDirectory<T>(_ body: (String) throws -> T) rethrows -> T {\n    let dir = createTemporaryDirectory()\n    defer {\n        try? FileManager.default.removeItem(atPath: dir)\n    }\n    return try body(dir)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc withTemporaryDirectory<T>(_ body: (String) async throws -> T) async rethrows -> T {\n    let dir = createTemporaryDirectory()\n    defer {\n        try? FileManager.default.removeItem(atPath: dir)\n    }\n    return try await body(dir)\n}\n\n/// This function creates a filename that can be used for a temporary UNIX domain socket path.\n///\n/// If the temporary directory is too long to store a UNIX domain socket path, it will `chdir` into the temporary\n/// directory and return a short-enough path. The iOS simulator is known to have too long paths.\nfunc withTemporaryUnixDomainSocketPathName<T>(\n    directory: String = temporaryDirectory,\n    _ body: (String) throws -> T\n) throws -> T {\n    // this is racy but we're trying to create the shortest possible path so we can't add a directory...\n    let (fd, path) = openTemporaryFile()\n    try! Posix.close(descriptor: fd)\n    try! FileManager.default.removeItem(atPath: path)\n\n    let saveCurrentDirectory = FileManager.default.currentDirectoryPath\n    let restoreSavedCWD: Bool\n    let shortEnoughPath: String\n    do {\n        _ = try SocketAddress(unixDomainSocketPath: path)\n        // this seems to be short enough for a UDS\n        shortEnoughPath = path\n        restoreSavedCWD = false\n    } catch SocketAddressError.unixDomainSocketPathTooLong {\n        _ = FileManager.default.changeCurrentDirectoryPath(\n            URL(fileURLWithPath: path).deletingLastPathComponent().absoluteString\n        )\n        shortEnoughPath = URL(fileURLWithPath: path).lastPathComponent\n        restoreSavedCWD = true\n        print(\n            \"WARNING: Path '\\(path)' could not be used as UNIX domain socket path, using chdir & '\\(shortEnoughPath)'\"\n        )\n    }\n    defer {\n        if FileManager.default.fileExists(atPath: path) {\n            try? FileManager.default.removeItem(atPath: path)\n        }\n        if restoreSavedCWD {\n            _ = FileManager.default.changeCurrentDirectoryPath(saveCurrentDirectory)\n        }\n    }\n    return try body(shortEnoughPath)\n}\n\nfunc withTemporaryFile<T>(\n    content: String? = nil,\n    _ body: (NIOCore.NIOFileHandle, String) throws -> T\n) rethrows -> T {\n    let (fd, path) = openTemporaryFile()\n    let fileHandle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fd)\n    defer {\n        XCTAssertNoThrow(try fileHandle.close())\n        XCTAssertEqual(0, unlink(path))\n    }\n    if let content = content {\n        try Array(content.utf8).withUnsafeBufferPointer { ptr in\n            var toWrite = ptr.count\n            var start = ptr.baseAddress!\n            while toWrite > 0 {\n                let res = try Posix.write(descriptor: fd, pointer: start, size: toWrite)\n                switch res {\n                case .processed(let written):\n                    toWrite -= written\n                    start = start + written\n                case .wouldBlock:\n                    XCTFail(\"unexpectedly got .wouldBlock from a file\")\n                    continue\n                }\n            }\n            XCTAssertEqual(0, lseek(fd, 0, SEEK_SET))\n        }\n    }\n    return try body(fileHandle, path)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nfunc withTemporaryFile<T>(\n    content: String? = nil,\n    _ body: @escaping (NIOCore.NIOFileHandle, String) async throws -> T\n) async rethrows -> T {\n    let (fd, path) = openTemporaryFile()\n    let fileHandle = NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor: fd)\n    defer {\n        XCTAssertNoThrow(try fileHandle.close())\n        XCTAssertEqual(0, unlink(path))\n    }\n    if let content = content {\n        try Array(content.utf8).withUnsafeBufferPointer { ptr in\n            var toWrite = ptr.count\n            var start = ptr.baseAddress!\n            while toWrite > 0 {\n                let res = try Posix.write(descriptor: fd, pointer: start, size: toWrite)\n                switch res {\n                case .processed(let written):\n                    toWrite -= written\n                    start = start + written\n                case .wouldBlock:\n                    XCTFail(\"unexpectedly got .wouldBlock from a file\")\n                    continue\n                }\n            }\n            XCTAssertEqual(0, lseek(fd, 0, SEEK_SET))\n        }\n    }\n    return try await body(fileHandle, path)\n}\nvar temporaryDirectory: String {\n    get {\n        #if targetEnvironment(simulator)\n        // Simulator temp directories are so long (and contain the user name) that they're not usable\n        // for UNIX Domain Socket paths (which are limited to 103 bytes).\n        return \"/tmp\"\n        #else\n        #if os(Linux)\n        return \"/tmp\"\n        #else\n        if #available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) {\n            return FileManager.default.temporaryDirectory.path\n        } else {\n            return \"/tmp\"\n        }\n        #endif  // os\n        #endif  // targetEnvironment\n    }\n}\n\nfunc createTemporaryDirectory() -> String {\n    let template = \"\\(temporaryDirectory)/.NIOTests-temp-dir_XXXXXX\"\n\n    var templateBytes = template.utf8 + [0]\n    let templateBytesCount = templateBytes.count\n    templateBytes.withUnsafeMutableBufferPointer { ptr in\n        ptr.baseAddress!.withMemoryRebound(to: Int8.self, capacity: templateBytesCount) {\n            (ptr: UnsafeMutablePointer<Int8>) in\n            let ret = mkdtemp(ptr)\n            XCTAssertNotNil(ret)\n        }\n    }\n    templateBytes.removeLast()\n    return String(decoding: templateBytes, as: Unicode.UTF8.self)\n}\n\nfunc openTemporaryFile() -> (CInt, String) {\n    let template = \"\\(temporaryDirectory)/nio_XXXXXX\"\n    var templateBytes = template.utf8 + [0]\n    let templateBytesCount = templateBytes.count\n    let fd = templateBytes.withUnsafeMutableBufferPointer { ptr in\n        ptr.baseAddress!.withMemoryRebound(to: Int8.self, capacity: templateBytesCount) {\n            (ptr: UnsafeMutablePointer<Int8>) in\n            mkstemp(ptr)\n        }\n    }\n    templateBytes.removeLast()\n    return (fd, String(decoding: templateBytes, as: Unicode.UTF8.self))\n}\n\nextension Channel {\n    func syncCloseAcceptingAlreadyClosed() throws {\n        do {\n            try self.close().wait()\n        } catch ChannelError.alreadyClosed {\n            // we're happy with this one\n        } catch let e {\n            throw e\n        }\n    }\n}\n\nfinal class ByteCountingHandler: ChannelInboundHandler, RemovableChannelHandler {\n    typealias InboundIn = ByteBuffer\n\n    private let numBytes: Int\n    private let promise: EventLoopPromise<ByteBuffer>\n    private var buffer: ByteBuffer!\n\n    init(numBytes: Int, promise: EventLoopPromise<ByteBuffer>) {\n        self.numBytes = numBytes\n        self.promise = promise\n    }\n\n    func handlerAdded(context: ChannelHandlerContext) {\n        buffer = context.channel.allocator.buffer(capacity: numBytes)\n        if self.numBytes == 0 {\n            self.promise.succeed(buffer)\n        }\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        var currentBuffer = Self.unwrapInboundIn(data)\n        buffer.writeBuffer(&currentBuffer)\n\n        if buffer.readableBytes == numBytes {\n            promise.succeed(buffer)\n        }\n    }\n\n    func assertReceived(buffer: ByteBuffer) throws {\n        let received = try promise.futureResult.wait()\n        XCTAssertEqual(buffer, received)\n    }\n}\n\nfinal class NonAcceptingServerSocket: ServerSocket {\n    private var errors: [Int32]\n\n    init(errors: [Int32]) throws {\n        // Reverse so it's cheaper to remove errors.\n        self.errors = errors.reversed()\n        try super.init(protocolFamily: .inet, setNonBlocking: true)\n    }\n\n    override func accept(setNonBlocking: Bool) throws -> Socket? {\n        if let err = self.errors.last {\n            _ = self.errors.removeLast()\n            throw IOError(errnoCode: err, reason: \"accept\")\n        }\n        return nil\n    }\n}\n\nfunc assertSetGetOptionOnOpenAndClosed<Option: ChannelOption>(\n    channel: Channel,\n    option: Option,\n    value: Option.Value\n) throws {\n    _ = try channel.setOption(option, value: value).wait()\n    _ = try channel.getOption(option).wait()\n    try channel.close().wait()\n    try channel.closeFuture.wait()\n\n    do {\n        _ = try channel.setOption(option, value: value).wait()\n        // We're okay with no error\n    } catch let err as ChannelError where err == .ioOnClosedChannel {\n        // as well as already closed channels.\n    }\n\n    do {\n        _ = try channel.getOption(option).wait()\n        // We're okay with no error\n    } catch let err as ChannelError where err == .ioOnClosedChannel {\n        // as well as already closed channels.\n    }\n}\n\nfunc assertNoThrowWithValue<T>(\n    _ body: @autoclosure () throws -> T,\n    defaultValue: T? = nil,\n    message: String? = nil,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws -> T {\n    do {\n        return try body()\n    } catch {\n        XCTFail(\"\\(message.map { $0 + \": \" } ?? \"\")unexpected error \\(error) thrown\", file: (file), line: line)\n        if let defaultValue = defaultValue {\n            return defaultValue\n        } else {\n            throw error\n        }\n    }\n}\n\nfunc resolverDebugInformation(\n    eventLoop: EventLoop,\n    host: String,\n    previouslyReceivedResult: SocketAddress\n) throws -> String {\n    func printSocketAddress(_ socketAddress: SocketAddress) -> String {\n        switch socketAddress {\n        case .unixDomainSocket(_):\n            return \"uds\"\n        case .v4(let sa):\n            return __testOnly_addressDescription(sa.address)\n        case .v6(let sa):\n            return __testOnly_addressDescription(sa.address)\n        }\n    }\n    let res = GetaddrinfoResolver(loop: eventLoop, aiSocktype: .stream, aiProtocol: .tcp)\n    let ipv6Results = try assertNoThrowWithValue(res.initiateAAAAQuery(host: host, port: 0).wait()).map(\n        printSocketAddress\n    )\n    let ipv4Results = try assertNoThrowWithValue(res.initiateAQuery(host: host, port: 0).wait()).map(printSocketAddress)\n\n    return \"\"\"\n        when trying to resolve '\\(host)' we've got the following results:\n        - previous try: \\(printSocketAddress(previouslyReceivedResult))\n        - all results:\n        IPv4: \\(ipv4Results)\n        IPv6: \\(ipv6Results)\n        \"\"\"\n}\n\nfunc assert(\n    _ condition: @autoclosure () -> Bool,\n    within time: TimeAmount,\n    testInterval: TimeAmount? = nil,\n    _ message: String = \"condition not satisfied in time\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let testInterval = testInterval ?? TimeAmount.nanoseconds(time.nanoseconds / 5)\n    let endTime = NIODeadline.now() + time\n\n    repeat {\n        if condition() { return }\n        usleep(UInt32(testInterval.nanoseconds / 1000))\n    } while NIODeadline.now() < endTime\n\n    if !condition() {\n        XCTFail(message, file: (file), line: line)\n    }\n}\n\nfunc getBoolSocketOption(\n    channel: Channel,\n    level: NIOBSDSocket.OptionLevel,\n    name: NIOBSDSocket.Option,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws -> Bool {\n    try assertNoThrowWithValue(\n        channel.getOption(ChannelOptions.Types.SocketOption(level: level, name: name)),\n        file: (file),\n        line: line\n    ).wait() != 0\n}\n\nfunc assertSuccess<Value>(_ result: Result<Value, Error>, file: StaticString = #filePath, line: UInt = #line) {\n    guard case .success = result else { return XCTFail(\"Expected result to be successful\", file: (file), line: line) }\n}\n\nfunc assertFailure<Value>(_ result: Result<Value, Error>, file: StaticString = #filePath, line: UInt = #line) {\n    guard case .failure = result else { return XCTFail(\"Expected result to be a failure\", file: (file), line: line) }\n}\n\n/// Fulfills the promise when the respective event is first received.\n///\n/// - Note: Once this is used more widely and shows value, we might want to put it into `NIOTestUtils`.\nfinal class FulfillOnFirstEventHandler: ChannelDuplexHandler, Sendable {\n    typealias InboundIn = Any\n    typealias OutboundIn = Any\n\n    struct ExpectedEventMissing: Error {}\n\n    private let channelRegisteredPromise: EventLoopPromise<Void>?\n    private let channelUnregisteredPromise: EventLoopPromise<Void>?\n    private let channelActivePromise: EventLoopPromise<Void>?\n    private let channelInactivePromise: EventLoopPromise<Void>?\n    private let channelReadPromise: EventLoopPromise<Void>?\n    private let channelReadCompletePromise: EventLoopPromise<Void>?\n    private let channelWritabilityChangedPromise: EventLoopPromise<Void>?\n    private let userInboundEventTriggeredPromise: EventLoopPromise<Void>?\n    private let errorCaughtPromise: EventLoopPromise<Void>?\n    private let registerPromise: EventLoopPromise<Void>?\n    private let bindPromise: EventLoopPromise<Void>?\n    private let connectPromise: EventLoopPromise<Void>?\n    private let writePromise: EventLoopPromise<Void>?\n    private let flushPromise: EventLoopPromise<Void>?\n    private let readPromise: EventLoopPromise<Void>?\n    private let closePromise: EventLoopPromise<Void>?\n    private let triggerUserOutboundEventPromise: EventLoopPromise<Void>?\n\n    init(\n        channelRegisteredPromise: EventLoopPromise<Void>? = nil,\n        channelUnregisteredPromise: EventLoopPromise<Void>? = nil,\n        channelActivePromise: EventLoopPromise<Void>? = nil,\n        channelInactivePromise: EventLoopPromise<Void>? = nil,\n        channelReadPromise: EventLoopPromise<Void>? = nil,\n        channelReadCompletePromise: EventLoopPromise<Void>? = nil,\n        channelWritabilityChangedPromise: EventLoopPromise<Void>? = nil,\n        userInboundEventTriggeredPromise: EventLoopPromise<Void>? = nil,\n        errorCaughtPromise: EventLoopPromise<Void>? = nil,\n        registerPromise: EventLoopPromise<Void>? = nil,\n        bindPromise: EventLoopPromise<Void>? = nil,\n        connectPromise: EventLoopPromise<Void>? = nil,\n        writePromise: EventLoopPromise<Void>? = nil,\n        flushPromise: EventLoopPromise<Void>? = nil,\n        readPromise: EventLoopPromise<Void>? = nil,\n        closePromise: EventLoopPromise<Void>? = nil,\n        triggerUserOutboundEventPromise: EventLoopPromise<Void>? = nil\n    ) {\n        self.channelRegisteredPromise = channelRegisteredPromise\n        self.channelUnregisteredPromise = channelUnregisteredPromise\n        self.channelActivePromise = channelActivePromise\n        self.channelInactivePromise = channelInactivePromise\n        self.channelReadPromise = channelReadPromise\n        self.channelReadCompletePromise = channelReadCompletePromise\n        self.channelWritabilityChangedPromise = channelWritabilityChangedPromise\n        self.userInboundEventTriggeredPromise = userInboundEventTriggeredPromise\n        self.errorCaughtPromise = errorCaughtPromise\n        self.registerPromise = registerPromise\n        self.bindPromise = bindPromise\n        self.connectPromise = connectPromise\n        self.writePromise = writePromise\n        self.flushPromise = flushPromise\n        self.readPromise = readPromise\n        self.closePromise = closePromise\n        self.triggerUserOutboundEventPromise = triggerUserOutboundEventPromise\n    }\n\n    func handlerRemoved(context: ChannelHandlerContext) {\n        self.channelRegisteredPromise?.fail(ExpectedEventMissing())\n        self.channelUnregisteredPromise?.fail(ExpectedEventMissing())\n        self.channelActivePromise?.fail(ExpectedEventMissing())\n        self.channelInactivePromise?.fail(ExpectedEventMissing())\n        self.channelReadPromise?.fail(ExpectedEventMissing())\n        self.channelReadCompletePromise?.fail(ExpectedEventMissing())\n        self.channelWritabilityChangedPromise?.fail(ExpectedEventMissing())\n        self.userInboundEventTriggeredPromise?.fail(ExpectedEventMissing())\n        self.errorCaughtPromise?.fail(ExpectedEventMissing())\n        self.registerPromise?.fail(ExpectedEventMissing())\n        self.bindPromise?.fail(ExpectedEventMissing())\n        self.connectPromise?.fail(ExpectedEventMissing())\n        self.writePromise?.fail(ExpectedEventMissing())\n        self.flushPromise?.fail(ExpectedEventMissing())\n        self.readPromise?.fail(ExpectedEventMissing())\n        self.closePromise?.fail(ExpectedEventMissing())\n        self.triggerUserOutboundEventPromise?.fail(ExpectedEventMissing())\n    }\n\n    func channelRegistered(context: ChannelHandlerContext) {\n        self.channelRegisteredPromise?.succeed(())\n        context.fireChannelRegistered()\n    }\n\n    func channelUnregistered(context: ChannelHandlerContext) {\n        self.channelUnregisteredPromise?.succeed(())\n        context.fireChannelUnregistered()\n    }\n\n    func channelActive(context: ChannelHandlerContext) {\n        self.channelActivePromise?.succeed(())\n        context.fireChannelActive()\n    }\n\n    func channelInactive(context: ChannelHandlerContext) {\n        self.channelInactivePromise?.succeed(())\n        context.fireChannelInactive()\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        self.channelReadPromise?.succeed(())\n        context.fireChannelRead(data)\n    }\n\n    func channelReadComplete(context: ChannelHandlerContext) {\n        self.channelReadCompletePromise?.succeed(())\n        context.fireChannelReadComplete()\n    }\n\n    func channelWritabilityChanged(context: ChannelHandlerContext) {\n        self.channelWritabilityChangedPromise?.succeed(())\n        context.fireChannelWritabilityChanged()\n    }\n\n    func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n        self.userInboundEventTriggeredPromise?.succeed(())\n        context.fireUserInboundEventTriggered(event)\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.errorCaughtPromise?.succeed(())\n        context.fireErrorCaught(error)\n    }\n\n    func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) {\n        self.registerPromise?.succeed(())\n        context.register(promise: promise)\n    }\n\n    func bind(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.bindPromise?.succeed(())\n        context.bind(to: to, promise: promise)\n    }\n\n    func connect(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) {\n        self.connectPromise?.succeed(())\n        context.connect(to: to, promise: promise)\n    }\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        self.writePromise?.succeed(())\n        context.write(data, promise: promise)\n    }\n\n    func flush(context: ChannelHandlerContext) {\n        self.flushPromise?.succeed(())\n        context.flush()\n    }\n\n    func read(context: ChannelHandlerContext) {\n        self.readPromise?.succeed(())\n        context.read()\n    }\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.closePromise?.succeed(())\n        context.close(mode: mode, promise: promise)\n    }\n\n    func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {\n        self.triggerUserOutboundEventPromise?.succeed(())\n        context.triggerUserOutboundEvent(event, promise: promise)\n    }\n}\n\nfunc forEachActiveChannelType<T>(\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: @escaping (Channel) throws -> T\n) throws -> [T] {\n    let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        XCTAssertNoThrow(try group.syncShutdownGracefully())\n    }\n    let channelEL = group.next()\n\n    let lock = NIOLock()\n    var ret: [T] = []\n    _ = try forEachCrossConnectedStreamChannelPair(file: (file), line: line) {\n        (chan1: Channel, chan2: Channel) throws -> Void in\n        var innerRet: [T] = [try body(chan1)]\n        if let parent = chan1.parent {\n            innerRet.append(try body(parent))\n        }\n        lock.withLock {\n            ret.append(contentsOf: innerRet)\n        }\n    }\n\n    // UDP\n    let udpChannel = DatagramBootstrap(group: channelEL)\n        .channelInitializer { channel in\n            XCTAssert(channel.eventLoop.inEventLoop)\n            return channelEL.makeSucceededFuture(())\n        }\n        .bind(host: \"127.0.0.1\", port: 0)\n    defer {\n        XCTAssertNoThrow(try udpChannel.wait().syncCloseAcceptingAlreadyClosed())\n    }\n\n    return try lock.withLock {\n        ret.append(try body(udpChannel.wait()))\n        return ret\n    }\n}\n\nfunc withTCPServerChannel<R>(\n    bindTarget: SocketAddress? = nil,\n    group: EventLoopGroup,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel) throws -> R\n) throws -> R {\n    let server = try ServerBootstrap(group: group)\n        .serverChannelOption(.socketOption(.so_reuseaddr), value: 1)\n        .bind(to: bindTarget ?? .init(ipAddress: \"127.0.0.1\", port: 0))\n        .wait()\n    do {\n        let result = try body(server)\n        try server.close().wait()\n        return result\n    } catch {\n        try? server.close().wait()\n        throw error\n    }\n}\n\nfunc withCrossConnectedSockAddrChannels<R>(\n    bindTarget: SocketAddress,\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    let serverGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        XCTAssertNoThrow(try serverGroup.syncShutdownGracefully())\n    }\n    let clientGroup: MultiThreadedEventLoopGroup\n    if forceSeparateEventLoops {\n        clientGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    } else {\n        clientGroup = serverGroup\n    }\n    defer {\n        // this may fail if clientGroup === serverGroup\n        try? clientGroup.syncShutdownGracefully()\n    }\n    let serverChannelEL = serverGroup.next()\n    let clientChannelEL = clientGroup.next()\n\n    let tcpAcceptedChannel = serverChannelEL.makePromise(of: Channel.self)\n    let tcpServerChannel = try assertNoThrowWithValue(\n        ServerBootstrap(group: serverChannelEL)\n            .childChannelInitializer { channel in\n                let accepted = channel.eventLoop.makePromise(of: Void.self)\n                accepted.futureResult.map {\n                    channel\n                }.cascade(to: tcpAcceptedChannel)\n                return channel.pipeline.addHandler(FulfillOnFirstEventHandler(channelActivePromise: accepted))\n            }\n            .bind(to: bindTarget)\n            .wait(),\n        file: (file),\n        line: line\n    )\n    defer {\n        XCTAssertNoThrow(try tcpServerChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    let tcpClientChannel = try assertNoThrowWithValue(\n        ClientBootstrap(group: clientChannelEL)\n            .channelInitializer { channel in\n                XCTAssert(channel.eventLoop.inEventLoop)\n                return channel.eventLoop.makeSucceededFuture(())\n            }\n            .connect(to: tcpServerChannel.localAddress!)\n            .wait()\n    )\n    defer {\n        XCTAssertNoThrow(try tcpClientChannel.syncCloseAcceptingAlreadyClosed())\n    }\n\n    return try body(try tcpAcceptedChannel.futureResult.wait(), tcpClientChannel)\n}\n\nfunc withCrossConnectedTCPChannels<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    try withCrossConnectedSockAddrChannels(\n        bindTarget: .init(ipAddress: \"127.0.0.1\", port: 0),\n        forceSeparateEventLoops: forceSeparateEventLoops,\n        body\n    )\n}\n\nfunc withCrossConnectedUnixDomainSocketChannels<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    try withTemporaryDirectory { tempDir in\n        let bindTarget = try SocketAddress(unixDomainSocketPath: tempDir + \"/s\")\n        return try withCrossConnectedSockAddrChannels(\n            bindTarget: bindTarget,\n            forceSeparateEventLoops: forceSeparateEventLoops,\n            body\n        )\n    }\n}\n\nfunc withCrossConnectedPipeChannels<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> R {\n    let channel1Group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    defer {\n        XCTAssertNoThrow(try channel1Group.syncShutdownGracefully(), file: (file), line: line)\n    }\n    let channel2Group: MultiThreadedEventLoopGroup\n    if forceSeparateEventLoops {\n        channel2Group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    } else {\n        channel2Group = channel1Group\n    }\n    defer {\n        // may fail if pipe1Group == pipe2Group\n        try? channel2Group.syncShutdownGracefully()\n    }\n\n    var result: R? = nil\n\n    XCTAssertNoThrow(\n        try withPipe { pipe1Read, pipe1Write -> [NIOFileHandle] in\n            try withPipe { pipe2Read, pipe2Write -> [NIOFileHandle] in\n                try pipe1Read.withUnsafeFileDescriptor { pipe1Read in\n                    try pipe1Write.withUnsafeFileDescriptor { pipe1Write in\n                        try pipe2Read.withUnsafeFileDescriptor { pipe2Read in\n                            try pipe2Write.withUnsafeFileDescriptor { pipe2Write in\n                                let channel1 = try NIOPipeBootstrap(group: channel1Group)\n                                    .takingOwnershipOfDescriptors(input: pipe1Read, output: pipe2Write)\n                                    .wait()\n                                defer {\n                                    XCTAssertNoThrow(try channel1.syncCloseAcceptingAlreadyClosed())\n                                }\n                                let channel2 = try NIOPipeBootstrap(group: channel2Group)\n                                    .takingOwnershipOfDescriptors(input: pipe2Read, output: pipe1Write)\n                                    .wait()\n                                defer {\n                                    XCTAssertNoThrow(try channel2.syncCloseAcceptingAlreadyClosed())\n                                }\n                                result = try body(channel1, channel2)\n                            }\n                        }\n                    }\n                }\n                XCTAssertNoThrow(try pipe1Read.takeDescriptorOwnership(), file: (file), line: line)\n                XCTAssertNoThrow(try pipe1Write.takeDescriptorOwnership(), file: (file), line: line)\n                XCTAssertNoThrow(try pipe2Read.takeDescriptorOwnership(), file: (file), line: line)\n                XCTAssertNoThrow(try pipe2Write.takeDescriptorOwnership(), file: (file), line: line)\n                return []\n            }\n            return []  // the channels are closing the pipes\n        },\n        file: (file),\n        line: line\n    )\n    return result!\n}\n\nfunc forEachCrossConnectedStreamChannelPair<R>(\n    forceSeparateEventLoops: Bool = false,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    _ body: (Channel, Channel) throws -> R\n) throws -> [R] {\n    let r1 = try withCrossConnectedTCPChannels(forceSeparateEventLoops: forceSeparateEventLoops, body)\n    let r2 = try withCrossConnectedPipeChannels(forceSeparateEventLoops: forceSeparateEventLoops, body)\n    let r3 = try withCrossConnectedUnixDomainSocketChannels(forceSeparateEventLoops: forceSeparateEventLoops, body)\n    return [r1, r2, r3]\n}\n\nextension EventLoopFuture {\n    var isFulfilled: Bool {\n        if self.eventLoop.inEventLoop {\n            // Easy, we're on the EventLoop. Let's just use our knowledge that we run completed future callbacks\n            // immediately.\n            var fulfilled = false\n            self.assumeIsolated().whenComplete { _ in\n                fulfilled = true\n            }\n            return fulfilled\n        } else {\n            let fulfilledBox = NIOLockedValueBox(false)\n            let group = DispatchGroup()\n\n            group.enter()\n            self.eventLoop.execute {\n                let isFulfilled = self.isFulfilled  // This will now enter the above branch.\n                fulfilledBox.withLockedValue {\n                    $0 = isFulfilled\n                }\n                group.leave()\n            }\n            group.wait()  // this is very nasty but this is for tests only, so...\n            return fulfilledBox.withLockedValue { $0 }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/ThreadTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Dispatch\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport XCTest\n\n@testable import NIOPosix\n\nclass ThreadTest: XCTestCase {\n    func testCurrentThreadWorks() {\n        let s = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        NIOThread.spawnAndRun { t in\n            XCTAssertTrue(t.isCurrentSlow)\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            s.signal()\n        }\n        s.wait()\n    }\n\n    func testCurrentThreadIsNotTrueOnOtherThread() {\n        let s = DispatchSemaphore(value: 0)\n        let thread1 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread1)\n        }\n        let thread2 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread2)\n        }\n        NIOThread.spawnAndRun { t1 in\n            NIOThread.spawnAndRun { t2 in\n                XCTAssertFalse(t1.isCurrentSlow)\n                XCTAssertTrue(t2.isCurrentSlow)\n                thread1.withLockedValue { thread in\n                    thread = t1\n                }\n                thread2.withLockedValue { thread in\n                    thread = t2\n                }\n                s.signal()\n            }\n        }\n        s.wait()\n    }\n\n    func testThreadSpecificsAreNilWhenNotPresent() {\n        class SomeClass {}\n        let s = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        NIOThread.spawnAndRun { t in\n            let tsv: ThreadSpecificVariable<SomeClass> = ThreadSpecificVariable()\n            XCTAssertNil(tsv.currentValue)\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            s.signal()\n        }\n        s.wait()\n    }\n\n    func testThreadSpecificsWorks() {\n        class SomeClass {}\n        let s = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        NIOThread.spawnAndRun { t in\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            let tsv: ThreadSpecificVariable<SomeClass> = ThreadSpecificVariable()\n            XCTAssertNil(tsv.currentValue)\n            let expected = SomeClass()\n            tsv.currentValue = expected\n            XCTAssert(expected === tsv.currentValue)\n            s.signal()\n        }\n        s.wait()\n    }\n\n    func testThreadSpecificsAreNotAvailableOnADifferentThread() {\n        class SomeClass {}\n        let s = DispatchSemaphore(value: 0)\n        let thread1 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread1)\n        }\n        let thread2 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread2)\n        }\n        NIOThread.spawnAndRun { t1 in\n            let tsv = ThreadSpecificVariable<SomeClass>()\n            XCTAssertNil(tsv.currentValue)\n            tsv.currentValue = SomeClass()\n            XCTAssertNotNil(tsv.currentValue)\n            NIOThread.spawnAndRun { t2 in\n                XCTAssertNil(tsv.currentValue)\n                thread1.withLockedValue { thread in\n                    thread = t1\n                }\n                thread2.withLockedValue { thread in\n                    thread = t2\n                }\n                s.signal()\n            }\n        }\n        s.wait()\n    }\n\n    func testThreadSpecificDoesNotLeakIfThreadExitsWhilstSet() {\n        let s = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n        weak var weakSome: SomeClass? = nil\n        NIOThread.spawnAndRun { t in\n            let some = SomeClass(sem: s)\n            weakSome = some\n            let tsv = ThreadSpecificVariable<SomeClass>()\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            tsv.currentValue = some\n            XCTAssertNotNil(tsv.currentValue)\n        }\n        s.wait()\n        XCTAssertNil(weakSome)\n    }\n\n    func testThreadSpecificDoesNotLeakIfThreadExitsAfterUnset() {\n        let s = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n        weak var weakSome: SomeClass? = nil\n        NIOThread.spawnAndRun { t in\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            let some = SomeClass(sem: s)\n            weakSome = some\n            let tsv = ThreadSpecificVariable<SomeClass>()\n            tsv.currentValue = some\n            XCTAssertNotNil(tsv.currentValue)\n            tsv.currentValue = nil\n        }\n        s.wait()\n        XCTAssertNil(weakSome)\n    }\n\n    func testThreadSpecificDoesNotLeakIfReplacedWithNewValue() {\n        let s1 = DispatchSemaphore(value: 0)\n        let s2 = DispatchSemaphore(value: 0)\n        let s3 = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n        weak var weakSome1: SomeClass? = nil\n        weak var weakSome2: SomeClass? = nil\n        weak var weakSome3: SomeClass? = nil\n        NIOThread.spawnAndRun { t in\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            let some1 = SomeClass(sem: s1)\n            weakSome1 = some1\n            let some2 = SomeClass(sem: s2)\n            weakSome2 = some2\n            let some3 = SomeClass(sem: s3)\n            weakSome3 = some3\n\n            let tsv = ThreadSpecificVariable<SomeClass>()\n            tsv.currentValue = some1\n            XCTAssertNotNil(tsv.currentValue)\n            tsv.currentValue = some2\n            XCTAssertNotNil(tsv.currentValue)\n            tsv.currentValue = some3\n            XCTAssertNotNil(tsv.currentValue)\n        }\n        s1.wait()\n        s2.wait()\n        s3.wait()\n        XCTAssertNil(weakSome1)\n        XCTAssertNil(weakSome2)\n        XCTAssertNil(weakSome3)\n    }\n\n    func testSharingThreadSpecificVariableWorks() {\n        let s = DispatchSemaphore(value: 0)\n        let thread1 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread1)\n        }\n        let threads = NIOLockedValueBox<[NIOThread]>([])\n        defer {\n            for thread in threads.withLockedValue({ $0 }) {\n                thread.join()\n            }\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n        weak var weakSome: SomeClass? = nil\n        NIOThread.spawnAndRun { t1 in\n            thread1.withLockedValue { thread in\n                thread = t1\n            }\n            let some = SomeClass(sem: s)\n            weakSome = some\n            let tsv = ThreadSpecificVariable<SomeClass>()\n            for _ in 0..<10 {\n                NIOThread.spawnAndRun { t in\n                    threads.withLockedValue { threads in\n                        threads.append(t)\n                    }\n                    tsv.currentValue = some\n                }\n            }\n        }\n        s.wait()\n        XCTAssertNil(weakSome)\n    }\n\n    func testThreadSpecificInitWithValueWorks() throws {\n        class SomeClass {}\n        let tsv = ThreadSpecificVariable(value: SomeClass())\n        XCTAssertNotNil(tsv.currentValue)\n    }\n\n    func testThreadSpecificDoesNotLeakWhenOutOfScopeButThreadStillRunning() {\n        let s = DispatchSemaphore(value: 0)\n        let thread = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread)\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n        weak var weakSome: SomeClass? = nil\n        weak var weakTSV: ThreadSpecificVariable<SomeClass>? = nil\n        NIOThread.spawnAndRun { t in\n            thread.withLockedValue { thread in\n                thread = t\n            }\n            {\n                let some = SomeClass(sem: s)\n                weakSome = some\n                let tsv = ThreadSpecificVariable<SomeClass>()\n                weakTSV = tsv\n                tsv.currentValue = some\n                XCTAssertNotNil(tsv.currentValue)\n                XCTAssertNotNil(weakTSV)\n            }()\n        }\n        s.wait()\n        assert(weakSome == nil, within: .seconds(1))\n        assert(weakTSV == nil, within: .seconds(1))\n    }\n\n    func testThreadSpecificDoesNotLeakIfThreadExitsWhilstSetOnMultipleThreads() {\n        let numberOfThreads = 6\n        let s = DispatchSemaphore(value: 0)\n        let threads = NIOLockedValueBox<[NIOThread]>([])\n        defer {\n            for thread in threads.withLockedValue({ $0 }) {\n                thread.join()\n            }\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n\n        for _ in 0..<numberOfThreads {\n            NIOThread.spawnAndRun { t in\n                threads.withLockedValue { threads in\n                    threads.append(t)\n                }\n                let some = SomeClass(sem: s)\n                let tsv = ThreadSpecificVariable<SomeClass>()\n                tsv.currentValue = some\n                XCTAssertNotNil(tsv.currentValue)\n            }\n        }\n\n        let timeout: DispatchTime = .now() + .seconds(1)\n        for _ in 0..<numberOfThreads {\n            switch s.wait(timeout: timeout) {\n            case .success:\n                ()\n            case .timedOut:\n                XCTFail(\"timed out\")\n            }\n        }\n    }\n\n    func testThreadSpecificDoesNotLeakWhenOutOfScopeButSetOnMultipleThreads() {\n        let t1Sem = DispatchSemaphore(value: 0)\n        let t2Sem = DispatchSemaphore(value: 0)\n        let thread1 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread1)\n        }\n        let thread2 = NIOLockedValueBox<NIOThread?>(nil)\n        defer {\n            Self.joinThread(thread2)\n        }\n        class SomeClass {\n            let s: DispatchSemaphore\n            init(sem: DispatchSemaphore) { self.s = sem }\n            deinit {\n                s.signal()\n            }\n        }\n        var globalTSVs: [ThreadSpecificVariable<SomeClass>] = []\n        let globalTSVLock = NIOLock()\n        ({\n            let tsv = ThreadSpecificVariable<SomeClass>()\n            globalTSVLock.withLock {\n                globalTSVs.append(tsv)\n                globalTSVs.append(tsv)\n            }\n        })()\n\n        weak var weakSome1: SomeClass? = nil\n        weak var weakSome2: SomeClass? = nil\n        weak var weakTSV: ThreadSpecificVariable<SomeClass>? = nil\n        NIOThread.spawnAndRun { t1 in\n            thread1.withLockedValue { thread in\n                thread = t1\n            }\n            {\n                let some = SomeClass(sem: t1Sem)\n                weakSome1 = some\n                var tsv: ThreadSpecificVariable<SomeClass>!\n                globalTSVLock.withLock {\n                    tsv = globalTSVs.removeFirst()\n                }\n                weakTSV = tsv\n                tsv.currentValue = some\n                XCTAssertNotNil(tsv.currentValue)\n                XCTAssertNotNil(weakTSV)\n            }()\n        }\n        NIOThread.spawnAndRun { t2 in\n            thread2.withLockedValue { thread in\n                thread = t2\n            }\n            {\n                let some = SomeClass(sem: t2Sem)\n                weakSome2 = some\n                var tsv: ThreadSpecificVariable<SomeClass>!\n                globalTSVLock.withLock {\n                    tsv = globalTSVs.removeFirst()\n                }\n                weakTSV = tsv\n                tsv.currentValue = some\n                XCTAssertNotNil(tsv.currentValue)\n                XCTAssertNotNil(weakTSV)\n            }()\n        }\n        t2Sem.wait()  // wait on the other thread's `some` deallocation\n        assert(weakSome1 == nil, within: .seconds(1))\n        assert(weakTSV == nil, within: .seconds(1))\n\n        t1Sem.wait()  // wait on the other thread's `some` deallocation\n        assert(weakSome2 == nil, within: .seconds(1))\n        assert(weakTSV == nil, within: .seconds(1))\n    }\n\n    // MARK: - Helpers\n    static func joinThread(_ thread: NIOLockedValueBox<NIOThread?>, file: StaticString = #filePath, line: UInt = #line)\n    {\n        if let thread = thread.withLockedValue({ $0 }) {\n            thread.join()\n        } else {\n            XCTFail(\"thread unexpectedly nil\", file: file, line: line)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/UniversalBootstrapSupportTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOEmbedded\nimport NIOPosix\nimport NIOTestUtils\nimport XCTest\n\nclass UniversalBootstrapSupportTest: XCTestCase {\n\n    func testBootstrappingWorks() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        final class DropChannelReadsHandler: ChannelInboundHandler {\n            typealias InboundIn = Any\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                // drop\n            }\n        }\n\n        final class DummyTLSProvider: NIOClientTLSProvider {\n            typealias Bootstrap = ClientBootstrap\n\n            final class DropInboundEventsHandler: ChannelInboundHandler {\n                typealias InboundIn = Any\n\n                func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {\n                    // drop\n                }\n            }\n\n            func enableTLS(_ bootstrap: ClientBootstrap) -> ClientBootstrap {\n                bootstrap.protocolHandlers {\n                    [DropInboundEventsHandler()]\n                }\n            }\n        }\n\n        final class FishOutChannelHandler: ChannelInboundHandler, Sendable {\n            typealias InboundIn = Channel\n\n            private let _acceptedChannels = NIOLockedValueBox<[Channel]>([])\n\n            var acceptedChannels: [Channel] {\n                self._acceptedChannels.withLockedValue { $0 }\n            }\n\n            let firstArrived: EventLoopPromise<Void>\n\n            init(firstArrived: EventLoopPromise<Void>) {\n                self.firstArrived = firstArrived\n            }\n\n            func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n                let channel = Self.unwrapInboundIn(data)\n                let count = self._acceptedChannels.withLockedValue { channels in\n                    channels.append(channel)\n                    return channels.count\n                }\n                if count == 1 {\n                    self.firstArrived.succeed(())\n                }\n                context.fireChannelRead(data)\n            }\n        }\n\n        XCTAssertNoThrow(\n            try withTCPServerChannel(group: group) { server in\n                let firstArrived = group.next().makePromise(of: Void.self)\n                let counter1 = EventCounterHandler()\n                let counter2 = EventCounterHandler()\n                let channelFisher = FishOutChannelHandler(firstArrived: firstArrived)\n                XCTAssertNoThrow(try server.pipeline.addHandler(channelFisher).wait())\n\n                let client = try NIOClientTCPBootstrap(ClientBootstrap(group: group), tls: DummyTLSProvider())\n                    .channelInitializer { channel in\n                        channel.eventLoop.makeCompletedFuture {\n                            try channel.pipeline.syncOperations.addHandlers(\n                                counter1,\n                                DropChannelReadsHandler(),\n                                counter2\n                            )\n                        }\n                    }\n                    .channelOption(.autoRead, value: false)\n                    .connectTimeout(.hours(1))\n                    .enableTLS()\n                    .connect(to: server.localAddress!)\n                    .wait()\n                defer {\n                    XCTAssertNoThrow(try client.close().wait())\n                }\n\n                var buffer = client.allocator.buffer(capacity: 16)\n                buffer.writeString(\"hello\")\n                var maybeAcceptedChannel: Channel? = nil\n                XCTAssertNoThrow(try firstArrived.futureResult.wait())\n                XCTAssertNoThrow(\n                    maybeAcceptedChannel = try server.eventLoop.submit {\n                        XCTAssertEqual(1, channelFisher.acceptedChannels.count)\n                        return channelFisher.acceptedChannels.first\n                    }.wait()\n                )\n                guard let acceptedChannel = maybeAcceptedChannel else {\n                    XCTFail(\"couldn't fish out the accepted channel\")\n                    return\n                }\n                XCTAssertNoThrow(try acceptedChannel.writeAndFlush(buffer).wait())\n\n                // auto-read is off, so we shouldn't see any reads/channelReads\n                XCTAssertEqual(0, counter1.readCalls)\n                XCTAssertEqual(0, counter2.readCalls)\n                XCTAssertEqual(0, counter1.channelReadCalls)\n                XCTAssertEqual(0, counter2.channelReadCalls)\n\n                // let's do a read\n                XCTAssertNoThrow(\n                    try client.eventLoop.submit {\n                        client.read()\n                    }.wait()\n                )\n                XCTAssertEqual(1, counter1.readCalls)\n                XCTAssertEqual(1, counter2.readCalls)\n\n                // let's check that the order is right\n                XCTAssertNoThrow(\n                    try client.eventLoop.submit { [buffer] in\n                        client.pipeline.fireChannelRead(buffer)\n                        client.pipeline.fireUserInboundEventTriggered(buffer)\n                    }.wait()\n                )\n\n                // the protocol handler which was added by the \"TLS\" implementation should be first, it however drops\n                // inbound events so we shouldn't see them\n                XCTAssertEqual(0, counter1.userInboundEventTriggeredCalls)\n                XCTAssertEqual(0, counter2.userInboundEventTriggeredCalls)\n\n                // the channelReads so have gone through but only to counter1\n                XCTAssertGreaterThanOrEqual(counter1.channelReadCalls, 1)\n                XCTAssertEqual(0, counter2.channelReadCalls)\n            }\n        )\n    }\n\n    func testBootstrapOverrideOfShortcutOptions() {\n        final class FakeBootstrap: NIOClientTCPBootstrapProtocol {\n            func channelInitializer(_ handler: @escaping (Channel) -> EventLoopFuture<Void>) -> Self {\n                fatalError(\"Not implemented\")\n            }\n\n            func protocolHandlers(_ handlers: @escaping () -> [ChannelHandler]) -> Self {\n                fatalError(\"Not implemented\")\n            }\n\n            var regularOptionsSeen = false\n            func channelOption<Option>(_ option: Option, value: Option.Value) -> Self where Option: ChannelOption {\n                regularOptionsSeen = true\n                return self\n            }\n\n            var convenienceOptionConsumed = false\n            func _applyChannelConvenienceOptions(_ options: inout ChannelOptions.TCPConvenienceOptions) -> FakeBootstrap\n            {\n                if options.consumeAllowLocalEndpointReuse().isSet {\n                    convenienceOptionConsumed = true\n                }\n                return self\n            }\n\n            func connectTimeout(_ timeout: TimeAmount) -> Self {\n                fatalError(\"Not implemented\")\n            }\n\n            func connect(host: String, port: Int) -> EventLoopFuture<Channel> {\n                fatalError(\"Not implemented\")\n            }\n\n            func connect(to address: SocketAddress) -> EventLoopFuture<Channel> {\n                fatalError(\"Not implemented\")\n            }\n\n            func connect(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n                fatalError(\"Not implemented\")\n            }\n        }\n\n        // Check consumption works.\n        let consumingFake = FakeBootstrap()\n        _ = NIOClientTCPBootstrap(consumingFake, tls: NIOInsecureNoTLS())\n            .channelConvenienceOptions([.allowLocalEndpointReuse])\n        XCTAssertTrue(consumingFake.convenienceOptionConsumed)\n        XCTAssertFalse(consumingFake.regularOptionsSeen)\n\n        // Check default behaviour works.\n        let nonConsumingFake = FakeBootstrap()\n        _ = NIOClientTCPBootstrap(nonConsumingFake, tls: NIOInsecureNoTLS())\n            .channelConvenienceOptions([.allowRemoteHalfClosure])\n        XCTAssertFalse(nonConsumingFake.convenienceOptionConsumed)\n        XCTAssertTrue(nonConsumingFake.regularOptionsSeen)\n\n        // Both at once.\n        let bothFake = FakeBootstrap()\n        _ = NIOClientTCPBootstrap(bothFake, tls: NIOInsecureNoTLS())\n            .channelConvenienceOptions([.allowRemoteHalfClosure, .allowLocalEndpointReuse])\n        XCTAssertTrue(bothFake.convenienceOptionConsumed)\n        XCTAssertTrue(bothFake.regularOptionsSeen)\n    }\n}\n\n// Prove we've not broken implementors of NIOClientTCPBootstrapProtocol by adding a new method.\nprivate class UniversalWithoutNewMethods: NIOClientTCPBootstrapProtocol {\n    func channelInitializer(_ handler: @escaping (Channel) -> EventLoopFuture<Void>) -> Self {\n        self\n    }\n\n    func protocolHandlers(_ handlers: @escaping () -> [ChannelHandler]) -> Self {\n        self\n    }\n\n    func channelOption<Option>(_ option: Option, value: Option.Value) -> Self where Option: ChannelOption {\n        self\n    }\n\n    func connectTimeout(_ timeout: TimeAmount) -> Self {\n        self\n    }\n\n    func connect(host: String, port: Int) -> EventLoopFuture<Channel> {\n        EmbeddedEventLoop().makePromise(of: Channel.self).futureResult\n    }\n\n    func connect(to address: SocketAddress) -> EventLoopFuture<Channel> {\n        EmbeddedEventLoop().makePromise(of: Channel.self).futureResult\n    }\n\n    func connect(unixDomainSocketPath: String) -> EventLoopFuture<Channel> {\n        EmbeddedEventLoop().makePromise(of: Channel.self).futureResult\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/VsockAddressTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOPosix\n\nclass VsockAddressTest: XCTestCase {\n\n    func testDescriptionWorks() throws {\n        XCTAssertEqual(VsockAddress(cid: .host, port: 12345).description, \"[VSOCK]2:12345\")\n        XCTAssertEqual(VsockAddress(cid: .any, port: 12345).description, \"[VSOCK]-1:12345\")\n        XCTAssertEqual(VsockAddress(cid: .host, port: .any).description, \"[VSOCK]2:-1\")\n        XCTAssertEqual(VsockAddress(cid: .any, port: .any).description, \"[VSOCK]-1:-1\")\n    }\n\n    func testInitializeFromIntegerLiteral() throws {\n        XCTAssertEqual(VsockAddress.ContextID(integerLiteral: 0), 0)\n        XCTAssertEqual(VsockAddress.Port(integerLiteral: 0), 0)\n        XCTAssertEqual(VsockAddress.ContextID(integerLiteral: 4_294_967_295), 4_294_967_295)\n        XCTAssertEqual(VsockAddress.Port(integerLiteral: 4_294_967_295), 4_294_967_295)\n    }\n\n    func testInitializeFromInt() throws {\n        XCTAssertEqual(VsockAddress.ContextID(0), 0)\n        XCTAssertEqual(VsockAddress.ContextID(4_294_967_295), 4_294_967_295)\n        XCTAssertEqual(VsockAddress.Port(0), 0)\n        XCTAssertEqual(VsockAddress.Port(4_294_967_295), 4_294_967_295)\n    }\n\n    func testSocketAddressEqualitySpecialValues() throws {\n        XCTAssertEqual(\n            VsockAddress(cid: .any, port: 12345),\n            .init(cid: .init(rawValue: UInt32(bitPattern: -1)), port: 12345)\n        )\n        XCTAssertEqual(VsockAddress(cid: .hypervisor, port: 12345), .init(cid: 0, port: 12345))\n        XCTAssertEqual(VsockAddress(cid: .host, port: 12345), .init(cid: 2, port: 12345))\n    }\n\n    func testSocketAddressEquality() throws {\n        XCTAssertEqual(VsockAddress(cid: 0, port: 0), .init(cid: 0, port: 0))\n        XCTAssertEqual(VsockAddress(cid: 1, port: 0), .init(cid: 1, port: 0))\n        XCTAssertEqual(VsockAddress(cid: 0, port: 1), .init(cid: 0, port: 1))\n\n        XCTAssertNotEqual(VsockAddress(cid: 0, port: 0), .init(cid: 1, port: 0))\n        XCTAssertNotEqual(VsockAddress(cid: 0, port: 0), .init(cid: 0, port: 1))\n    }\n\n    func testGetLocalCID() throws {\n        try XCTSkipUnless(System.supportsVsockLoopback, \"No vsock loopback transport available\")\n\n        let socket = try ServerSocket(protocolFamily: .vsock, setNonBlocking: true)\n        defer { try? socket.close() }\n\n        // Check we can get the local CID using the static property on ContextID.\n        let localCID = try socket.withUnsafeHandle(VsockAddress.ContextID.getLocalContextID)\n\n        // Check the local CID from the socket matches.\n        XCTAssertEqual(try socket.getLocalVsockContextID(), localCID)\n\n        // Check the local CID from the channel option matches.\n        let singleThreadedELG = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer { XCTAssertNoThrow(try singleThreadedELG.syncShutdownGracefully()) }\n        let eventLoop = singleThreadedELG.next()\n        let channel = try ServerSocketChannel(\n            serverSocket: socket,\n            eventLoop: eventLoop as! SelectableEventLoop,\n            group: singleThreadedELG\n        )\n        XCTAssertEqual(try channel.getOption(.localVsockContextID).wait(), localCID)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOPosixTests/XCTest+AsyncAwait.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the AsyncHTTPClient open source project\n//\n// Copyright (c) 2021 Apple Inc. and the AsyncHTTPClient project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n// Copyright 2021, gRPC Authors All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport XCTest\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertThrowsError<T>(\n    _ expression: () async throws -> T,\n    file: StaticString = #filePath,\n    line: UInt = #line,\n    verify: (Error) -> Void = { _ in }\n) async {\n    do {\n        _ = try await expression()\n        XCTFail(\"Expression did not throw error\", file: file, line: line)\n    } catch {\n        verify(error)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertNoThrow<T>(\n    _ expression: @autoclosure () async throws -> T,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async {\n    do {\n        _ = try await expression()\n    } catch {\n        XCTFail(\"Expression did throw error: \\(error)\", file: file, line: line)\n    }\n}\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\ninternal func XCTAssertNoThrowWithResult<Result>(\n    _ expression: @autoclosure () async throws -> Result,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) async -> Result? {\n    do {\n        return try await expression()\n    } catch {\n        XCTFail(\"Expression did throw: \\(error)\", file: file, line: line)\n    }\n    return nil\n}\n"
  },
  {
    "path": "Tests/NIOSingletonsTests/GlobalSingletonsTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\nimport NIOCore\nimport NIOPosix\nimport XCTest\n\nfinal class NIOSingletonsTests: XCTestCase {\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    func testSingletonMultiThreadedEventLoopWorks() async throws {\n        let works = try await MultiThreadedEventLoopGroup.singleton.any().submit { \"yes\" }.get()\n        XCTAssertEqual(works, \"yes\")\n    }\n\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    func testSingletonBlockingPoolWorks() async throws {\n        let works = try await NIOThreadPool.singleton.runIfActive(\n            eventLoop: MultiThreadedEventLoopGroup.singleton.any()\n        ) {\n            \"yes\"\n        }.get()\n        XCTAssertEqual(works, \"yes\")\n    }\n\n    func testCannotShutdownMultiGroup() {\n        XCTAssertThrowsError(try MultiThreadedEventLoopGroup.singleton.syncShutdownGracefully()) { error in\n            XCTAssertEqual(.unsupportedOperation, error as? EventLoopError)\n        }\n    }\n\n    func testCannotShutdownBlockingPool() {\n        XCTAssertThrowsError(try NIOThreadPool.singleton.syncShutdownGracefully()) { error in\n            XCTAssert(error is NIOThreadPoolError.UnsupportedOperation)\n        }\n    }\n\n    func testMultiGroupThreadPrefix() {\n        XCTAssert(\n            MultiThreadedEventLoopGroup.singleton.description.contains(\"NIO-SGLTN-\"),\n            \"\\(MultiThreadedEventLoopGroup.singleton.description)\"\n        )\n\n        for _ in 0..<100 {\n            let someEL = MultiThreadedEventLoopGroup.singleton.next()\n            XCTAssert(someEL.description.contains(\"NIO-SGLTN-\"), \"\\(someEL.description)\")\n        }\n    }\n\n    func testSingletonsAreEnabledAndCanBeReadMoreThanOnce() {\n        XCTAssertTrue(NIOSingletons.singletonsEnabledSuggestion)\n        XCTAssertTrue(NIOSingletons.singletonsEnabledSuggestion)\n        XCTAssertTrue(NIOSingletons.singletonsEnabledSuggestion)\n    }\n\n    func testCanCreateClientBootstrapWithoutSpecifyingTypeName() {\n        _ = ClientBootstrap(group: .singletonMultiThreadedEventLoopGroup)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTLSTests/ApplicationProtocolNegotiationHandlerTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOTLS\nimport NIOTestUtils\nimport XCTest\n\nprivate class ReadCompletedHandler: ChannelInboundHandler {\n    public typealias InboundIn = Any\n    public var readCompleteCount: Int\n\n    init() {\n        readCompleteCount = 0\n    }\n\n    public func channelReadComplete(context: ChannelHandlerContext) {\n        readCompleteCount += 1\n    }\n}\n\nfinal class DuplicatingReadHandler: ChannelInboundHandler {\n    typealias InboundIn = String\n\n    private let channel: EmbeddedChannel\n\n    private var hasDuplicatedRead = false\n\n    init(embeddedChannel: EmbeddedChannel) {\n        self.channel = embeddedChannel\n    }\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        if !self.hasDuplicatedRead {\n            self.hasDuplicatedRead = true\n            try! self.channel.writeInbound(Self.unwrapInboundIn(data))\n        }\n        context.fireChannelRead(data)\n    }\n}\n\nclass ApplicationProtocolNegotiationHandlerTests: XCTestCase {\n    private enum EventType {\n        case basic\n    }\n\n    private let negotiatedEvent: TLSUserEvent = .handshakeCompleted(negotiatedProtocol: \"h2\")\n    private let negotiatedResult: ALPNResult = .negotiated(\"h2\")\n\n    func testChannelProvidedToCallback() throws {\n        let emChannel = EmbeddedChannel()\n        let loop = emChannel.eventLoop as! EmbeddedEventLoop\n        var called = false\n\n        let handler = ApplicationProtocolNegotiationHandler { result, channel in\n            called = true\n            XCTAssertEqual(result, self.negotiatedResult)\n            XCTAssertTrue(emChannel === channel)\n            return loop.makeSucceededFuture(())\n        }\n\n        try emChannel.pipeline.syncOperations.addHandler(handler)\n        emChannel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n        XCTAssertTrue(called)\n    }\n\n    func testIgnoresUnknownUserEvents() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            XCTFail(\"Negotiation fired\")\n            return loop.makeSucceededFuture(())\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Fire a pair of events that should be ignored.\n        channel.pipeline.fireUserInboundEventTriggered(EventType.basic)\n        channel.pipeline.fireUserInboundEventTriggered(TLSUserEvent.shutdownCompleted)\n\n        // The channel handler should still be in the pipeline.\n        try channel.pipeline.assertContains(handler: handler)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    private func negotiateTest(event: TLSUserEvent, expectedResult: ALPNResult) throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: Void.self)\n\n        var called = false\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            XCTAssertEqual(self.negotiatedResult, result)\n            called = true\n            return continuePromise.futureResult\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Fire the handshake complete event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // At this time the callback should have fired, but the handler should still be in\n        // the pipeline.\n        XCTAssertTrue(called)\n        try channel.pipeline.assertContains(handler: handler)\n\n        // Now we fire the future.\n        continuePromise.succeed(())\n\n        // Now the handler should have removed itself from the pipeline.\n        try channel.pipeline.assertDoesNotContain(handler: handler)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testCallbackReflectsNotificationResult() throws {\n        try negotiateTest(event: negotiatedEvent, expectedResult: negotiatedResult)\n    }\n\n    func testCallbackNotesFallbackForNoNegotiation() throws {\n        try negotiateTest(event: .handshakeCompleted(negotiatedProtocol: \"\"), expectedResult: .fallback)\n    }\n\n    func testNoBufferingBeforeEventFires() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            XCTFail(\"Should not be called\")\n            return loop.makeSucceededFuture(())\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // The data we write should not be buffered.\n        try channel.writeInbound(\"hello\")\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"hello\"))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testBufferingWhileWaitingForFuture() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: Void.self)\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            continuePromise.futureResult\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // At this point all writes should be buffered.\n        try channel.writeInbound(\"writes\")\n        try channel.writeInbound(\"are\")\n        try channel.writeInbound(\"buffered\")\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        // Complete the pipeline swap.\n        continuePromise.succeed(())\n\n        // Now everything should have been unbuffered.\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"writes\"))\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"are\"))\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"buffered\"))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testNothingBufferedDoesNotFireReadCompleted() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: Void.self)\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            continuePromise.futureResult\n        }\n        let readCompleteHandler = ReadCompletedHandler()\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.syncOperations.addHandler(readCompleteHandler)\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // At this time, readComplete hasn't fired.\n        XCTAssertEqual(readCompleteHandler.readCompleteCount, 0)\n\n        // Now satisfy the future, which forces data unbuffering. As we haven't buffered any data,\n        // readComplete should not be fired.\n        continuePromise.succeed(())\n        XCTAssertEqual(readCompleteHandler.readCompleteCount, 0)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testUnbufferingFiresReadCompleted() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: Void.self)\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            continuePromise.futureResult\n        }\n        let readCompleteHandler = ReadCompletedHandler()\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.syncOperations.addHandler(readCompleteHandler)\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // Send a write, which is buffered.\n        try channel.writeInbound(\"a write\")\n\n        // At this time, readComplete hasn't fired.\n        XCTAssertEqual(readCompleteHandler.readCompleteCount, 1)\n\n        // Now satisfy the future, which forces data unbuffering. This should fire readComplete.\n        continuePromise.succeed(())\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"a write\"))\n\n        XCTAssertEqual(readCompleteHandler.readCompleteCount, 2)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testUnbufferingHandlesReentrantReads() throws {\n        let channel = EmbeddedChannel()\n        let continuePromise = channel.eventLoop.makePromise(of: Void.self)\n\n        let handler = ApplicationProtocolNegotiationHandler { result in\n            continuePromise.futureResult\n        }\n        let readCompleteHandler = ReadCompletedHandler()\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.syncOperations.addHandler(DuplicatingReadHandler(embeddedChannel: channel))\n        try channel.pipeline.syncOperations.addHandler(readCompleteHandler)\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // Send a write, which is buffered.\n        try channel.writeInbound(\"a write\")\n\n        // At this time, readComplete hasn't fired.\n        XCTAssertEqual(readCompleteHandler.readCompleteCount, 1)\n\n        // Now satisfy the future, which forces data unbuffering. This should fire readComplete.\n        continuePromise.succeed(())\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"a write\"))\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"a write\"))\n\n        XCTAssertEqual(readCompleteHandler.readCompleteCount, 3)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTLSTests/NIOTypedApplicationProtocolNegotiationHandlerTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOTLS\nimport NIOTestUtils\nimport XCTest\n\nfinal class NIOTypedApplicationProtocolNegotiationHandlerTests: XCTestCase {\n    enum NegotiationResult: Equatable {\n        case negotiated(ALPNResult)\n        case failed\n    }\n\n    private let negotiatedEvent: TLSUserEvent = .handshakeCompleted(negotiatedProtocol: \"h2\")\n    private let negotiatedResult: ALPNResult = .negotiated(\"h2\")\n\n    func testPromiseIsCompleted() throws {\n        let channel = EmbeddedChannel()\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result, channel in\n            channel.eventLoop.makeSucceededFuture(.negotiated(result))\n        }\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.syncOperations.removeHandler(handler).wait()\n        XCTAssertThrowsError(try handler.protocolNegotiationResult.wait()) { error in\n            XCTAssertEqual(error as? ChannelError, .inappropriateOperationForState)\n        }\n    }\n\n    func testChannelProvidedToCallback() throws {\n        let emChannel = EmbeddedChannel()\n        let loop = emChannel.eventLoop as! EmbeddedEventLoop\n        var called = false\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result, channel in\n            called = true\n            XCTAssertEqual(result, self.negotiatedResult)\n            XCTAssertTrue(emChannel === channel)\n            return loop.makeSucceededFuture(.negotiated(result))\n        }\n\n        try emChannel.pipeline.syncOperations.addHandler(handler)\n        emChannel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n        XCTAssertTrue(called)\n\n        XCTAssertEqual(try handler.protocolNegotiationResult.wait(), .negotiated(negotiatedResult))\n    }\n\n    func testIgnoresUnknownUserEvents() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result in\n            XCTFail(\"Negotiation fired\")\n            return loop.makeSucceededFuture(.failed)\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Fire a pair of events that should be ignored.\n        channel.pipeline.fireUserInboundEventTriggered(\"FakeEvent\")\n        channel.pipeline.fireUserInboundEventTriggered(TLSUserEvent.shutdownCompleted)\n\n        // The channel handler should still be in the pipeline.\n        try channel.pipeline.assertContains(handler: handler)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testNoBufferingBeforeEventFires() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result in\n            XCTFail(\"Should not be called\")\n            return loop.makeSucceededFuture(.failed)\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // The data we write should not be buffered.\n        try channel.writeInbound(\"hello\")\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"hello\"))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testBufferingWhileWaitingForFuture() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: NegotiationResult.self)\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result in\n            continuePromise.futureResult\n        }\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // At this point all writes should be buffered.\n        try channel.writeInbound(\"writes\")\n        try channel.writeInbound(\"are\")\n        try channel.writeInbound(\"buffered\")\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n\n        // Complete the pipeline swap.\n        continuePromise.succeed(.failed)\n\n        // Now everything should have been unbuffered.\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"writes\"))\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"are\"))\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"buffered\"))\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testNothingBufferedDoesNotFireReadCompleted() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: NegotiationResult.self)\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result in\n            continuePromise.futureResult\n        }\n        let eventCounterHandler = EventCounterHandler()\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.addHandler(eventCounterHandler).wait()\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // At this time, readComplete hasn't fired.\n        XCTAssertEqual(eventCounterHandler.channelReadCompleteCalls, 0)\n\n        // Now satisfy the future, which forces data unbuffering. As we haven't buffered any data,\n        // readComplete should not be fired.\n        continuePromise.succeed(.failed)\n        XCTAssertEqual(eventCounterHandler.channelReadCompleteCalls, 0)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testUnbufferingFiresReadCompleted() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: NegotiationResult.self)\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result in\n            continuePromise.futureResult\n        }\n        let eventCounterHandler = EventCounterHandler()\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.addHandler(eventCounterHandler).wait()\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // Send a write, which is buffered.\n        try channel.writeInbound(\"a write\")\n\n        // At this time, readComplete hasn't fired.\n        XCTAssertEqual(eventCounterHandler.channelReadCompleteCalls, 1)\n\n        // Now satisfy the future, which forces data unbuffering. This should fire readComplete.\n        continuePromise.succeed(.failed)\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"a write\"))\n\n        XCTAssertEqual(eventCounterHandler.channelReadCompleteCalls, 2)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func testUnbufferingHandlesReentrantReads() throws {\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: NegotiationResult.self)\n\n        let handler = NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> { result in\n            continuePromise.futureResult\n        }\n        let eventCounterHandler = EventCounterHandler()\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n        try channel.pipeline.syncOperations.addHandler(DuplicatingReadHandler(embeddedChannel: channel))\n        try channel.pipeline.syncOperations.addHandler(eventCounterHandler)\n\n        // Fire in the event.\n        channel.pipeline.fireUserInboundEventTriggered(negotiatedEvent)\n\n        // Send a write, which is buffered.\n        try channel.writeInbound(\"a write\")\n\n        // At this time, readComplete hasn't fired.\n        XCTAssertEqual(eventCounterHandler.channelReadCompleteCalls, 1)\n\n        // Now satisfy the future, which forces data unbuffering. This should fire readComplete.\n        continuePromise.succeed(.failed)\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"a write\"))\n        XCTAssertNoThrow(XCTAssertEqual(try channel.readInbound()!, \"a write\"))\n\n        XCTAssertEqual(eventCounterHandler.channelReadCompleteCalls, 3)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTLSTests/SNIHandlerTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOEmbedded\nimport NIOFoundationCompat\nimport NIOTLS\nimport XCTest\n\n@testable import NIOCore\n\nprivate let libressl227HelloNoSNI = \"\"\"\n    FgMBATkBAAE1AwNqcHrXsRJKtLx2HC1BXLt+kAk7SnCMk8qK\n    QPmv7L3u7QAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQAAdAALAAQDAAECAAoAOgA4\n    AA4ADQAZABwACwAMABsAGAAJAAoAGgAWABcACAAGAAcAFAAV\n    AAQABQASABMAAQACAAMADwAQABEAIwAAAA0AJgAkBgEGAgYD\n    7+8FAQUCBQMEAQQCBAPu7u3tAwEDAgMDAgECAgID\n    \"\"\"\n\nprivate let libressl227HelloWithSNI = \"\"\"\n    FgMBAU0BAAFJAwN/gCauChg0p2XhDp6z2+gRqMeyb5zfxBOW\n    dtGXsknrcAAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQAAiAAAABAADgAAC2h0dHBi\n    aW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwAY\n    AAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwAP\n    ABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7u\n    7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let openssl102HelloNoSNI = \"\"\"\n    FgMBAS8BAAErAwPmgeNB1uuTN/P5ZlOjLQMHjxgIotE2796Z\n    ILeQHLg/ZQAArMAwwCzAKMAkwBTACgClAKMAoQCfAGsAagBp\n    AGgAOQA4ADcANgCIAIcAhgCFwDLALsAqwCbAD8AFAJ0APQA1\n    AITAL8ArwCfAI8ATwAkApACiAKAAngBnAEAAPwA+ADMAMgAx\n    ADAAmgCZAJgAlwBFAEQAQwBCwDHALcApwCXADsAEAJwAPAAv\n    AJYAQQAHwBHAB8AMwAIABQAEwBLACAAWABMAEAANwA3AAwAK\n    AP8CAQAAVQALAAQDAAECAAoAHAAaABcAGQAcABsAGAAaABYA\n    DgANAAsADAAJAAoAIwAAAA0AIAAeBgEGAgYDBQEFAgUDBAEE\n    AgQDAwEDAgMDAgECAgIDAA8AAQE=\n    \"\"\"\n\nprivate let openssl102HelloWithSNI = \"\"\"\n    FgMBAUMBAAE/AwO0rkxuVnE+GcBdNP2UJwTCVSi2H2NbIngp\n    eTzpoVc+kgAArMAwwCzAKMAkwBTACgClAKMAoQCfAGsAagBp\n    AGgAOQA4ADcANgCIAIcAhgCFwDLALsAqwCbAD8AFAJ0APQA1\n    AITAL8ArwCfAI8ATwAkApACiAKAAngBnAEAAPwA+ADMAMgAx\n    ADAAmgCZAJgAlwBFAEQAQwBCwDHALcApwCXADsAEAJwAPAAv\n    AJYAQQAHwBHAB8AMwAIABQAEwBLACAAWABMAEAANwA3AAwAK\n    AP8CAQAAaQAAABAADgAAC2h0dHBiaW4ub3JnAAsABAMAAQIA\n    CgAcABoAFwAZABwAGwAYABoAFgAOAA0ACwAMAAkACgAjAAAA\n    DQAgAB4GAQYCBgMFAQUCBQMEAQQCBAMDAQMCAwMCAQICAgMA\n    DwABAQ==\n    \"\"\"\n\nprivate let curlWithSecureTransport = \"\"\"\n    FgMBAL4BAAC6AwNZ54sY4KDX3NJ7JTk/ER+MdC3dT72bCG8P\n    wFcIw08qJAAARAD/wCzAK8AkwCPACsAJwAjAMMAvwCjAJ8AU\n    wBPAEgCfAJ4AawBnADkAMwAWAJ0AnAA9ADwANQAvAAoArwCu\n    AI0AjACLAQAATQAAABAADgAAC2h0dHBiaW4ub3JnAAoACAAG\n    ABcAGAAZAAsAAgEAAA0AEgAQBAECAQUBBgEEAwIDBQMGAwAF\n    AAUBAAAAAAASAAAAFwAA\n    \"\"\"\n\nprivate let safariWithSecureTransport = \"\"\"\n    FgMBAOEBAADdAwP1UKyAyXfMC35xny6EHejdgPt7aPoHdeQG\n    /1FuKmniSQAAKMAswCvAJMAjwArACcypwDDAL8AowCfAFMAT\n    zKgAnQCcAD0APAA1AC8BAACM/wEAAQAAAAAQAA4AAAtodHRw\n    YmluLm9yZwAXAAAADQAUABIEAwgEBAEFAwgFBQEIBgYBAgEA\n    BQAFAQAAAAAzdAAAABIAAAAQADAALgJoMgVoMi0xNgVoMi0x\n    NQVoMi0xNAhzcGR5LzMuMQZzcGR5LzMIaHR0cC8xLjEACwAC\n    AQAACgAIAAYAHQAXABg=\n    \"\"\"\n\nprivate let chromeWithBoringSSL = \"\"\"\n    FgMBAMIBAAC+AwMTXqvA3thIWxHtp1Fpf56+YmWbfaNxMO4f\n    DSUKnu6d/gAAHBoawCvAL8AswDDMqcyowBPAFACcAJ0ALwA1\n    AAoBAAB5qqoAAP8BAAEAAAAAEAAOAAALaHR0cGJpbi5vcmcA\n    FwAAACMAAAANABQAEgQDCAQEAQUDCAUFAQgGBgECAQAFAAUB\n    AAAAAAASAAAAEAAOAAwCaDIIaHR0cC8xLjF1UAAAAAsAAgEA\n    AAoACgAIWloAHQAXABjKygABAA==\n    \"\"\"\n\nprivate let firefoxWithNSS = \"\"\"\n    FgMBALcBAACzAwN6qgxS1T0PTzYdLZ+3CvMBosugW1anTOsO\n    blZjJ+/adgAAHsArwC/MqcyowCzAMMAKwAnAE8AUADMAOQAv\n    ADUACgEAAGwAAAAQAA4AAAtodHRwYmluLm9yZwAXAAD/AQAB\n    AAAKAAoACAAdABcAGAAZAAsAAgEAACMAAAAQAA4ADAJoMgho\n    dHRwLzEuMQAFAAUBAAAAAAANABgAFgQDBQMGAwgECAUIBgQB\n    BQEGAQIDAgE=\n    \"\"\"\n\nprivate let alertFatalInternalError = \"FQMDAAICUA==\"\n\nprivate let invalidTlsVersion = \"\"\"\n    FgQAALcBAACzAwN6qgxS1T0PTzYdLZ+3CvMBosugW1anTOsO\n    blZjJ+/adgAAHsArwC/MqcyowCzAMMAKwAnAE8AUADMAOQAv\n    ADUACgEAAGwAAAAQAA4AAAtodHRwYmluLm9yZwAXAAD/AQAB\n    AAAKAAoACAAdABcAGAAZAAsAAgEAACMAAAAQAA4ADAJoMgho\n    dHRwLzEuMQAFAAUBAAAAAAANABgAFgQDBQMGAwgECAUIBgQB\n    BQEGAQIDAgE=\n    \"\"\"\n\nprivate let clientKeyExchange = \"\"\"\n    FgMDAJYQAACSkQQAR/1YL9kZ13n6OWVy6VMLqc++ZTHfZVlt\n    RlLYoziZSu7tKZ9UUMvZJ5BCcH3juFGM9wftZi0PIjKuRrBZ\n    erk++KawYtxuaIwDGwinj70hmUxB9jQSa0M9NXXNVHZWgMSX\n    YVj3N8SBAfmGbWQbH9uONzieFuVYwkmVEidIlE7A04gHP9id\n    Oy5Badfl6Ab5fDg=\n    \"\"\"\n\nprivate let invalidHandshakeLength = \"\"\"\n    FgMBALcBAQCzAwN6qgxS1T0PTzYdLZ+3CvMBosugW1anTOsO\n    blZjJ+/adgAAHsArwC/MqcyowCzAMMAKwAnAE8AUADMAOQAv\n    ADUACgEAAGwAAAAQAA4AAAtodHRwYmluLm9yZwAXAAD/AQAB\n    AAAKAAoACAAdABcAGAAZAAsAAgEAACMAAAAQAA4ADAJoMgho\n    dHRwLzEuMQAFAAUBAAAAAAANABgAFgQDBQMGAwgECAUIBgQB\n    BQEGAQIDAgE=\n    \"\"\"\n\nprivate let invalidCipherSuitesLength = \"\"\"\n    FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U/\n    lEvy1/7zGQDw/8wUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQAAiAAAABAADgAAC2h0dHBi\n    aW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwAY\n    AAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwAP\n    ABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7u\n    7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let invalidCompressionLength = \"\"\"\n    'FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U\n    /lEvy1/7zGQAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawB\n    qADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQD\n    AAITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMA\n    xwC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsA\n    IABYAE8ANwAMACgAVABIACQD//wAAiAAAABAADgAAC2h0dHB\n    iaW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwA\n    YAAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwA\n    PABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7\n    u7e0DAQMCAwMCAQICAgM='\n    \"\"\"\n\nprivate let invalidExtensionLength = \"\"\"\n    FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U/\n    lEvy1/7zGQAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQDw/wAAABAADgAAC2h0dHBi\n    aW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwAY\n    AAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwAP\n    ABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7u\n    7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let invalidIndividualExtensionLength = \"\"\"\n    FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U/\n    lEvy1/7zGQAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQAAiAAA8P8ADgAAC2h0dHBi\n    aW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwAY\n    AAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwAP\n    ABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7u\n    7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let unknownNameType = \"\"\"\n    'FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U\n    /lEvy1/7zGQAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawB\n    qADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQD\n    AAITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMA\n    xwC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsA\n    IABYAE8ANwAMACgAVABIACQD/AQAAiAAAABAADgEAC2h0dHB\n    iaW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwA\n    YAAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwA\n    PABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7\n    u7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let invalidNameLength = \"\"\"\n    FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U/\n    lEvy1/7zGQAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQAAiAAAABAADgD/8Gh0dHBi\n    aW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwAY\n    AAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwAP\n    ABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7u\n    7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let invalidNameExtensionLength = \"\"\"\n    FgMBAU0BAAFJAwNyvld+G6aaYHyOf2Q6A5P7pFYdY9oWq6U/\n    lEvy1/7zGQAAmMwUzBPMFcAwwCzAKMAkwBTACgCjAJ8AawBq\n    ADkAOP+FAMQAwwCIAIcAgcAywC7AKsAmwA/ABQCdAD0ANQDA\n    AITAL8ArwCfAI8ATwAkAogCeAGcAQAAzADIAvgC9AEUARMAx\n    wC3AKcAlwA7ABACcADwALwC6AEHAEcAHwAzAAgAFAATAEsAI\n    ABYAE8ANwAMACgAVABIACQD/AQAAiAAAABDw/wAAC2h0dHBi\n    aW4ub3JnAAsABAMAAQIACgA6ADgADgANABkAHAALAAwAGwAY\n    AAkACgAaABYAFwAIAAYABwAUABUABAAFABIAEwABAAIAAwAP\n    ABAAEQAjAAAADQAmACQGAQYCBgPv7wUBBQIFAwQBBAIEA+7u\n    7e0DAQMCAwMCAQICAgM=\n    \"\"\"\n\nprivate let ludicrouslyTruncatedPacket = \"FgMBAAEB\"\n\nprivate let fuzzingInputOne = \"FgMAAAQAAgo=\"\n\nextension ChannelPipeline {\n    func contains(handler: ChannelHandler) throws -> Bool {\n        do {\n            _ = try self.syncOperations.context(handler: handler)\n            return true\n        } catch ChannelPipelineError.notFound {\n            return false\n        }\n    }\n    func assertDoesNotContain(handler: ChannelHandler) throws {\n        XCTAssertFalse(try contains(handler: handler))\n    }\n\n    func assertContains(handler: ChannelHandler) throws {\n        XCTAssertTrue(try contains(handler: handler))\n    }\n}\n\nclass SNIHandlerTest: XCTestCase {\n    private func bufferForBase64String(string: String) -> ByteBuffer {\n        let data = Data(base64Encoded: string, options: .ignoreUnknownCharacters)!\n        let allocator = ByteBufferAllocator()\n        var buffer = allocator.buffer(capacity: data.count)\n        buffer.writeBytes(data)\n        return buffer\n    }\n\n    /// Drip-feeds the client hello in one byte at a time.\n    /// Also asserts that the channel handler does not remove itself from\n    /// the pipeline or emit its buffered data until the future fires.\n    func dripFeedHello(clientHello: String, expectedResult: SNIResult) throws {\n        var called = false\n        var buffer = bufferForBase64String(string: clientHello)\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: Void.self)\n\n        let handler = ByteToMessageHandler(\n            SNIHandler { result in\n                XCTAssertEqual(expectedResult, result)\n                called = true\n                return continuePromise.futureResult\n            }\n        )\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // The handler will run when the last byte of the extension data is sent.\n        // We don't know when that is, so don't try to predict it. However,\n        // for this entire time the handler should remain in the pipeline and not\n        // forward on any data.\n        while buffer.readableBytes > 0 {\n            let writeableData = buffer.readSlice(length: 1)!\n            try channel.writeInbound(writeableData)\n            loop.run()\n\n            XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n            try channel.pipeline.assertContains(handler: handler)\n        }\n\n        // The callback should now have fired, but the handler should still not have\n        // sent on any data and should still be in the pipeline.\n        XCTAssertTrue(called)\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))\n        try channel.pipeline.assertContains(handler: handler)\n\n        // Now we're going to complete the promise and run the loop. This should cause the complete\n        // ClientHello to be sent on, and the SNIHandler to be removed from the pipeline.\n        continuePromise.succeed(())\n        loop.run()\n\n        let writtenBuffer: ByteBuffer = try channel.readInbound() ?? channel.allocator.buffer(capacity: 0)\n        let writtenData = writtenBuffer.getData(at: writtenBuffer.readerIndex, length: writtenBuffer.readableBytes)\n        let expectedData = Data(base64Encoded: clientHello, options: .ignoreUnknownCharacters)!\n        XCTAssertEqual(writtenData, expectedData)\n\n        try channel.pipeline.assertDoesNotContain(handler: handler)\n\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    /// Blasts the client hello in as a single string. This is not expected to reveal bugs\n    /// that the drip feed doesn't hit: it just helps to find more gross logic bugs.\n    func blastHello(clientHello: String, expectedResult: SNIResult) throws {\n        var called = false\n        let buffer = bufferForBase64String(string: clientHello)\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n        let continuePromise = loop.makePromise(of: Void.self)\n\n        let handler = ByteToMessageHandler(\n            SNIHandler { result in\n                XCTAssertEqual(expectedResult, result)\n                called = true\n                return continuePromise.futureResult\n            }\n        )\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Ok, let's go.\n        try channel.writeInbound(buffer)\n        loop.run()\n\n        // The callback should have fired, but the handler should not have\n        // sent on any data and should still be in the pipeline.\n        XCTAssertTrue(called)\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound(as: ByteBuffer.self)))\n        try channel.pipeline.assertContains(handler: handler)\n\n        // Now we're going to complete the promise and run the loop. This should cause the complete\n        // ClientHello to be sent on, and the SNIHandler to be removed from the pipeline.\n        continuePromise.succeed(())\n        loop.run()\n\n        let writtenBuffer: ByteBuffer? = try channel.readInbound()\n        if let writtenBuffer = writtenBuffer {\n            let writtenData = writtenBuffer.getData(at: writtenBuffer.readerIndex, length: writtenBuffer.readableBytes)\n            let expectedData = Data(base64Encoded: clientHello, options: .ignoreUnknownCharacters)!\n            XCTAssertEqual(writtenData, expectedData)\n        } else {\n            XCTFail(\"no inbound data available\")\n        }\n\n        try channel.pipeline.assertDoesNotContain(handler: handler)\n        XCTAssertTrue(try channel.finish().isClean)\n    }\n\n    func assertIncompleteInput(clientHello: String) throws {\n        let buffer = bufferForBase64String(string: clientHello)\n        let channel = EmbeddedChannel()\n        let loop = channel.eventLoop as! EmbeddedEventLoop\n\n        let handler = ByteToMessageHandler(\n            SNIHandler { result in\n                XCTFail(\"Handler was called\")\n                return loop.makeSucceededFuture(())\n            }\n        )\n\n        try channel.pipeline.syncOperations.addHandler(handler)\n\n        // Ok, let's go.\n        try channel.writeInbound(buffer)\n        loop.run()\n\n        // The callback should not have fired, the handler should still be in the pipeline,\n        // and no data should have been written.\n        XCTAssertNoThrow(XCTAssertNil(try channel.readInbound(as: ByteBuffer.self)))\n        try channel.pipeline.assertContains(handler: handler)\n\n        XCTAssertNoThrow(try channel.finish())\n    }\n\n    func testLibre227NoSNIDripFeed() throws {\n        try dripFeedHello(clientHello: libressl227HelloNoSNI, expectedResult: .fallback)\n    }\n\n    func testLibre227WithSNIDripFeed() throws {\n        try dripFeedHello(clientHello: libressl227HelloWithSNI, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testOpenSSL102NoSNIDripFeed() throws {\n        try dripFeedHello(clientHello: openssl102HelloNoSNI, expectedResult: .fallback)\n    }\n\n    func testOpenSSL102WithSNIDripFeed() throws {\n        try dripFeedHello(clientHello: openssl102HelloWithSNI, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testCurlSecureTransportDripFeed() throws {\n        try dripFeedHello(clientHello: curlWithSecureTransport, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testSafariDripFeed() throws {\n        try dripFeedHello(clientHello: safariWithSecureTransport, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testChromeDripFeed() throws {\n        try dripFeedHello(clientHello: chromeWithBoringSSL, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testFirefoxDripFeed() throws {\n        try dripFeedHello(clientHello: firefoxWithNSS, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testLibre227NoSNIBlast() throws {\n        try blastHello(clientHello: libressl227HelloNoSNI, expectedResult: .fallback)\n    }\n\n    func testLibre227WithSNIBlast() throws {\n        try blastHello(clientHello: libressl227HelloWithSNI, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testOpenSSL102NoSNIBlast() throws {\n        try blastHello(clientHello: openssl102HelloNoSNI, expectedResult: .fallback)\n    }\n\n    func testOpenSSL102WithSNIBlast() throws {\n        try blastHello(clientHello: openssl102HelloWithSNI, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testCurlSecureTransportBlast() throws {\n        try blastHello(clientHello: curlWithSecureTransport, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testSafariBlast() throws {\n        try blastHello(clientHello: safariWithSecureTransport, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testChromeBlast() throws {\n        try blastHello(clientHello: chromeWithBoringSSL, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testFirefoxBlast() throws {\n        try blastHello(clientHello: firefoxWithNSS, expectedResult: .hostname(\"httpbin.org\"))\n    }\n\n    func testIgnoresUnknownRecordTypes() throws {\n        try blastHello(clientHello: alertFatalInternalError, expectedResult: .fallback)\n    }\n\n    func testIgnoresUnknownTlsVersions() throws {\n        try blastHello(clientHello: invalidTlsVersion, expectedResult: .fallback)\n    }\n\n    func testIgnoresNonClientHelloHandshakeMessages() throws {\n        try blastHello(clientHello: clientKeyExchange, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidHandshakeLength() throws {\n        try blastHello(clientHello: invalidHandshakeLength, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidCipherSuiteLength() throws {\n        try blastHello(clientHello: invalidCipherSuitesLength, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidCompressionLength() throws {\n        try blastHello(clientHello: invalidCompressionLength, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidExtensionLength() throws {\n        try blastHello(clientHello: invalidExtensionLength, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidIndividualExtensionLength() throws {\n        try blastHello(clientHello: invalidIndividualExtensionLength, expectedResult: .fallback)\n    }\n\n    func testIgnoresUnknownNameType() throws {\n        try blastHello(clientHello: unknownNameType, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidNameLength() throws {\n        try blastHello(clientHello: invalidNameLength, expectedResult: .fallback)\n    }\n\n    func testIgnoresInvalidNameExtensionLength() throws {\n        try blastHello(clientHello: invalidNameExtensionLength, expectedResult: .fallback)\n    }\n\n    func testLudicrouslyTruncatedPacket() throws {\n        try blastHello(clientHello: ludicrouslyTruncatedPacket, expectedResult: .fallback)\n    }\n\n    func testFuzzingInputOne() throws {\n        try assertIncompleteInput(clientHello: fuzzingInputOne)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTestUtilsTests/ByteToMessageDecoderVerifierTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOPosix\nimport NIOTestUtils\nimport XCTest\n\n@testable import NIOCore\n\ntypealias VerificationError = ByteToMessageDecoderVerifier.VerificationError<String>\n\nclass ByteToMessageDecoderVerifierTest: XCTestCase {\n    func testWrongResults() {\n        struct AlwaysProduceY: ByteToMessageDecoder {\n            typealias InboundOut = String\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                buffer.moveReaderIndex(to: buffer.writerIndex)\n                context.fireChannelRead(Self.wrapInboundOut(\"Y\"))\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                while try self.decode(context: context, buffer: &buffer) == .continue {}\n                return .needMoreData\n            }\n        }\n\n        XCTAssertThrowsError(\n            try ByteToMessageDecoderVerifier.verifyDecoder(\n                stringInputOutputPairs: [(\"x\", [\"x\"])],\n                decoderFactory: AlwaysProduceY.init\n            )\n        ) {\n            error in\n            switch error {\n            case let error as VerificationError:\n                XCTAssertEqual(1, error.inputs.count)\n                switch error.errorCode {\n                case .wrongProduction(let actual, let expected):\n                    XCTAssertEqual(\"Y\", actual)\n                    XCTAssertEqual(\"x\", expected)\n                default:\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testNoOutputWhenWeShouldHaveOutput() {\n        struct NeverProduce: ByteToMessageDecoder {\n            typealias InboundOut = String\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                buffer.moveReaderIndex(to: buffer.writerIndex)\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                while try self.decode(context: context, buffer: &buffer) == .continue {}\n                return .needMoreData\n            }\n        }\n\n        XCTAssertThrowsError(\n            try ByteToMessageDecoderVerifier.verifyDecoder(\n                stringInputOutputPairs: [(\"x\", [\"x\"])],\n                decoderFactory: NeverProduce.init\n            )\n        ) {\n            error in\n            switch error {\n            case let error as VerificationError:\n                XCTAssertEqual(1, error.inputs.count)\n                switch error.errorCode {\n                case .underProduction(let expected):\n                    XCTAssertEqual(\"x\", expected)\n                default:\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testOutputWhenWeShouldNotProduceOutput() {\n        struct ProduceTooEarly: ByteToMessageDecoder {\n            typealias InboundOut = String\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                context.fireChannelRead(Self.wrapInboundOut(\"Y\"))\n                return .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                while try self.decode(context: context, buffer: &buffer) == .continue {}\n                return .needMoreData\n            }\n        }\n\n        XCTAssertThrowsError(\n            try ByteToMessageDecoderVerifier.verifyDecoder(\n                stringInputOutputPairs: [(\"xxxxxx\", [\"Y\"])],\n                decoderFactory: ProduceTooEarly.init\n            )\n        ) {\n            error in\n            switch error {\n            case let error as VerificationError:\n                switch error.errorCode {\n                case .overProduction(let actual):\n                    XCTAssertEqual(\"Y\", actual)\n                default:\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n\n    func testLeftovers() {\n        struct NeverDoAnything: ByteToMessageDecoder {\n            typealias InboundOut = String\n\n            func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {\n                .needMoreData\n            }\n\n            func decodeLast(\n                context: ChannelHandlerContext,\n                buffer: inout ByteBuffer,\n                seenEOF: Bool\n            ) throws -> DecodingState {\n                while try self.decode(context: context, buffer: &buffer) == .continue {}\n                if buffer.readableBytes > 0 {\n                    context.fireChannelRead(Self.wrapInboundOut(\"leftover\"))\n                }\n                return .needMoreData\n            }\n        }\n\n        XCTAssertThrowsError(\n            try ByteToMessageDecoderVerifier.verifyDecoder(\n                stringInputOutputPairs: [(\"xxxxxx\", [])],\n                decoderFactory: NeverDoAnything.init\n            )\n        ) {\n            error in\n            switch error {\n            case let error as VerificationError:\n                switch error.errorCode {\n                case .leftOversOnDeconstructingChannel(\n                    let inbound,\n                    let outbound,\n                    pendingOutbound: let pending\n                ):\n                    XCTAssertEqual(0, outbound.count)\n                    XCTAssertEqual([\"leftover\"], inbound.map { $0.tryAs(type: String.self) })\n                    XCTAssertEqual(0, pending.count)\n                default:\n                    XCTFail(\"unexpected error: \\(error)\")\n                }\n            default:\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTestUtilsTests/EventCounterHandlerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOTestUtils\nimport XCTest\n\nclass EventCounterHandlerTest: XCTestCase {\n    private var channel: EmbeddedChannel!\n    private var handler: EventCounterHandler!\n\n    override func setUp() {\n        self.handler = EventCounterHandler()\n        self.channel = EmbeddedChannel(handler: self.handler)\n    }\n\n    override func tearDown() {\n        self.handler = nil\n        XCTAssertNoThrow(try self.channel?.finish())\n        self.channel = nil\n    }\n\n    func testNothingButEmbeddedChannelInit() {\n        // EmbeddedChannel calls register\n        XCTAssertEqual([\"channelRegistered\", \"register\"], self.handler.allTriggeredEvents())\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.channelRegisteredCalls)\n        XCTAssertEqual(1, self.handler.registerCalls)\n    }\n\n    func testNothing() {\n        let handler = EventCounterHandler()\n        XCTAssertNoThrow(try self.channel.pipeline.addHandler(handler).wait())\n        XCTAssertEqual([], handler.allTriggeredEvents())\n        XCTAssertNoThrow(try handler.checkValidity())\n    }\n\n    func testInboundWrite() {\n        XCTAssertNoThrow(try self.channel.writeInbound(()))\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"channelRead\", \"channelReadComplete\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.channelRegisteredCalls)\n        XCTAssertEqual(1, self.handler.registerCalls)\n        XCTAssertEqual(1, self.handler.channelReadCalls)\n        XCTAssertEqual(1, self.handler.channelReadCompleteCalls)\n    }\n\n    func testOutboundWrite() {\n        XCTAssertNoThrow(try self.channel.writeOutbound(()))\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"write\", \"flush\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.channelRegisteredCalls)\n        XCTAssertEqual(1, self.handler.registerCalls)\n        XCTAssertEqual(1, self.handler.writeCalls)\n        XCTAssertEqual(1, self.handler.flushCalls)\n    }\n\n    func testConnectChannel() {\n        XCTAssertNoThrow(try self.channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"connect\", \"channelActive\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.channelRegisteredCalls)\n        XCTAssertEqual(1, self.handler.registerCalls)\n        XCTAssertEqual(1, self.handler.connectCalls)\n        XCTAssertEqual(1, self.handler.channelActiveCalls)\n    }\n\n    func testBindChannel() {\n        XCTAssertNoThrow(try self.channel.bind(to: .init(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"bind\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.channelRegisteredCalls)\n        XCTAssertEqual(1, self.handler.registerCalls)\n        XCTAssertEqual(1, self.handler.bindCalls)\n    }\n\n    func testConnectAndCloseChannel() {\n        XCTAssertNoThrow(try self.channel.connect(to: .init(ipAddress: \"1.2.3.4\", port: 5678)).wait())\n        XCTAssertNoThrow(try self.channel.close().wait())\n        XCTAssertEqual(\n            [\n                \"channelRegistered\", \"register\", \"connect\", \"channelActive\", \"close\", \"channelInactive\",\n                \"channelUnregistered\",\n            ],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.channelRegisteredCalls)\n        XCTAssertEqual(1, self.handler.registerCalls)\n        XCTAssertEqual(1, self.handler.connectCalls)\n        XCTAssertEqual(1, self.handler.channelActiveCalls)\n        XCTAssertEqual(1, self.handler.channelInactiveCalls)\n        XCTAssertEqual(1, self.handler.closeCalls)\n        XCTAssertEqual(1, self.handler.channelUnregisteredCalls)\n\n        self.channel = nil  // don't let tearDown close it\n    }\n\n    func testError() {\n        struct Dummy: Error {}\n        self.channel.pipeline.fireErrorCaught(Dummy())\n\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"errorCaught\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.errorCaughtCalls)\n\n        XCTAssertThrowsError(try self.channel.throwIfErrorCaught())\n    }\n\n    func testEventsWithoutArguments() {\n        let noArgEvents: [((ChannelPipeline) -> () -> Void, String)] = [\n            (ChannelPipeline.fireChannelRegistered, \"channelRegistered\"),\n            (ChannelPipeline.fireChannelUnregistered, \"channelUnregistered\"),\n            (ChannelPipeline.fireChannelActive, \"channelActive\"),\n            (ChannelPipeline.fireChannelInactive, \"channelInactive\"),\n            (ChannelPipeline.fireChannelReadComplete, \"channelReadComplete\"),\n            (ChannelPipeline.fireChannelWritabilityChanged, \"channelWritabilityChanged\"),\n            (ChannelPipeline.flush, \"flush\"),\n            (ChannelPipeline.read, \"read\"),\n        ]\n\n        for (fire, name) in noArgEvents {\n            let channel = EmbeddedChannel()\n            defer {\n                XCTAssertNoThrow(try channel.finish())\n            }\n            let handler = EventCounterHandler()\n\n            XCTAssertNoThrow(try channel.pipeline.addHandler(handler).wait())\n            XCTAssertEqual([], handler.allTriggeredEvents())\n            fire(channel.pipeline)()\n            XCTAssertEqual([name], handler.allTriggeredEvents())\n        }\n    }\n\n    func testInboundUserEvent() {\n        self.channel.pipeline.fireUserInboundEventTriggered(())\n\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"userInboundEventTriggered\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.userInboundEventTriggeredCalls)\n    }\n\n    func testOutboundUserEvent() {\n        self.channel.pipeline.triggerUserOutboundEvent((), promise: nil)\n\n        XCTAssertEqual(\n            [\"channelRegistered\", \"register\", \"triggerUserOutboundEvent\"],\n            self.handler.allTriggeredEvents()\n        )\n        XCTAssertNoThrow(try self.handler.checkValidity())\n        XCTAssertEqual(1, self.handler.triggerUserOutboundEventCalls)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTestUtilsTests/ManualTaskExecutorTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOTestUtils\nimport Synchronization\nimport XCTest\n\nclass ManualTaskExecutorTest: XCTestCase {\n    @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n    func testManualTaskExecutor() async {\n        await withDiscardingTaskGroup { group in\n            await withManualTaskExecutor { taskExecutor in\n                let taskDidRun = Mutex(false)\n\n                group.addTask(executorPreference: taskExecutor) {\n                    taskDidRun.withLock { $0 = true }\n                }\n\n                // Run task\n                XCTAssertFalse(taskDidRun.withLock { $0 })\n                taskExecutor.runUntilQueueIsEmpty()\n                XCTAssertTrue(taskDidRun.withLock { $0 })\n            }\n        }\n    }\n\n    @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)\n    func testTwoManualTaskExecutors() async {\n        await withDiscardingTaskGroup { group in\n            await withManualTaskExecutors { taskExecutor1, taskExecutor2 in\n                let task1DidRun = Mutex(false)\n                let task2DidRun = Mutex(false)\n\n                group.addTask(executorPreference: taskExecutor1) {\n                    task1DidRun.withLock { $0 = true }\n                }\n\n                group.addTask(executorPreference: taskExecutor2) {\n                    task2DidRun.withLock { $0 = true }\n                }\n\n                // Run task 1\n                XCTAssertFalse(task1DidRun.withLock { $0 })\n                taskExecutor1.runUntilQueueIsEmpty()\n                XCTAssertTrue(task1DidRun.withLock { $0 })\n\n                // Run task 2\n                XCTAssertFalse(task2DidRun.withLock { $0 })\n                taskExecutor2.runUntilQueueIsEmpty()\n                XCTAssertTrue(task2DidRun.withLock { $0 })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTestUtilsTests/NIOHTTP1TestServerTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOHTTP1\nimport NIOPosix\nimport NIOTestUtils\nimport XCTest\n\ntypealias SendableRequestPart = HTTPPart<HTTPRequestHead, ByteBuffer>\n\nextension HTTPClientRequestPart {\n    init(_ target: SendableRequestPart) {\n        switch target {\n        case .head(let head):\n            self = .head(head)\n        case .body(let body):\n            self = .body(.byteBuffer(body))\n        case .end(let end):\n            self = .end(end)\n        }\n    }\n}\n\nextension SendableRequestPart {\n    init(_ target: HTTPClientRequestPart) throws {\n        switch target {\n        case .head(let head):\n            self = .head(head)\n        case .body(.byteBuffer(let body)):\n            self = .body(body)\n        case .body(.fileRegion):\n            throw NIOHTTP1TestServerError(\n                reason: \"FileRegion is not Sendable and cannot be passed across concurrency domains\"\n            )\n        case .end(let end):\n            self = .end(end)\n        }\n    }\n}\n\n/// A helper handler to transform a Sendable request into a\n/// non-Sendable one, to manage warnings.\nprivate final class TransformerHandler: ChannelOutboundHandler {\n    typealias OutboundIn = SendableRequestPart\n    typealias OutboundOut = HTTPClientRequestPart\n\n    func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {\n        let response = self.unwrapOutboundIn(data)\n        context.write(self.wrapOutboundOut(.init(response)), promise: nil)\n    }\n}\n\nclass NIOHTTP1TestServerTest: XCTestCase {\n    private var group: EventLoopGroup!\n    private let allocator = ByteBufferAllocator()\n\n    override func setUp() {\n        self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.group.syncShutdownGracefully())\n        self.group = nil\n    }\n\n    func connect(serverPort: Int, responsePromise: EventLoopPromise<String>) throws -> EventLoopFuture<Channel> {\n        let bootstrap = ClientBootstrap(group: self.group)\n            .channelOption(.socketOption(.so_reuseaddr), value: 1)\n            .channelInitializer { channel in\n                channel.eventLoop.makeCompletedFuture {\n                    let sync = channel.pipeline.syncOperations\n                    try sync.addHTTPClientHandlers(position: .first, leftOverBytesStrategy: .fireError)\n                    try sync.addHandler(AggregateBodyHandler())\n                    try sync.addHandler(TestHTTPHandler(responsePromise: responsePromise))\n                    try sync.addHandler(TransformerHandler())\n                }\n            }\n        return bootstrap.connect(host: \"127.0.0.1\", port: serverPort)\n    }\n\n    private func sendRequest(channel: Channel, uri: String, message: String) {\n        let requestBuffer = allocator.buffer(string: message)\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        headers.add(name: \"Content-Length\", value: \"\\(requestBuffer.readableBytes)\")\n\n        let requestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: uri,\n            headers: headers\n        )\n\n        channel.write(SendableRequestPart.head(requestHead), promise: nil)\n        channel.write(SendableRequestPart.body(requestBuffer), promise: nil)\n        channel.writeAndFlush(SendableRequestPart.end(nil), promise: nil)\n    }\n\n    private func sendRequestTo(_ url: URL, body: String) throws -> EventLoopFuture<String> {\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        let channel = try connect(serverPort: url.port!, responsePromise: responsePromise).wait()\n        sendRequest(channel: channel, uri: url.path, message: body)\n        return responsePromise.futureResult\n    }\n\n    func testTheExampleInTheDocs() {\n        // Setup the test environment.\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        let allocator = ByteBufferAllocator()\n        let testServer = NIOHTTP1TestServer(group: group)\n        defer {\n            XCTAssertNoThrow(try testServer.stop())\n            XCTAssertNoThrow(try group.syncShutdownGracefully())\n        }\n\n        // Use your library to send a request to the server.\n        let requestBody = \"ping\"\n        var requestComplete: EventLoopFuture<String>!\n        XCTAssertNoThrow(\n            requestComplete = try sendRequestTo(\n                URL(string: \"http://127.0.0.1:\\(testServer.serverPort)/some-route\")!,\n                body: requestBody\n            )\n        )\n\n        // Assert the server received the expected request.\n        // Use custom methods if you only want some specific assertions on part\n        // of the request.\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                .head(\n                    .init(\n                        version: .http1_1,\n                        method: .GET,\n                        uri: \"/some-route\",\n                        headers: .init([\n                            (\"Content-Type\", \"text/plain; charset=utf-8\"),\n                            (\"Content-Length\", \"4\"),\n                        ])\n                    )\n                ),\n                try testServer.readInbound()\n            )\n        )\n        var requestBuffer = allocator.buffer(capacity: 128)\n        requestBuffer.writeString(requestBody)\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                .body(requestBuffer),\n                try testServer.readInbound()\n            )\n        )\n        XCTAssertNoThrow(\n            XCTAssertEqual(\n                .end(nil),\n                try testServer.readInbound()\n            )\n        )\n\n        // Make the server send a response to the client.\n        let responseBody = \"pong\"\n        var responseBuffer = allocator.buffer(capacity: 128)\n        responseBuffer.writeString(responseBody)\n        XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.body(.byteBuffer(responseBuffer))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n\n        // Assert that the client received the response from the server.\n        XCTAssertNoThrow(XCTAssertEqual(responseBody, try requestComplete.wait()))\n    }\n\n    func testSimpleRequest() {\n        let uri = \"/request\"\n        let requestMessage = \"request message\"\n        let responseMessage = \"response message\"\n        let testServer = NIOHTTP1TestServer(group: self.group)\n        defer {\n            XCTAssertNoThrow(try testServer.stop())\n        }\n\n        // Establish the connection and send the request\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        var channel: Channel!\n        XCTAssertNoThrow(\n            channel = try self.connect(serverPort: testServer.serverPort, responsePromise: responsePromise).wait()\n        )\n\n        // Send a request to the server\n        self.sendRequest(channel: channel, uri: uri, message: requestMessage)\n        let response = responsePromise.futureResult\n\n        // Assert we received the expected request\n        XCTAssertNoThrow(try testServer.readInbound().assertHead(expectedURI: uri))\n        XCTAssertNoThrow(try testServer.readInbound().assertBody(expectedMessage: requestMessage))\n        XCTAssertNoThrow(try testServer.readInbound().assertEnd())\n\n        // Send the response to the client\n        let responseBuffer = allocator.buffer(string: responseMessage)\n        XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.body(.byteBuffer(responseBuffer))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n\n        // Verify that the client got what the server sent\n        XCTAssertNoThrow(XCTAssertEqual(responseMessage, try response.wait()))\n    }\n\n    func testConcurrentRequests() {\n        let testServer = NIOHTTP1TestServer(group: self.group)\n        defer {\n            XCTAssertNoThrow(try testServer.stop())\n        }\n\n        // Establish two \"concurrent\" requests\n        let request1URI = \"/request1\"\n        let request1Message = \"Request #1\"\n        let response1Promise = self.group.next().makePromise(of: String.self)\n        var channel1: Channel!\n        XCTAssertNoThrow(\n            channel1 = try self.connect(serverPort: testServer.serverPort, responsePromise: response1Promise).wait()\n        )\n\n        let request2URI = \"/request2\"\n        let request2Message = \"Request #2\"\n        let response2Promise = self.group.next().makePromise(of: String.self)\n        var channel2: Channel!\n        XCTAssertNoThrow(\n            channel2 = try self.connect(serverPort: testServer.serverPort, responsePromise: response2Promise).wait()\n        )\n\n        // Both channels are connected to the server. Request on `channel1`\n        // connected connection first so `testServer` will handle it completely\n        // before moving on to the request on `channel2`.\n\n        // Send a request to the server using the second channel (Accepted but the server is not handling it)\n        self.sendRequest(channel: channel2, uri: request2URI, message: request2Message)\n\n        // Check that nothing happened. The server is blocked waiting for the first\n        // request to complete so it times out and throws when we try to read from it\n        // before the first request completes.\n        XCTAssertThrowsError(try testServer.readInbound(deadline: .now() + .milliseconds(5)))\n\n        // Send a request to the server using the second channel (Currently handled by the server)\n        self.sendRequest(channel: channel1, uri: request1URI, message: request1Message)\n\n        // Assert we received the expected request from client1\n        XCTAssertNoThrow(try testServer.readInbound().assertHead(expectedURI: request1URI))\n        XCTAssertNoThrow(try testServer.readInbound().assertBody(expectedMessage: request1Message))\n        XCTAssertNoThrow(try testServer.readInbound().assertEnd())\n\n        // Send the response to client1\n        let response1Message = \"Response #1\"\n        let response1Buffer = allocator.buffer(string: response1Message)\n        XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.body(.byteBuffer(response1Buffer))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n\n        // Assert we received the expected request from client2\n        XCTAssertNoThrow(try testServer.readInbound().assertHead(expectedURI: request2URI))\n        XCTAssertNoThrow(try testServer.readInbound().assertBody(expectedMessage: request2Message))\n        XCTAssertNoThrow(try testServer.readInbound().assertEnd())\n\n        // Send the response to client2\n        let response2Message = \"Response #2\"\n        let response2Buffer = allocator.buffer(string: response2Message)\n        XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.body(.byteBuffer(response2Buffer))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n\n        // Verify that the each client got their own response\n        XCTAssertNoThrow(XCTAssertEqual(response1Message, try response1Promise.futureResult.wait()))\n        XCTAssertNoThrow(XCTAssertEqual(response2Message, try response2Promise.futureResult.wait()))\n    }\n\n    func testTestWebServerCanBeReleased() {\n        weak var weakTestServer: NIOHTTP1TestServer? = nil\n        func doIt() {\n            let testServer = NIOHTTP1TestServer(group: self.group)\n            weakTestServer = testServer\n            XCTAssertNoThrow(try testServer.stop())\n        }\n        doIt()\n        assert(weakTestServer == nil, within: .milliseconds(500))\n    }\n\n    func testStopClosesAcceptedChannel() {\n        let testServer = NIOHTTP1TestServer(group: self.group)\n\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        var channel: Channel!\n        XCTAssertNoThrow(\n            channel = try self.connect(\n                serverPort: testServer.serverPort,\n                responsePromise: responsePromise\n            ).wait()\n        )\n        self.sendRequest(channel: channel, uri: \"/uri\", message: \"hello\")\n\n        XCTAssertNoThrow(try testServer.readInbound().assertHead(expectedURI: \"/uri\"))\n        XCTAssertNoThrow(try testServer.readInbound().assertBody(expectedMessage: \"hello\"))\n        XCTAssertNoThrow(try testServer.readInbound().assertEnd())\n\n        XCTAssertNoThrow(try testServer.stop())\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n    }\n\n    func testReceiveAndVerify() {\n        let testServer = NIOHTTP1TestServer(group: self.group)\n\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        var channel: Channel!\n        XCTAssertNoThrow(\n            channel = try self.connect(\n                serverPort: testServer.serverPort,\n                responsePromise: responsePromise\n            ).wait()\n        )\n        self.sendRequest(channel: channel, uri: \"/uri\", message: \"hello\")\n\n        XCTAssertNoThrow(\n            try testServer.receiveHeadAndVerify { head in\n                XCTAssertEqual(head.uri, \"/uri\")\n            }\n        )\n\n        XCTAssertNoThrow(\n            try testServer.receiveBodyAndVerify { buffer in\n                XCTAssertEqual(buffer, ByteBuffer(string: \"hello\"))\n            }\n        )\n\n        XCTAssertNoThrow(\n            try testServer.receiveEndAndVerify { trailers in\n                XCTAssertNil(trailers)\n            }\n        )\n\n        XCTAssertNoThrow(try testServer.stop())\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n    }\n\n    func testReceive() throws {\n        let testServer = NIOHTTP1TestServer(group: self.group)\n\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        var channel: Channel!\n        XCTAssertNoThrow(\n            channel = try self.connect(\n                serverPort: testServer.serverPort,\n                responsePromise: responsePromise\n            ).wait()\n        )\n        self.sendRequest(channel: channel, uri: \"/uri\", message: \"hello\")\n\n        let head = try assertNoThrowWithValue(try testServer.receiveHead())\n        XCTAssertEqual(head.uri, \"/uri\")\n\n        let body = try assertNoThrowWithValue(try testServer.receiveBody())\n        XCTAssertEqual(body, ByteBuffer(string: \"hello\"))\n\n        let trailers = try assertNoThrowWithValue(try testServer.receiveEnd())\n        XCTAssertNil(trailers)\n\n        XCTAssertNoThrow(try testServer.stop())\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n    }\n\n    func testReceiveAndVerifyWrongPart() {\n        let testServer = NIOHTTP1TestServer(group: self.group)\n\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        var channel: Channel!\n        XCTAssertNoThrow(\n            channel = try self.connect(\n                serverPort: testServer.serverPort,\n                responsePromise: responsePromise\n            ).wait()\n        )\n        self.sendRequest(channel: channel, uri: \"/uri\", message: \"hello\")\n\n        XCTAssertThrowsError(try testServer.receiveEndAndVerify()) { error in\n            XCTAssert(error is NIOHTTP1TestServerError)\n        }\n\n        XCTAssertThrowsError(try testServer.receiveHeadAndVerify()) { error in\n            XCTAssert(error is NIOHTTP1TestServerError)\n        }\n\n        XCTAssertThrowsError(try testServer.receiveBodyAndVerify()) { error in\n            XCTAssert(error is NIOHTTP1TestServerError)\n        }\n\n        XCTAssertNoThrow(try testServer.stop())\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n    }\n\n    func testReceiveBodyWithoutAggregation() {\n        let testServer = NIOHTTP1TestServer(group: self.group, aggregateBody: false)\n\n        let responsePromise = self.group.next().makePromise(of: String.self)\n        var channel: Channel!\n        XCTAssertNoThrow(\n            channel = try self.connect(\n                serverPort: testServer.serverPort,\n                responsePromise: responsePromise\n            ).wait()\n        )\n\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        let requestHead = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/uri\", headers: headers)\n        channel.writeAndFlush(SendableRequestPart.head(requestHead), promise: nil)\n        XCTAssertNoThrow(\n            try testServer.receiveHeadAndVerify { head in\n                XCTAssertEqual(head.uri, \"/uri\")\n                XCTAssertEqual(head.headers[\"Content-Type\"], [\"text/plain; charset=utf-8\"])\n            }\n        )\n        XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n\n        for _ in 0..<10 {\n            channel.writeAndFlush(\n                SendableRequestPart.body(ByteBuffer(string: \"ping\")),\n                promise: nil\n            )\n            XCTAssertNoThrow(\n                try testServer.receiveBodyAndVerify { buffer in\n                    XCTAssertEqual(String(buffer: buffer), \"ping\")\n                }\n            )\n            XCTAssertNoThrow(try testServer.writeOutbound(.body(.byteBuffer(ByteBuffer(string: \"pong\")))))\n        }\n\n        channel.writeAndFlush(SendableRequestPart.end(nil), promise: nil)\n        XCTAssertNoThrow(\n            try testServer.receiveEndAndVerify { trailers in\n                XCTAssertNil(trailers)\n            }\n        )\n        XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n\n        XCTAssertNoThrow(try testServer.stop())\n        XCTAssertNotNil(channel)\n        XCTAssertNoThrow(try channel.closeFuture.wait())\n    }\n\n    func testCloseChannelWhileItIsWaiting() throws {\n        let testServer = NIOHTTP1TestServer(group: self.group, aggregateBody: false)\n        let firstResponsePromise = self.group.next().makePromise(of: String.self)\n        let firstChannel = try self.connect(serverPort: testServer.serverPort, responsePromise: firstResponsePromise)\n            .wait()\n\n        // Send a request head and wait for it to be sent, and received at the test server so we know the connection is well underway.\n        let requestHead = HTTPRequestHead(version: .http1_1, method: .POST, uri: \"/uri\")\n        firstChannel.writeAndFlush(SendableRequestPart.head(requestHead), promise: nil)\n        XCTAssertNoThrow(\n            try testServer.receiveHeadAndVerify { head in\n                XCTAssertEqual(head.uri, \"/uri\")\n            }\n        )\n\n        // Create a second channel now.\n        let secondResponsePromise = self.group.next().makePromise(of: String.self)\n        let secondChannel = try self.connect(serverPort: testServer.serverPort, responsePromise: secondResponsePromise)\n            .wait()\n\n        // To burn a little time and convince ourselves that things are going fairly well, we can send a body payload on the first channel\n        // and confirm it comes through.\n        firstChannel.writeAndFlush(\n            SendableRequestPart.body(ByteBuffer(string: \"ping\")),\n            promise: nil\n        )\n        XCTAssertNoThrow(\n            try testServer.receiveBodyAndVerify { buffer in\n                XCTAssertEqual(String(buffer: buffer), \"ping\")\n            }\n        )\n\n        // Now, close the second channel.\n        try secondChannel.close().wait()\n\n        // Now we can complete the transaction.\n        firstChannel.writeAndFlush(SendableRequestPart.end(nil), promise: nil)\n        XCTAssertNoThrow(\n            try testServer.receiveEndAndVerify { trailers in\n                XCTAssertNil(trailers)\n            }\n        )\n        XCTAssertNoThrow(try testServer.writeOutbound(.head(.init(version: .http1_1, status: .ok))))\n        XCTAssertNoThrow(try testServer.writeOutbound(.end(nil)))\n\n        // The promise for the second should error.\n        XCTAssertThrowsError(try secondResponsePromise.futureResult.wait())\n    }\n}\n\nprivate final class TestHTTPHandler: ChannelInboundHandler {\n    public typealias InboundIn = HTTPClientResponsePart\n    public typealias OutboundOut = HTTPClientRequestPart\n\n    private let responsePromise: EventLoopPromise<String>\n\n    init(responsePromise: EventLoopPromise<String>) {\n        self.responsePromise = responsePromise\n    }\n\n    public func handlerRemoved(context: ChannelHandlerContext) {\n        struct HandlerRemovedBeforeReceivingFullRequestError: Error {}\n        self.responsePromise.fail(HandlerRemovedBeforeReceivingFullRequestError())\n    }\n\n    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch Self.unwrapInboundIn(data) {\n        case .head(let responseHead):\n            guard case .ok = responseHead.status else {\n                self.responsePromise.fail(ResponseError.badStatus)\n                return\n            }\n        case .body(let byteBuffer):\n            // We're using AggregateBodyHandler so we see all the body content at once\n            let string = String(buffer: byteBuffer)\n            self.responsePromise.succeed(string)\n        case .end:\n            context.close(promise: nil)\n        }\n    }\n\n    public func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.responsePromise.fail(error)\n        context.close(promise: nil)\n    }\n}\n\nextension HTTPServerRequestPart {\n    func assertHead(expectedURI: String, file: StaticString = #filePath, line: UInt = #line) {\n        switch self {\n        case .head(let head):\n            XCTAssertEqual(.GET, head.method)\n            XCTAssertEqual(expectedURI, head.uri)\n            XCTAssertEqual(\"text/plain; charset=utf-8\", head.headers[\"Content-Type\"].first)\n        default:\n            XCTFail(\"Expected head, got \\(self)\", file: (file), line: line)\n        }\n    }\n\n    func assertBody(expectedMessage: String, file: StaticString = #filePath, line: UInt = #line) {\n        switch self {\n        case .body(let buffer):\n            // Note that the test server coalesces the body parts for us.\n            XCTAssertEqual(\n                expectedMessage,\n                String(decoding: buffer.readableBytesView, as: Unicode.UTF8.self)\n            )\n        default:\n            XCTFail(\"Expected body, got \\(self)\", file: (file), line: line)\n        }\n    }\n\n    func assertEnd(file: StaticString = #filePath, line: UInt = #line) {\n        switch self {\n        case .end(_):\n            ()\n        default:\n            XCTFail(\"Expected end, got \\(self)\", file: (file), line: line)\n        }\n    }\n}\n\nprivate final class AggregateBodyHandler: ChannelInboundHandler {\n    typealias InboundIn = HTTPClientResponsePart\n    typealias InboundOut = HTTPClientResponsePart\n\n    var receivedSoFar: ByteBuffer? = nil\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        switch Self.unwrapInboundIn(data) {\n        case .head:\n            context.fireChannelRead(data)\n        case .body(var buffer):\n            self.receivedSoFar.setOrWriteBuffer(&buffer)\n        case .end:\n            if let receivedSoFar = self.receivedSoFar {\n                context.fireChannelRead(Self.wrapInboundOut(.body(receivedSoFar)))\n            }\n            context.fireChannelRead(data)\n        }\n    }\n}\n\nprivate enum ResponseError: Error {\n    case badStatus\n    case missingResponse\n}\n\nfunc assert(\n    _ condition: @autoclosure () -> Bool,\n    within time: TimeAmount,\n    testInterval: TimeAmount? = nil,\n    _ message: String = \"condition not satisfied in time\",\n    file: StaticString = #filePath,\n    line: UInt = #line\n) {\n    let testInterval = testInterval ?? TimeAmount.nanoseconds(time.nanoseconds / 5)\n    let endTime = NIODeadline.now() + time\n\n    repeat {\n        if condition() { return }\n        usleep(UInt32(testInterval.nanoseconds / 1000))\n    } while NIODeadline.now() < endTime\n\n    if !condition() {\n        XCTFail(message, file: (file), line: line)\n    }\n}\n\nfunc assertNoThrowWithValue<T>(\n    _ body: @autoclosure () throws -> T,\n    defaultValue: T? = nil,\n    message: String? = nil,\n    file: StaticString = #filePath,\n    line: UInt = #line\n) throws -> T {\n    do {\n        return try body()\n    } catch {\n        XCTFail(\"\\(message.map { $0 + \": \" } ?? \"\")unexpected error \\(error) thrown\", file: (file), line: line)\n        if let defaultValue = defaultValue {\n            return defaultValue\n        } else {\n            throw error\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/NIOTests/NIOTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIO\nimport XCTest\n\n/// This test suite is focused just on confirming that the umbrella NIO module behaves as expected.\nfinal class NIOTests: XCTestCase {\n    func testCanUseTheVariousNIOTypes() {\n        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)\n        defer {\n            try! group.syncShutdownGracefully()\n        }\n\n        let channel = EmbeddedChannel()\n        XCTAssertNoThrow(try channel.finish())\n\n        let buffer = ByteBuffer()\n        XCTAssertEqual(buffer.readableBytes, 0)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/ByteBufferWebSocketTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOWebSocket\nimport XCTest\n\nfinal class ByteBufferWebSocketTests: XCTestCase {\n    private var buffer = ByteBuffer()\n\n    // MARK: - getWebSocketErrorCode(at:) Tests\n\n    func testGetWebSocketErrorCode_WithValidCode() {\n        let expected = WebSocketErrorCode.protocolError\n        buffer.write(webSocketErrorCode: expected)\n\n        let result = buffer.getWebSocketErrorCode(at: 0)\n        XCTAssertNotNil(result)\n        XCTAssertEqual(result, expected)\n        XCTAssertEqual(buffer.readerIndex, 0, \"get should not mutate readerIndex\")\n    }\n\n    func testGetWebSocketErrorCode_OutOfBoundsIndex() {\n        // Write two codes, but try to get at an index beyond buffer\n        let errorCode = WebSocketErrorCode.policyViolation\n        buffer.write(webSocketErrorCode: errorCode)\n\n        let result = buffer.getWebSocketErrorCode(at: 10)\n        XCTAssertNil(result, \"Should return nil for out-of-bounds index\")\n    }\n\n    func testGetWebSocketErrorCode_EmptyBuffer() {\n        let result = buffer.getWebSocketErrorCode(at: 0)\n        XCTAssertNil(result, \"Should return nil on empty buffer\")\n    }\n\n    func testGetWebSocketErrorCode_RepeatedAccess() {\n        let errorCode = WebSocketErrorCode.goingAway\n        buffer.write(webSocketErrorCode: errorCode)\n\n        let result1 = buffer.getWebSocketErrorCode(at: 0)\n        let result2 = buffer.getWebSocketErrorCode(at: 0)\n        XCTAssertEqual(result1, result2)\n        XCTAssertEqual(buffer.readableBytes, 2)\n        XCTAssertEqual(buffer.readerIndex, 0)\n    }\n\n    // MARK: - write(webSocketErrorCode:) Tests\n\n    func testWriteWebSocketErrorCode() {\n        let errorCode = WebSocketErrorCode.protocolError\n        buffer.write(webSocketErrorCode: errorCode)\n\n        // Should have written 2 bytes (UInt16)\n        XCTAssertEqual(buffer.readableBytes, 2)\n\n        let peeked = buffer.peekWebSocketErrorCode()\n        XCTAssertEqual(peeked, errorCode)\n    }\n\n    // MARK: - readWebSocketErrorCode() Tests\n\n    func testReadWebSocketErrorCode_Valid() {\n        let expected = WebSocketErrorCode.policyViolation\n        buffer.write(webSocketErrorCode: expected)\n\n        let result = buffer.readWebSocketErrorCode()\n        XCTAssertNotNil(result)\n        XCTAssertEqual(result, expected, \"readWebSocketErrorCode should decode the correct code\")\n        XCTAssertEqual(buffer.readableBytes, 0, \"Buffer should be consumed after reading\")\n    }\n\n    func testReadWebSocketErrorCode_NotEnoughBytes() {\n        // Write 1 byte\n        buffer.writeInteger(UInt8(0x02))\n        let result = buffer.readWebSocketErrorCode()\n        XCTAssertNil(result, \"Should return nil if insufficient bytes\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"Reader index should not move if read fails\")\n    }\n\n    func testPeekThenReadConsistency() {\n        let errorCode = WebSocketErrorCode.goingAway\n        buffer.write(webSocketErrorCode: errorCode)\n\n        // Peek first\n        let peeked = buffer.peekWebSocketErrorCode()\n        XCTAssertEqual(peeked, errorCode)\n\n        // Then read\n        let read = buffer.readWebSocketErrorCode()\n        XCTAssertEqual(read, errorCode)\n\n        // After read peeking again should fail\n        let afterRead = buffer.peekWebSocketErrorCode()\n        XCTAssertNil(afterRead)\n    }\n\n    func testMultipleWritesAndReads() {\n        let errorCodes: [WebSocketErrorCode] = [.goingAway, .unacceptableData, .protocolError]\n        for errorCode in errorCodes {\n            buffer.write(webSocketErrorCode: errorCode)\n        }\n\n        // Peek each one before reading to verify\n        for (index, expected) in errorCodes.enumerated() {\n            let offset = index * 2\n            let peeked = buffer.getWebSocketErrorCode(at: buffer.readerIndex + offset)\n            XCTAssertEqual(peeked, expected)\n        }\n\n        for expected in errorCodes {\n            let read = buffer.readWebSocketErrorCode()\n            XCTAssertEqual(read, expected)\n        }\n\n        XCTAssertEqual(buffer.readableBytes, 0, \"Buffer should be fully consumed\")\n    }\n\n    // MARK: - peekWebSocketErrorCode() Tests\n\n    func testPeekWebSocketErrorCode_Normal() {\n        var buffer = ByteBuffer()\n        let errorCode = WebSocketErrorCode(codeNumber: 1002)\n        buffer.write(webSocketErrorCode: errorCode)\n\n        guard let webSocketCode = buffer.peekWebSocketErrorCode() else {\n            XCTFail(\"Expected to read a valid WebSocketErrorCode.\")\n            return\n        }\n        XCTAssertEqual(webSocketCode, errorCode, \"Should match the written error code.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekWebSocketErrorCode() should not advance the reader index.\")\n    }\n\n    func testPeekWebSocketErrorCode_NotEnoughBytes() {\n        var buffer = ByteBuffer()\n        // Only write a single byte, insufficient for a UInt16.\n        buffer.writeInteger(UInt8(0x03))\n        let code = buffer.peekWebSocketErrorCode()\n        XCTAssertNil(code, \"Should return nil if not enough bytes to form an error code.\")\n    }\n\n    func testPeekWebSocketErrorCode_Repeated() {\n        var buffer = ByteBuffer()\n        let errorCode = WebSocketErrorCode(codeNumber: 1011)\n        buffer.write(webSocketErrorCode: errorCode)\n\n        let firstPeek = buffer.peekWebSocketErrorCode()\n        let secondPeek = buffer.peekWebSocketErrorCode()\n        XCTAssertEqual(firstPeek, secondPeek, \"Repeated peeks should yield the same code.\")\n        XCTAssertEqual(buffer.readerIndex, 0, \"peekWebSocketErrorCode() should not advance reader index.\")\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/NIOWebSocketClientUpgraderTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOWebSocket\nimport XCTest\n\n/// a mock random number generator which will return the given `numbers` in order\nprivate struct TestRandomNumberGenerator: RandomNumberGenerator {\n    var numbers: [UInt64]\n    var nextRandomNumberIndex: Int\n    init(numbers: [UInt64], nextRandomNumberIndex: Int = 0) {\n        self.numbers = numbers\n        self.nextRandomNumberIndex = nextRandomNumberIndex\n    }\n    mutating func next() -> UInt64 {\n        defer { nextRandomNumberIndex += 1 }\n        return numbers[nextRandomNumberIndex % numbers.count]\n    }\n}\n\nfinal class NIOWebSocketClientUpgraderTests: XCTestCase {\n    func testRandomRequestKey() {\n        var generator = TestRandomNumberGenerator(numbers: [10, 11])\n        let requestKey = NIOWebSocketClientUpgrader.randomRequestKey(using: &generator)\n        XCTAssertEqual(requestKey, \"AAAAAAAAAAoAAAAAAAAACw==\")\n    }\n    func testRandomRequestKeyWithSystemRandomNumberGenerator() {\n        XCTAssertEqual(\n            NIOWebSocketClientUpgrader.randomRequestKey().count,\n            24,\n            \"request key must be exactly 16 bytes long and this corresponds to 24 characters in base64\"\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/NIOWebSocketFrameAggregatorTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\nimport XCTest\n\nfinal class NIOWebSocketFrameAggregatorTests: XCTestCase {\n    var channel: EmbeddedChannel!\n\n    override func setUp() {\n        channel = EmbeddedChannel(\n            handler: NIOWebSocketFrameAggregator(\n                minNonFinalFragmentSize: 1,\n                maxAccumulatedFrameCount: 4,\n                maxAccumulatedFrameSize: 32\n            )\n        )\n    }\n\n    override func tearDown() {\n        XCTAssertEqual(try self.channel.finish().isClean, true)\n    }\n\n    func testEmptyButFinalFrameIsForwardedEvenIfMinNonFinalFragmentSizeIsGreaterThanZero() {\n        let frame = WebSocketFrame(fin: true, opcode: .binary, data: ByteBuffer())\n        XCTAssertNoThrow(try channel.writeInbound(frame))\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), frame)\n    }\n\n    func testTooSmallAndNonFinalFrameThrows() {\n        let frame = WebSocketFrame(fin: false, opcode: .binary, data: ByteBuffer())\n        XCTAssertThrowsError(try channel.writeInbound(frame))\n    }\n\n    func testTooBigFrameThrows() {\n        let frame = WebSocketFrame(fin: false, opcode: .binary, data: ByteBuffer(repeating: 2, count: 33))\n        XCTAssertThrowsError(try channel.writeInbound(frame))\n    }\n\n    func testTooBigAccumulatedFrameThrows() {\n        let frame1 = WebSocketFrame(fin: false, opcode: .binary, data: ByteBuffer(repeating: 2, count: 32))\n        XCTAssertNoThrow(try channel.writeInbound(frame1))\n\n        let frame2 = WebSocketFrame(fin: false, opcode: .binary, data: ByteBuffer(repeating: 3, count: 1))\n        XCTAssertThrowsError(try channel.writeInbound(frame2))\n    }\n\n    func testTooManyFramesThrow() {\n        let firstFrame = WebSocketFrame(fin: false, opcode: .binary, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(firstFrame))\n        let fragment = WebSocketFrame(fin: false, opcode: .continuation, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        XCTAssertThrowsError(try channel.writeInbound(fragment))\n    }\n    func testAlmostTooManyFramesDoNotThrow() {\n        let firstFrame = WebSocketFrame(fin: false, opcode: .binary, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(firstFrame))\n        let fragment = WebSocketFrame(fin: false, opcode: .continuation, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        let lastFrame = WebSocketFrame(fin: true, opcode: .continuation, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(lastFrame))\n\n        let completeFrame = WebSocketFrame(fin: true, opcode: .binary, data: ByteBuffer(repeating: 2, count: 8))\n\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), completeFrame)\n    }\n\n    func testTextFrameIsStillATextFrameAfterAggregation() {\n        let firstFrame = WebSocketFrame(fin: false, opcode: .text, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(firstFrame))\n        let fragment = WebSocketFrame(fin: false, opcode: .continuation, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        let lastFrame = WebSocketFrame(fin: true, opcode: .continuation, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(lastFrame))\n\n        let completeFrame = WebSocketFrame(fin: true, opcode: .text, data: ByteBuffer(repeating: 2, count: 8))\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), completeFrame)\n    }\n\n    func testPingFrameIsForwarded() {\n        let controlFrame = WebSocketFrame(fin: true, opcode: .ping, data: ByteBuffer())\n        XCTAssertNoThrow(try channel.writeInbound(controlFrame))\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), controlFrame)\n\n        let fragment = WebSocketFrame(fin: false, opcode: .text, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n\n        XCTAssertNoThrow(try channel.writeInbound(controlFrame))\n        XCTAssertEqual(\n            try channel.readInbound(as: WebSocketFrame.self),\n            controlFrame,\n            \"should forward control frames during buffering\"\n        )\n    }\n\n    func testPongFrameIsForwarded() {\n        let controlFrame = WebSocketFrame(fin: true, opcode: .pong, data: ByteBuffer())\n        XCTAssertNoThrow(try channel.writeInbound(controlFrame))\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), controlFrame)\n\n        let fragment = WebSocketFrame(fin: false, opcode: .text, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n\n        XCTAssertNoThrow(try channel.writeInbound(controlFrame))\n        XCTAssertEqual(\n            try channel.readInbound(as: WebSocketFrame.self),\n            controlFrame,\n            \"should forward control frames during buffering\"\n        )\n    }\n\n    func testCloseConnectionFrameIsForwarded() {\n        let controlFrame = WebSocketFrame(fin: true, opcode: .connectionClose, data: ByteBuffer())\n        XCTAssertNoThrow(try channel.writeInbound(controlFrame))\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), controlFrame)\n\n        let fragment = WebSocketFrame(fin: false, opcode: .text, data: ByteBuffer(repeating: 2, count: 2))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n\n        XCTAssertNoThrow(try channel.writeInbound(controlFrame))\n        XCTAssertEqual(\n            try channel.readInbound(as: WebSocketFrame.self),\n            controlFrame,\n            \"should forward control frames during buffering\"\n        )\n    }\n\n    func testFrameAggregationWithMask() {\n        var firstFrameData = ByteBuffer(repeating: 2, count: 2)\n        let firsFrameMask: WebSocketMaskingKey = [1, 2, 3, 4]\n        firstFrameData.webSocketMask(firsFrameMask)\n        let firstFrame = WebSocketFrame(fin: false, opcode: .binary, maskKey: firsFrameMask, data: firstFrameData)\n        XCTAssertNoThrow(try channel.writeInbound(firstFrame))\n\n        var fragmentData = ByteBuffer(repeating: 3, count: 2)\n        let fragmentMaskKey: WebSocketMaskingKey = [5, 6, 7, 8]\n        fragmentData.webSocketMask(fragmentMaskKey)\n        let fragment = WebSocketFrame(fin: false, opcode: .continuation, maskKey: fragmentMaskKey, data: fragmentData)\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n        XCTAssertNoThrow(try channel.writeInbound(fragment))\n\n        var lastFrameData = ByteBuffer(repeating: 4, count: 2)\n        let lastFrameMaskKey: WebSocketMaskingKey = [9, 10, 11, 12]\n        lastFrameData.webSocketMask(lastFrameMaskKey)\n        let lastFrame = WebSocketFrame(fin: true, opcode: .continuation, maskKey: lastFrameMaskKey, data: lastFrameData)\n        XCTAssertNoThrow(try channel.writeInbound(lastFrame))\n\n        let completeFrame = WebSocketFrame(\n            fin: true,\n            opcode: .binary,\n            data: ByteBuffer(bytes: [2, 2, 3, 3, 3, 3, 4, 4])\n        )\n        XCTAssertEqual(try channel.readInbound(as: WebSocketFrame.self), completeFrame)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/WebSocketClientEndToEndTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport NIOHTTP1\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOWebSocket\n\nextension EmbeddedChannel {\n\n    fileprivate func readByteBufferOutputAsString() throws -> String? {\n\n        if let requestBuffer: ByteBuffer = try self.readOutbound() {\n            return requestBuffer.getString(at: 0, length: requestBuffer.readableBytes)\n        }\n\n        return nil\n    }\n}\n\nextension ChannelPipeline {\n\n    fileprivate func assertDoesNotContain<Handler: ChannelHandler>(\n        handlerType: Handler.Type,\n        file: StaticString = #filePath,\n        line: UInt = #line\n    ) throws {\n        XCTAssertThrowsError(try self.syncOperations.context(handlerType: handlerType), file: (file), line: line) {\n            error in\n            XCTAssertEqual(.notFound, error as? ChannelPipelineError)\n        }\n    }\n\n    fileprivate func assertContains<Handler: ChannelHandler>(handlerType: Handler.Type) throws {\n        do {\n            _ = try self.syncOperations.context(handlerType: handlerType)\n        } catch ChannelPipelineError.notFound {\n            XCTFail(\"Did not find handler\")\n        }\n    }\n}\n\nprivate func setUpClientChannel(\n    clientHTTPHandler: RemovableChannelHandler & Sendable,\n    clientUpgraders: [NIOHTTPClientProtocolUpgrader & Sendable],\n    _ upgradeCompletionHandler: @escaping @Sendable (ChannelHandlerContext) -> Void\n) throws -> EmbeddedChannel {\n\n    let channel = EmbeddedChannel()\n\n    let config: NIOHTTPClientUpgradeSendableConfiguration = (\n        upgraders: clientUpgraders,\n        completionHandler: { context in\n            channel.pipeline.syncOperations.removeHandler(clientHTTPHandler, promise: nil)\n            upgradeCompletionHandler(context)\n        }\n    )\n\n    try channel.pipeline.addHTTPClientHandlers(withClientUpgrade: config).flatMap({\n        channel.pipeline.addHandler(clientHTTPHandler)\n    }).wait()\n\n    try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n        .wait()\n\n    return channel\n}\n\n// A HTTP handler that will send an initial request which can be augmented by the upgrade handler.\nprivate final class BasicHTTPHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n    fileprivate typealias InboundIn = HTTPClientResponsePart\n    fileprivate typealias OutboundOut = HTTPClientRequestPart\n\n    fileprivate func channelActive(context: ChannelHandlerContext) {\n        // We are connected. It's time to send the message to the server to initialise the upgrade dance.\n        self.fireSendRequest(context: context)\n    }\n}\n\n// A HTTP handler that will send a request and then fail if it receives a response or an error.\n// It can be used when there is a successful upgrade as the handler should be removed by the upgrader.\nprivate final class ExplodingHTTPHandler: ChannelInboundHandler, RemovableChannelHandler, Sendable {\n    fileprivate typealias InboundIn = HTTPClientResponsePart\n    fileprivate typealias OutboundOut = HTTPClientRequestPart\n\n    fileprivate func channelActive(context: ChannelHandlerContext) {\n        // We are connected. It's time to send the message to the server to initialise the upgrade dance.\n        self.fireSendRequest(context: context)\n    }\n\n    fileprivate func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        XCTFail(\"Received unexpected read\")\n    }\n\n    fileprivate func errorCaught(context: ChannelHandlerContext, error: Error) {\n        XCTFail(\"Received unexpected error\")\n    }\n}\n\nextension ChannelInboundHandler where OutboundOut == HTTPClientRequestPart {\n\n    fileprivate func fireSendRequest(context: ChannelHandlerContext) {\n\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        headers.add(name: \"Content-Length\", value: \"\\(0)\")\n\n        let requestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/\",\n            headers: headers\n        )\n\n        context.write(Self.wrapOutboundOut(.head(requestHead)), promise: nil)\n\n        let emptyBuffer = context.channel.allocator.buffer(capacity: 0)\n        let body = HTTPClientRequestPart.body(.byteBuffer(emptyBuffer))\n        context.write(Self.wrapOutboundOut(body), promise: nil)\n\n        context.writeAndFlush(Self.wrapOutboundOut(.end(nil)), promise: nil)\n    }\n}\n\nprivate class WebSocketRecorderHandler: ChannelInboundHandler, ChannelOutboundHandler {\n    typealias OutboundIn = WebSocketFrame\n\n    typealias InboundIn = WebSocketFrame\n    typealias OutboundOut = WebSocketFrame\n\n    public var frames: [WebSocketFrame] = []\n    public var errors: [Error] = []\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let frame = Self.unwrapInboundIn(data)\n        self.frames.append(frame)\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.errors.append(error)\n        context.fireErrorCaught(error)\n    }\n}\n\nprivate func basicRequest(path: String = \"/\") -> String {\n    \"GET \\(path) HTTP/1.1\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 0\"\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nclass WebSocketClientEndToEndTests: XCTestCase {\n    func testSimpleUpgradeSucceeds() throws {\n\n        let upgradeHandlerCallbackFired = NIOLockedValueBox(false)\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n        let responseKey = \"yKEqitDFPE81FyIhKTm+ojBqigk=\"\n\n        let basicUpgrader = NIOWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [basicUpgrader]\n        ) { _ in\n\n            // This is called before the upgrader gets called.\n            upgradeHandlerCallbackFired.withLockedValue { $0 = true }\n        }\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                basicRequest()\n                    + \"\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Key: \\(requestKey)\\r\\nSec-WebSocket-Version: 13\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Push the successful server response.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Accept:\\(responseKey)\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Once upgraded, validate the http pipeline has been removed.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n\n        // Check that the pipeline now has the correct websocket handlers added.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertContains(handlerType: WebSocketFrameEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertContains(handlerType: ByteToMessageHandler<WebSocketFrameDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertContains(handlerType: WebSocketRecorderHandler.self)\n        )\n\n        XCTAssert(upgradeHandlerCallbackFired.withLockedValue { $0 })\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    func testRejectUpgradeIfMissingAcceptKey() throws {\n\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n\n        let basicUpgrader = NIOWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: BasicHTTPHandler(),\n            clientUpgraders: [basicUpgrader]\n        ) { _ in\n        }\n\n        // Push the successful server response but with a missing accept key.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\n\\r\\n\"\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(.upgraderDeniedUpgrade, error as? NIOHTTPClientUpgradeError)\n        }\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    func testRejectUpgradeIfIncorrectAcceptKey() throws {\n\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n        let responseKey = \"notACorrectKeyL1am=F1y=nn=\"\n\n        let basicUpgrader = NIOWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: BasicHTTPHandler(),\n            clientUpgraders: [basicUpgrader]\n        ) { _ in\n        }\n\n        // Push the successful server response but with an incorrect response key.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Accept:\\(responseKey)\\r\\n\\r\\n\"\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(.upgraderDeniedUpgrade, error as? NIOHTTPClientUpgradeError)\n        }\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    func testRejectUpgradeIfNotWebsocket() throws {\n\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n        let responseKey = \"yKEqitDFPE81FyIhKTm+ojBqigk=\"\n\n        let basicUpgrader = NIOWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: BasicHTTPHandler(),\n            clientUpgraders: [basicUpgrader]\n        ) { _ in\n        }\n\n        // Push the successful server response with an incorrect protocol.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: myProtocol\\r\\nSec-WebSocket-Accept:\\(responseKey)\\r\\n\\r\\n\"\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(.responseProtocolNotFound, error as? NIOHTTPClientUpgradeError)\n        }\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    fileprivate func runSuccessfulUpgrade() throws -> (EmbeddedChannel, WebSocketRecorderHandler) {\n        let basicUpgrader = NIOWebSocketClientUpgrader(\n            requestKey: \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\",\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        let clientChannel = try setUpClientChannel(\n            clientHTTPHandler: ExplodingHTTPHandler(),\n            clientUpgraders: [basicUpgrader]\n        ) { _ in\n        }\n\n        // Push the successful server response.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Accept:yKEqitDFPE81FyIhKTm+ojBqigk=\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // We now have a successful upgrade, clear the output channels read to test the frames.\n        XCTAssertNoThrow(try clientChannel.readOutbound(as: ByteBuffer.self))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Ok, now grab the handler. We can do this with sync operations, because this is an\n        // EmbeddedChannel.\n        let handler = try clientChannel.pipeline.syncOperations.handler(type: WebSocketRecorderHandler.self)\n\n        return (clientChannel, handler)\n\n    }\n\n    func testSendAFewFrames() throws {\n\n        let (clientChannel, _) = try self.runSuccessfulUpgrade()\n\n        // Send a frame or two, to confirm that the Websocket pipeline works.\n        let stringSentInFrame = \"hello, world\"\n\n        var data = clientChannel.allocator.buffer(capacity: 12)\n        data.writeString(stringSentInFrame)\n\n        let dataFrame = WebSocketFrame(fin: true, opcode: .binary, data: data)\n\n        XCTAssertNoThrow(try clientChannel.writeOutbound(dataFrame))\n\n        clientChannel.embeddedEventLoop.run()\n\n        let outboundAsString = try clientChannel.readAllOutboundBuffers().allAsString()\n        XCTAssert(outboundAsString.contains(stringSentInFrame))\n\n        // Frame number two coming up.\n        let stringSentInSecondFrame = \"two\"\n\n        var dataTwo = clientChannel.allocator.buffer(capacity: 3)\n        dataTwo.writeString(stringSentInSecondFrame)\n\n        let pingFrame = WebSocketFrame(fin: true, opcode: .text, data: dataTwo)\n        XCTAssertNoThrow(try clientChannel.writeAndFlush(pingFrame).wait())\n\n        clientChannel.embeddedEventLoop.run()\n\n        let pingAsString = try clientChannel.readAllOutboundBuffers().allAsString()\n        XCTAssert(pingAsString.contains(stringSentInSecondFrame))\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    private func encodeFrame(dataString: String, opcode: WebSocketOpcode) throws -> (WebSocketFrame, [UInt8]) {\n\n        let serverChannel = EmbeddedChannel()\n        defer {\n            XCTAssertNoThrow(try serverChannel.finish())\n        }\n\n        var buffer = serverChannel.allocator.buffer(capacity: 11)\n        buffer.writeString(dataString)\n\n        let dataFrame = WebSocketFrame(fin: true, opcode: .binary, data: buffer)\n\n        try serverChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder())\n        serverChannel.writeAndFlush(dataFrame, promise: nil)\n\n        return (dataFrame, try serverChannel.readAllOutboundBytes())\n    }\n\n    func testReceiveAFewFrames() throws {\n\n        let (clientChannel, recorder) = try self.runSuccessfulUpgrade()\n        defer {\n            XCTAssertNoThrow(try clientChannel.finish(acceptAlreadyClosed: true))\n        }\n\n        // Listen out for a frame or two, to confirm that the Websocket pipeline works.\n        let (binaryFrame, binaryFrameAsBytes) = try self.encodeFrame(dataString: \"hello, back\", opcode: .binary)\n\n        var data = clientChannel.allocator.buffer(capacity: binaryFrameAsBytes.count)\n        data.writeBytes(binaryFrameAsBytes)\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(data))\n\n        clientChannel.embeddedEventLoop.run()\n\n        XCTAssertEqual(recorder.frames, [binaryFrame])\n\n        // Frame number two coming up.\n        let (textFrame, textFrameAsBytes) = try self.encodeFrame(dataString: \"two\", opcode: .text)\n\n        var dataTwo = clientChannel.allocator.buffer(capacity: textFrameAsBytes.count)\n        dataTwo.writeBytes(textFrameAsBytes)\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(dataTwo))\n\n        clientChannel.embeddedEventLoop.run()\n\n        XCTAssertEqual([binaryFrame, textFrame], recorder.frames)\n        XCTAssertEqual(0, recorder.errors.count)\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    func testErrorHandlerMaskFrameForClient() throws {\n\n        let (clientChannel, _) = try self.runSuccessfulUpgrade()\n        let maskBitMask: UInt8 = 0x80\n\n        var data = clientChannel.allocator.buffer(capacity: 4)\n        // A fake frame header that claims that the length of the frame is 16385 bytes,\n        // larger than the frame max.\n        data.writeBytes([0x81, 0xFE, 0x40, 0x01])\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(data)) { error in\n            XCTAssertEqual(.invalidFrameLength, error as? NIOWebSocketError)\n        }\n\n        clientChannel.embeddedEventLoop.run()\n        var buffer = try clientChannel.readAllOutboundBuffers()\n\n        guard let (_, secondByte) = buffer.readMultipleIntegers(as: (UInt8, UInt8).self) else {\n            XCTFail(\"Insufficient bytes from WebSocket frame\")\n            return\n        }\n\n        let maskedBit = (secondByte & maskBitMask)\n        XCTAssertEqual(0x80, maskedBit)\n\n        XCTAssertNoThrow(!clientChannel.isActive)\n        XCTAssertTrue(try clientChannel.finish(acceptAlreadyClosed: true).isClean)\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal class TypedWebSocketClientEndToEndTests: WebSocketClientEndToEndTests {\n    func setUpClientChannel(\n        clientUpgraders: [any NIOTypedHTTPClientProtocolUpgrader<Void>],\n        notUpgradingCompletionHandler: @Sendable @escaping (Channel) -> EventLoopFuture<Void>\n    ) throws -> (EmbeddedChannel, EventLoopFuture<Void>) {\n\n        let channel = EmbeddedChannel()\n\n        var headers = HTTPHeaders()\n        headers.add(name: \"Content-Type\", value: \"text/plain; charset=utf-8\")\n        headers.add(name: \"Content-Length\", value: \"\\(0)\")\n\n        let requestHead = HTTPRequestHead(\n            version: .http1_1,\n            method: .GET,\n            uri: \"/\",\n            headers: headers\n        )\n\n        let config = NIOTypedHTTPClientUpgradeConfiguration(\n            upgradeRequestHead: requestHead,\n            upgraders: clientUpgraders,\n            notUpgradingCompletionHandler: notUpgradingCompletionHandler\n        )\n\n        let upgradeResult = try channel.pipeline.syncOperations.configureUpgradableHTTPClientPipeline(\n            configuration: .init(upgradeConfiguration: config)\n        )\n\n        try channel.connect(to: SocketAddress(ipAddress: \"127.0.0.1\", port: 0))\n            .wait()\n\n        return (channel, upgradeResult)\n    }\n\n    override func testSimpleUpgradeSucceeds() throws {\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n        let responseKey = \"yKEqitDFPE81FyIhKTm+ojBqigk=\"\n\n        let basicUpgrader = NIOTypedWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let (clientChannel, upgradeResult) = try setUpClientChannel(\n            clientUpgraders: [basicUpgrader],\n            notUpgradingCompletionHandler: { $0.eventLoop.makeSucceededVoidFuture() }\n        )\n\n        // Read the server request.\n        if let requestString = try clientChannel.readByteBufferOutputAsString() {\n            XCTAssertEqual(\n                requestString,\n                basicRequest()\n                    + \"\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Key: \\(requestKey)\\r\\nSec-WebSocket-Version: 13\\r\\n\\r\\n\"\n            )\n        } else {\n            XCTFail()\n        }\n\n        // Push the successful server response.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Accept:\\(responseKey)\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // Once upgraded, validate the http pipeline has been removed.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: HTTPRequestEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: ByteToMessageHandler<HTTPResponseDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertDoesNotContain(handlerType: NIOHTTPClientUpgradeHandler.self)\n        )\n\n        // Check that the pipeline now has the correct websocket handlers added.\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertContains(handlerType: WebSocketFrameEncoder.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertContains(handlerType: ByteToMessageHandler<WebSocketFrameDecoder>.self)\n        )\n        XCTAssertNoThrow(\n            try clientChannel.pipeline\n                .assertContains(handlerType: WebSocketRecorderHandler.self)\n        )\n\n        try upgradeResult.wait()\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n    }\n\n    override func testRejectUpgradeIfMissingAcceptKey() throws {\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n\n        let basicUpgrader = NIOTypedWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let (clientChannel, upgradeResult) = try setUpClientChannel(\n            clientUpgraders: [basicUpgrader],\n            notUpgradingCompletionHandler: { $0.eventLoop.makeSucceededVoidFuture() }\n        )\n\n        // Push the successful server response but with a missing accept key.\n        let response = \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\n\\r\\n\"\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, NIOHTTPClientUpgradeError.upgraderDeniedUpgrade)\n        }\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        XCTAssertThrowsError(try upgradeResult.wait()) { error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, NIOHTTPClientUpgradeError.upgraderDeniedUpgrade)\n        }\n    }\n\n    override func testRejectUpgradeIfIncorrectAcceptKey() throws {\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n        let responseKey = \"notACorrectKeyL1am=F1y=nn=\"\n\n        let basicUpgrader = NIOTypedWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let (clientChannel, upgradeResult) = try setUpClientChannel(\n            clientUpgraders: [basicUpgrader],\n            notUpgradingCompletionHandler: { $0.eventLoop.makeSucceededVoidFuture() }\n        )\n\n        // Push the successful server response but with an incorrect response key.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Accept:\\(responseKey)\\r\\n\\r\\n\"\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, NIOHTTPClientUpgradeError.upgraderDeniedUpgrade)\n        }\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        XCTAssertThrowsError(try upgradeResult.wait()) { error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, NIOHTTPClientUpgradeError.upgraderDeniedUpgrade)\n        }\n    }\n\n    override func testRejectUpgradeIfNotWebsocket() throws {\n        let requestKey = \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\"\n        let responseKey = \"yKEqitDFPE81FyIhKTm+ojBqigk=\"\n\n        let basicUpgrader = NIOTypedWebSocketClientUpgrader(\n            requestKey: requestKey,\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let (clientChannel, upgradeResult) = try setUpClientChannel(\n            clientUpgraders: [basicUpgrader],\n            notUpgradingCompletionHandler: { $0.eventLoop.makeSucceededVoidFuture() }\n        )\n\n        // Push the successful server response with an incorrect protocol.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: myProtocol\\r\\nSec-WebSocket-Accept:\\(responseKey)\\r\\n\\r\\n\"\n\n        XCTAssertThrowsError(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response))) {\n            error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, NIOHTTPClientUpgradeError.responseProtocolNotFound)\n        }\n\n        // Close the pipeline.\n        XCTAssertNoThrow(try clientChannel.close().wait())\n\n        XCTAssertThrowsError(try upgradeResult.wait()) { error in\n            XCTAssertEqual(error as? NIOHTTPClientUpgradeError, NIOHTTPClientUpgradeError.responseProtocolNotFound)\n        }\n    }\n\n    override fileprivate func runSuccessfulUpgrade() throws -> (EmbeddedChannel, WebSocketRecorderHandler) {\n        let basicUpgrader = NIOTypedWebSocketClientUpgrader(\n            requestKey: \"OfS0wDaT5NoxF2gqm7Zj2YtetzM=\",\n            upgradePipelineHandler: { (channel: Channel, _: HTTPResponseHead) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(WebSocketRecorderHandler())\n                }\n            }\n        )\n\n        // The process should kick-off independently by sending the upgrade request to the server.\n        let (clientChannel, upgradeResult) = try setUpClientChannel(\n            clientUpgraders: [basicUpgrader],\n            notUpgradingCompletionHandler: { $0.eventLoop.makeSucceededVoidFuture() }\n        )\n\n        // Push the successful server response.\n        let response =\n            \"HTTP/1.1 101 Switching Protocols\\r\\nConnection: upgrade\\r\\nUpgrade: websocket\\r\\nSec-WebSocket-Accept:yKEqitDFPE81FyIhKTm+ojBqigk=\\r\\n\\r\\n\"\n\n        XCTAssertNoThrow(try clientChannel.writeInbound(clientChannel.allocator.buffer(string: response)))\n\n        clientChannel.embeddedEventLoop.run()\n\n        // We now have a successful upgrade, clear the output channels read to test the frames.\n        XCTAssertNoThrow(try clientChannel.readOutbound(as: ByteBuffer.self))\n\n        clientChannel.embeddedEventLoop.run()\n\n        try upgradeResult.wait()\n\n        // Ok, now grab the handler. We can do this with sync operations, because this is an\n        // EmbeddedChannel.\n        let handler = try clientChannel.pipeline.syncOperations.handler(type: WebSocketRecorderHandler.self)\n\n        return (clientChannel, handler)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/WebSocketFrameDecoderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\nimport XCTest\n\nprivate class CloseSwallower: ChannelOutboundHandler, RemovableChannelHandler {\n    typealias OutboundIn = Any\n    typealias OutboundOut = Any\n\n    private var closePromise: EventLoopPromise<Void>? = nil\n    private var context: ChannelHandlerContext? = nil\n\n    func allowClose() {\n        self.context!.close(promise: self.closePromise)\n        self.context = nil\n    }\n\n    func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) {\n        self.closePromise = promise\n        self.context = context\n    }\n}\n\n/// A class that calls context.close() when it receives a decoded websocket frame, and validates that it does\n/// not receive two.\nprivate final class SynchronousCloser: ChannelInboundHandler {\n    typealias InboundIn = WebSocketFrame\n\n    private var closeFrame: WebSocketFrame?\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let frame = Self.unwrapInboundIn(data)\n        guard case .connectionClose = frame.opcode else {\n            context.fireChannelRead(data)\n            return\n        }\n\n        // Ok, connection close. Confirm we haven't seen one before.\n        XCTAssertNil(self.closeFrame)\n        self.closeFrame = frame\n\n        // Now we're going to call close.\n        context.close(promise: nil)\n    }\n}\n\nfinal class WebSocketFrameDecoderTest: XCTestCase {\n    var decoderChannel: EmbeddedChannel!\n    var encoderChannel: EmbeddedChannel!\n    var buffer: ByteBuffer!\n\n    override func setUp() {\n        self.decoderChannel = EmbeddedChannel()\n        self.encoderChannel = EmbeddedChannel()\n        self.buffer = decoderChannel.allocator.buffer(capacity: 128)\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(ByteToMessageHandler(WebSocketFrameDecoder()))\n        )\n        XCTAssertNoThrow(try self.encoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder()))\n    }\n\n    override func tearDown() {\n        XCTAssertNoThrow(try self.encoderChannel.finish())\n        _ = try? self.decoderChannel.finish()\n        self.encoderChannel = nil\n        self.buffer = nil\n    }\n\n    private func frameForFrame(_ frame: WebSocketFrame) -> WebSocketFrame? {\n        self.encoderChannel.writeAndFlush(frame, promise: nil)\n\n        do {\n            while let d = try self.encoderChannel.readOutbound(as: ByteBuffer.self) {\n                XCTAssertNoThrow(try self.decoderChannel.writeInbound(d))\n            }\n\n            guard let producedFrame: WebSocketFrame = try self.decoderChannel.readInbound() else {\n                XCTFail(\"Did not produce a frame\")\n                return nil\n            }\n\n            // Should only have gotten one frame!\n            XCTAssertNoThrow(XCTAssertNil(try self.decoderChannel.readInbound(as: WebSocketFrame.self)))\n            return producedFrame\n        } catch {\n            XCTFail(\"unexpected error: \\(error)\")\n            return nil\n        }\n    }\n\n    private func assertFrameRoundTrips(frame: WebSocketFrame) {\n        XCTAssertEqual(frameForFrame(frame), frame)\n    }\n\n    private func assertFrameDoesNotRoundTrip(frame: WebSocketFrame) {\n        XCTAssertNotEqual(frameForFrame(frame), frame)\n    }\n\n    private func swapDecoder(for handler: ChannelHandler) {\n        // We need to insert a decoder that doesn't do error handling. We still insert\n        // an encoder because we want to fail gracefully if a frame is written.\n        let f = self.decoderChannel.pipeline.context(handlerType: ByteToMessageHandler<WebSocketFrameDecoder>.self)\n            .assumeIsolated()\n            .flatMap { context in\n                if let handler = context.handler as? RemovableChannelHandler {\n                    return self.decoderChannel.pipeline.syncOperations.removeHandler(handler)\n                } else {\n                    return context.eventLoop.makeFailedFuture(ChannelError.unremovableHandler)\n                }\n            }\n\n        // we need to run the event loop here because removal is not synchronous\n        (self.decoderChannel.eventLoop as! EmbeddedEventLoop).run()\n\n        XCTAssertNoThrow(\n            try f.flatMapThrowing {\n                try self.decoderChannel.pipeline.syncOperations.addHandler(handler)\n            }.nonisolated().wait()\n        )\n    }\n\n    func testFramesWithoutBodies() throws {\n        let frame = WebSocketFrame(fin: true, opcode: .ping, data: self.buffer)\n        assertFrameRoundTrips(frame: frame)\n    }\n\n    func testFramesWithExtensionDataDontRoundTrip() throws {\n        // We don't know what the extensions are, so all data goes in...well...data.\n        self.buffer.writeBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        let frame = WebSocketFrame(\n            fin: false,\n            opcode: .binary,\n            data: self.buffer.getSlice(at: self.buffer.readerIndex, length: 5)!,\n            extensionData: self.buffer.getSlice(at: self.buffer.readerIndex + 5, length: 5)!\n        )\n        assertFrameDoesNotRoundTrip(frame: frame)\n    }\n\n    func testFramesWithExtensionDataCanBeRecovered() throws {\n        self.buffer.writeBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        let frame = WebSocketFrame(\n            fin: false,\n            opcode: .binary,\n            data: self.buffer.getSlice(at: self.buffer.readerIndex, length: 5)!,\n            extensionData: self.buffer.getSlice(at: self.buffer.readerIndex + 5, length: 5)!\n        )\n        var newFrame = frameForFrame(frame)!\n        // Copy some data out into the extension on the frame. The first 5 bytes are extension.\n        newFrame.extensionData = newFrame.data.readSlice(length: 5)\n        XCTAssertEqual(newFrame, frame)\n    }\n\n    func testFramesWithReservedBitsSetRoundTrip() throws {\n        self.buffer.writeBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        let frame = WebSocketFrame(\n            fin: false,\n            rsv1: true,\n            rsv2: true,\n            rsv3: true,\n            opcode: .binary,\n            data: self.buffer\n        )\n        assertFrameRoundTrips(frame: frame)\n    }\n\n    func testFramesWith16BitLengthsRoundTrip() throws {\n        self.buffer.writeBytes(Array(repeating: UInt8(4), count: 300))\n        let frame = WebSocketFrame(\n            fin: true,\n            opcode: .binary,\n            data: self.buffer\n        )\n        assertFrameRoundTrips(frame: frame)\n    }\n\n    func testFramesWith64BitLengthsRoundTrip() throws {\n        // We need a new decoder channel here, because the max length would otherwise trigger an error.\n        _ = try! self.decoderChannel.finish()\n        self.decoderChannel = EmbeddedChannel()\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(\n                ByteToMessageHandler(WebSocketFrameDecoder(maxFrameSize: 80000))\n            )\n        )\n\n        self.buffer.writeBytes(Array(repeating: UInt8(4), count: 66000))\n        let frame = WebSocketFrame(\n            fin: true,\n            opcode: .binary,\n            data: self.buffer\n        )\n        assertFrameRoundTrips(frame: frame)\n    }\n\n    func testMaskedFramesRoundTripWithMaskingIntact() throws {\n        self.buffer.writeBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        let frame = WebSocketFrame(\n            fin: false,\n            opcode: .binary,\n            maskKey: [0x80, 0x77, 0x11, 0x33],\n            data: self.buffer\n        )\n        let producedFrame = frameForFrame(frame)!\n        XCTAssertEqual(producedFrame.fin, frame.fin)\n        XCTAssertEqual(producedFrame.rsv1, frame.rsv1)\n        XCTAssertEqual(producedFrame.rsv2, frame.rsv2)\n        XCTAssertEqual(producedFrame.rsv3, frame.rsv3)\n        XCTAssertEqual(producedFrame.maskKey, frame.maskKey)\n        XCTAssertEqual(producedFrame.length, frame.length)\n\n        // The produced frame contains the masked data in its data field.\n        var maskedBuffer = self.buffer!\n        maskedBuffer.webSocketMask([0x80, 0x77, 0x11, 0x33])\n        XCTAssertEqual(maskedBuffer, producedFrame.data)\n\n        // But we can get the unmasked data back.\n        XCTAssertEqual(producedFrame.unmaskedData, self.buffer)\n    }\n\n    func testMaskedFramesRoundTripWithMaskingIntactEvenWithExtensions() throws {\n        self.buffer.writeBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n        let frame = WebSocketFrame(\n            fin: false,\n            opcode: .binary,\n            maskKey: [0x80, 0x77, 0x11, 0x33],\n            data: self.buffer.getSlice(at: self.buffer.readerIndex + 5, length: 5)!,\n            extensionData: self.buffer.getSlice(at: self.buffer.readerIndex, length: 5)!\n        )\n        var producedFrame = frameForFrame(frame)!\n        XCTAssertEqual(producedFrame.fin, frame.fin)\n        XCTAssertEqual(producedFrame.rsv1, frame.rsv1)\n        XCTAssertEqual(producedFrame.rsv2, frame.rsv2)\n        XCTAssertEqual(producedFrame.rsv3, frame.rsv3)\n        XCTAssertEqual(producedFrame.maskKey, frame.maskKey)\n        XCTAssertEqual(producedFrame.length, frame.length)\n\n        // The produced frame contains the masked data in its data field, but doesn't know which is extension and which\n        // is not. Let's fix that up first.\n        producedFrame.extensionData = producedFrame.data.readSlice(length: 5)\n\n        var maskedBuffer = self.buffer!\n        maskedBuffer.webSocketMask([0x80, 0x77, 0x11, 0x33])\n        XCTAssertEqual(maskedBuffer.getSlice(at: maskedBuffer.readerIndex + 5, length: 5)!, producedFrame.data)\n        XCTAssertEqual(maskedBuffer.getSlice(at: maskedBuffer.readerIndex, length: 5)!, producedFrame.extensionData)\n\n        // But we can get the unmasked data back.\n        XCTAssertEqual(producedFrame.unmaskedData, self.buffer.getSlice(at: self.buffer.readerIndex + 5, length: 5)!)\n        XCTAssertEqual(\n            producedFrame.unmaskedExtensionData,\n            self.buffer.getSlice(at: self.buffer.readerIndex, length: 5)!\n        )\n    }\n\n    func testDecoderRejectsOverlongFrames() throws {\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims that the length of the frame is 16385 bytes,\n        // larger than the frame max.\n        self.buffer.writeBytes([0x81, 0xFE, 0x40, 0x01])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.invalidFrameLength, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xF1], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testDecoderRejectsFragmentedControlFrames() throws {\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims this is a fragmented ping frame.\n        self.buffer.writeBytes([0x09, 0x00])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.fragmentedControlFrame, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xEA], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testDecoderRejectsMultibyteControlFrameLengths() throws {\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims this is a ping frame with 126 bytes of data.\n        self.buffer.writeBytes([0x89, 0x7E, 0x00, 0x7E])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.multiByteControlFrameLength, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xEA], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testIgnoresFurtherDataAfterRejectedFrame() throws {\n        let swallower = CloseSwallower()\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(swallower, position: .first))\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims this is a fragmented ping frame.\n        self.buffer.writeBytes([0x09, 0x00])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.fragmentedControlFrame, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xEA], try self.decoderChannel.readAllOutboundBytes()))\n\n        // Now write another broken frame, this time an overlong frame.\n        self.buffer.clear()\n        let wrongFrame: [UInt8] = [0x81, 0xFE, 0x40, 0x01]\n        self.buffer.writeBytes(wrongFrame)\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            if case .some(.dataReceivedInErrorState(let innerError, let data)) = error as? ByteToMessageDecoderError {\n                // ok\n                XCTAssertEqual(.fragmentedControlFrame, innerError as? NIOWebSocketError)\n                XCTAssertEqual(wrongFrame, Array(data.readableBytesView))\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n\n        // No extra data should have been sent.\n        XCTAssertNoThrow(XCTAssertNil(try self.decoderChannel.readOutbound()))\n\n        // Allow the channel to close.\n        swallower.allowClose()\n\n        // Take the handler out for cleanliness.\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.removeHandler(swallower).wait())\n    }\n\n    func testClosingSynchronouslyOnChannelRead() throws {\n        // We're going to send a connectionClose frame and confirm we only see it once.\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(SynchronousCloser()))\n\n        var errorCodeBuffer = self.encoderChannel.allocator.buffer(capacity: 4)\n        errorCodeBuffer.write(webSocketErrorCode: .normalClosure)\n        let frame = WebSocketFrame(fin: true, opcode: .connectionClose, data: errorCodeBuffer)\n\n        // Write the frame, send it through the decoder channel. We need to do this in one go to trigger\n        // a double-parse edge case.\n        self.encoderChannel.write(frame, promise: nil)\n        var frameBuffer = self.decoderChannel.allocator.buffer(capacity: 10)\n        while var d = try self.encoderChannel.readOutbound(as: ByteBuffer.self) {\n            frameBuffer.writeBuffer(&d)\n        }\n        XCTAssertNoThrow(try self.decoderChannel.writeInbound(frameBuffer))\n\n        // No data should have been sent or received.\n        XCTAssertNoThrow(XCTAssertNil(try self.decoderChannel.readOutbound()))\n        XCTAssertNoThrow(XCTAssertNil(try self.decoderChannel.readInbound(as: WebSocketFrame.self)))\n    }\n\n    func testDecoderRejectsOverlongFramesWithNoAutomaticErrorHandling() {\n        // We need to insert a decoder that doesn't do error handling. We still insert\n        // an encoder because we want to fail gracefully if a frame is written.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n\n        // A fake frame header that claims that the length of the frame is 16385 bytes,\n        // larger than the frame max.\n        self.buffer.writeBytes([0x81, 0xFE, 0x40, 0x01])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.invalidFrameLength, error as? NIOWebSocketError)\n        }\n\n        // No error frame should be written.\n        XCTAssertNoThrow(XCTAssertEqual([], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testDecoderRejectsFragmentedControlFramesWithNoAutomaticErrorHandling() throws {\n        // We need to insert a decoder that doesn't do error handling. We still insert\n        // an encoder because we want to fail gracefully if a frame is written.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n\n        // A fake frame header that claims this is a fragmented ping frame.\n        self.buffer.writeBytes([0x09, 0x00])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.fragmentedControlFrame, error as? NIOWebSocketError)\n        }\n\n        // No error frame should be written.\n        XCTAssertNoThrow(XCTAssertEqual([], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testDecoderRejectsMultibyteControlFrameLengthsWithNoAutomaticErrorHandling() throws {\n        // We need to insert a decoder that doesn't do error handling. We still insert\n        // an encoder because we want to fail gracefully if a frame is written.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n\n        // A fake frame header that claims this is a ping frame with 126 bytes of data.\n        self.buffer.writeBytes([0x89, 0x7E, 0x00, 0x7E])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.multiByteControlFrameLength, error as? NIOWebSocketError)\n        }\n\n        // No error frame should be written.\n        XCTAssertNoThrow(XCTAssertEqual([], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testIgnoresFurtherDataAfterRejectedFrameWithNoAutomaticErrorHandling() {\n        // We need to insert a decoder that doesn't do error handling. We still insert\n        // an encoder because we want to fail gracefully if a frame is written.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n\n        // A fake frame header that claims this is a fragmented ping frame.\n        self.buffer.writeBytes([0x09, 0x00])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.fragmentedControlFrame, error as? NIOWebSocketError)\n        }\n\n        // No error frame should be written.\n        XCTAssertNoThrow(XCTAssertEqual([], try self.decoderChannel.readAllOutboundBytes()))\n\n        // Now write another broken frame, this time an overlong frame.\n        self.buffer.clear()\n        let wrongFrame: [UInt8] = [0x81, 0xFE, 0x40, 0x01]\n        self.buffer.writeBytes(wrongFrame)\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            if case .some(.dataReceivedInErrorState(let innerError, let data)) = error as? ByteToMessageDecoderError {\n                // ok\n                XCTAssertEqual(.fragmentedControlFrame, innerError as? NIOWebSocketError)\n                XCTAssertEqual(wrongFrame, Array(data.readableBytesView))\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n\n        // No extra data should have been sent.\n        XCTAssertNoThrow(XCTAssertNil(try self.decoderChannel.readOutbound()))\n    }\n\n    func testDecoderRejectsOverlongFramesWithSeparateErrorHandling() throws {\n        // We need to insert a decoder that doesn't do error handling, and then a separate error\n        // handler.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims that the length of the frame is 16385 bytes,\n        // larger than the frame max.\n        self.buffer.writeBytes([0x81, 0xFE, 0x40, 0x01])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.invalidFrameLength, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xF1], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testDecoderRejectsFragmentedControlFramesWithSeparateErrorHandling() throws {\n        // We need to insert a decoder that doesn't do error handling, and then a separate error\n        // handler.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims this is a fragmented ping frame.\n        self.buffer.writeBytes([0x09, 0x00])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.fragmentedControlFrame, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xEA], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testDecoderRejectsMultibyteControlFrameLengthsWithSeparateErrorHandling() throws {\n        // We need to insert a decoder that doesn't do error handling, and then a separate error\n        // handler.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims this is a ping frame with 126 bytes of data.\n        self.buffer.writeBytes([0x89, 0x7E, 0x00, 0x7E])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.multiByteControlFrameLength, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual(try self.decoderChannel.readAllOutboundBytes(), [0x88, 0x02, 0x03, 0xEA]))\n    }\n\n    func testIgnoresFurtherDataAfterRejectedFrameWithSeparateErrorHandling() {\n        let swallower = CloseSwallower()\n        // We need to insert a decoder that doesn't do error handling, and then a separate error\n        // handler.\n        self.swapDecoder(for: ByteToMessageHandler(WebSocketFrameDecoder()))\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(swallower, position: .first))\n\n        // A fake frame header that claims this is a fragmented ping frame.\n        self.buffer.writeBytes([0x09, 0x00])\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.fragmentedControlFrame, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual(try self.decoderChannel.readAllOutboundBytes(), [0x88, 0x02, 0x03, 0xEA]))\n\n        // Now write another broken frame, this time an overlong frame.\n        self.buffer.clear()\n        let wrongFrame: [UInt8] = [0x81, 0xFE, 0x40, 0x01]\n        self.buffer.writeBytes(wrongFrame)\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            if case .some(.dataReceivedInErrorState(let innerError, let data)) = error as? ByteToMessageDecoderError {\n                // ok\n                XCTAssertEqual(.fragmentedControlFrame, innerError as? NIOWebSocketError)\n                XCTAssertEqual(wrongFrame, Array(data.readableBytesView))\n            } else {\n                XCTFail(\"unexpected error: \\(error)\")\n            }\n        }\n\n        // No extra data should have been sent.\n        XCTAssertNoThrow(XCTAssertNil(try self.decoderChannel.readOutbound()))\n\n        // Allow the channel to close.\n        swallower.allowClose()\n\n        // Take the handler out for cleanliness.\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.removeHandler(swallower).wait())\n    }\n\n    func testErrorHandlerDoesNotSwallowRandomErrors() throws {\n        XCTAssertNoThrow(\n            try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder(), position: .first)\n        )\n        XCTAssertNoThrow(try self.decoderChannel.pipeline.syncOperations.addHandler(WebSocketProtocolErrorHandler()))\n\n        // A fake frame header that claims that the length of the frame is 16385 bytes,\n        // larger than the frame max.\n        self.buffer.writeBytes([0x81, 0xFE, 0x40, 0x01])\n\n        struct Dummy: Error {}\n\n        self.decoderChannel.pipeline.fireErrorCaught(Dummy())\n        XCTAssertThrowsError(try self.decoderChannel.throwIfErrorCaught()) { error in\n            XCTAssertNotNil(error as? Dummy, \"unexpected error: \\(error)\")\n        }\n\n        XCTAssertThrowsError(try self.decoderChannel.writeInbound(self.buffer)) { error in\n            XCTAssertEqual(.invalidFrameLength, error as? NIOWebSocketError)\n        }\n\n        // We expect that an error frame will have been written out.\n        XCTAssertNoThrow(XCTAssertEqual([0x88, 0x02, 0x03, 0xF1], try self.decoderChannel.readAllOutboundBytes()))\n    }\n\n    func testWebSocketFrameDescription() {\n        let byteBuffer = ByteBuffer()\n        let webSocketFrame = WebSocketFrame(\n            fin: true,\n            rsv1: true,\n            rsv2: true,\n            rsv3: true,\n            opcode: .binary,\n            maskKey: nil,\n            data: byteBuffer,\n            extensionData: nil\n        )\n\n        let expectedOutput = \"\"\"\n            maskKey: nil, \\\n            fin: true, \\\n            rsv1: true, \\\n            rsv2: true, \\\n            rsv3: true, \\\n            opcode: WebSocketOpcode.binary, \\\n            length: 0, \\\n            data: \\(String(describing: byteBuffer)), \\\n            extensionData: nil, \\\n            unmaskedData: \\(String(describing: byteBuffer)), \\\n            unmaskedDataExtension: nil\n            \"\"\"\n\n        XCTAssertEqual(expectedOutput, String(describing: webSocketFrame))\n    }\n\n    func testWebSocketFrameDebugDescription() {\n        let byteBuffer = ByteBuffer()\n        let webSocketFrame = WebSocketFrame(\n            fin: true,\n            rsv1: true,\n            rsv2: true,\n            rsv3: true,\n            opcode: .binary,\n            maskKey: nil,\n            data: byteBuffer,\n            extensionData: nil\n        )\n\n        let expectedOutput = \"\"\"\n            (\\\n            maskKey: nil, \\\n            fin: true, \\\n            rsv1: true, \\\n            rsv2: true, \\\n            rsv3: true, \\\n            opcode: WebSocketOpcode.binary, \\\n            length: 0, \\\n            data: \\(String(describing: byteBuffer)), \\\n            extensionData: nil, \\\n            unmaskedData: \\(String(describing: byteBuffer)), \\\n            unmaskedDataExtension: nil\\\n            )\n            \"\"\"\n\n        XCTAssertEqual(expectedOutput, webSocketFrame.debugDescription)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/WebSocketFrameEncoderTest.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOEmbedded\nimport NIOWebSocket\nimport XCTest\n\nextension EmbeddedChannel {\n    func readAllOutboundBuffers() throws -> ByteBuffer {\n        var buffer = self.allocator.buffer(capacity: 100)\n        while var writtenData = try self.readOutbound(as: ByteBuffer.self) {\n            buffer.writeBuffer(&writtenData)\n        }\n\n        return buffer\n    }\n\n    func readAllOutboundBytes() throws -> [UInt8] {\n        var buffer = try self.readAllOutboundBuffers()\n        return buffer.readAllBytes()\n    }\n}\n\nextension ByteBuffer {\n    mutating func readAllBytes() -> [UInt8] {\n        self.readBytes(length: self.readableBytes)!\n    }\n}\n\npublic final class WebSocketFrameEncoderTest: XCTestCase {\n    public var channel: EmbeddedChannel!\n    public var buffer: ByteBuffer!\n\n    public override func setUp() {\n        self.channel = EmbeddedChannel()\n        self.buffer = channel.allocator.buffer(capacity: 128)\n        XCTAssertNoThrow(try self.channel.pipeline.syncOperations.addHandler(WebSocketFrameEncoder()))\n    }\n\n    public override func tearDown() {\n        XCTAssertNoThrow(try self.channel.finish())\n        self.channel = nil\n        self.buffer = nil\n    }\n\n    private func assertFrameEncodes(frame: WebSocketFrame, expectedBytes: [UInt8]) {\n        self.channel.writeAndFlush(frame, promise: nil)\n        XCTAssertNoThrow(XCTAssertEqual(expectedBytes, try self.channel.readAllOutboundBytes()))\n    }\n\n    func testBasicFrameEncoding() throws {\n        let dataString = \"hello, world!\"\n        self.buffer.writeString(\"hello, world!\")\n        let frame = WebSocketFrame(fin: true, opcode: .binary, data: self.buffer)\n        let expectedBytes = [0x82, UInt8(dataString.count)] + Array(dataString.utf8)\n        assertFrameEncodes(frame: frame, expectedBytes: expectedBytes)\n    }\n\n    func test16BitFrameLength() throws {\n        let dataBytes = Array(repeating: UInt8(4), count: 1000)\n        self.buffer.writeBytes(dataBytes)\n        let frame = WebSocketFrame(fin: true, opcode: .text, data: self.buffer)\n        let expectedBytes = [0x81, UInt8(126), UInt8(0x03), UInt8(0xE8)] + dataBytes\n        assertFrameEncodes(frame: frame, expectedBytes: expectedBytes)\n    }\n\n    func test64BitFrameLength() throws {\n        let dataBytes = Array(repeating: UInt8(4), count: 65536)\n        self.buffer.writeBytes(dataBytes)\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, data: self.buffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        let expectedBytes: [UInt8] = [0x82, 0x7F, 0, 0, 0, 0, 0, 1, 0, 0]\n        XCTAssertNoThrow(XCTAssertEqual(expectedBytes[...], try self.channel.readAllOutboundBytes()[..<10]))\n    }\n\n    func testEncodesEachReservedBitProperly() throws {\n        let firstFrame = WebSocketFrame(fin: true, rsv1: true, opcode: .binary, data: self.buffer)\n        let secondFrame = WebSocketFrame(fin: false, rsv2: true, opcode: .text, data: self.buffer)\n        let thirdFrame = WebSocketFrame(fin: true, rsv3: true, opcode: .ping, data: self.buffer)\n\n        assertFrameEncodes(frame: firstFrame, expectedBytes: [0xC2, 0x0])\n        assertFrameEncodes(frame: secondFrame, expectedBytes: [0x21, 0x0])\n        assertFrameEncodes(frame: thirdFrame, expectedBytes: [0x99, 0x0])\n    }\n\n    func testEncodesExtensionDataCorrectly() throws {\n        let dataBytes: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n        self.buffer.writeBytes(dataBytes)\n\n        let frame = WebSocketFrame(\n            fin: false,\n            opcode: .text,\n            data: self.buffer.getSlice(at: self.buffer.readerIndex, length: 5)!,\n            extensionData: self.buffer.getSlice(at: self.buffer.readerIndex + 5, length: 5)!\n        )\n        assertFrameEncodes(\n            frame: frame,\n            expectedBytes: [0x01, 0x0A, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5]\n        )\n    }\n\n    func testMasksDataCorrectly() throws {\n        let dataBytes: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n        self.buffer.writeBytes(dataBytes)\n\n        let frame = WebSocketFrame(\n            fin: true,\n            opcode: .binary,\n            maskKey: maskKey,\n            data: self.buffer.getSlice(at: self.buffer.readerIndex, length: 5)!,\n            extensionData: self.buffer.getSlice(at: self.buffer.readerIndex + 5, length: 5)!\n        )\n        assertFrameEncodes(\n            frame: frame,\n            expectedBytes: [\n                0x82, 0x8A, 0x80, 0x08, 0x10, 0x01, 0x86, 0x0F, 0x18, 0x08, 0x8A, 0x09, 0x12, 0x02, 0x84, 0x0D,\n            ]\n        )\n    }\n\n    func testFrameEncoderReusesHeaderBufferWherePossible() {\n        let dataBytes: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n        self.buffer.writeBytes(dataBytes)\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: self.buffer)\n\n        // We're going to send the above frame twice, and capture the value of the backing pointer each time. It should\n        // be identical in both cases so long as we force the header buffer to nil between uses.\n        var headerBuffer: ByteBuffer? = nil\n        self.channel.writeAndFlush(frame, promise: nil)\n        XCTAssertNoThrow(headerBuffer = try self.channel.readOutbound(as: ByteBuffer.self))\n\n        let originalPointer = headerBuffer?.withVeryUnsafeBytes { UInt(bitPattern: $0.baseAddress!) }\n        headerBuffer = nil\n        XCTAssertNoThrow(try self.channel.readOutbound(as: ByteBuffer.self))  // Throw away the body data.\n\n        self.channel.writeAndFlush(frame, promise: nil)\n        XCTAssertNoThrow(headerBuffer = try self.channel.readOutbound(as: ByteBuffer.self))\n\n        let newPointer = headerBuffer?.withVeryUnsafeBytes { UInt(bitPattern: $0.baseAddress!) }\n        XCTAssertNoThrow(try self.channel.readOutbound(as: ByteBuffer.self))  // Throw away the body data again.\n        XCTAssertEqual(originalPointer, newPointer)\n        XCTAssertNotNil(originalPointer)\n    }\n\n    func testFrameEncoderCanPrependHeaderToApplicationBuffer() {\n        let dataBytes: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 6 spare bytes for this header.\n        self.buffer.moveWriterIndex(forwardBy: 6)\n        self.buffer.moveReaderIndex(forwardBy: 6)\n        self.buffer.writeBytes(dataBytes)\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: originalBuffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var result: ByteBuffer? = nil\n        XCTAssertNoThrow(result = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertEqual(\n            result?.readAllBytes(),\n            [0x82, 0x8A, 0x80, 0x08, 0x10, 0x01, 0x81, 0x0A, 0x13, 0x05, 0x85, 0x0E, 0x17, 0x09, 0x89, 0x02]\n        )\n    }\n\n    func testFrameEncoderCanPrependHeaderToExtensionBuffer() {\n        let dataBytes: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 6 spare bytes, but let's leave even more room.\n        self.buffer.moveWriterIndex(forwardBy: 16)\n        self.buffer.moveReaderIndex(forwardBy: 16)\n        self.buffer.writeBytes(dataBytes)\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        // We need an extra buffer for application data, but it'll be empty.\n        let applicationOriginalBuffer = ByteBufferAllocator().buffer(capacity: 1024)\n\n        let frame = WebSocketFrame(\n            fin: true,\n            opcode: .binary,\n            maskKey: maskKey,\n            data: applicationOriginalBuffer,\n            extensionData: originalBuffer\n        )\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var extensionBuffer: ByteBuffer? = nil\n        var applicationBuffer: ByteBuffer? = nil\n        XCTAssertNoThrow(extensionBuffer = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(applicationBuffer = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        XCTAssertEqual(\n            extensionBuffer?.readAllBytes(),\n            [0x82, 0x8A, 0x80, 0x08, 0x10, 0x01, 0x81, 0x0A, 0x13, 0x05, 0x85, 0x0E, 0x17, 0x09, 0x89, 0x02]\n        )\n        XCTAssertEqual(applicationBuffer?.readAllBytes(), [])\n    }\n\n    func testFrameEncoderCanPrependMediumHeader() {\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 8 spare bytes for this header.\n        self.buffer.moveWriterIndex(forwardBy: 8)\n        self.buffer.moveReaderIndex(forwardBy: 8)\n        self.buffer.writeBytes(repeatElement(0, count: 126))\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: originalBuffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var result: ByteBuffer? = nil\n        XCTAssertNoThrow(result = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        // The header size should be 8 bytes: leading byte, length, 2 extra length bytes, 4 byte mask.\n        XCTAssertEqual(\n            result?.readBytes(length: 8),\n            [0x82, 0xFE, 0x00, 0x7E, 0x80, 0x08, 0x10, 0x01]\n        )\n    }\n\n    func testFrameEncoderCanPrependLargeHeader() {\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 14 spare bytes for this header.\n        self.buffer.moveWriterIndex(forwardBy: 14)\n        self.buffer.moveReaderIndex(forwardBy: 14)\n        self.buffer.writeBytes(repeatElement(0, count: Int(UInt16.max) + 1))\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: originalBuffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var result: ByteBuffer? = nil\n        XCTAssertNoThrow(result = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        // The header size should be 14 bytes: leading byte, length, 8 extra length bytes, 4 byte mask.\n        XCTAssertEqual(\n            result?.readBytes(length: 14),\n            [0x82, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x08, 0x10, 0x01]\n        )\n    }\n\n    func testFrameEncoderFailsToPrependHeaderWithInsufficientSpace() {\n        let dataBytes: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 6 spare bytes for this header, so let's only free up 5.\n        self.buffer.moveWriterIndex(forwardBy: 5)\n        self.buffer.moveReaderIndex(forwardBy: 5)\n        self.buffer.writeBytes(dataBytes)\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: originalBuffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var result: ByteBuffer? = nil\n        XCTAssertNoThrow(result = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNotNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        // This will only be the frame header.\n        XCTAssertEqual(\n            result?.readAllBytes(),\n            [0x82, 0x8A, 0x80, 0x08, 0x10, 0x01]\n        )\n    }\n\n    func testFrameEncoderFailsToPrependMediumHeaderWithInsufficientSpace() {\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 8 spare bytes for this header, so let's only leave 7.\n        self.buffer.moveWriterIndex(forwardBy: 7)\n        self.buffer.moveReaderIndex(forwardBy: 7)\n        self.buffer.writeBytes(repeatElement(0, count: 126))\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: originalBuffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var result: ByteBuffer? = nil\n        XCTAssertNoThrow(result = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNotNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        // This will only be the frame header.\n        XCTAssertEqual(\n            result?.readAllBytes(),\n            [0x82, 0xFE, 0x00, 0x7E, 0x80, 0x08, 0x10, 0x01]\n        )\n    }\n\n    func testFrameEncoderFailsToPrependLargeHeaderWithInsufficientSpace() {\n        let maskKey: WebSocketMaskingKey = [0x80, 0x08, 0x10, 0x01]\n\n        // We need 14 spare bytes for this header, so let's only leave 13\n        self.buffer.moveWriterIndex(forwardBy: 13)\n        self.buffer.moveReaderIndex(forwardBy: 13)\n        self.buffer.writeBytes(repeatElement(0, count: Int(UInt16.max) + 1))\n\n        let originalBuffer = self.buffer!\n        self.buffer = nil  // gotta nil out here to enable prepending\n\n        let frame = WebSocketFrame(fin: true, opcode: .binary, maskKey: maskKey, data: originalBuffer)\n        self.channel.writeAndFlush(frame, promise: nil)\n\n        var result: ByteBuffer? = nil\n        XCTAssertNoThrow(result = try self.channel.readOutbound(as: ByteBuffer.self))\n        XCTAssertNoThrow(XCTAssertNotNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n        XCTAssertNoThrow(XCTAssertNil(try self.channel.readOutbound(as: ByteBuffer.self)))\n\n        // This will only be the frame header.\n        XCTAssertEqual(\n            result?.readAllBytes(),\n            [0x82, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x08, 0x10, 0x01]\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/WebSocketMaskingKeyTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOCore\nimport NIOWebSocket\nimport XCTest\n\nfinal class WebSocketMaskingKeyTests: XCTestCase {\n    var generator = SystemRandomNumberGenerator()\n    func testRandomMaskingKey() {\n        let key = WebSocketMaskingKey.random(using: &generator)\n        var buffer = ByteBuffer(bytes: [1, 2, 3, 4, 5, 6, 7, 8])\n        buffer.webSocketMask(key)\n        buffer.webSocketUnmask(key)\n        XCTAssertEqual(buffer, ByteBuffer(bytes: [1, 2, 3, 4, 5, 6, 7, 8]))\n    }\n\n    func testRandomMaskingKeyIsNotAlwaysZero() {\n        XCTAssertTrue(\n            (0..<1000).contains { _ in\n                WebSocketMaskingKey.random(using: &generator) != [0, 0, 0, 0]\n            },\n            \"at least 1 of 1000 random masking keys should not be all zeros\"\n        )\n    }\n\n    func testRandomMaskingKeyIsNotAlwaysZeroWithDefaultGenerator() {\n        XCTAssertTrue(\n            (0..<1000).contains { _ in\n                WebSocketMaskingKey.random() != [0, 0, 0, 0]\n            },\n            \"at least 1 of 1000 random masking keys with default generator should not be all zeros\"\n        )\n    }\n\n    func testGetReservedBits() {\n        let frame = WebSocketFrame(rsv1: true, opcode: .binary, data: .init())\n        XCTAssertEqual(frame.reservedBits.contains(.rsv1), true)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv2), false)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv3), false)\n        let frame2 = WebSocketFrame(rsv2: true, opcode: .binary, data: .init())\n        XCTAssertEqual(frame2.reservedBits.contains(.rsv1), false)\n        XCTAssertEqual(frame2.reservedBits.contains(.rsv2), true)\n        XCTAssertEqual(frame2.reservedBits.contains(.rsv3), false)\n        let frame3 = WebSocketFrame(rsv3: true, opcode: .binary, data: .init())\n        XCTAssertEqual(frame3.reservedBits.contains(.rsv1), false)\n        XCTAssertEqual(frame3.reservedBits.contains(.rsv2), false)\n        XCTAssertEqual(frame3.reservedBits.contains(.rsv3), true)\n    }\n\n    func testSetReservedBits() {\n        var frame = WebSocketFrame(opcode: .binary, data: .init())\n        frame.reservedBits = .rsv1\n        XCTAssertEqual(frame.reservedBits.contains(.rsv1), true)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv2), false)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv3), false)\n        XCTAssertEqual(frame.fin, false)\n        XCTAssertEqual(frame.opcode, .binary)\n        frame.reservedBits = .rsv2\n        XCTAssertEqual(frame.reservedBits.contains(.rsv1), false)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv2), true)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv3), false)\n        XCTAssertEqual(frame.fin, false)\n        XCTAssertEqual(frame.opcode, .binary)\n        frame.reservedBits = .rsv3\n        XCTAssertEqual(frame.reservedBits.contains(.rsv1), false)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv2), false)\n        XCTAssertEqual(frame.reservedBits.contains(.rsv3), true)\n        XCTAssertEqual(frame.fin, false)\n        XCTAssertEqual(frame.opcode, .binary)\n    }\n}\n"
  },
  {
    "path": "Tests/NIOWebSocketTests/WebSocketServerEndToEndTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport NIOConcurrencyHelpers\nimport NIOEmbedded\nimport NIOHTTP1\nimport XCTest\n\n@testable import NIOCore\n@testable import NIOWebSocket\n\nextension EmbeddedChannel {\n    func readAllInboundBuffers() throws -> ByteBuffer {\n        var buffer = self.allocator.buffer(capacity: 100)\n        while var writtenData: ByteBuffer = try self.readInbound() {\n            buffer.writeBuffer(&writtenData)\n        }\n\n        return buffer\n    }\n\n    func finishAcceptingAlreadyClosed() throws {\n        do {\n            let result = try self.finish().isClean\n            XCTAssertTrue(result)\n        } catch ChannelError.alreadyClosed {\n            // ok\n        }\n    }\n}\n\nextension ByteBuffer {\n    func allAsString() -> String {\n        self.getString(at: self.readerIndex, length: self.readableBytes)!\n    }\n}\n\nextension EmbeddedChannel {\n    func writeString(_ string: String) -> EventLoopFuture<Void> {\n        self.writeAndFlush(self.allocator.buffer(string: string))\n    }\n}\n\nprivate func interactInMemory(\n    _ first: EmbeddedChannel,\n    _ second: EmbeddedChannel,\n    eventLoop: EmbeddedEventLoop\n) throws {\n    var operated: Bool\n\n    repeat {\n        eventLoop.run()\n        operated = false\n\n        if let data = try first.readOutbound(as: ByteBuffer.self) {\n            operated = true\n            try second.writeInbound(data)\n        }\n        if let data = try second.readOutbound(as: ByteBuffer.self) {\n            operated = true\n            try first.writeInbound(data)\n        }\n    } while operated\n}\n\nprivate func assertResponseIs(response: String, expectedResponseLine: String, expectedResponseHeaders: [String]) {\n    var lines = response.split(separator: \"\\r\\n\", omittingEmptySubsequences: false).map { String($0) }\n\n    // We never expect a response body here. This means we need the last two entries to be empty strings.\n    XCTAssertEqual(\"\", lines.removeLast())\n    XCTAssertEqual(\"\", lines.removeLast())\n\n    // Check the response line is correct.\n    let actualResponseLine = lines.removeFirst()\n    XCTAssertEqual(expectedResponseLine, actualResponseLine)\n\n    // For each header, find it in the actual response headers and remove it.\n    for expectedHeader in expectedResponseHeaders {\n        guard let index = lines.firstIndex(of: expectedHeader) else {\n            XCTFail(\"Could not find header \\\"\\(expectedHeader)\\\"\")\n            return\n        }\n        lines.remove(at: index)\n    }\n\n    // That should be all the headers.\n    XCTAssertEqual(lines.count, 0)\n}\n\nprivate class WebSocketRecorderHandler: ChannelInboundHandler {\n    typealias InboundIn = WebSocketFrame\n    typealias OutboundOut = WebSocketFrame\n\n    fileprivate var frames: [WebSocketFrame] = []\n    fileprivate var errors: [Error] = []\n\n    func channelRead(context: ChannelHandlerContext, data: NIOAny) {\n        let frame = Self.unwrapInboundIn(data)\n        self.frames.append(frame)\n    }\n\n    func errorCaught(context: ChannelHandlerContext, error: Error) {\n        self.errors.append(error)\n        context.fireErrorCaught(error)\n    }\n}\n\nstruct WebSocketServerUpgraderConfiguration {\n    let maxFrameSize: Int\n    let automaticErrorHandling: Bool\n    let shouldUpgrade: @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>\n    let upgradePipelineHandler: @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<Void>\n\n    @preconcurrency\n    init(\n        maxFrameSize: Int = 1 << 14,\n        automaticErrorHandling: Bool = true,\n        shouldUpgrade: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>,\n        upgradePipelineHandler: @escaping @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture<Void>\n    ) {\n        self.maxFrameSize = maxFrameSize\n        self.automaticErrorHandling = automaticErrorHandling\n        self.shouldUpgrade = shouldUpgrade\n        self.upgradePipelineHandler = upgradePipelineHandler\n    }\n}\n\nclass WebSocketServerEndToEndTests: XCTestCase {\n    func createTestFixtures(\n        upgraders: [WebSocketServerUpgraderConfiguration],\n        loop: EmbeddedEventLoop? = nil\n    ) -> (loop: EmbeddedEventLoop, serverChannel: EmbeddedChannel, clientChannel: EmbeddedChannel) {\n        let loop = loop ?? EmbeddedEventLoop()\n        let serverChannel = EmbeddedChannel(loop: loop)\n        let upgraders: [HTTPServerProtocolUpgrader & Sendable] = upgraders.map {\n            NIOWebSocketServerUpgrader(\n                maxFrameSize: $0.maxFrameSize,\n                automaticErrorHandling: $0.automaticErrorHandling,\n                shouldUpgrade: $0.shouldUpgrade,\n                upgradePipelineHandler: $0.upgradePipelineHandler\n            )\n        }\n        XCTAssertNoThrow(\n            try serverChannel.pipeline.configureHTTPServerPipeline(\n                withServerUpgrade: (\n                    upgraders: upgraders,\n                    completionHandler: { (context: ChannelHandlerContext) in }\n                )\n            ).wait()\n        )\n        let clientChannel = EmbeddedChannel(loop: loop)\n        return (loop: loop, serverChannel: serverChannel, clientChannel: clientChannel)\n    }\n\n    private func upgradeRequest(\n        path: String = \"/\",\n        extraHeaders: [String: String],\n        protocolName: String = \"websocket\"\n    ) -> String {\n        let extraHeaderString = extraHeaders.map { hdr in \"\\(hdr.key): \\(hdr.value)\" }.joined(separator: \"\\r\\n\")\n        return \"GET \\(path) HTTP/1.1\\r\\nHost: example.com\\r\\nConnection: upgrade\\r\\nUpgrade: \\(protocolName)\\r\\n\"\n            + extraHeaderString + \"\\r\\n\\r\\n\"\n    }\n\n    func testBasicUpgradeDance() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        loop.run()\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n    }\n\n    func testUpgradeWithProtocolName() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(\n            extraHeaders: [\"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\"],\n            protocolName: \"WebSocket\"\n        )\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n    }\n\n    func testCanRejectUpgrade() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(nil) },\n            upgradePipelineHandler: { (channel, req) in\n                XCTFail(\"Should not have called\")\n                return channel.eventLoop.makeSucceededFuture(())\n            }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        let buffer = server.allocator.buffer(string: upgradeRequest)\n\n        // Write this directly to the server.\n        XCTAssertThrowsError(try server.writeInbound(buffer)) { error in\n            XCTAssertEqual(.unsupportedWebSocketTarget, error as? NIOWebSocketUpgradeError)\n        }\n\n        // Nothing gets written.\n        XCTAssertNoThrow(XCTAssertEqual(try server.readAllOutboundBuffers().allAsString(), \"\"))\n    }\n\n    func testCanDelayAcceptingUpgrade() throws {\n        // This accept promise is going to be written to from a callback. This is only safe because we use\n        // embedded channels.\n        let acceptPromise = NIOLockedValueBox<EventLoopPromise<HTTPHeaders?>?>(nil)\n        let upgradeComplete = NIOLockedValueBox(false)\n\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in\n                let promise = channel.eventLoop.makePromise(of: Optional<HTTPHeaders>.self)\n                acceptPromise.withLockedValue { $0 = promise }\n                return promise.futureResult\n            },\n            upgradePipelineHandler: { (channel, req) in\n                upgradeComplete.withLockedValue { $0 = true }\n                return channel.eventLoop.makeSucceededFuture(())\n            }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        XCTAssertNil(acceptPromise.withLockedValue { $0 })\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNotNil(acceptPromise)\n\n        // No upgrade should have occurred yet.\n        XCTAssertNoThrow(XCTAssertNil(try client.readInbound(as: ByteBuffer.self)))\n        XCTAssertFalse(upgradeComplete.withLockedValue { $0 })\n\n        // Satisfy the promise. This will cause the upgrade to complete.\n        acceptPromise.withLockedValue { $0?.succeed(HTTPHeaders()) }\n        loop.run()\n        XCTAssertTrue(upgradeComplete.withLockedValue { $0 })\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n    }\n\n    func testRequiresVersion13() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"12\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        let buffer = server.allocator.buffer(string: upgradeRequest)\n\n        // Write this directly to the server.\n        XCTAssertThrowsError(try server.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidUpgradeHeader, error as? NIOWebSocketUpgradeError)\n        }\n\n        // Nothing gets written.\n        XCTAssertNoThrow(XCTAssertEqual(try server.readAllOutboundBuffers().allAsString(), \"\"))\n    }\n\n    func testRequiresVersionHeader() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\"])\n        let buffer = server.allocator.buffer(string: upgradeRequest)\n\n        // Write this directly to the server.\n        XCTAssertThrowsError(try server.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidUpgradeHeader, error as? NIOWebSocketUpgradeError)\n        }\n\n        // Nothing gets written.\n        XCTAssertNoThrow(XCTAssertEqual(try server.readAllOutboundBuffers().allAsString(), \"\"))\n    }\n\n    func testRequiresKeyHeader() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\"Sec-WebSocket-Version\": \"13\"])\n        let buffer = server.allocator.buffer(string: upgradeRequest)\n\n        // Write this directly to the server.\n        XCTAssertThrowsError(try server.writeInbound(buffer)) { error in\n            XCTAssertEqual(.invalidUpgradeHeader, error as? NIOWebSocketUpgradeError)\n        }\n\n        // Nothing gets written.\n        XCTAssertNoThrow(XCTAssertEqual(try server.readAllOutboundBuffers().allAsString(), \"\"))\n    }\n\n    func testUpgradeMayAddCustomHeaders() throws {\n        let upgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in\n                var hdrs = HTTPHeaders()\n                hdrs.add(name: \"TestHeader\", value: \"TestValue\")\n                return channel.eventLoop.makeSucceededFuture(hdrs)\n            },\n            upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [upgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                    \"TestHeader: TestValue\",\n                ]\n            )\n        )\n    }\n\n    func testMayRegisterMultipleWebSocketEndpoints() throws {\n        func buildHandler(path: String) -> WebSocketServerUpgraderConfiguration {\n            WebSocketServerUpgraderConfiguration(\n                shouldUpgrade: { (channel, head) in\n                    guard head.uri == \"/\\(path)\" else { return channel.eventLoop.makeSucceededFuture(nil) }\n                    var hdrs = HTTPHeaders()\n                    hdrs.add(name: \"Target\", value: path)\n                    return channel.eventLoop.makeSucceededFuture(hdrs)\n                },\n                upgradePipelineHandler: { (channel, req) in channel.eventLoop.makeSucceededFuture(()) }\n            )\n        }\n        let first = buildHandler(path: \"first\")\n        let second = buildHandler(path: \"second\")\n        let third = buildHandler(path: \"third\")\n\n        let (loop, server, client) = self.createTestFixtures(upgraders: [first, second, third])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(\n            path: \"/third\",\n            extraHeaders: [\"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\"]\n        )\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                    \"Target: third\",\n                ]\n            )\n        )\n    }\n\n    func testSendAFewFrames() throws {\n        let embeddedEventLoop = EmbeddedEventLoop()\n        let recorder = NIOLoopBound(WebSocketRecorderHandler(), eventLoop: embeddedEventLoop)\n\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(recorder.value)\n                }\n            }\n        )\n\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader], loop: embeddedEventLoop)\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n\n        // Put a frame encoder in the client pipeline.\n        XCTAssertNoThrow(try client.pipeline.syncOperations.addHandler(WebSocketFrameEncoder()))\n\n        var data = client.allocator.buffer(capacity: 12)\n        data.writeString(\"hello, world\")\n\n        // Let's send a frame or two, to confirm that this works.\n        let dataFrame = WebSocketFrame(fin: true, opcode: .binary, data: data)\n        XCTAssertNoThrow(try client.writeAndFlush(dataFrame).wait())\n\n        let pingFrame = WebSocketFrame(fin: true, opcode: .ping, data: client.allocator.buffer(capacity: 0))\n        XCTAssertNoThrow(try client.writeAndFlush(pingFrame).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertEqual(recorder.value.frames, [dataFrame, pingFrame])\n    }\n\n    func testMaxFrameSize() throws {\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            maxFrameSize: 16,\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in\n                channel.eventLoop.makeSucceededFuture(())\n            }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader])\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finish())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n\n        let decoder =\n            ((try server.pipeline.syncOperations.context(handlerType: ByteToMessageHandler<WebSocketFrameDecoder>.self))\n            .handler as! ByteToMessageHandler<WebSocketFrameDecoder>).decoder\n        XCTAssertEqual(16, decoder?.maxFrameSize)\n    }\n\n    func testAutomaticErrorHandling() throws {\n        let embeddedEventLoop = EmbeddedEventLoop()\n        let recorder = NIOLoopBound(WebSocketRecorderHandler(), eventLoop: embeddedEventLoop)\n\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(recorder.value)\n                }\n            }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader], loop: embeddedEventLoop)\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finishAcceptingAlreadyClosed())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n\n        // Send a fake frame header that claims this is a ping frame with 126 bytes of data.\n        var data = client.allocator.buffer(capacity: 12)\n        data.writeBytes([0x89, 0x7E, 0x00, 0x7E])\n        XCTAssertNoThrow(try client.writeAndFlush(data).wait())\n\n        XCTAssertThrowsError(try interactInMemory(client, server, eventLoop: loop)) { error in\n            XCTAssertEqual(NIOWebSocketError.multiByteControlFrameLength, error as? NIOWebSocketError)\n        }\n\n        XCTAssertEqual(recorder.value.errors.count, 1)\n        XCTAssertEqual(recorder.value.errors.first as? NIOWebSocketError, .some(.multiByteControlFrameLength))\n\n        // The client should have received a close frame, if we'd continued interacting.\n        XCTAssertNoThrow(XCTAssertEqual(try server.readAllOutboundBytes(), [0x88, 0x02, 0x03, 0xEA]))\n    }\n\n    func testNoAutomaticErrorHandling() throws {\n        let embeddedEventLoop = EmbeddedEventLoop()\n        let recorder = NIOLoopBound(WebSocketRecorderHandler(), eventLoop: embeddedEventLoop)\n\n        let basicUpgrader = WebSocketServerUpgraderConfiguration(\n            automaticErrorHandling: false,\n            shouldUpgrade: { (channel, head) in channel.eventLoop.makeSucceededFuture(HTTPHeaders()) },\n            upgradePipelineHandler: { (channel, req) in\n                channel.eventLoop.makeCompletedFuture {\n                    try channel.pipeline.syncOperations.addHandler(recorder.value)\n                }\n            }\n        )\n        let (loop, server, client) = self.createTestFixtures(upgraders: [basicUpgrader], loop: embeddedEventLoop)\n        defer {\n            XCTAssertNoThrow(try client.finish())\n            XCTAssertNoThrow(try server.finishAcceptingAlreadyClosed())\n            XCTAssertNoThrow(try loop.syncShutdownGracefully())\n        }\n\n        let upgradeRequest = self.upgradeRequest(extraHeaders: [\n            \"Sec-WebSocket-Version\": \"13\", \"Sec-WebSocket-Key\": \"AQIDBAUGBwgJCgsMDQ4PEC==\",\n        ])\n        XCTAssertNoThrow(try client.writeString(upgradeRequest).wait())\n        XCTAssertNoThrow(try interactInMemory(client, server, eventLoop: loop))\n\n        XCTAssertNoThrow(\n            assertResponseIs(\n                response: try client.readAllInboundBuffers().allAsString(),\n                expectedResponseLine: \"HTTP/1.1 101 Switching Protocols\",\n                expectedResponseHeaders: [\n                    \"Upgrade: websocket\", \"Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=\", \"Connection: upgrade\",\n                ]\n            )\n        )\n\n        // Send a fake frame header that claims this is a ping frame with 126 bytes of data.\n        var data = client.allocator.buffer(capacity: 12)\n        data.writeBytes([0x89, 0x7E, 0x00, 0x7E])\n        XCTAssertNoThrow(try client.writeAndFlush(data).wait())\n\n        XCTAssertThrowsError(try interactInMemory(client, server, eventLoop: loop)) { error in\n            XCTAssertEqual(NIOWebSocketError.multiByteControlFrameLength, error as? NIOWebSocketError)\n        }\n\n        XCTAssertEqual(recorder.value.errors.count, 1)\n        XCTAssertEqual(recorder.value.errors.first as? NIOWebSocketError, .some(.multiByteControlFrameLength))\n\n        // The client should not have received a close frame, if we'd continued interacting.\n        XCTAssertNoThrow(XCTAssertEqual([], try server.readAllOutboundBytes()))\n    }\n}\n\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal class TypedWebSocketServerEndToEndTests: WebSocketServerEndToEndTests {\n    override func createTestFixtures(\n        upgraders: [WebSocketServerUpgraderConfiguration],\n        loop: EmbeddedEventLoop? = nil\n    ) -> (loop: EmbeddedEventLoop, serverChannel: EmbeddedChannel, clientChannel: EmbeddedChannel) {\n        let loop = loop ?? EmbeddedEventLoop()\n        let serverChannel = EmbeddedChannel(loop: loop)\n        let upgraders = upgraders.map {\n            NIOTypedWebSocketServerUpgrader(\n                maxFrameSize: $0.maxFrameSize,\n                enableAutomaticErrorHandling: $0.automaticErrorHandling,\n                shouldUpgrade: $0.shouldUpgrade,\n                upgradePipelineHandler: $0.upgradePipelineHandler\n            )\n        }\n\n        XCTAssertNoThrow(\n            try serverChannel.pipeline.syncOperations.configureUpgradableHTTPServerPipeline(\n                configuration: .init(\n                    upgradeConfiguration: NIOTypedHTTPServerUpgradeConfiguration<Void>(\n                        upgraders: upgraders,\n                        notUpgradingCompletionHandler: { $0.eventLoop.makeSucceededVoidFuture() }\n                    )\n                )\n            )\n        )\n        let clientChannel = EmbeddedChannel(loop: loop)\n        return (loop: loop, serverChannel: serverChannel, clientChannel: clientChannel)\n    }\n}\n"
  },
  {
    "path": "dev/alloc-limits-from-test-output",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# This script allows you to consume any Jenkins/alloc counter run output and\n# convert it into the right for for the docker-compose script.\n\nset -eu\n\nmode_flag=${1---docker-compose}\n\nfunction usage() {\n    echo >&1 \"Usage: $0 [--docker-compose|--export|--json]\"\n    echo >&1\n    echo >&1 \"Example:\"\n    echo >&1 \"  # copy the output from the Jenkins CI into your clipboard, then\"\n    echo >&1 \"  pbpaste | $0 --docker-compose\"\n}\n\nfunction die() {\n    echo >&2 \"ERROR: $*\"\n    exit 1\n}\n\ncase \"$mode_flag\" in\n    --docker-compose)\n        mode=docker\n        ;;\n    --export)\n        mode=\"export\"\n        ;;\n    --json)\n        mode=json\n        ;;\n    *)\n        usage\n        exit 1\n        ;;\nesac\n\n# stdin is coming from a terminal, i.e. nothing is being piped in.\nif [[ -t 0 ]]; then\n    usage\n    exit 1\nfi\n\nfunction allow_slack() {\n    raw=\"$1\"\n    if [[ ! \"$raw\" =~ ^[0-9]+$ ]]; then\n        die \"not a malloc count: '$raw'\"\n    fi\n    if [[ \"$raw\" -lt 1000 ]]; then\n        echo \"$raw\"\n        return\n    fi\n\n    allocs=$raw\n    while true; do\n        allocs=$(( allocs + 1 ))\n        if [[ \"$allocs\" =~ [0-9]+00$ || \"$allocs\" =~ [0-9]+50$ ]]; then\n            echo \"$allocs\"\n            return\n        fi\n    done\n}\n\njson_blob=\"{\"\n\nlines=$(grep -e \"total number of mallocs\" -e \".total_allocations\" -e \"export MAX_ALLOCS_ALLOWED_\" | \\\n    sed -e \"s/: total number of mallocs: /=/g\" \\\n        -e \"s/.total_allocations: /=/g\" \\\n        -e \"s/info: /test_/g\" \\\n        -e \"s/export MAX_ALLOCS_ALLOWED_/test_/g\" | \\\n    grep -Eo 'test_[a-zA-Z0-9_-]+=[0-9]+' | sort | uniq)\n\nwhile read -r info; do\n    test_name=$(echo \"$info\" | sed \"s/test_//g\" | cut -d= -f1 )\n    allocs=$(allow_slack \"$(echo \"$info\" | cut -d= -f2 | sed \"s/ //g\")\")\n    case \"$mode\" in\n        docker)\n            echo \"      - MAX_ALLOCS_ALLOWED_$test_name=$allocs\"\n            ;;\n        export)\n            echo \"export MAX_ALLOCS_ALLOWED_$test_name=$allocs\"\n            ;;\n        json)\n            json_blob=\"${json_blob}\"$'\\n'\"    \\\"$test_name\\\": $allocs,\"\n            ;;\n        *)\n            die \"Unexpected mode: $mode\"\n            ;;\n    esac\ndone <<< \"$lines\"\n\nif [[ \"$mode\" == \"json\" ]]; then\n    json_blob=$(sed '$ s/,$//g' <<< \"$json_blob\")\n    json_blob+=$'\\n'\"}\"\n    echo \"$json_blob\"\nfi\n"
  },
  {
    "path": "dev/boxed-existentials.d",
    "content": "#!/usr/sbin/dtrace -q -s\n/*===----------------------------------------------------------------------===*\n *\n *  This source file is part of the SwiftNIO open source project\n *\n *  Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n *  Licensed under Apache License v2.0\n *\n *  See LICENSE.txt for license information\n *  See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n *\n *  SPDX-License-Identifier: Apache-2.0\n *\n *===----------------------------------------------------------------------===*/\n\n/*\n * example invocation:\n *   sudo dev/boxed-existentials.d -c .build/release/NIOHTTP1Server\n */\n\npid$target::__swift_allocate_boxed_opaque_existential*:entry {\n    ustack();\n}\n"
  },
  {
    "path": "dev/generate-bytebuffer-multi-int.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nfunction gen() {\n    how_many=$1\n\n    # READ\n    echo \"    @inlinable\"\n    echo \"    @_alwaysEmitIntoClient\"\n    echo -n \"    public mutating func readMultipleIntegers<T1: FixedWidthInteger\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n: FixedWidthInteger\"\n    done\n    echo -n \">(\"\n    echo -n \"endianness: Endianness = .big, as: (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo -n \").Type = (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo -n \").self) -> (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo \")? {\"\n    echo \"        var bytesRequired: Int = MemoryLayout<T1>.size\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo \"        bytesRequired &+= MemoryLayout<T$n>.size\"\n    done\n    echo\n    echo \"        guard self.readableBytes >= bytesRequired else {\"\n    echo \"            return nil\"\n    echo \"        }\"\n    echo\n    for n in $(seq 1 \"$how_many\"); do\n        echo \"        var v$n: T$n = 0\"\n    done\n    echo \"        var offset = 0\"\n    echo \"        self.readWithUnsafeReadableBytes { ptr -> Int in\"\n    echo \"            assert(ptr.count >= bytesRequired)\"\n    echo \"            let basePtr = ptr.baseAddress! // safe, ptr is non-empty\"\n    for n in $(seq 1 \"$how_many\"); do\n        echo \"            withUnsafeMutableBytes(of: &v$n) { destPtr in\"\n        echo \"                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T$n>.size)\"\n        echo \"            }\"\n        echo \"            offset = offset &+ MemoryLayout<T$n>.size\"\n    done\n    echo \"            assert(offset == bytesRequired)\"\n    echo \"            return offset\"\n    echo \"        }\"\n    echo \"        switch endianness {\"\n    for endianness in big little; do\n        echo \"        case .$endianness:\"\n        echo -n \"            return (T1(${endianness}Endian: v1)\"\n        for n in $(seq 2 \"$how_many\"); do\n            echo -n \", T$n(${endianness}Endian: v$n)\"\n        done\n        echo \")\"\n    done\n    echo \"        }\"\n    echo \"    }\"\n    echo\n\n    # PEEK\n    echo \"    @inlinable\"\n    echo \"    @_alwaysEmitIntoClient\"\n    echo -n \"    public func peekMultipleIntegers<T1: FixedWidthInteger\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n: FixedWidthInteger\"\n    done\n    echo -n \">(\"\n    echo -n \"endianness: Endianness = .big, as: (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo -n \").Type = (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo -n \").self) -> (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo \")? {\"\n    echo \"        var copy = self\"\n    echo \"        return copy.readMultipleIntegers(endianness: endianness, as: \\`as\\`)\"\n    echo \"    }\"\n    echo\n\n    # WRITE\n    echo \"    @inlinable\"\n    echo \"    @_alwaysEmitIntoClient\"\n    echo \"    @discardableResult\"\n    echo -n \"    public mutating func writeMultipleIntegers<T1: FixedWidthInteger\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n: FixedWidthInteger\"\n    done\n    echo -n \">(_ value1: T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", _ value$n: T$n\"\n    done\n    echo -n \", endianness: Endianness = .big, as: (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo -n \").Type = (T1\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo -n \", T$n\"\n    done\n    echo \").self) -> Int {\"\n    for n in $(seq 1 \"$how_many\"); do\n        echo \"        var v$n: T$n\"\n    done\n    echo \"        switch endianness {\"\n    for endianness in .big .little; do\n        echo \"        case $endianness:\"\n        for n in $(seq 1 \"$how_many\"); do\n            echo \"            v$n = value$n${endianness}Endian\"\n        done\n    done\n    echo \"        }\"\n    echo\n    echo \"        var spaceNeeded: Int = MemoryLayout<T1>.size\"\n    for n in $(seq 2 \"$how_many\"); do\n        echo \"        spaceNeeded &+= MemoryLayout<T$n>.size\"\n    done\n    echo\n    echo \"        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in\"\n    echo \"            assert(ptr.count >= spaceNeeded)\"\n    echo \"            var offset = 0\"\n    echo \"            let basePtr = ptr.baseAddress! // safe: pointer is non zero length\"\n    for n in $(seq 1 \"$how_many\"); do\n        echo \"            (basePtr + offset).copyMemory(from: &v$n, byteCount: MemoryLayout<T$n>.size)\"\n        echo \"            offset = offset &+ MemoryLayout<T$n>.size\"\n    done\n    echo \"            assert(offset == spaceNeeded)\"\n    echo \"            return offset\"\n    echo \"        }\"\n    echo \"    }\"\n    echo\n}\n\ngrep -q \"ByteBuffer\" \"${BASH_SOURCE[0]}\" || {\n    echo >&2 \"ERROR: ${BASH_SOURCE[0]}: file or directory not found (this should be this script)\"\n    exit 1\n}\n\n{\ncat <<\"EOF\"\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// NOTE: THIS FILE IS AUTO-GENERATED BY dev/generate-bytebuffer-multi-int.sh\nEOF\necho\n\necho \"extension ByteBuffer {\"\n\n# note:\n# - widening the inverval below (eg. going from {2..15} to {2..25}) is Semver minor\n# - narrowing the interval below is SemVer _MAJOR_!\nfor n in {2..15}; do\n    gen \"$n\"\ndone\necho \"}\"\n} > \"$here/../Sources/NIOCore/ByteBuffer-multi-int.swift\"\n"
  },
  {
    "path": "dev/git.commit.template",
    "content": "One line description of your change\n\nMotivation:\n\nExplain here the context, and why you're making that change.\nWhat is the problem you're trying to solve.\n\nModifications:\n\nDescribe the modifications you've done.\n\nResult:\n\nAfter your change, what will change.\n"
  },
  {
    "path": "dev/lldb-smoker",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nnumber_of_breaks=2000\npackage_dir=$(cd \"${1-\"$here/..\"}\" && pwd -P)\nfiles=( \"$package_dir\"/Sources/*/*.swift \"$package_dir\"/Tests/*/*.swift )\n\nfunction random_array_element() {\n    arr=(\"${!1}\")\n    echo ${arr[\"$[RANDOM % ${#arr[@]}]\"]}\n}\n\nfunction number_of_lines() {\n    wc -l < \"$1\"\n}\n\nfunction random_line_number() {\n    echo $(( 1 + ( RANDOM % $(number_of_lines \"$1\") ) ))\n}\n\necho \"Package dir: $package_dir\"\n( set -eux && cd \"$package_dir\" && swift build --build-tests )\nxctest_bundle=( \"$package_dir/.build/debug\"/*PackageTests.xctest )\necho \"xctest bundle: $xctest_bundle\"\n\nif [[ ! -e \"$xctest_bundle\" ]]; then\n    echo >&2 \"ERROR: Couldn't find xctest bundle at $xctest_bundle\"\n    exit 1\nfi\nrun_command=()\nif [[ \"$(uname -s)\" == Darwin ]]; then\n    xctest=$(xcrun -f xctest)\n    run_command+=( \"$xctest\" \"$xctest_bundle\" )\nelse\n    run_command+=( \"$xctest_bundle\" )\nfi\n\nlldb_file=()\nfor f in $(seq \"$number_of_breaks\"); do\n    file=$(random_array_element \"files[@]\")\n    line=$(random_line_number \"$file\")\n\n    lldb_file+=( \"break set -o true -f '$file' -l '$line'\" )\ndone\nlldb_file+=( run )\nfor f in $(seq \"$number_of_breaks\"); do\n    lldb_file+=( 'frame variable --show-all-children' )\n\n    lldb_file+=( cont )\ndone\n\nlldb_response_file=$(mktemp /tmp/lldb-smoker_XXXXXX)\nfor command in \"${lldb_file[@]}\"; do\n    echo \"$command\" >> \"$lldb_response_file\"\ndone\n\necho \"LLDB response file: $lldb_response_file\"\nsleep 0.5\nlldb_command=( lldb --batch --source \"$lldb_response_file\" -- \\\n    \"${run_command[@]}\" )\n\nset +e\nset -x\n\"${lldb_command[@]}\"\nset +x\nset -e\n\necho \"LLDB response file: $lldb_response_file\"\necho \"LLDB command: ${lldb_command[*]}\"\n"
  },
  {
    "path": "dev/make-single-file-spm",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nfunction setup_swiftpm_package() {\n    destination=\"$1\"\n    main_module_name=\"$2\"\n    shift; shift\n\n    modules=()\n    dependencies=()\n    dep_mods=()\n\n    for module in \"$@\"; do\n        shift\n        if [[ \"$module\" == \"--\" ]]; then\n            break\n        fi\n        modules+=( \"$module\" )\n    done\n\n    for dependency in \"$@\"; do\n        shift\n        if [[ \"$dependency\" == \"--\" ]]; then\n            break\n        fi\n        dependencies+=( \"$dependency\" )\n    done\n\n    for dep_mod in \"$@\"; do\n        shift\n        if [[ \"$dep_mod\" == \"--\" ]]; then\n            break\n        fi\n        dep_mods+=( \"$dep_mod\" )\n    done\n\n    cd \"$destination\"\n    cat > Package.swift <<\"EOF\"\n// swift-tools-version:5.7\nimport PackageDescription\n\nvar targets: [PackageDescription.Target] = [\nEOF\n\n    mods_before=()\n    if [[ ${#modules} -gt 0 ]]; then\n        for module in \"${modules[@]}\"; do\n            echo \"    .target(name: \\\"$module\\\", dependencies: [\" >> Package.swift\n            if [[ ${#mods_before} -gt 0 ]]; then\n                for inner_module in \"${mods_before[@]}\"; do\n                    echo \"\\\"$inner_module\\\", \" >> Package.swift\n                done\n            fi\n            echo \"]),\" >> Package.swift\n            mods_before+=( \"$module\" )\n        done\n    fi\n\n    echo \"    .target(name: \\\"$main_module_name\\\", dependencies: [\" >> Package.swift\n    if [[ ${#modules} -gt 0 ]]; then\n        for module in \"${modules[@]}\"; do\n            echo \"\\\"$module\\\", \" >> Package.swift\n        done\n    fi\n    if [[ ${#dep_mods} -gt 0 ]]; then\n        for module in \"${dep_mods[@]}\"; do\n            echo \"\\\"$module\\\", \" >> Package.swift\n        done\n    fi\n    echo \"])]\" >> Package.swift\n    cat >> Package.swift <<EOF\nlet package = Package(\n    name: \"$main_module_name\",\n    products: [\n        .executable(name: \"$main_module_name\", targets: [\"$main_module_name\"])\n    ],\n    dependencies: [\nEOF\n\n    if [[ \"${#dependencies}\" -gt 0 ]]; then\n        for dependency in \"${dependencies[@]}\"; do\n            echo \"$dependency\" >> Package.swift\n        done\n    fi\n\n    cat >> Package.swift <<EOF\n    ],\n    targets: targets\n)\nEOF\n}\n\nfunction usage() {\n    echo >&2 \"Usage: $0 FILE COMMAND\"\n    echo >&2\n    echo >&2 \"COMMANDs:\"\n    echo >&2 \"  xcode # Open this project in Xcode\"\n    echo >&2 \"  mallocs # Show the malloc aggregation for running this project\"\n    echo >&2 \"  build # Build this project\"\n    echo >&2 \"  lldb # Compile and open project in lldb\"\n    echo >&2 \"  run # Run this project\"\n    echo >&2\n    echo >&2 \"FILE format example:\"\n    echo >&2\n    echo >&2 \"// DEPENDENCY: https://github.com/apple/swift-nio.git 1.0.0 NIO NIOHTTP1\"\n    echo >&2 \"// ^^^ this indicates a dependency\"\n    echo >&2 \"// this is code in the main module\"\n    echo >&2\n    echo >&2 \"import NIO\"\n    echo >&2 \"import Foo\"\n    echo >&2\n    echo >&2 \"print(Foo.hello)\"\n    echo >&2\n    echo >&2 \"// MODULE: Foo\"\n    echo >&2 \"// everything here is now in module Foo\"\n    echo >&2\n    echo >&2 \"public let hello = \\\"Hello World\\\"\"\n}\n\nif [[ $# -lt 2 ]]; then\n    usage\n    exit 1\nfi\n\ndestination=$(mktemp -d /tmp/test_package_XXXXXX)\nfile=\"$1\"\ncommand=\"$2\"\nshift; shift\n\nmain_module_name=\"TestApp\"\nmkdir -p \"$destination/Sources/$main_module_name\"\ncurrent_module_file=\"$destination/Sources/$main_module_name/main.swift\"\ncurrent_module_name=\"$main_module_name\"\nall_modules=()\nall_dependencies=()\nall_dependency_modules=()\nnumber_of_lines=0\n\nwhile IFS=\"\" read -r line; do\n    if [[ \"$line\" =~ ^//\\ MODULE:\\ (.*)$ ]]; then\n        module=${BASH_REMATCH[1]}\n\n        all_modules+=( \"$module\" )\n        mkdir -p \"$destination/Sources/$module\"\n        current_module_file=\"$destination/Sources/$module/module.swift\"\n        for (( i=0; i <= number_of_lines; i++ )); do\n            echo >> \"$current_module_file\"\n        done\n    elif [[ \"$line\" =~ ^//\\ DEPENDENCY:\\ ([^ ]+)\\ ([^ ]+)\\ (.*)$ ]]; then\n        url=${BASH_REMATCH[1]}\n        version=${BASH_REMATCH[2]}\n        dep_mods=( ${BASH_REMATCH[3]} )\n        echo \"dependency $url $version, modules: ${dep_mods[*]}\"\n        all_dependencies+=( \".package(url: \\\"$url\\\", from: \\\"$version\\\"), \" )\n        all_dependency_modules+=( ${dep_mods[@]} )\n    else\n        echo \"$line\" >> \"$current_module_file\"\n    fi\n    number_of_lines=$(( number_of_lines + 1 ))\ndone < \"$file\"\n\necho \"all extra modules: ${all_modules[@]+\"${all_modules[@]}\"}\"\nsetup_swiftpm_package \"$destination\" \\\n    \"$main_module_name\" \\\n    \"${all_modules[@]+\"${all_modules[@]}\"}\" \\\n    -- \\\n    \"${all_dependencies[@]+\"${all_dependencies[@]}\"}\" \\\n    -- \\\n    \"${all_dependency_modules[@]+\"${all_dependency_modules[@]}\"}\"\n\ncd \"$destination\"\nswift package dump-package > /dev/null\necho \"SwiftPM package in:\"\necho \"  $destination\"\nbuild_mode=release\nbinary=\"$destination/.build/$build_mode/$main_module_name\"\necho \"  $binary\"\n\nfunction compile() {\n    swift build -c \"$build_mode\" \"$@\"\n}\n\ncase \"$command\" in\n    xcode)\n        xed .\n        ;;\n    xcodeproj)\n        swift package generate-xcodeproj\n        xed \"$main_module_name.xcodeproj\"\n        ;;\n    run)\n        compile \"$@\"\n        swift run -c \"$build_mode\" \"$main_module_name\" \"$@\"\n        ;;\n    build)\n        compile \"$@\"\n        ;;\n    hopper)\n        compile \"$@\"\n        hopperv4 -l Mach-O -e \"$binary\"\n        ;;\n    lldb)\n        compile \"$@\"\n        lldb \"$binary\"\n        ;;\n    mallocs)\n        compile \"$@\"\n        sudo  \"$here/malloc-aggregation.d\" -c \"$binary\"\n        ;;\n    *)\n        echo \"ERROR: unknown command $command\"\n        ;;\nesac\n"
  },
  {
    "path": "dev/malloc-aggregation.bt",
    "content": "#!/usr/bin/env bpftrace\n/*===----------------------------------------------------------------------===*\n *\n *  This source file is part of the SwiftNIO open source project\n *\n *  Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors\n *  Licensed under Apache License v2.0\n *\n *  See LICENSE.txt for license information\n *  See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n *\n *  SPDX-License-Identifier: Apache-2.0\n *\n *===----------------------------------------------------------------------===*/\n\n/*\n * Example invocation:\n *   sudo dev/malloc-aggregation.bt -c .build/release/NIOHTTP1Server\n *\n * This will frequently lack symbols, so consider using the pid-based version:\n *   sudo dev/malloc-aggregation.bt -p 19898\n */\n\nBEGIN {\n    printf(\"\\n\\n\");\n    printf(\"=====\\n\");\n    printf(\"This will collect stack shots of allocations and print it when \");\n    printf(\"you exit bpftrace.\\n\");\n    printf(\"So go ahead, run your tests and then press Ctrl+C in this window \");\n    printf(\"to see the aggregated result\\n\");\n    printf(\"=====\\n\");\n}\n\nuprobe:*:aligned_alloc,\nuprobe:*:calloc,\nuprobe:*:malloc,\nuprobe:*:posix_memalign,\nuprobe:*:realloc,\nuprobe:*:reallocf,\nuprobe:*:valloc,\nuprobe:*:malloc_zone_calloc,\nuprobe:*:malloc_zone_malloc,\nuprobe:*:malloc_zone_memalign,\nuprobe:*:malloc_zone_realloc,\nuprobe:*:malloc_zone_valloc {\n    @malloc_calls[ustack()] = count();\n}\n\nEND {\n    print(@malloc_calls);\n}\n"
  },
  {
    "path": "dev/malloc-aggregation.d",
    "content": "#!/usr/sbin/dtrace -q -s\n/*===----------------------------------------------------------------------===*\n *\n *  This source file is part of the SwiftNIO open source project\n *\n *  Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n *  Licensed under Apache License v2.0\n *\n *  See LICENSE.txt for license information\n *  See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n *\n *  SPDX-License-Identifier: Apache-2.0\n *\n *===----------------------------------------------------------------------===*/\n\n/*\n * example invocation:\n *   sudo dev/malloc-aggregation.d -c .build/release/NIOHTTP1Server\n */\n\n::BEGIN {\n    printf(\"\\n\\n\");\n    printf(\"=====\\n\");\n    printf(\"This will collect stack shots of allocations and print it when \");\n    printf(\"you exit dtrace.\\n\");\n    printf(\"So go ahead, run your tests and then press Ctrl+C in this window \");\n    printf(\"to see the aggregated result\\n\");\n    printf(\"=====\\n\");\n}\n\npid$target::aligned_alloc:entry,\npid$target::calloc:entry,\npid$target::malloc:entry,\npid$target::posix_memalign:entry,\npid$target::realloc:entry,\npid$target::reallocf:entry,\npid$target::valloc:entry,\npid$target::malloc_type_aligned_alloc:entry,\npid$target::malloc_type_calloc:entry,\npid$target::malloc_type_malloc:entry,\npid$target::malloc_type_posix_memalign:entry,\npid$target::malloc_type_realloc:entry,\npid$target::malloc_type_valloc:entry,\npid$target::malloc_zone_calloc:entry,\npid$target::malloc_zone_malloc:entry,\npid$target::malloc_zone_memalign:entry,\npid$target::malloc_zone_realloc:entry,\npid$target::malloc_zone_valloc:entry {\n    @malloc_calls[ustack()] = count();\n}\n\n::END {\n    printa(@malloc_calls);\n}\n"
  },
  {
    "path": "dev/stackdiff/Package.swift",
    "content": "// swift-tools-version: 6.1\n//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"stackdiff\",\n    // Required for Regex support\n    platforms: [.macOS(.v13)],\n    dependencies: [\n        .package(url: \"https://github.com/apple/swift-argument-parser.git\", from: \"1.5.0\")\n    ],\n    targets: [\n        .executableTarget(\n            name: \"stackdiff\",\n            dependencies: [\n                .target(name: \"Stacks\"),\n                .product(\n                    name: \"ArgumentParser\",\n                    package: \"swift-argument-parser\"\n                ),\n            ]\n        ),\n        .target(\n            name: \"Stacks\"\n        ),\n        .testTarget(\n            name: \"StacksTests\",\n            dependencies: [\n                .target(name: \"Stacks\")\n            ]\n        ),\n    ]\n)\n"
  },
  {
    "path": "dev/stackdiff/Sources/Stacks/AggregateStacks.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\n/// A collection of weighted stacks aggregated by their partial stacks.\n///\n/// Effectively a wrapper aound `[PartialStack: [WeightedStack]]` with a few helpers.\npublic struct AggregateStacks {\n    private var storage: [PartialStack: [WeightedStack]]\n\n    public init() {\n        self.storage = [:]\n    }\n\n    /// The set of all partial stacks under which weighted stacks have been aggregated.\n    public var partialStacks: Set<PartialStack> {\n        Set(self.storage.keys)\n    }\n\n    /// The net allocations of all aggregated stacks.\n    public var netAllocations: Int {\n        self.storage.values.reduce(0) { partial, stackAllocs in\n            partial + stackAllocs.netAllocations\n        }\n    }\n\n    /// Adds a weighted stack under the given partial stack.\n    public mutating func groupWeightedStack(_ stack: WeightedStack, by partial: PartialStack) {\n        self.storage[partial, default: []].append(stack)\n    }\n\n    /// Regroups a set of stack from under one partial stack to another.\n    public mutating func regroupStacks(from source: PartialStack, to destination: PartialStack) {\n        guard let stacks = self.removeWeightedStacks(groupedUnder: source) else {\n            return\n        }\n\n        self.storage[destination, default: []].append(contentsOf: stacks)\n    }\n\n    /// Removes all weighted stacks which are grouped under the given partial stack.\n    @discardableResult\n    public mutating func removeWeightedStacks(groupedUnder partial: PartialStack) -> [WeightedStack]? {\n        self.storage.removeValue(forKey: partial)\n    }\n\n    /// Returns the net allocations of all stacks grouped under the given partial stack.\n    public func netAllocations(groupedBy stack: PartialStack) -> Int {\n        self.storage[stack]?.netAllocations ?? 0\n    }\n\n    /// Returns all weighted stacks grouped under the given partial stack.\n    public func weightedStacks(groupedBy stack: PartialStack) -> [WeightedStack] {\n        self.storage[stack, default: []]\n    }\n\n    /// Returns a new aggregate only containing pairs which return true for the given predidate.\n    public func filter(\n        isIncluded: ((key: PartialStack, value: [WeightedStack])) -> Bool\n    ) -> AggregateStacks {\n        var other = AggregateStacks()\n        other.storage = self.storage.filter(isIncluded)\n        return other\n    }\n\n    /// Removes all pairs which return true for the given predicate.\n    public mutating func removeAll(\n        where predicate: ((key: PartialStack, value: [WeightedStack])) -> Bool\n    ) {\n        for (stack, stackAllocs) in self.storage {\n            if predicate((stack, stackAllocs)) {\n                self.storage.removeValue(forKey: stack)\n            }\n        }\n    }\n\n    /// Returns a list of key-values pairs sorted by the given comparator.\n    public func sorted(\n        by comparator: (\n            (key: PartialStack, value: [WeightedStack]),\n            (key: PartialStack, value: [WeightedStack])\n        ) -> Bool\n    ) -> [(key: PartialStack, value: [WeightedStack])] {\n        self.storage.sorted(by: comparator)\n    }\n}\n\nextension AggregateStacks {\n    public mutating func subtract(_ other: AggregateStacks) {\n        for (partialStack, weightedStacks) in other.storage {\n            for var weightedStack in weightedStacks {\n                weightedStack.allocations = -weightedStack.allocations\n                self.groupWeightedStack(weightedStack, by: partialStack)\n            }\n        }\n    }\n\n    public func subtracting(_ other: AggregateStacks) -> AggregateStacks {\n        var copy = self\n        copy.subtract(other)\n        return copy\n    }\n}\n\nextension [WeightedStack] {\n    public var netAllocations: Int {\n        self.reduce(0) { $0 + $1.allocations }\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/Stacks/Parsing/BPFTraceParser.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\n\n/// Parses output from NIO's `malloc-aggregation.bt` bpftrace script.\npublic struct BPFTraceParser: StackParser {\n    private static var allocationsRegex: Regex<(Substring, Substring)> {\n        /^]: (\\d+)$/\n    }\n\n    private var state: ParseState\n    private var stacks: [WeightedStack]\n\n    private init() {\n        self.stacks = []\n        self.state = .parsingHeader\n    }\n\n    private enum ParseResult {\n        case needsNextLine\n        case parsedStack(Stack, Int)\n    }\n\n    private enum ParseState {\n        case parsingHeader\n        case parsingStack(ParsingStackState)\n    }\n\n    private struct ParsingStackState {\n        var lines: [String]\n\n        init() {\n            self.lines = []\n        }\n\n        mutating func parse(_ line: String) -> (ParseState, ParseResult) {\n            if let match = line.firstMatch(of: BPFTraceParser.allocationsRegex) {\n                if let count = Int(match.1) {\n                    return (.parsingHeader, .parsedStack(Stack(self.lines), count))\n                } else {\n                    fatalError(\"Failed to convert '\\(match.1)' to an Int\")\n                }\n            } else {\n                let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines)\n                let split = trimmed.split(separator: \"+\")\n                self.lines.append(split.first.map { String($0) } ?? trimmed)\n                return (.parsingStack(self), .needsNextLine)\n            }\n        }\n    }\n\n    /// Parses input which looks roughly like the following:\n    ///\n    /// ```\n    /// Attaching 14 probes...\n    ///\n    ///\n    /// =====\n    /// This will collect stack shots of allocations and print it when you exit bpftrace.\n    /// So go ahead, run your tests and then press Ctrl+C in this window to see the aggregated result\n    /// =====\n    /// @malloc_calls[\n    ///     malloc+0\n    ///     swift_allocObject+52\n    ///     $s7NIOCore19ByteBufferAllocatorV023zeroCapacityWithDefaultD0_WZ+52\n    ///     swift::threading_impl::once_slow(swift::threading_impl::once_t&, void (*)(void*), void*)+184\n    ///     $s7NIOCore19ByteBufferAllocatorV023zeroCapacityWithDefaultD0AA0bC0Vvau+28\n    ///     $s6NIOSSH25SSHConnectionStateMachineV011SentVersionC0V04idleC09allocatorAeC04IdleC0V_7NIOCore19ByteBufferAllocatorVtcfC+140\n    ///     $s6NIOSSH25SSHConnectionStateMachineV22processOutboundMessage_6buffer9allocator4loopyAA10SSHMessageO_7NIOCore10ByteBufferVzAJ0mN9AllocatorVAJ9EventLoop_ptKF+2104\n    ///     $s6NIOSSH13NIOSSHHandlerC12writeMessage33_8AEACA5B3544E7B06ED6DDDF9DC39B98LL_7context7promiseyAA08SSHMultiD0V_7NIOCore21ChannelHandlerContextCAJ16EventLoopPromiseVyytGSgtKF+928\n    ///     $s6NIOSSH13NIOSSHHandlerC10initialize33_8AEACA5B3544E7B06ED6DDDF9DC39B98LL7contexty7NIOCore21ChannelHandlerContextC_tF+224\n    ///     $s7NIOCore21ChannelHandlerContextC06invokeB6Active33_F5AC316541457BD146E3694279514AA3LLyyF+68\n    ///     $s7NIOCore15ChannelPipelineC21SynchronousOperationsV04fireB10RegisteredyyFTm+44\n    ///     $s11NIOEmbedded19EmbeddedChannelCoreC7NIOCore0cD0AadEP8connect02to7promiseyAD13SocketAddressO_AD16EventLoopPromiseVyytGSgtFTW+100\n    ///     $s7NIOCore18HeadChannelHandlerCAA01_c8OutboundD0A2aDP7connect7context2to7promiseyAA0cD7ContextC_AA13SocketAddressOAA16EventLoopPromiseVyytGSgtFTW+96\n    ///     $s7NIOCore21ChannelHandlerContextC13invokeConnect33_F5AC316541457BD146E3694279514AA3LL2to7promiseyAA13SocketAddressO_AA16EventLoopPromiseVyytGSgtF+88\n    ///     $s7NIOCore23_ChannelOutboundHandlerPAAE4bind7context2to7promiseyAA0bD7ContextC_AA13SocketAddressOAA16EventLoopPromiseVyytGSgtFTf4nnnd_nTm+64\n    ///     $s7NIOCore23_ChannelOutboundHandlerPAAE7connect7context2to7promiseyAA0bD7ContextC_AA13SocketAddressOAA16EventLoopPromiseVyytGSgtF+36\n    ///     $s7NIOCore21ChannelHandlerContextC13invokeConnect33_F5AC316541457BD146E3694279514AA3LL2to7promiseyAA13SocketAddressO_AA16EventLoopPromiseVyytGSgtF+88\n    ///     $s7NIOCore15ChannelPipelineC5bind033_F5AC316541457BD146E3694279514AA3LL2to7promiseyAA13SocketAddressO_AA16EventLoopPromiseVyytGSgtFTm+80\n    ///     0xabd80ee67d34\n    ///     $s11NIOEmbedded15EmbeddedChannelC7connect2to7promisey7NIOCore13SocketAddressO_AG16EventLoopPromiseVyytGSgtF+1104\n    ///     $s11NIOEmbedded15EmbeddedChannelC7NIOCore0C15OutboundInvokerAadEP7connect2to7promiseyAD13SocketAddressO_AD16EventLoopPromiseVyytGSgtFTW+20\n    ///     $s7NIOCore22ChannelOutboundInvokerPAAE7connect2to4file4lineAA15EventLoopFutureCyytGAA13SocketAddressO_s12StaticStringVSutFTf4nddn_n+76\n    ///     $s16NIOSSHBenchmarks26runOneCommandPerConnection19numberOfConnectionsySi_tKF+964\n    ///     $s16NIOSSHBenchmarks10benchmarksyycvpfiyycfU_y9BenchmarkACCKcfU_+68\n    ///     $s9BenchmarkAAC_13configuration7closure5setup8teardownABSgSS_AB13ConfigurationVyABKcyyYaKcSgAJtcfcyABcfU_+48\n    ///     0xabd80ecd9a0c\n    ///     0xabd80ecfab98\n    ///     swift::runJobInEstablishedExecutorContext(swift::Job*)+412\n    ///     swift_job_run+156\n    ///     _dispatch_continuation_pop+236\n    ///     _dispatch_async_redirect_invoke+184\n    ///     _dispatch_worker_thread+432\n    ///     0xe35cdd8c595c\n    ///     0xe35cdd92ba4c\n    /// ]: 1\n    /// ```\n    private mutating func parse(lines: some Sequence<String>) -> [WeightedStack] {\n        for line in lines {\n            switch self.parseNextState(line) {\n            case .parsedStack(let stack, let count):\n                self.stacks.append(WeightedStack(stack: stack, allocations: count))\n\n            case .needsNextLine:\n                ()\n            }\n        }\n\n        return self.stacks\n    }\n\n    private mutating func parseNextState(_ line: String) -> ParseResult {\n        switch self.state {\n        case .parsingHeader:\n            if line == \"@malloc_calls[\" {\n                self.state = .parsingStack(ParsingStackState())\n                return .needsNextLine\n            } else {\n                return .needsNextLine\n            }\n\n        case .parsingStack(var state):\n            let (state, result) = state.parse(line)\n            self.state = state\n            return result\n        }\n    }\n}\n\nextension BPFTraceParser {\n    public static func parse(lines: some Sequence<String>) -> [WeightedStack] {\n        var parser = Self()\n        return parser.parse(lines: lines)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/Stacks/Parsing/DTraceParser.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\n\n/// Parses output from NIO's `malloc-aggregation.d` DTrace script.\npublic struct DTraceParser: StackParser {\n    private static var allocationsRegex: Regex<(Substring, Substring)> {\n        /^ +(\\d+)$/\n    }\n\n    private var state: ParseState\n    private var stacks: [WeightedStack]\n\n    private init() {\n        self.stacks = []\n        self.state = .parsingHeader\n    }\n\n    private enum ParseResult {\n        case `continue`\n        case needsNextLine\n        case parsedStack(Stack, Int)\n    }\n\n    private enum ParseState {\n        case parsingHeader\n        case parsingStack(ParsingStackState)\n    }\n\n    private struct ParsingStackState {\n        var lines: [String]\n\n        init() {\n            self.lines = []\n        }\n\n        mutating func parse(_ line: String) -> (ParseState, ParseResult) {\n            if let match = line.firstMatch(of: DTraceParser.allocationsRegex) {\n                if let count = Int(match.1) {\n                    return (.parsingHeader, .parsedStack(Stack(self.lines), count))\n                } else {\n                    fatalError(\"Failed to convert '\\(match.1)' to an Int\")\n                }\n            } else {\n                let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines)\n                let split = trimmed.split(separator: \"+0x\")\n                self.lines.append(split.first.map { String($0) } ?? trimmed)\n                return (.parsingStack(self), .needsNextLine)\n            }\n        }\n    }\n\n    /// Parses input which looks roughly like the following:\n    ///\n    /// ```\n    /// =====\n    /// This will collect stack shots of allocations and print it when you exit dtrace.\n    /// So go ahead, run your tests and then press Ctrl+C in this window to see the aggregated result\n    /// =====\n    /// 20896284696\n    ///\n    ///               libsystem_malloc.dylib`malloc_type_posix_memalign\n    ///               libobjc.A.dylib`id2data(objc_object*, SyncKind, usage)+0x1a0\n    ///               libobjc.A.dylib`_objc_sync_enter_kind+0x1c\n    ///               libobjc.A.dylib`initializeNonMetaClass+0xa8\n    ///               ...\n    ///               libdispatch.dylib`_dispatch_client_callout+0x10\n    ///               libdispatch.dylib`_dispatch_once_callout+0x20\n    ///               libswiftCore.dylib`swift_getCanonicalPrespecializedGenericMetadata+0xc8\n    ///               libswiftCore.dylib`__swift_instantiateCanonicalPrespecializedGenericMetadata+0x28\n    ///               libswiftCore.dylib`_ContiguousArrayBuffer .init(_uninitializedCount:minimumCapacity:)+0x3c\n    ///               do-some-allocs`specialized static do_some_allocs.main()+0x5c\n    ///               do-some-allocs`do_some_allocs_main+0xc\n    ///                 1\n    ///\n    ///               libsystem_malloc.dylib`malloc_type_posix_memalign\n    ///               libobjc.A.dylib`id2data(objc_object*, SyncKind, usage)+0x1a0\n    ///               libobjc.A.dylib`_objc_sync_enter_kind+0x1c\n    ///               ...\n    /// ```\n    private mutating func parse(lines: some Sequence<String>) -> [WeightedStack] {\n        for line in lines {\n            loop: while true {\n                switch self.parseNextState(line) {\n                case .parsedStack(let stack, let count):\n                    self.stacks.append(WeightedStack(stack: stack, allocations: count))\n                    break loop\n\n                case .continue:\n                    ()\n\n                case .needsNextLine:\n                    break loop\n                }\n            }\n        }\n\n        return self.stacks\n    }\n\n    private mutating func parseNextState(_ line: String) -> ParseResult {\n        switch self.state {\n        case .parsingHeader:\n            if line.hasPrefix(\" \") {\n                // Loop around and parse the line as a stack.\n                self.state = .parsingStack(ParsingStackState())\n                return .continue\n            } else {\n                return .needsNextLine\n            }\n\n        case .parsingStack(var state):\n            let (state, result) = state.parse(line)\n            self.state = state\n            return result\n        }\n    }\n}\n\nextension DTraceParser {\n    public static func parse(lines: some Sequence<String>) -> [WeightedStack] {\n        var parser = Self()\n        return parser.parse(lines: lines)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/Stacks/Parsing/HeaptrackParser.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Foundation\n\n/// Parses output from `heaptrack analyze`.\npublic struct HeaptrackParser: StackParser {\n    private let regex = /^(\\d+) calls with/\n    private var state: ParseState\n    private var stacks: [WeightedStack]\n\n    private init() {\n        self.stacks = []\n        self.state = .parsingHeader\n    }\n\n    private enum ParseResult {\n        case needsNextLine\n        case parsedStack(Stack, Int)\n    }\n\n    private enum ParseState {\n        case parsingHeader\n        case parsingStack(ParsingStackState)\n    }\n\n    private struct ParsingStackState {\n        var count: Int\n        var lines: [String]\n\n        init(count: Int) {\n            self.count = count\n            self.lines = []\n        }\n\n        private static var prefixesToIgnore: [String] {\n            [\"      in\", \"      at\", \"    0x\"]\n        }\n\n        mutating func parse(_ line: String) -> (ParseState, ParseResult) {\n            if Self.prefixesToIgnore.contains(where: { line.contains($0) }) {\n                return (.parsingStack(self), .needsNextLine)\n            } else if line.starts(with: \"    \") {\n                self.lines.append(line.trimmingCharacters(in: .whitespacesAndNewlines))\n                return (.parsingStack(self), .needsNextLine)\n            } else {\n                return (.parsingHeader, .parsedStack(Stack(self.lines), self.count))\n            }\n        }\n    }\n\n    /// Parses input which looks roughly like the following:\n    ///\n    /// ```\n    /// reading file \"heaptrack.simple-handshake.b.gz\" - please wait, this might take some time...\n    /// Debuggee command was: ./.build/release/simple-handshake\n    /// finished reading file, now analyzing data:\n    ///\n    /// MOST CALLS TO ALLOCATION FUNCTIONS\n    /// 488867 calls to allocation functions with 28.16K peak consumption from\n    /// CNIOBoringSSL_OPENSSL_malloc\n    ///   at Sources/CNIOBoringSSL/crypto/mem.cc:249\n    ///   in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n    /// 3000 calls with 80B peak consumption from:\n    ///   CNIOBoringSSL_OPENSSL_zalloc\n    ///     at Sources/CNIOBoringSSL/crypto/mem.cc:266\n    ///     in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n    ///   CNIOBoringSSL_ASN1_item_ex_new\n    ///     at Sources/CNIOBoringSSL/crypto/asn1/tasn_new.cc:153\n    /// ...\n    ///   __libc_start_main\n    ///     in /lib/aarch64-linux-gnu/libc.so.6\n    /// 3000 calls with 96B peak consumption from:\n    ///   CNIOBoringSSL_ASN1_STRING_type_new\n    ///     at Sources/CNIOBoringSSL/crypto/asn1/asn1_lib.cc:329\n    ///     in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n    ///   ASN1_primitive_new(ASN1_VALUE_st**, ASN1_ITEM_st const*)\n    /// ...\n    /// ```\n    private mutating func parse(lines: some Sequence<String>) -> [WeightedStack] {\n        for line in lines {\n            loop: while true {\n                switch self.parseNextState(line) {\n                case .parsedStack(let stack, let count):\n                    self.stacks.append(WeightedStack(stack: stack, allocations: count))\n\n                case .needsNextLine:\n                    break loop\n                }\n            }\n        }\n\n        return self.stacks\n    }\n\n    private mutating func parseNextState(_ line: String) -> ParseResult {\n        switch self.state {\n        case .parsingHeader:\n            return self.parseHeader(line)\n\n        case .parsingStack(var state):\n            let (state, result) = state.parse(line)\n            self.state = state\n            return result\n        }\n    }\n\n    private mutating func parseHeader(_ line: String) -> ParseResult {\n        if let match = line.firstMatch(of: self.regex) {\n            // At the start of a stack.\n            guard let count = Int(match.1) else {\n                fatalError(\"Failed to convert '\\(match.1)' to an Int\")\n            }\n\n            self.state = .parsingStack(ParsingStackState(count: count))\n        }\n\n        return .needsNextLine\n    }\n}\n\nextension HeaptrackParser {\n    public static func parse(lines: some Sequence<String>) -> [WeightedStack] {\n        var parser = Self()\n        return parser.parse(lines: lines)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/Stacks/Parsing/StackParser.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\npublic protocol StackParser {\n    static func parse(lines: some Sequence<String>) throws -> [WeightedStack]\n}\n\npublic protocol StackProtocol {\n    var lines: [String] { get }\n}\n\nextension StackProtocol {\n    /// Returns a stack with at most `maxLength` lines from the start of the current stack.\n    public func prefix(_ maxLength: Int) -> PartialStack {\n        PartialStack(self.lines.prefix(max(0, maxLength)))\n    }\n\n    /// Returns a stack with at most `maxLength` lines from the end of the current stack.\n    public func suffix(_ maxLength: Int) -> PartialStack {\n        PartialStack(self.lines.suffix(max(0, maxLength)))\n    }\n}\n\n/// The lines of a full stack trace.\npublic struct Stack: Hashable, StackProtocol {\n    public var lines: [String]\n\n    public init(_ lines: [String]) {\n        self.lines = lines\n    }\n\n    public init(_ weighted: WeightedStack) {\n        self = weighted.stack\n    }\n}\n\n/// The lines of a possibly incomplete stack trace.\npublic struct PartialStack: Hashable, StackProtocol {\n    public var lines: [String]\n\n    public init(_ lines: some Sequence<String>) {\n        self.lines = Array(lines)\n    }\n}\n\n/// A stack with an associated number of allocations\npublic struct WeightedStack: Hashable, StackProtocol {\n    public var stack: Stack\n    public var allocations: Int\n\n    public var lines: [String] {\n        self.stack.lines\n    }\n\n    public init(lines: [String], allocations: Int) {\n        self.init(stack: Stack(lines), allocations: allocations)\n    }\n\n    public init(stack: Stack, allocations: Int) {\n        self.stack = stack\n        self.allocations = allocations\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/Stacks/Similarity.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\npublic enum Similarity {\n    /// Returns the Levenshtein distance between two strings and their similarity score.\n    ///\n    /// See also: https://en.wikipedia.org/wiki/Levenshtein_distance\n    ///\n    /// The score is normalized to 0...1, with 1 indicting an exact match. Scores are calculated\n    /// as `1 - levenshtein(a, b) / max(length(a), length(b))`.\n    public static func levenshtein(_ a: String, _ b: String) -> (distance: Int, similarity: Double) {\n        Self.levenshtein(Array(a.utf8), Array(b.utf8))\n    }\n\n    private static func levenshtein(\n        _ a: [UInt8],\n        _ b: [UInt8]\n    ) -> (distance: Int, similarity: Double) {\n        if a.isEmpty, b.isEmpty {\n            // Perfect match.\n            return (0, 1.0)\n        } else if a.isEmpty {\n            // A is empty, B isn't. Distance is length of B.\n            return (b.count, 0.0)\n        } else if b.isEmpty {\n            // B is empty, A isn't. Distance is length of A.\n            return (a.count, 0.0)\n        }\n\n        var distance = Array(0...b.count)\n\n        for rowIndex in 1...a.count {\n            var previous = distance[0]\n            distance[0] = rowIndex\n\n            for colIndex in 1...b.count {\n                let temp = distance[colIndex]\n\n                if a[rowIndex - 1] == b[colIndex - 1] {\n                    distance[colIndex] = previous\n                } else {\n                    distance[colIndex] = 1 + min(distance[colIndex - 1], previous, distance[colIndex])\n                }\n\n                previous = temp\n            }\n        }\n\n        let editDistance = distance[b.count]\n        let similarity = 1 - (Double(editDistance) / Double(max(a.count, b.count)))\n        return (editDistance, similarity)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/stackdiff/StackFormatter.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Stacks\n\nenum StackFormatter {\n    static func lines<Stack: StackProtocol>(\n        forStack stack: Stack,\n        prefixedWith linePrefix: String = \"\",\n        dropFirst: Int = 0,\n        dropLast: Int = 0,\n        maxWidth: Int? = nil\n    ) -> [String] {\n        var lines = [String]()\n        lines.reserveCapacity(stack.lines.count - dropFirst - dropLast)\n\n        if dropFirst > 0 {\n            lines.append(linePrefix + \"...skipping \\(dropFirst) common lines...\")\n        }\n\n        for line in stack.lines.dropFirst(dropFirst).dropLast(dropLast) {\n            lines.append(linePrefix + line)\n        }\n\n        if dropLast > 0 {\n            lines.append(linePrefix + \"...skipping \\(dropLast) common lines...\")\n        }\n\n        if let maxWidth = maxWidth {\n            return lines.map { $0.truncated(to: maxWidth) }\n        } else {\n            return lines\n        }\n    }\n\n    static func lines(\n        forStack stack: some StackProtocol,\n        weightedSubstacks: [WeightedStack],\n        prefixedWith linePrefix: String = \"\",\n        substackPrefix: String = \"\",\n        maxWidth: Int? = nil\n    ) -> [String] {\n        var lines = [String]()\n\n        // If theres' only a single substack, compress it into the main stack.\n        if weightedSubstacks.count == 1, let substack = weightedSubstacks.first {\n            lines.append(\"\\(linePrefix)ALLOCATIONS: \\(substack.allocations)\")\n            lines.append(\n                contentsOf: Self.lines(\n                    forStack: substack.stack,\n                    prefixedWith: linePrefix,\n                    maxWidth: maxWidth\n                )\n            )\n            return lines\n        }\n\n        let totalAllocs = weightedSubstacks.reduce(0) { $0 + $1.allocations }\n        lines.append(\"\\(linePrefix)ALLOCATIONS: \\(totalAllocs)\")\n        lines.append(\n            contentsOf: Self.lines(\n                forStack: stack,\n                prefixedWith: linePrefix,\n                maxWidth: maxWidth\n            )\n        )\n        for substack in weightedSubstacks {\n            // Add a divider between substacks.\n            lines.append(\"\")\n            lines.append(\"\\(linePrefix)\\(substackPrefix)ALLOCATIONS: \\(substack.allocations)\")\n            // Treat the substack as a regular stack.\n            let substackLines = Self.lines(\n                forStack: substack.suffix(substack.lines.count - stack.lines.count),\n                prefixedWith: linePrefix + substackPrefix,\n                maxWidth: maxWidth\n            )\n            lines.append(contentsOf: substackLines)\n        }\n\n        return lines\n    }\n}\n\nextension String {\n    func truncated(to maxLength: Int, continuation: String = \"...\") -> String {\n        let length = self.count\n\n        if length <= maxLength {\n            return self\n        }\n\n        let toRemove = (length - maxLength) + continuation.count\n\n        var copy = self\n        copy.removeLast(toRemove)\n        copy.append(contentsOf: continuation)\n\n        return copy\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/stackdiff/Stackdiff+Diff.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport ArgumentParser\nimport Stacks\n\nstruct Diff: ParsableCommand {\n    @OptionGroup\n    var options: StackdiffOptions\n\n    @Argument(help: \"Path of first file to analyze\")\n    var fileA: String\n\n    @Argument(help: \"Path of second file to analyze\")\n    var fileB: String\n\n    @Flag\n    var showMergedStacks: Bool = false\n\n    func run() throws {\n        let a = try self.options.load(file: self.fileA)\n        let b = try self.options.load(file: self.fileB)\n\n        print(\"--- ONLY IN A (\\(self.fileA))\")\n        print(\"\")\n        let aOnlyStacks = a.partialStacks.subtracting(b.partialStacks)\n        let aOnlyAggregate = a.filter { aOnlyStacks.contains($0.key) }\n        self.printSortedStacks(aOnlyAggregate)\n\n        print(\"--- ONLY IN B (\\(self.fileB))\")\n        print(\"\")\n        let bOnlyStacks = b.partialStacks.subtracting(a.partialStacks)\n        let bOnlyAggregate = b.filter { bOnlyStacks.contains($0.key) }\n        self.printSortedStacks(bOnlyAggregate)\n\n        print(\"--- IN BOTH A AND B\")\n        print(\"\")\n        let inBoth = a.partialStacks.intersection(b.partialStacks)\n        let diff = a.subtracting(b).filter {\n            inBoth.contains($0.key) && $0.value.netAllocations != 0\n        }\n        self.printSortedStacks(diff)\n\n        print(\"--- SUMMARY\")\n        print(\"\")\n\n        let allocsA = a.netAllocations\n        let allocsB = b.netAllocations\n        print(\"Allocs from all stacks in A:\", allocsA)\n        print(\"Allocs from all stacks in B:\", allocsB)\n        print(\"Difference:\", allocsA - allocsB)\n        print(\"\")\n\n        let uniqueAllocsA = aOnlyAggregate.netAllocations\n        let uniqueAllocsB = bOnlyAggregate.netAllocations\n        print(\"Allocs from stacks only in A:\", uniqueAllocsA)\n        print(\"Allocs from stacks only in B:\", uniqueAllocsB)\n        print(\"Difference:\", uniqueAllocsA - uniqueAllocsB)\n        print(\"\")\n\n        // Stacks in both A and B.\n        let commonStacks = a.partialStacks.intersection(b.partialStacks)\n        let commonAllocsA = a.filter { commonStacks.contains($0.key) }.netAllocations\n        let commonAllocsB = b.filter { commonStacks.contains($0.key) }.netAllocations\n        print(\"Allocs from common stacks in A:\", commonAllocsA)\n        print(\"Allocs from common stacks in B:\", commonAllocsB)\n        print(\"Difference:\", commonAllocsA - commonAllocsB)\n    }\n\n    private func printSortedStacks(_ stacks: AggregateStacks) {\n        let sorted = stacks.sorted(by: { $0.value.netAllocations > $1.value.netAllocations })\n        if sorted.isEmpty {\n            print(\"(none)\\n\")\n        }\n        for (stack, weightedSubstacks) in sorted {\n            for line in StackFormatter.lines(\n                forStack: stack,\n                weightedSubstacks: weightedSubstacks,\n                substackPrefix: \"    \"\n            ) {\n                print(line)\n            }\n            print(\"\")\n        }\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/stackdiff/Stackdiff+Dump.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport ArgumentParser\n\nstruct Dump: ParsableCommand {\n    @Argument\n    var file: String\n\n    @OptionGroup\n    var options: StackdiffOptions\n\n    func run() throws {\n        let aggregate = try self.options.load(file: self.file)\n        let allocs = aggregate.netAllocations\n\n        // Sort by allocations.\n        let sortedStacks = aggregate.sorted {\n            $0.value.netAllocations > $1.value.netAllocations\n        }\n\n        for (stack, weightedSubstacks) in sortedStacks {\n            for line in StackFormatter.lines(\n                forStack: stack,\n                weightedSubstacks: weightedSubstacks,\n                substackPrefix: \"    \"\n            ) {\n                print(line)\n            }\n            print(\"\")\n        }\n\n        print(\"TOTAL ALLOCATIONS: \\(allocs)\")\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/stackdiff/Stackdiff+Merge.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport ArgumentParser\nimport Stacks\n\n#if canImport(Darwin)\nimport Darwin\n#elseif canImport(Glibc)\nimport Glibc\n#elseif canImport(Musl)\nimport Musl\n#endif\n\nstruct Merge: ParsableCommand {\n    @OptionGroup\n    var options: StackdiffOptions\n\n    @Argument(help: \"Path of first file to analyze\")\n    var fileA: String\n\n    @Argument(help: \"Path of second file to analyze\")\n    var fileB: String\n\n    @Flag(help: \"Automatically merge stacks if they're similar enough.\")\n    var autoMerge = false\n\n    @Option(help: \"The minimum similarity score for stacks to be merged automatically (requires --auto-merge)\")\n    var autoMergeThreshold = 0.9\n\n    @Flag(help: \"Automatically skip stacks that aren't similar enough.\")\n    var autoSkip = false\n\n    @Option(help: \"The similarity below which a stack will be skipped automatically (requires --auto-skip)\")\n    var autoSkipThreshold = 0.55\n\n    func run() throws {\n        // The blank line in the message is intentional so that the formatting in the backtrace\n        // is correct.\n        assertionFailure(\n            \"\"\"\n\n            *******************************************************************************\n            **                                                                           **\n            **       Debug mode is too slow! Please build and run in release mode.       **\n            **                                                                           **\n            *******************************************************************************\n            \"\"\"\n        )\n\n        let a = try self.options.load(file: self.fileA)\n        let b = try self.options.load(file: self.fileB)\n\n        var onlyA = a.partialStacks.subtracting(b.partialStacks)\n        var onlyB = b.partialStacks.subtracting(a.partialStacks)\n\n        // Merged contains stacks from A and B, with B recorded as negative allocations. Any\n        // stacks grouped under the same partial stack should end up netting to zero. Any that\n        // don't are changes in allocations between the two stacks.\n        var merged = a.subtracting(b)\n\n        print(\"Input A\")\n        print(\"- File:\", self.fileA)\n        print(\"- Allocations:\", a.netAllocations)\n        print(\"- Stacks:\", a.partialStacks.count)\n        print(\"- Stacks only in A:\", onlyA.count)\n        print(\"\")\n        print(\"Input B\")\n        print(\"- File:\", self.fileB)\n        print(\"- Allocations:\", b.netAllocations)\n        print(\"- Stacks:\", b.partialStacks.count)\n        print(\"- Stacks only in B:\", onlyB.count)\n        print(\"\")\n        print(\"Total stacks:\", a.partialStacks.union(b.partialStacks).count)\n        print(\"Allocation delta (A-B):\", a.netAllocations - b.netAllocations)\n        print(\"\")\n        print(\"About to start merging stacks, hit enter to continue ...\")\n        _ = readLine()\n\n        if onlyA.count > 0 {\n            self.mergeAllocations(from: onlyA, label: \"A only\", in: &merged) {\n                onlyA.remove($0)\n                onlyB.remove($1)\n            }\n        }\n\n        if onlyB.count > 0 {\n            self.mergeAllocations(from: onlyB, label: \"B only\", in: &merged) {\n                onlyB.remove($0)\n                onlyA.remove($1)\n            }\n        }\n\n        ANSI.clearTerminal()\n\n        // Remove empty stacks.\n        print(\"Finished merging stacks, removing stacks with net zero allocations.\")\n        merged.removeAll { $0.value.netAllocations == 0 }\n        print(\"Stacks remaining: \\(merged.partialStacks.count)\")\n        print(\"Net allocations: \\(merged.netAllocations)\")\n        print(\"\")\n\n        for (stack, weightedSubstacks) in merged.sorted(by: { $0.value.netAllocations > $1.value.netAllocations }) {\n            for line in StackFormatter.lines(\n                forStack: stack,\n                weightedSubstacks: weightedSubstacks,\n                substackPrefix: \"    \"\n            ) {\n                print(line)\n            }\n            print(\"\")\n        }\n    }\n\n    private func mergeAllocations(\n        from partialStacks: Set<PartialStack>,\n        label: String,\n        in aggregate: inout AggregateStacks,\n        onMerge: (_ original: PartialStack, _ mergedWith: PartialStack) -> Void = { _, _ in }\n    ) {\n        // Make repeated runs deterministic.\n        let sortedStacks = partialStacks.sorted { $0.lines.joined() > $1.lines.joined() }\n        for (stackIndex, stack) in sortedStacks.enumerated() {\n            // Only merge with other stacks where the net allocs isn't zero.\n            let candidateStacks = aggregate.partialStacks.subtracting(partialStacks).filter { key in\n                aggregate.netAllocations(groupedBy: key) != 0\n            }\n\n            // Order by decreasing similarity.\n            let candidates = candidateStacks.map { candidate in\n                let (_, similarity) = Similarity.levenshtein(stack, candidate)\n                return (stack: candidate, similarity: similarity)\n            }.sorted { lhs, rhs in\n                lhs.similarity > rhs.similarity\n            }\n\n            for (candidateIndex, candidate) in candidates.enumerated() {\n                let done = self.evaluateCandidate(\n                    candidate.stack,\n                    against: stack,\n                    similarity: candidate.similarity,\n                    label: label,\n                    stackN: stackIndex + 1,\n                    stackCount: sortedStacks.count,\n                    candidateN: candidateIndex + 1,\n                    candidateCount: candidates.count,\n                    expandStacks: false,\n                    aggregate: &aggregate,\n                    onMerge: onMerge\n                )\n\n                if done {\n                    break\n                }\n            }\n        }\n    }\n\n    private func evaluateCandidate(\n        _ candidate: PartialStack,\n        against stack: PartialStack,\n        similarity: Double,\n        label: String,\n        stackN: Int,\n        stackCount: Int,\n        candidateN: Int,\n        candidateCount: Int,\n        expandStacks: Bool,\n        aggregate: inout AggregateStacks,\n        onMerge: (PartialStack, PartialStack) -> Void\n    ) -> Bool {\n        ANSI.clearTerminal()\n        print(\"Finding candidates for stack \\(stackN) of \\(stackCount) (S1) from \\(label) ...\")\n        print(\"Looking at candidate stack \\(candidateN) of \\(candidateCount) (S2) ...\")\n\n        self.printCandidateSummary(\n            stack: stack,\n            candidate: candidate,\n            similarity: similarity,\n            aggregate: aggregate,\n            expanded: expandStacks\n        )\n\n        if self.autoMerge && similarity >= self.autoMergeThreshold {\n            aggregate.regroupStacks(from: stack, to: candidate)\n            onMerge(stack, candidate)\n            print(\"Outcome: auto-merged\")\n            return true\n        }\n\n        if self.autoSkip && similarity < self.autoSkipThreshold {\n            print(\"Outcome: auto-skipped\")\n            return true\n        }\n\n        while true {\n            switch self.getUserInput() {\n            case .accept:\n                // Remove the stacks from A and B.\n                aggregate.regroupStacks(from: stack, to: candidate)\n                onMerge(stack, candidate)\n                print(\"Outcome: merged (by user)\")\n                return true\n\n            case .reject:\n                // Add a new line to make the output clearer.\n                print(\"\")\n                print(\"Outcome: rejected (by user)\")\n                ANSI.clearTerminal()\n                return false\n\n            case .skip:\n                print(\"Outcome: skipped (by user)\")\n                return true\n\n            case .expand:\n                return self.evaluateCandidate(\n                    candidate,\n                    against: stack,\n                    similarity: similarity,\n                    label: label,\n                    stackN: stackN,\n                    stackCount: stackCount,\n                    candidateN: candidateN,\n                    candidateCount: candidateCount,\n                    expandStacks: true,\n                    aggregate: &aggregate,\n                    onMerge: onMerge\n                )\n            }\n        }\n    }\n\n    private enum UserInput {\n        case accept\n        case reject\n        case skip\n        case expand\n\n        init?(_ input: String, onNoInput: UserInput) {\n            switch input.lowercased() {\n            case \"y\", \"yes\":\n                self = .accept\n            case \"n\", \"no\":\n                self = .reject\n            case \"s\", \"skip\":\n                self = .skip\n            case \"e\", \"expand\":\n                self = .expand\n            case \"\":\n                self = onNoInput\n            default:\n                return nil\n            }\n        }\n    }\n\n    private func getUserInput() -> UserInput {\n        func underline(_ string: String) -> String {\n            \"\\u{001B}[4m\\(string)\\u{001B}[0m\"\n        }\n\n        let yes = \"[\" + underline(\"y\") + \"]es\"\n        let no = underline(\"n\") + \"o\"\n        let skip = underline(\"s\") + \"kip\"\n        let expand = underline(\"e\") + \"xpand\"\n\n        while true {\n            print(\"\")\n            print(\"Accept (\\(yes)/\\(no)/\\(skip)/\\(expand))?: \", terminator: \"\")\n            if let userInput = readLine(), let decision = UserInput(userInput, onNoInput: .accept) {\n                return decision\n            }\n        }\n    }\n\n    private func printCandidateSummary(\n        stack: PartialStack,\n        candidate: PartialStack,\n        similarity: Double,\n        aggregate: AggregateStacks,\n        expanded: Bool = false\n    ) {\n        print(\"\")\n\n        func makeAllocTable() -> [[String]] {\n            var table: [[Any]] = []\n            table.append([\"\", \"A\", \"B\", \"Net\"])\n\n            let (sourcePos, sourceNeg) = aggregate.weightedStacks(\n                groupedBy: stack\n            ).reduce((0, 0)) { partial, allocStack in\n                if allocStack.allocations > 0 {\n                    return (partial.0 + allocStack.allocations, partial.1)\n                } else {\n                    return (partial.0, partial.1 + allocStack.allocations)\n                }\n            }\n            var sourceNet: Int { sourcePos + sourceNeg }\n            table.append([\"S1\", sourcePos, sourceNeg, sourceNet])\n\n            let (candPos, candNeg) = aggregate.weightedStacks(\n                groupedBy: candidate\n            ).reduce((0, 0)) { partial, allocStack in\n                if allocStack.allocations > 0 {\n                    return (partial.0 + allocStack.allocations, partial.1)\n                } else {\n                    return (partial.0, partial.1 + allocStack.allocations)\n                }\n            }\n            var candNet: Int { candPos + candNeg }\n            table.append([\"S2\", candPos, candNeg, candNet])\n            table.append([\"Total\", sourcePos + candPos, sourceNeg + candNeg, sourceNet + candNet])\n\n            return table.map { row in\n                row.map { String(describing: $0) }\n            }\n        }\n\n        print(\"Allocations:\")\n        self.printFormattedTable(makeAllocTable())\n        print(\"\")\n\n        // Highlight weak/strong matches.\n        let similarityText: String\n        if similarity < self.autoSkipThreshold {\n            similarityText = ANSI.red(String(describing: similarity))\n        } else if similarity >= self.autoMergeThreshold {\n            similarityText = ANSI.green(String(describing: similarity))\n        } else {\n            similarityText = ANSI.yellow(String(describing: similarity))\n        }\n\n        print(\"Stack similarity:\", similarityText)\n        print(\"\")\n\n        let (dropFirst, dropLast): (Int, Int)\n        if expanded {\n            (dropFirst, dropLast) = (0, 0)\n        } else {\n            (dropFirst, dropLast) = self.lengthOfCommonPrefixAndSuffix(stack.lines, candidate.lines)\n        }\n\n        // Grab the window size to clip long lines.\n        var windowSize = winsize()\n        _ = ioctl(STDOUT_FILENO, TIOCGWINSZ, &windowSize)\n\n        for line in StackFormatter.lines(\n            forStack: stack,\n            prefixedWith: \"S1| \",\n            dropFirst: dropFirst,\n            dropLast: dropLast,\n            maxWidth: Int(windowSize.ws_col)\n        ) {\n            print(line)\n        }\n\n        print(\"\")\n\n        for line in StackFormatter.lines(\n            forStack: candidate,\n            prefixedWith: \"S2| \",\n            dropFirst: dropFirst,\n            dropLast: dropLast,\n            maxWidth: Int(windowSize.ws_col)\n        ) {\n            print(line)\n        }\n    }\n\n    private func printFormattedTable(_ table: [[String]]) {\n        precondition(!table.isEmpty)\n        precondition(table.allSatisfy { $0.count == table[0].count })\n\n        var columnWidths = Array(repeating: 0, count: table[0].count)\n        for row in table {\n            for colIndex in row.indices {\n                let width = row[colIndex].count\n                if width > columnWidths[colIndex] {\n                    columnWidths[colIndex] = width\n                }\n            }\n        }\n\n        for row in table {\n            var line = \"\"\n            var iterator = zip(row, columnWidths).makeIterator()\n            var current = iterator.next()\n            while let (cell, width) = current {\n                line += String(repeating: \" \", count: width - cell.count + 1)  // Add an extra space\n                line += cell\n                line += \" \"\n\n                current = iterator.next()\n                if current != nil {\n                    line += \"|\"\n                }\n            }\n            print(line)\n        }\n    }\n\n    private func lengthOfCommonPrefix(_ a: some Sequence<String>, _ b: some Sequence<String>) -> Int {\n        var length = 0\n\n        for (x, y) in zip(a, b) {\n            if x == y {\n                length += 1\n            } else {\n                break\n            }\n        }\n\n        return length\n    }\n\n    private func lengthOfCommonSuffix(_ a: some Sequence<String>, _ b: some Sequence<String>) -> Int {\n        self.lengthOfCommonPrefix(a.reversed(), b.reversed())\n    }\n\n    private func lengthOfCommonPrefixAndSuffix(_ a: [String], _ b: [String]) -> (Int, Int) {\n        if a == b {\n            return (a.count, 0)\n        }\n\n        let prefixLength = self.lengthOfCommonPrefix(a, b)\n\n        if prefixLength == a.count || prefixLength == b.count {\n            return (prefixLength, 0)\n        }\n\n        let suffixLength = self.lengthOfCommonSuffix(a, b)\n\n        return (prefixLength, suffixLength)\n    }\n}\n\nextension Similarity {\n    static func levenshtein(\n        _ a: PartialStack,\n        _ b: PartialStack\n    ) -> (distance: Int, similarity: Double) {\n        Self.levenshtein(a.lines.joined(), b.lines.joined())\n    }\n}\n\nenum ANSI {\n    static func clearTerminal() {\n        print(\"\\u{1B}[H\\u{1B}[2J\", terminator: \"\")\n    }\n\n    static func red(_ text: String) -> String {\n        \"\\u{001B}[31m\\(text)\\u{001B}[0m\"\n    }\n\n    static func green(_ text: String) -> String {\n        \"\\u{001B}[32m\\(text)\\u{001B}[0m\"\n    }\n\n    static func yellow(_ text: String) -> String {\n        \"\\u{001B}[33m\\(text)\\u{001B}[0m\"\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Sources/stackdiff/Stackdiff.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport ArgumentParser\nimport Foundation\nimport Stacks\n\n@main\nstruct Stackdiff: ParsableCommand {\n    static var configuration: CommandConfiguration {\n        CommandConfiguration(subcommands: [Diff.self, Dump.self, Merge.self])\n    }\n}\n\nstruct StackdiffOptions: ParsableArguments {\n    @Option(help: \"The maximum stack depth used when comparing stacks.\")\n    var depth: Int?\n\n    @Option(help: \"The minimum number of allocations for a stack to be included.\")\n    var minAllocations: Int = 1000\n\n    @Option(help: \"The format of the input files.\")\n    var format: Format\n\n    @Option(help: \"If set, only stacks containing this string are included.\")\n    var filter: String?\n\n    enum Format: String, ExpressibleByArgument, CaseIterable {\n        case heaptrack\n        case dtrace\n        case bpftrace\n    }\n}\n\nextension StackdiffOptions {\n    func load(file: String) throws -> AggregateStacks {\n        try AggregateStacks.load(\n            contentsOf: file,\n            format: self.format,\n            depth: self.depth,\n            minAllocations: self.minAllocations,\n            filter: self.filter\n        )\n    }\n}\n\nextension AggregateStacks {\n    static func load(\n        contentsOf file: String,\n        format: StackdiffOptions.Format,\n        depth: Int?,\n        minAllocations: Int,\n        filter: String?\n    ) throws -> Self {\n        let lines = try readLinesOfFile(file)\n\n        let stacks: [WeightedStack]\n        switch format {\n        case .heaptrack:\n            stacks = HeaptrackParser.parse(lines: lines)\n        case .dtrace:\n            stacks = DTraceParser.parse(lines: lines)\n        case .bpftrace:\n            stacks = BPFTraceParser.parse(lines: lines)\n        }\n\n        // Combine equivalent stacks.\n        var dedupedStacks: [Stack: Int] = [:]\n        for stack in stacks {\n            dedupedStacks[stack.stack, default: 0] += stack.allocations\n        }\n\n        var aggregate = AggregateStacks()\n\n        for (stack, allocations) in dedupedStacks {\n            let weightedStack = WeightedStack(stack: stack, allocations: allocations)\n            let partialStack = weightedStack.prefix(depth ?? .max)\n            aggregate.groupWeightedStack(weightedStack, by: partialStack)\n        }\n\n        // Remove light stacks\n        for stack in aggregate.partialStacks {\n            if aggregate.netAllocations(groupedBy: stack) < minAllocations {\n                aggregate.removeWeightedStacks(groupedUnder: stack)\n            }\n        }\n\n        // Remove stacks which don't contain the filter string.\n        if let filter = filter {\n            for stack in aggregate.partialStacks {\n                if stack.lines.contains(where: { $0.contains(filter) }) {\n                    continue\n                } else {\n                    aggregate.removeWeightedStacks(groupedUnder: stack)\n                }\n            }\n        }\n\n        return aggregate\n    }\n}\n\nprivate func readLinesOfFile(_ path: String) throws -> [String] {\n    let fileData = try Data(contentsOf: URL(filePath: path))\n    let file = String(decoding: fileData, as: UTF8.self)\n    let lines = Array(file.components(separatedBy: .newlines))\n    return lines\n}\n"
  },
  {
    "path": "dev/stackdiff/Tests/StacksTests/AggregateStackTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Stacks\nimport Testing\n\nstruct AggregateStackTests {\n    @Test\n    func netAllocations() {\n        var aggregate = AggregateStacks()\n        #expect(aggregate.netAllocations == 0)\n\n        aggregate.groupWeightedStack(\n            WeightedStack(lines: [\"a\"], allocations: 100),\n            by: PartialStack([\"a\"])\n        )\n\n        #expect(aggregate.netAllocations == 100)\n\n        aggregate.groupWeightedStack(\n            WeightedStack(lines: [\"a\"], allocations: -10),\n            by: PartialStack([\"a\"])\n        )\n\n        #expect(aggregate.netAllocations == 90)\n    }\n\n    @Test\n    func groupWeightedStack() {\n        var aggregate = AggregateStacks()\n\n        let partial = PartialStack([\"a\"])\n        let weighted = [\"a\", \"b\", \"c\"].map { line in\n            WeightedStack(lines: [\"a\"] + [line], allocations: 10)\n        }\n\n        for weightedStack in weighted {\n            aggregate.groupWeightedStack(weightedStack, by: partial)\n        }\n\n        aggregate.groupWeightedStack(\n            WeightedStack(lines: [], allocations: 0),\n            by: PartialStack([\"b\"])\n        )\n\n        #expect(aggregate.netAllocations(groupedBy: partial) == 30)\n\n        let grouped = aggregate.weightedStacks(groupedBy: partial)\n        #expect(grouped == weighted)\n    }\n\n    @Test\n    func removeWeightedStacks() {\n        var aggregate = AggregateStacks()\n        let partial = PartialStack([\"a\"])\n\n        // Nothing to remove.\n        #expect(aggregate.removeWeightedStacks(groupedUnder: partial) == nil)\n\n        // Add then remove.\n        let weighted = WeightedStack(lines: [\"a\"], allocations: 100)\n        aggregate.groupWeightedStack(weighted, by: partial)\n        #expect(aggregate.removeWeightedStacks(groupedUnder: partial) == [weighted])\n    }\n\n    @Test\n    func filter() {\n        var aggregate = AggregateStacks()\n\n        let partialA = PartialStack([\"a\"])\n        let partialB = PartialStack([\"b\"])\n        aggregate.groupWeightedStack(WeightedStack(lines: [\"a\"], allocations: 10), by: partialA)\n        aggregate.groupWeightedStack(WeightedStack(lines: [\"b\"], allocations: -10), by: partialB)\n        #expect(aggregate.netAllocations == 0)\n\n        let filtered = aggregate.filter { $0.key.lines == [\"a\"] }\n        #expect(filtered.netAllocations == 10)\n    }\n\n    @Test\n    func removeAll() {\n        var aggregate = AggregateStacks()\n\n        let partialA = PartialStack([\"a\"])\n        let partialB = PartialStack([\"b\"])\n        aggregate.groupWeightedStack(WeightedStack(lines: [\"a\"], allocations: 10), by: partialA)\n        aggregate.groupWeightedStack(WeightedStack(lines: [\"b\"], allocations: -10), by: partialB)\n        #expect(aggregate.netAllocations == 0)\n\n        aggregate.removeAll { $0.key.lines == [\"a\"] }\n        #expect(aggregate.netAllocations == -10)\n    }\n\n    @Test\n    func subtract() {\n        let weighted = WeightedStack(lines: [], allocations: 10)\n\n        var aggregateA = AggregateStacks()\n        aggregateA.groupWeightedStack(weighted, by: PartialStack([\"m\"]))\n        aggregateA.groupWeightedStack(weighted, by: PartialStack([\"n\"]))\n\n        var aggregateB = AggregateStacks()\n        aggregateB.groupWeightedStack(weighted, by: PartialStack([\"m\"]))\n        aggregateB.groupWeightedStack(weighted, by: PartialStack([\"o\"]))\n\n        let diff = aggregateA.subtracting(aggregateB)\n\n        // m=10 in A and B\n        #expect(diff.netAllocations(groupedBy: PartialStack([\"m\"])) == 0)\n        #expect(diff.weightedStacks(groupedBy: PartialStack([\"m\"])).count == 2)\n\n        // n=10 in A and not present in B\n        #expect(diff.netAllocations(groupedBy: PartialStack([\"n\"])) == 10)\n        #expect(diff.weightedStacks(groupedBy: PartialStack([\"n\"])).count == 1)\n\n        // o=10 in B and not present in A\n        #expect(diff.netAllocations(groupedBy: PartialStack([\"o\"])) == -10)\n        #expect(diff.weightedStacks(groupedBy: PartialStack([\"o\"])).count == 1)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Tests/StacksTests/DTraceParserTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Stacks\nimport Testing\n\nstruct DTraceParserTests {\n    @Test\n    func parsing() throws {\n        // Real input but modified to be a lot shorter.\n        let input = \"\"\"\n\n            =====\n            This will collect stack shots of allocations and print it when you exit dtrace.\n            So go ahead, run your tests and then press Ctrl+C in this window to see the aggregated result\n            =====\n            20896284696\n\n\n                          libsystem_malloc.dylib`malloc_type_calloc\n                          libobjc.A.dylib`class_createInstance+0x4c\n                          libdispatch.dylib`_os_object_alloc_realized+0x20\n                          libdispatch.dylib`_dispatch_client_callout+0x10\n                          libdispatch.dylib`_dispatch_once_callout+0x20\n                          libswiftCore.dylib`swift_dynamicCast+0x60\n                          libswiftCore.dylib`_print_unlocked<A, B>(_:_:)+0x2e4\n                           13\n\n                          libsystem_malloc.dylib`malloc_type_malloc\n                          libswiftCore.dylib`swift_allocObject+0x88\n                          libswiftCore.dylib`_ContiguousArrayBuffer.init(_uninitializedCount:minimumCapacity:)+0xa0\n                          do-some-allocs`specialized static do_some_allocs.main()+0x5c\n                          do-some-allocs`do_some_allocs_main+0xc\n                          dyld`start+0x1870\n                        10000\n\n            \"\"\"\n\n        let lines = input.split(separator: \"\\n\").map { String($0) }\n        let stacks = DTraceParser.parse(lines: lines)\n\n        try #require(stacks.count == 2)\n\n        let stack0 = stacks[0]\n        let expected0 = WeightedStack(\n            lines: [\n                \"libsystem_malloc.dylib`malloc_type_calloc\",\n                \"libobjc.A.dylib`class_createInstance\",\n                \"libdispatch.dylib`_os_object_alloc_realized\",\n                \"libdispatch.dylib`_dispatch_client_callout\",\n                \"libdispatch.dylib`_dispatch_once_callout\",\n                \"libswiftCore.dylib`swift_dynamicCast\",\n                \"libswiftCore.dylib`_print_unlocked<A, B>(_:_:)\",\n            ],\n            allocations: 13\n        )\n        #expect(stack0 == expected0)\n\n        let stack1 = stacks[1]\n        let expected1 = WeightedStack(\n            lines: [\n                \"libsystem_malloc.dylib`malloc_type_malloc\",\n                \"libswiftCore.dylib`swift_allocObject\",\n                \"libswiftCore.dylib`_ContiguousArrayBuffer.init(_uninitializedCount:minimumCapacity:)\",\n                \"do-some-allocs`specialized static do_some_allocs.main()\",\n                \"do-some-allocs`do_some_allocs_main\",\n                \"dyld`start\",\n            ],\n            allocations: 10000\n        )\n        #expect(stack1 == expected1)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Tests/StacksTests/HeaptrackParserTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Stacks\nimport Testing\n\nstruct HeaptrackParserTests {\n    @Test\n    func parsing() throws {\n        // Real input but modified to be a lot shorter.\n        let input = \"\"\"\n            reading file \"heaptrack.simple-handshake.a.gz\" - please wait, this might take some time...\n            Debuggee command was: ./.build/release/simple-handshake\n            finished reading file, now analyzing data:\n\n            MOST CALLS TO ALLOCATION FUNCTIONS\n            488872 calls to allocation functions with 28.16K peak consumption from\n            CNIOBoringSSL_OPENSSL_malloc\n              at Sources/CNIOBoringSSL/crypto/mem.cc:249\n              in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n            3000 calls with 80B peak consumption from:\n                CNIOBoringSSL_OPENSSL_zalloc\n                  at Sources/CNIOBoringSSL/crypto/mem.cc:266\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                CNIOBoringSSL_ASN1_item_ex_new\n                  at Sources/CNIOBoringSSL/crypto/asn1/tasn_new.cc:153\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                ASN1_template_new(ASN1_VALUE_st**, ASN1_TEMPLATE_st const*)\n                  at Sources/CNIOBoringSSL/crypto/asn1/tasn_new.cc:236\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                CNIOBoringSSL_ASN1_item_ex_new\n                  at Sources/CNIOBoringSSL/crypto/asn1/tasn_new.cc:161\n                asn1_item_ex_d2i(ASN1_VALUE_st**, unsigned char const**, long, ASN1_ITEM_st const*, int, int, char, crypto_buffer_st*, int)\n                  at Sources/CNIOBoringSSL/crypto/asn1/tasn_dec.cc:378\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                static simple_handshake.SimpleHandshake.$main() throws -> ()\n                  at //<compiler-generated>:40\n                simple_handshake_main\n                  at /code/Sources/simple-handshake/SimpleHandshake.swift:0\n                0xffff935b73fa\n                  in /lib/aarch64-linux-gnu/libc.so.6\n                __libc_start_main\n                  in /lib/aarch64-linux-gnu/libc.so.6\n            2000 calls with 96B peak consumption from:\n                CNIOBoringSSL_ASN1_STRING_type_new\n                  at Sources/CNIOBoringSSL/crypto/asn1/asn1_lib.cc:329\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                ASN1_primitive_new(ASN1_VALUE_st**, ASN1_ITEM_st const*)\n                  at Sources/CNIOBoringSSL/crypto/asn1/tasn_new.cc:294\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                static simple_handshake.SimpleHandshake.main() throws -> ()\n                  at /code/Sources/simple-handshake/SimpleHandshake.swift:43\n                  in /code/.build/aarch64-unknown-linux-gnu/release/simple-handshake\n                static simple_handshake.SimpleHandshake.$main() throws -> ()\n                  at //<compiler-generated>:40\n                simple_handshake_main\n                  at /code/Sources/simple-handshake/SimpleHandshake.swift:0\n                0xffff935b73fa\n                  in /lib/aarch64-linux-gnu/libc.so.6\n                __libc_start_main\n                  in /lib/aarch64-linux-gnu/libc.so.6\n\n\n            total runtime: 0.44s.\n            calls to allocation functions: 638104 (1440415/s)\n            temporary memory allocations: 56039 (126498/s)\n            peak heap memory consumption: 190.22K\n            peak RSS (including heaptrack overhead): 21.92M\n            total memory leaked: 5.54K\n            \"\"\"\n\n        let lines = input.split(separator: \"\\n\").map { String($0) }\n        let stacks = HeaptrackParser.parse(lines: lines)\n\n        try #require(stacks.count == 2)\n\n        let stack0 = stacks[0]\n        let expected0 = WeightedStack(\n            lines: [\n                \"CNIOBoringSSL_OPENSSL_zalloc\",\n                \"CNIOBoringSSL_ASN1_item_ex_new\",\n                \"ASN1_template_new(ASN1_VALUE_st**, ASN1_TEMPLATE_st const*)\",\n                \"CNIOBoringSSL_ASN1_item_ex_new\",\n                \"asn1_item_ex_d2i(ASN1_VALUE_st**, unsigned char const**, long, ASN1_ITEM_st const*, int, int, char, crypto_buffer_st*, int)\",\n                \"static simple_handshake.SimpleHandshake.$main() throws -> ()\",\n                \"simple_handshake_main\",\n                \"__libc_start_main\",\n            ],\n            allocations: 3000\n        )\n        #expect(stack0 == expected0)\n\n        let stack1 = stacks[1]\n        let expected1 = WeightedStack(\n            lines: [\n                \"CNIOBoringSSL_ASN1_STRING_type_new\",\n                \"ASN1_primitive_new(ASN1_VALUE_st**, ASN1_ITEM_st const*)\",\n                \"static simple_handshake.SimpleHandshake.main() throws -> ()\",\n                \"static simple_handshake.SimpleHandshake.$main() throws -> ()\",\n                \"simple_handshake_main\",\n                \"__libc_start_main\",\n            ],\n            allocations: 2000\n        )\n        #expect(stack1 == expected1)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff/Tests/StacksTests/SimilarityTests.swift",
    "content": "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the SwiftNIO open source project\n//\n// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//\n\nimport Stacks\nimport Testing\n\nstruct SimilarityTests {\n    @Test(arguments: [\"\", \"foo\", \"Foo\"])\n    func perfectMatch(_ input: String) {\n        let (distance, score) = Similarity.levenshtein(input, input)\n        #expect(distance == 0)\n        #expect(score == 1)\n    }\n\n    @Test(arguments: [(\"\", \"a\"), (\"a\", \"\"), (\"a\", \"b\"), (\"A\", \"a\")])\n    func maxDistance(_ lhs: String, _ rhs: String) {\n        let (distance, score) = Similarity.levenshtein(lhs, rhs)\n        #expect(distance == 1)\n        #expect(score == 0)\n    }\n\n    @Test\n    func kittenSitting() {\n        let (distance, _) = Similarity.levenshtein(\"kitten\", \"sitting\")\n        // k -> s\n        // e -> i\n        // +g\n        #expect(distance == 3)\n    }\n\n    @Test\n    func similarityScore() {\n        let (distance, similarity) = Similarity.levenshtein(\"aa\", \"bbaa\")\n        // +b\n        // +b\n        #expect(distance == 2)\n        // = 1 - lev(aa, bbaa) / max(len(aa), len(bbaa))\n        // = 1 - (2) / max(2, 4)\n        // = 1 - 2 / 4\n        // = 1 - 0.5\n        // = 0.5\n        #expect(similarity == 0.5)\n    }\n}\n"
  },
  {
    "path": "dev/stackdiff-dtrace.py",
    "content": "#!/usr/bin/env python3\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nimport collections\nimport re\nimport sys\n\nnum_regex = b\"^ +([0-9]+)$\"\n\n\ndef put_in_dict(path):\n    # Our input looks something like:\n    #\n    # =====\n    # This will collect stack shots of allocations and print it when you exit dtrace.\n    # So go ahead, run your tests and then press Ctrl+C in this window to see the aggregated result # noqa: E501\n    # =====\n    # DEBUG: After waiting 1 times, we quiesced to unfreeds=744\n    # test_1_reqs_1000_conn.total_allocations: 490000\n    # test_1_reqs_1000_conn.total_allocated_bytes: 42153000\n    # test_1_reqs_1000_conn.remaining_allocations: 0\n    # DEBUG: [[\"total_allocations\": 490000, \"total_allocated_bytes\": 42153000, ...\n    #\n    # (truncated)\n    #\n    #               libsystem_malloc.dylib`malloc_zone_malloc\n    #               libswiftCore.dylib`swift_slowAlloc+0x28\n    #               libswiftCore.dylib`swift_allocObject+0x27\n    #               test_1_reqs_1000_conn`closure #3 in SelectableEventLoop.run()+0x166\n    #               test_1_reqs_1000_conn`SelectableEventLoop.run()+0x234\n    #               test_1_reqs_1000_conn`closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:)+0x12e # noqa: E501\n    #               test_1_reqs_1000_conn`partial apply for closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:)+0x25 # noqa: E501\n    #               test_1_reqs_1000_conn`thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()+0xf # noqa: E501\n    #               test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()+0x11 # noqa: E501\n    #               test_1_reqs_1000_conn`closure #1 in static ThreadOpsPosix.run(handle:args:detachThread:)+0x1c9 # noqa: E501\n    #               libsystem_pthread.dylib`_pthread_start+0xe0\n    #               libsystem_pthread.dylib`thread_start+0xf\n    #             85945\n    #\n    #               libsystem_malloc.dylib`malloc_zone_malloc\n    #               libswiftCore.dylib`swift_slowAlloc+0x28\n    #               libswiftCore.dylib`swift_allocObject+0x27\n    # (truncated)\n    dictionary = collections.defaultdict(list)\n    with open(path, \"rb\") as f:\n        current_stack = []\n        for line in f:\n            if not line.startswith(b\" \"):\n                # All lines we're intereted in are indented so ignore this one.\n                pass\n            elif re.match(num_regex, line):\n                # The line contains just a number. This must be the end of a\n                # stack, i.e. the number of allocations.\n\n                # Build a key for the current stack. Each line looks\n                # like: 'libswiftCore.dylib`swift_allocObject+0x27'. We want\n                # everything before the '+'. We only take at most the first 8\n                # lines for the key so that we group 'similar' stacks in our\n                # output.\n                key = b\"\\n\".join(line.split(b\"+\")[0] for line in current_stack[:8])\n\n                # Record this stack and reset our state to build a new one.\n                dictionary[key].append((int(line), b\"\\n\".join(current_stack)))\n                current_stack = []\n            else:\n                # This line doesn't contain just a number. This might be an\n                # entry in the current stack.\n                stripped = line.strip()\n                if stripped != \"\":\n                    current_stack.append(stripped)\n\n    return dictionary\n\n\ndef total_count_for_key(d, key):\n    value = d[key]\n    return sum(map(lambda x: x[0], value))\n\n\ndef total_for_dictionary(d):\n    total = 0\n    for k in d.keys():\n        total += total_count_for_key(d, k)\n    return total\n\n\ndef extract_useful_keys(d):\n    keys = set()\n    for k in d.keys():\n        if total_count_for_key(d, k) >= 1000:\n            keys.add(k)\n    return keys\n\n\ndef print_dictionary_member(d, key):\n    print(total_count_for_key(d, key))\n    print(key.decode('utf8'))\n    print()\n    print_dictionary_member_detail(d, key)\n    print()\n\n\ndef print_dictionary_member_detail(d, key):\n    value = d[key]\n    for (count, stack) in value:\n        print(\"    %d\" % count)\n        print((b\"        \" + stack.replace(b\"\\n\", b\"\\n        \")).decode('utf8'))\n\n\ndef usage():\n    print(\"Usage: stackdiff-dtrace.py OLD-STACKS NEW-STACKS\")\n    print(\"\")\n    print(\"stackdiff-dtrace can diff aggregated stack traces as produced\")\n    print(\"by a `agg[ustack()] = count();` and printed with `printa(agg)`;\")\n    print(\"by a dtrace program.\")\n    print(\"\")\n    print(\"Full example leveraging the malloc aggregation:\")\n    print(\"  # get old stack traces\")\n    print(\"  sudo malloc-aggregation.d -c ./old-binary > /tmp/old\")\n    print(\"  # get new stack traces\")\n    print(\"  sudo malloc-aggregation.d -c ./new-binary > /tmp/new\")\n    print(\"  # diff them\")\n    print(\"  stackdiff-dtrace.py /tmp/old /tmp/new\")\n\n\nif len(sys.argv) != 3:\n    usage()\n    sys.exit(1)\n\nbefore_file = sys.argv[1]\nafter_file = sys.argv[2]\n\nafter_dict = put_in_dict(after_file)\nbefore_dict = put_in_dict(before_file)\n\nuseful_after_keys = extract_useful_keys(after_dict)\nuseful_before_keys = extract_useful_keys(before_dict)\n\nprint(\"\")\nprint(\"### only in AFTER\")\nonly_after_total = 0\nfor x in sorted(list(useful_after_keys - useful_before_keys)):\n    print_dictionary_member(after_dict, x)\n    only_after_total += total_count_for_key(after_dict, x)\nprint(\"Total for only in AFTER:  %d\" % only_after_total)\n\nprint(\"\")\nprint(\"### only in BEFORE\")\nonly_before_total = 0\nfor x in sorted(list(useful_before_keys - useful_after_keys)):\n    print_dictionary_member(before_dict, x)\n    only_before_total += total_count_for_key(before_dict, x)\nprint(\"Total for only in BEFORE:  %d\" % only_before_total)\n\nprint(\"\")\nprint(\"### different numbers\")\nfor x in sorted(list(useful_before_keys & useful_after_keys)):\n    before_count = total_count_for_key(before_dict, x)\n    after_count = total_count_for_key(after_dict, x)\n    if before_count != after_count:\n        print(\"before: %d, after: %d\" % (before_count,\n                                         after_count))\n        print(\"  AFTER\")\n        print_dictionary_member_detail(after_dict, x)\n        print(\"  BEFORE\")\n        print_dictionary_member_detail(before_dict, x)\n        print()\n\neverything_before = total_for_dictionary(before_dict)\neverything_after = total_for_dictionary(after_dict)\nprint(\"Total of _EVERYTHING_ BEFORE:  %d,  AFTER:  %d,  DIFFERENCE:  %d\" % (everything_before, everything_after, everything_after - everything_before))  # noqa: E501\n"
  },
  {
    "path": "dev/thresholds-from-benchmark-output.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# This script allows you to consume swift package benchmark output and\n# update JSON threshold files\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\nurl=\"${URL:=\"\"}\"\n\nif [ -z \"$url\" ]; then\n  fatal \"Pull request or workflow run URL must be specified.\"\nfi\n\n# Check for required tools\nGH_BIN=\"${GH_BIN:-$(which gh)}\" || fatal \"GH_BIN unset and no gh on PATH\"\nJQ_BIN=\"${JQ_BIN:-$(which jq)}\" || fatal \"JQ_BIN unset and no jq on PATH\"\nYQ_BIN=\"${YQ_BIN:-$(which yq)}\" || fatal \"YQ_BIN unset and no yq on PATH\"\n\nfetch_checks_for_pr() {\n    pr_url=$1\n\n    \"$GH_BIN\" pr checks \"$pr_url\" | grep Benchmarks | grep -v Construct\n}\n\nparse_url() {\n    workflow_url=$1\n    # https://github.com/apple/swift-nio/actions/runs/15269806473\n    # https://github.com/apple/swift-nio/pull/3257\n    if [[ \"$url\" =~ pull ]]; then\n        type=\"PR\"\n    elif [[ \"$url\" =~ actions/runs ]]; then\n        type=\"run\"\n    else\n        fatal \"Cannot parse URL: $url\"\n    fi\n    echo \"$url\" | awk -v type=\"$type\" -F '/' '{print $4, $5, type}'\n}\n\nparse_check() {\n    type=$1\n    check_line=$2\n\n    case \"$type\" in\n    \"PR\")\n        parse_check_for_pr \"$check_line\"\n        ;;\n\n    \"run\")\n        parse_check_for_workflow \"$check_line\"\n        ;;\n\n    *)\n        fatal \"Unknown type '$type'\"\n        # Add error handling commands here\n        ;;\n    esac\n}\n\nparse_check_for_workflow() {\n    check_line=$1\n\n    # Something like:\n    # ✓ Benchmarks / Benchmarks / Linux (5.10) in 5m10s (ID 42942543009)\n    echo \"$check_line\" | sed -En 's/.*ID ([0-9][0-9]*).*/\\1/p'\n}\n\nparse_check_for_pr() {\n    check_line=$1\n\n    # Something like:\n    # Benchmarks / Benchmarks / Linux (5.10)\tpass\t4m21s\thttps://github.com/apple/swift-nio-ssl/actions/runs/13793783082/job/38580234681\n    echo \"$check_line\" | sed -E 's/.*\\(([^\\)]+)\\).*github\\.com\\/(.*)\\/actions\\/runs\\/[0-9]+\\/job\\/([0-9]+)/\\3/g'\n}\n\nparse_workflow_url() {\n    workflow_url=$1\n    # https://github.com/apple/swift-nio/actions/runs/15269806473\n    echo \"$workflow_url\" | awk -F '/' '{print $8}'\n}\n\nfetch_checks_for_workflow() {\n    repo=$1\n    run=$2\n\n    \"$GH_BIN\" --repo \"$repo\" run view \"$run\" | grep Benchmarks | grep ID | grep -v Construct\n}\n\nfetch_check_logs() {\n    repo=$1\n    job=$2\n\n    log \"Pulling logs for $repo job $job\"\n    # We use `gh api` rather than `gh run view --log` because of https://github.com/cli/cli/issues/5011.\n    # Look for the table outputted by the benchmarks tool if there is a discrepancy\n    \"$GH_BIN\" api \"/repos/${repo}/actions/jobs/${job}/logs\"\n}\n\nscrape_benchmarks_output_diff() {\n    lines=$1\n    job=$2\n\n    log \"Scraping diff from log\"\n    # Trim out everything but the diff\n    git_diff=\"$(echo \"$lines\" | sed '1,/=== BEGIN DIFF ===/d' | sed '/Post job cleanup/,$d' | sed 's/^[0-9][0-9][0-9][0-9]-.*Z //')\"\n\n    echo \"$git_diff\"\n}\n\napply_benchmarks_output_diff() {\n    git_diff=$1\n\n    if [ -z \"$git_diff\" ]; then\n        log \"No git diff found to apply\"\n        return\n    fi\n\n    log \"Applying git diff\"\n    echo \"$git_diff\" | git apply\n}\n\nfilter_thresholds_to_allowlist() {\n    git_diff=$1\n\n    log \"Filtering thresholds\"\n    for thresholds_file in $(echo \"$git_diff\" | grep \"+++\" | sed -E 's/^\\+\\+\\+ b\\/(.*)$/\\1/g'); do\n        jq 'with_entries(select(.key | in({mallocCountTotal:1, memoryLeaked:1})))' \"$thresholds_file\" > temp.json && mv -f temp.json \"$thresholds_file\"\n    done\n}\n\n####\n\nread -r repo_org repo_name type <<< \"$(parse_url \"$url\")\"\nrepo=\"$repo_org/$repo_name\"\nlog \"URL is of type $type in $repo\"\n\ncase \"$type\" in\n\"PR\")\n    log \"Fetching checks for $url\"\n    check_lines=\"$(fetch_checks_for_pr \"$url\")\"\n\n    if [ -z \"$check_lines\" ]; then\n        fatal \"Could not locate benchmark checks on PR: $url\"\n    fi\n    ;;\n\n\"run\")\n    run=\"$(parse_workflow_url \"$url\")\"\n\n    log \"Fetching checks for $repo run $run\"\n    check_lines=\"$(fetch_checks_for_workflow \"$repo\" \"$run\")\"\n\n    if [ -z \"$check_lines\" ]; then\n        fatal \"Could not locate benchmark checks on workflow run: $url\"\n    fi\n    ;;\n\n*)\n    fatal \"Unknown type '$type'\"\n    ;;\nesac\n\nwhile read -r check_line; do\n    job=\"$(parse_check \"$type\" \"$check_line\")\"\n\n    lines=$(fetch_check_logs \"$repo\" \"$job\")\n\n    if [ -z \"$lines\" ]; then\n        log \"Nothing to update: $repo job: $job\"\n        continue\n    fi\n\n    git_diff=\"$(scrape_benchmarks_output_diff \"$lines\" \"$job\")\"\n    apply_benchmarks_output_diff \"$git_diff\"\n\n    filter_thresholds_to_allowlist \"$git_diff\"\n\ndone <<< \"$check_lines\"\n"
  },
  {
    "path": "dev/update-integration-test-thresholds.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# This script allows you to consume GitHub Actions integration test logs and\n# update allocation threshold JSON files automatically\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\nusage() {\n    echo >&2 \"Usage: $0 <url>\"\n    echo >&2 \"   or: URL=<url> $0\"\n    echo >&2\n    echo >&2 \"Example:\"\n    echo >&2 \"  $0 https://github.com/apple/swift-nio/pull/3442\"\n    echo >&2 \"  $0 https://github.com/apple/swift-nio/actions/runs/19234929677\"\n    echo >&2 \"  URL=https://github.com/apple/swift-nio/pull/3442 $0\"\n}\n\nurl=\"${1:-${URL:-}}\"\n\nif [ -z \"$url\" ]; then\n    usage\n    fatal \"Pull request or workflow run URL must be specified.\"\nfi\n\n# Check for required tools\nGH_BIN=\"${GH_BIN:-$(which gh)}\" || fatal \"GH_BIN unset and no gh on PATH\"\nJQ_BIN=\"${JQ_BIN:-$(which jq)}\" || fatal \"JQ_BIN unset and no jq on PATH\"\n\n# Check repository and script paths\nREPO_ROOT=\"$(git rev-parse --show-toplevel)\" || fatal \"Must be run from within git repository\"\nALLOC_LIMITS_SCRIPT=\"$REPO_ROOT/dev/alloc-limits-from-test-output\"\n\nif [ ! -x \"$ALLOC_LIMITS_SCRIPT\" ]; then\n    fatal \"alloc-limits-from-test-output script not found at: $ALLOC_LIMITS_SCRIPT\"\nfi\n\nTHRESHOLDS_DIR=\"${THRESHOLDS_DIR:-$REPO_ROOT/IntegrationTests/tests_04_performance/Thresholds}\"\n\nif [ ! -d \"$THRESHOLDS_DIR\" ]; then\n    fatal \"Thresholds directory not found at: $THRESHOLDS_DIR\"\nfi\n\n# Map job name pattern to threshold file name\nmap_version() {\n    check_line=$1\n\n    case \"$check_line\" in\n        *\"(5.8)\"*)\n            echo \"5.8\"\n            ;;\n        *\"(5.10)\"*)\n            echo \"5.10\"\n            ;;\n        *\"(6.0)\"*)\n            echo \"6.0\"\n            ;;\n        *\"(6.1)\"*)\n            echo \"6.1\"\n            ;;\n        *\"(6.2)\"*)\n            echo \"6.2\"\n            ;;\n        *\"(nightly-6.1)\"*)\n            echo \"nightly-6.1\"\n            ;;\n        *\"(nightly-next)\"*)\n            echo \"nightly-next\"\n            ;;\n        *\"(nightly-main)\"*)\n            echo \"nightly-main\"\n            ;;\n        *)\n            return 1\n            ;;\n    esac\n}\n\n# Track whether any files were updated\nupdated_count=0\n\nparse_url() {\n    workflow_url=$1\n    # https://github.com/apple/swift-nio/actions/runs/15269806473\n    # https://github.com/apple/swift-nio/actions/runs/19234929677/job/54982236271?pr=3442\n    # https://github.com/apple/swift-nio/pull/3257\n    if [[ \"$url\" =~ pull ]]; then\n        type=\"PR\"\n    elif [[ \"$url\" =~ actions/runs ]]; then\n        type=\"run\"\n    else\n        fatal \"Cannot parse URL: $url\"\n    fi\n    echo \"$url\" | awk -v type=\"$type\" -F '/' '{print $4, $5, type}'\n}\n\nparse_workflow_url() {\n    workflow_url=$1\n    # https://github.com/apple/swift-nio/actions/runs/15269806473\n    # https://github.com/apple/swift-nio/actions/runs/19234929677/job/54982236271?pr=3442\n    echo \"$workflow_url\" | sed -E 's|.*/actions/runs/([0-9]+).*|\\1|'\n}\n\nfetch_checks_for_pr() {\n    pr_url=$1\n\n    \"$GH_BIN\" pr checks \"$pr_url\" | grep \"Integration tests\" | grep -v Construct\n}\n\nfetch_checks_for_workflow() {\n    repo=$1\n    run=$2\n\n    \"$GH_BIN\" --repo \"$repo\" run view \"$run\" | grep \"Integration tests\" | grep ID | grep -v Construct\n}\n\nparse_check() {\n    type=$1\n    check_line=$2\n\n    case \"$type\" in\n    \"PR\")\n        parse_check_for_pr \"$check_line\"\n        ;;\n\n    \"run\")\n        parse_check_for_workflow \"$check_line\"\n        ;;\n\n    *)\n        fatal \"Unknown type '$type'\"\n        ;;\n    esac\n}\n\nparse_check_for_workflow() {\n    check_line=$1\n\n    # Something like:\n    # ✓ Integration tests / Integration tests / Linux (5.10) in 5m10s (ID 42942543009)\n    echo \"$check_line\" | sed -En 's/.*ID ([0-9][0-9]*).*/\\1/p'\n}\n\nparse_check_for_pr() {\n    check_line=$1\n\n    # Something like:\n    # Integration tests / Integration tests / Linux (5.10)\tpass\t4m21s\thttps://github.com/apple/swift-nio/actions/runs/13793783082/job/38580234681\n    echo \"$check_line\" | sed -E 's/.*\\(([^\\)]+)\\).*github\\.com\\/(.*)\\/actions\\/runs\\/[0-9]+\\/job\\/([0-9]+)/\\3/g'\n}\n\nextract_version_from_check_line() {\n    check_line=$1\n\n    # Extract version from job name like \"Integration tests / Linux (6.0)\" or \"X Integration tests / Linux (6.0) in 22m31s (ID 123)\"\n    if version=$(map_version \"$check_line\"); then\n        echo \"$version\"\n        return 0\n    fi\n\n    error \"Could not extract version from check line: $check_line\"\n    return 1\n}\n\nfetch_check_logs() {\n    version=$1\n    job=$2\n\n    log \"Pulling logs for Swift $version (job $job)\"\n    # We use `gh api` rather than `gh run view --log` because of https://github.com/cli/cli/issues/5011.\n    \"$GH_BIN\" api \"/repos/${repo}/actions/jobs/${job}/logs\"\n}\n\nupdate_threshold_file() {\n    version=$1\n    logs=$2\n\n    threshold_file=\"$THRESHOLDS_DIR/$version.json\"\n\n    # Compute relative path from repo root\n    threshold_file_relative=\"${threshold_file#\"$REPO_ROOT\"/}\"\n\n    # Parse logs and update threshold file\n    new_thresholds=$(echo \"$logs\" | \"$ALLOC_LIMITS_SCRIPT\" --json)\n\n    if [ -z \"$new_thresholds\" ]; then\n        error \"No thresholds extracted from logs for version $version\"\n        return 1\n    fi\n\n    # Compare old and new files (both sorted with jq) and only overwrite if there are substantive differences\n    if [ -f \"$threshold_file\" ]; then\n        old_normalized=$(\"$JQ_BIN\" -S --indent 4 . \"$threshold_file\" 2>/dev/null || echo \"\")\n        new_normalized=$(echo \"$new_thresholds\" | \"$JQ_BIN\" -S --indent 4 . 2>/dev/null || echo \"\")\n\n        if [ \"$old_normalized\" = \"$new_normalized\" ]; then\n            log \"No changes for $threshold_file_relative (skipping)\"\n            return 0\n        fi\n    fi\n\n    echo \"$new_thresholds\" | \"$JQ_BIN\" -S --indent 4 . > \"$threshold_file\"\n    log \"Updated $threshold_file_relative\"\n    updated_count=$((updated_count + 1))\n}\n\n####\n\nread -r repo_org repo_name type <<< \"$(parse_url \"$url\")\"\nrepo=\"$repo_org/$repo_name\"\nlog \"Processing $type in $repo\"\n\ncase \"$type\" in\n\"PR\")\n    log \"Fetching integration test checks from PR\"\n    check_lines=\"$(fetch_checks_for_pr \"$url\")\"\n\n    if [ -z \"$check_lines\" ]; then\n        fatal \"Could not locate integration test checks on PR: $url\"\n    fi\n    ;;\n\n\"run\")\n    run=\"$(parse_workflow_url \"$url\")\"\n\n    log \"Fetching integration test checks from workflow run $run\"\n    check_lines=\"$(fetch_checks_for_workflow \"$repo\" \"$run\")\"\n\n    if [ -z \"$check_lines\" ]; then\n        fatal \"Could not locate integration test checks on workflow run: $url\"\n    fi\n    ;;\n\n*)\n    fatal \"Unknown type '$type'\"\n    ;;\nesac\n\nwhile read -r check_line; do\n    version=\"$(extract_version_from_check_line \"$check_line\")\"\n\n    if [ -z \"$version\" ]; then\n        log \"Skipping check line (couldn't extract version): $check_line\"\n        continue\n    fi\n\n    job=\"$(parse_check \"$type\" \"$check_line\")\"\n\n    if [ -z \"$job\" ]; then\n        error \"Could not extract job ID from check line: $check_line\"\n        continue\n    fi\n\n    logs=$(fetch_check_logs \"$version\" \"$job\")\n\n    if [ -z \"$logs\" ]; then\n        log \"No logs found for Swift $version (job $job)\"\n        continue\n    fi\n\n    update_threshold_file \"$version\" \"$logs\"\n\ndone <<< \"$check_lines\"\n\nif [ \"$updated_count\" -eq 0 ]; then\n    log \"Done! No updates necessary\"\nelse\n    log \"Done! Updated $updated_count threshold file(s)\"\nfi\n"
  },
  {
    "path": "docs/advanced-performance-analysis.md",
    "content": "# Advanced performance analysis for CPU-bound programs\n\nMost performance problems can be handily debugged with [Instruments, `perf`, or FlameGraphs](https://github.com/swift-server/guides/blob/main/docs/performance.md). At times however, there are changes in performance that are very hard to understand and sometimes very counter intuitive.\n\n## Motivating example (feel free to skip)\nA motivating example is [this pull request](https://github.com/apple/swift-nio/pull/1733) which is supposed to improve the performance of `ByteToMessageDecoder`s in very specific cases. The expectation would be that most performance tests remain the same and everything that uses a `ByteToMessageDecoder` either remains the same or becomes a little faster. Of course, all the low-level microbenchmarks that don't even use `ByteToMessageDecoder`s should be totally unaffected by this change.\n\nFor the most part that was the case, except for two benchmarks in SwiftNIO's performance test suite for which the [results were](https://github.com/apple/swift-nio/pull/1733#issuecomment-766917189) very unexpected:\n\n<table border=\"1\">\n  <tr>\n    <td>benchmark name</td>\n    <td>run time with PR</td>\n    <td>run time before PR</td>\n    <td>which is faster</td>\n    <td>difference</td>\n  </tr>\n  <tr>\n    <td>circular_buffer_into_byte_buffer_1kb</td>\n    <td>0.05089386</td>\n    <td>0.041163118</td>\n    <td>previous</td>\n    <td>23%</td>\n  </tr>\n  <tr>\n    <td>circular_buffer_into_byte_buffer_1mb</td>\n    <td>0.094321349</td>\n    <td>0.082286637</td>\n    <td>previous</td>\n    <td>14%</td>\n  </tr>\n</table>\n\nThis means that for whatever reason, the totally unrelated benchmarks `circular_buffer_into_byte_buffer_*` got _slower_ by 23% and 14% respectively (measured in wall clock seconds) despite using none of the changed code.\n\n## Wall clock time\n\nTo start out, we need to verify if the benchmark results are stable regarding wall clock time. If there is too much variation, then it is likely that too much I/O or allocations etc are involved. If a benchmark is unstable because of I/O or allocations, there are better tools available than what is discussed here, for example `strace`, Instrument's \"Allocations\" instrument, or Xcode's Memory Graph Debugger. This document solely discusses _CPU-bound_ and mostly single-threaded performance analysis, ie. you should see one CPU core pegged at 100% for the whole duration of the benchmark.\n\n## Executed CPU instructions\n\nIf you have two versions of a program, one faster and one slower and you want to find out what is going on, then often it makes sense to look at the number of CPU instructions executed during the benchmark.\n\nOn Linux -- assuming you have access to the PMU (Performance Monitoring Unit) -- this is rather straightforward\n\n    perf stat -- ./benchmark arguments\n\nThe output will look similar to\n\n```\n Performance counter stats for './my-benchmark args':\n\n            449.96 msec task-clock                #    1.001 CPUs utilized\n                36      context-switches          #    0.080 K/sec\n                 9      cpu-migrations            #    0.020 K/sec\n              2989      page-faults               #    0.007 M/sec\n        1736698259      cycles                    #    3.860 GHz\n          53504877      stalled-cycles-frontend   #    3.08% frontend cycles idle\n        5927885177      instructions              #    3.41  insn per cycle\n                                                  #    0.01  stalled cycles per insn\n        1422566509      branches                  # 3161.555 M/sec\n            375326      branch-misses             #    0.03% of all branches\n\n       0.449450377 seconds time elapsed\n\n       0.442788000 seconds user\n       0.008050000 seconds sys\n```\n\nFirst, we can confirm that it is nicely CPU bound (`1.001 CPUs utilized`).\n\nWe can also see that we executed about 5.9B instructions during this benchmark run. The number of instructions executed itself is not very meaningful but it can be very useful when comparing between versions of the same code. For example, let's assume we changed some code and want to confirm in a benchmark that indeed we have made it faster, then it can be very useful to see that we have also reduced the number of instructions.\n\nWith `perf` you could run `perf stat -e instructions -- ./benchmark-before-change` and `perf stat -e instructions -- ./benchmark-after-change` and confirm that:\n\n1. The runtime (_time elapsed_) has gone down and\n2. the number of instructions executed has gone down too.\n\nNote that the time it takes to run an instruction varies wildly so it is in theory possible to reduce the number of instructions but make performance actually worse. An example would be if you traded a lot of simple arithmetic for memory accesses. Said that, in most cases where you reduced the number of instructions significantly, you will also see an improvement in the actual runtime. As a control, the number of instructions per cycle can also be useful as it would go down if you traded faster instructions for slower instructions.\n\nAnother place where instruction counts come in very handy is when you see this maybe impossible-sounding situation: the run time varies significantly but the number of executed instructions is _the same_. The motivating example is exactly this situation: The code executed is the _same_, confirmed by manually checking the generated assembly for the code run as well as checking that the number of instructions is almost equal. Because manual assembly analysis can easily go wrong, it's advisable to compare the number of executed instructions even if you convinced yourself that the executed code is the same. Of course, there are other options like single-stepping in a debugger but that gets tedious quickly. If the executed code and the inputs are the same, then the number of executed instructions should also be the same (ie. < 0.01% variance).\n\nThat begs the question: What can we do if we have the runtime differs despite running the exact same instructions? Assuming the code is CPU-bound, the answer is probably that the CPU cannot execute the instructions at the same velocity because it internally has to wait for something (such as memory, more instructions being decoded, another resource, ...). Many of these situations are referred to as CPU stalls.\n\n## CPU stalls\n\nWhen ending up in situations where a difference in run time is not clearly reflected in the instructions executed, it may be worth looking into CPU stalls. Modern CPUs may be unable to reach their full speed for a variety of reasons. For example it could be that the instruction decoder can't decode the instructions as fast as they could execute (be retired). Or instructions may have to wait to be executed because the data required is slow to load (cache misses etc).\n\nThe easiest way to look into such micro-architectural issues are through the CPU's performance counters and with `perf` they're quite easy to access.\n\nA good starting point for tracing stalls may be\n\n    perf stat -e instructions,stalled-cycles-frontend,uops_executed.stall_cycles,resource_stalls.any,cycle_activity.stalls_mem_any -- ./benchmark\n\nWhich instructs `perf` to collect the following performance counters:\n\n- `instructions`: The number of CPU instructions executed,\n- `stalled-cycles-frontend`: cycles where nothing happened because instructions cannot be decoded fast enough,\n- `uops_executed.stall_cycles`: the number of cycles where no (micro-)operations were dispatched to be executed on a given core,\n- `resource_stalls.any`: Stalls that occurred because the backend had to wait for resources (eg. memory)\n- `cycle_activity.stalls_mem_any`: execution stalls while memory subsystem has an outstanding load.\n\nwhich will yield output similar to\n\n```\n Performance counter stats for './fast circular_buffer_into_byte_buffer_1kb':\n\n        5927396603      instructions\n          64091849      stalled-cycles-frontend\n          38429768      uops_executed.stall_cycles\n          13278071      resource_stalls.any\n          22148955      cycle_activity.stalls_mem_any\n\n       0.452895518 seconds time elapsed\n```\n\nAnd just like for the instruction counts, the absolute counts of the stalled cycles are not that important, but they can be very important as a comparison. Going back to the motivating example, where we could see:\n\nfast version (`perf stat -e counters... -- ./fast`):\n\n```\n Performance counter stats for './fast circular_buffer_into_byte_buffer_1kb':\n\n        5927396603      instructions\n          34307940      uops_executed.stall_cycles\n          13109779      resource_stalls.any\n          18148622      cycle_activity.stalls_mem_any\n\n       0.409785892 seconds time elapsed\n```\n\nslow version (`perf stat -e counters... -- ./slow`):\n\n```\n Performance counter stats for './slow circular_buffer_into_byte_buffer_1kb':\n\n        5927358294      instructions\n         308782310      uops_executed.stall_cycles\n          14159547      resource_stalls.any\n         288072686      cycle_activity.stalls_mem_any\n\n       0.510635133 seconds time elapsed\n\n```\n\nWhat we can immediately see is that `resource_stalls.any` is pretty much the same in both cases, but `uops_executed.stall_cycles` and `cycle_activity.stalls_mem_any` are about an order of magnitude higher for the slow case. Remember, this is with the number of instructions being almost the same.\n\nSo in this case, we would have identified that the slowdown comes from us getting a lot of \"stall cycles\" in the CPU. Those are cycles where the CPU was free to run some (micro-)instructions but could not. Unfortunately, from this picture alone, it is unclear _why_ exactly the CPU couldn't actually run some more (micro-)operations. We’ve only learned a little so far, we need to dig deeper.\n\nOne strategy is to run\n\n    perf list | less\n\nand in there, search for \"stall\" (using `/stall`) and \"penalty\". This will yield some results of available performance counters that allow you to identify which particular stall it may be. It's worth to know that you can specify a bunch of them in one command line (comma separated). Figuring out which ones to choose is really an exercise in brute force with a little educated guessing, there aren't _that many_ such counters so it won't take you too long.  In the motivating example, the culprit turned out to be `dsb2mite_switches.penalty_cycles`\n\n```\n Performance counter stats for './fast circular_buffer_into_byte_buffer_1kb':\n\n           9943811      dsb2mite_switches.penalty_cycles\n\n       0.408032273 seconds time elapsed\n```\n\nvs\n\n```\n Performance counter stats for './slow circular_buffer_into_byte_buffer_1kb':\n\n         229285609      dsb2mite_switches.penalty_cycles\n\n       0.511033898 seconds time elapsed\n```\n\nThe names of these stalls/penalties can be quite opaque and understanding what exactly is going on can be rather hard without a pretty good understanding of how a particular CPU micro-architecture works. Nevertheless, being able to pinpoint why a slowdown happens can be very important as it may give information on what to change in the code.\n\nIn case you're wondering what `dsb2mite_switches.penalty_cycles` is, a web search revealed a nicely written [blogpost](https://easyperf.net/blog/2018/01/18/Code_alignment_issues) which discusses something very similar. Bottom line is that modern Intel CPUs have a MITE (Micro-operation Translation Engine) which seems to read the instruction stream in 16 byte chunks. So if the alignment of your code is changed (for example by adding/removing an unrelated function to/from your binary) you may incur a penalty if your instructions aren't aligned by 16 bytes (remember, Intel instructions are variable length). This does sound scary (and for some code it is) but the good news is that this should _very rarely_ matter outside of micro-benchmarks. If your whole run time is doing exactly what that micro-benchmark is doing, you should probably care. But most real-world code does much more and more diverse work than some arbitrary micro-benchmarks. So in this particular example we can safely ignore the \"regression\" which was just unlucky placement of the hot function in the binary. Nevertheless it was important to understand why the regression happened so we could safely decide it does not matter in this instance.\n\n## The bad news: PMU access\n\nUnfortunately, in some environments like Docker for Mac and other solutions relying on virtualisation it can be hard to get access to the PMU (the CPU's performance measuring unit). Check out this [guide](https://github.com/swift-server/guides/blob/main/docs/linux-perf.md#getting-perf-to-work) for tips on getting `perf` with PMU support to work in your environment.\n"
  },
  {
    "path": "docs/debugging-allocations.md",
    "content": "# How to debug allocation regressions\n\nUsually, your journey will start by detecting that an allocation test regressed. So let's first start by looking at how to run the allocation counter tests.\n\n## Running allocation counter tests\n\nThe allocation counter tests are usually run by NIO's integration test framework which lives in `IntegrationTests/`. In there, you first want to identify the test suite and test case that runs all the allocation counter tests. For the `swift-nio` repository that is\n\n    IntegrationTests/tests_04_performance/test_01_allocation_counts.sh\n\nNext to the test case (`test_01_allocation_counts.sh`) that runs the allocation counter tests should be a resource directory which contains the individual allocation counter tests. For `swift-nio` that is\n\n    IntegrationTests/tests_04_performance/test_01_resources\n\nFrom here on, this document expects that you are within this directory, so you might want to start with\n\n    cd IntegrationTests/tests_04_performance/test_01_resources/\n\nTo run all the allocation tests, simply invoke the runner script in there\n\n    ./run-nio-alloc-counter-tests.sh\n\nThe invocation of this script will take a while because it has to build all of SwiftNIO in release mode first, then it compiles the integration tests and runs them all, multiple times...\n\n### Understanding the output of the allocation counter tests\n\nThe output of this script will look something like\n\n```\n- /Users/johannes/devel/swift-nio/IntegrationTests/tests_04_performance/test_01_resources/test_future_lots_of_callbacks.swift\ntest_future_lots_of_callbacks.remaining_allocations: 0\ntest_future_lots_of_callbacks.total_allocations: 75001\ntest_future_lots_of_callbacks.total_allocated_bytes: 4138056\nDEBUG: [[\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0]]\n```\n\nwith this kind of block repeated for each allocation counter test. Let's go through and understand each line. The first line is the name of the specific allocation test. The most relevant part is the file name (`test_future_lots_of_callbacks.swift`). For this test, we seem to be testing how many allocations futures with many callbacks are doing.\n\n```\n- /Users/johannes/devel/swift-nio/IntegrationTests/tests_04_performance/test_01_resources/test_future_lots_of_callbacks.swift\n```\n\nNext, we see\n\n```\ntest_future_lots_of_callbacks.remaining_allocations: 0\ntest_future_lots_of_callbacks.total_allocations: 75001\ntest_future_lots_of_callbacks.total_allocated_bytes: 4138056\n```\n\nwhich are the aggregate values. The first line says `remaining_allocations: 0`, which means that this allocation test didn't leak, which is good! Then, we see\n\n    test_future_lots_of_callbacks.total_allocations: 75001\n\nwhich means that by the end of the test, we saw 75001 allocations in total. As a rule, we usually run the workload of every allocation test 1000 times. That means you want to divide 75001 by the 1000 runs to get the number of allocations per run. In other words: each iteration of this allocation test allocated 75 times. The extra one allocation is just some noise that we have to ignore: these are usually inserted by operations in the Swift runtime that need to initialize some state. In many (especially multi-threaded test cases) there is some noise, which is why we run the workload repeatedly, which makes it easy to tell the signal from the noise.\n\nFinally, we see\n\n    test_future_lots_of_callbacks.total_allocated_bytes: 4138056\n\nWhich is the total number of bytes allocated by this test.\n\n\nLast of all, we see\n\n```\nDEBUG: [[\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"remaining_allocations\": 0, \"total_allocated_bytes\": 4138056], [\"total_allocated_bytes\": 4138056, \"total_allocations\": 75001, \"remaining_allocations\": 0], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 75001, \"total_allocated_bytes\": 4138056], [\"total_allocations\": 75001, \"total_allocated_bytes\": 4138056, \"remaining_allocations\": 0]]\n```\n\nwhich is literally just the exact numbers of each of the 10 runs we considered. Note, the lines are prefixed with `DEBUG:` to make analysis of the output easier, it does _not_ mean we're running in debug mode. If you see a lot of fluctuation between the runs, then the allocation test doesn't allocate deterministically which would be something you want to fix. In the example above, we're totally stable to the last byte of allocated memory, so we have nothing to worry about with this test.\n\n## Important notes\n\nThe exact allocation counts are _not_ directly comparable between different operating systems and even different versions of the same operating system. Every new Swift version will also introduce differences (hopefully decreasing over time).\n\nThis means that if you get hit by a CI failure, you will have to first reproduce the regression locally by running the allocation counter tests once on `main` and then again on your failing branch.\n\n## Debugging a regression in a particular test\n\nBecause it takes quite a while to run the whole allocation counter test suite, there are some shortcuts you definitely want to know about. First, let's have a look at how we can run just single test.\n\n\n### Running a single test\n\nRunning a single test is very straightforward, pass the test's `.swift` file to the runner script. For example:\n\n    ./run-nio-alloc-counter-tests.sh test_future_lots_of_callbacks.swift\n\nYou will notice that it now runs faster but also that it still compiles SwiftNIO for every single time you run the program. So that's still rather slow. If you look closely at the output you will notice that it prints messages such as\n\n```\nFetching /private/tmp/.nio_alloc_counter_tests_5jMMhk/swift-nio\nFetching /private/tmp/.nio_alloc_counter_tests_5jMMhk/HookedFunctions\nFetching /private/tmp/.nio_alloc_counter_tests_5jMMhk/AtomicCounter\n```\n\nIf you change your working directory to common directory above (`/private/tmp/.nio_alloc_counter_tests_5jMMhk`), then you will find a regular Swift package there and you can just re-run the allocation counter tests using\n\n```\ncd /tmp/.nio_alloc_counter_tests_5jMMhk\nswift run -c release\n```\n\nwhich should run very quickly. But _do not_ forget to pass `-c release`, otherwise the results will be meaningless.\n\n### Debugging with other tools\n\nOften, you will want to use external tools such as Instruments or `dtrace` to analyse why a performance test regressed. Unfortunately, that is a little harder than you might expect because to implement the allocation tests, the allocation counter test framework actually [hijacks](https://github.com/apple/swift-nio/blob/main/IntegrationTests/tests_04_performance/test_01_resources/README.md) functions like `malloc` and `free`. The counting of allocations happens in the hijacked or 'hooked' functions.\nTo use an external memory analysis tool, it's best to not do the hooking and fortunately it's very straightforward to switch the hooking off.\n\nTo disable the hooking, run the runner script with `-- -n` followed by the file name of the test you would like to debug. For example\n\n    ./run-nio-alloc-counter-tests.sh -- -n test_future_lots_of_callbacks.swift\n\nWhen you run this, you will notice that every allocation counter test now outputs\n\n```\nFetching /private/tmp/.nio_alloc_counter_tests_0UDNXS/HookedFunctions\nFetching /private/tmp/.nio_alloc_counter_tests_0UDNXS/swift-nio\nFetching /private/tmp/.nio_alloc_counter_tests_0UDNXS/AtomicCounter\n[...]\ntest_future_lots_of_callbacks.total_allocations: 0\ntest_future_lots_of_callbacks.remaining_allocations: 0\ntest_future_lots_of_callbacks.total_allocated_bytes: 0\nDEBUG: [[\"total_allocations\": 0, \"remaining_allocations\": 0, \"total_allocated_bytes\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 0, \"total_allocated_bytes\": 0], [\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 0, \"total_allocations\": 0, \"remaining_allocations\": 0], [\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 0, \"remaining_allocations\": 0, \"total_allocations\": 0], [\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 0, \"remaining_allocations\": 0, \"total_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocated_bytes\": 0, \"total_allocations\": 0], [\"total_allocated_bytes\": 0, \"total_allocations\": 0, \"remaining_allocations\": 0]]\n```\n\nSee all the zeroes? Those are all zero because the hooking is disabled. In this mode the output itself is not very useful but you can now switch to using other tools like Intruments or `dtrace` to debug your allocations.\n\nAs explained before, you can change your working directory in the temporary directory (for example `cd /private/tmp/.nio_alloc_counter_tests_0UDNXS`) and invoke `swift run -c release` from there to run the allocation counter benchmark. Note that if you disabled hooking (by passing `-- -n`) it will still print only zeroes.\n\n### Debugging with Instruments\n\n1. Start Instruments\n2. Choose the \"Allocations\" instrument\n3. Tap the executable selector in the toolbar\n4. Click \"Choose Target...\"\n5. Tick \"Show Hidden Files\"\n6. Press Cmd+Shift+G\n7. Enter the temporary directory path of a non-hooked version of the allocation counter tests (for example `/private/tmp/.nio_alloc_counter_tests_0UDNXS`)\n8. Select `.build/release/`\n9. Find the binary that is named like your allocation counter test (eg. `test_lots_of_future_callbacks`)\n10. Click \"Choose\"\n11. Press the record button\n\nNow you should have a full Instruments allocations trace of the test run. To make sense of what's going on, switch the allocation lifespan from \"Created & Persisted\" to \"Created & Destroyed\". After that you should be able to see the type of the allocation and how many times it got allocated. Clicking on the little arrow next to the type name will reveal each individual allocation of this type and the responsible stack trace.\n\n### Debugging with `malloc-aggregation.d` or `malloc-aggreation.bt`\n\nSwiftNIO ships a `dtrace` script called `dev/malloc-aggregation.d` which can give you an aggregation of all allocations by stack trace, and an equivalent `bpftrace` script called `dev/malloc-aggregation.bt`. This means that you will see the stack trace of each allocation that happened and how many times this particular stack trace allocated.\n\nHere's an example of how to use the `dtrace` script:\n\n```\nsudo ~/path/to/swift-nio/dev/malloc-aggregation.d -c .build/release/test_future_lots_of_callbacks\n```\n\nThe `bpftrace` script can be invoked very similarly:\n\n```\nsudo ~/path/to/swift-nio/dev/malloc-aggregation.bt -c .build/release/test_future_lots_of_callbacks\n```\n\nHowever, for `bpftrace` it tends to work better if pid-based tracing is used instead. This is because `bpftrace` has a [known limitation where symbolication fails if the process being traced has existed before `bpftrace` does](https://github.com/bpftrace/bpftrace/issues/2118#issuecomment-1008694821). This can still be resolved using tools like `llvm-symbolizer`, but it's trickier.\n\nThe output will look something like\n\n```\n[...]\n              libsystem_malloc.dylib`malloc\n              libswiftCore.dylib`swift_slowAlloc+0x19\n              libswiftCore.dylib`swift_allocObject+0x27\n              test_1_reqs_1000_conn`SelectableEventLoop.run()+0x231\n              test_1_reqs_1000_conn`closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:)+0x106\n              test_1_reqs_1000_conn`partial apply for closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:)+0x2d\n              test_1_reqs_1000_conn`thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()+0xf\n              test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()+0x11\n              test_1_reqs_1000_conn`closure #1 in static ThreadOpsPosix.run(handle:args:detachThread:)+0x1e4\n              libsystem_pthread.dylib`_pthread_start+0x94\n              libsystem_pthread.dylib`thread_start+0xf\n           231000\n\n```\n\nrepeated many times. Each block means that the specific stack trace is responsible for some number of allocations: in the example above, `231000` allocations. Remember that the allocation counter tests run each test 11 times (1 warm up run and 10 measured runs), so this means that in each test run, the above stack trace allocated 21000 times. Also remember that we usually run the workload we want to test 1000 times. That means that in the real world, the above stack trace accounts for 21 out of the total number of allocations (231000 allocations / 11 runs / 1000 executions per run = 21).\n\nWhen you are looking at allocations in the setup of the test the numbers may be split into one allocation set of 10000 and another of 1000 - for measured code vs warm up run.\n\nThe output from `malloc-aggreation.d` can also be diffed using the `stackdiff-dtrace.py` script. This can be helpful to track down where additional allocations were made. Right now this strategy doesn't work for `bpftrace`, but a simple modification to the `stackdiff-dtrace` script should enable it.\n\nThe `stdout` from `malloc-aggregation.d` for the two runs to compare should be written to files, and then passsed to `stackdiff-dtrace.py`:\n\n```bash\n~/path/to/swift-nio/dev/stackdiff-dtrace.py stack_aggregation.old stack_aggregation.new\n```\n\nWhere `stack_aggregation.old` and `stack_aggregation.new` are the two outputs from `malloc-aggregation.d` to compare. The script will output the aggregated stacks which appear: \n\n- only in `stack_aggregation.old`,\n- only in `stack_aggregation.new`, and\n- any differences in numbers for stacks that appear in both.\n\nSimilar stack traces will be aggregated into a headline number for matching but where different the full stack traces which made up the collection will be printed indented.\n\nAllocations of less than 1000 in number are ignored - as the tests all run multiples of 1000 runs any values below this are almost certainly from setup in libraries we are using rather than as a consequence of our measured run.\n\nLet's look at some output.\n\n```\n### only in AFTER\n11000\nlibsystem_malloc.dylib`malloc\nlibswiftCore.dylib`swift_slowAlloc\nlibswiftCore.dylib`swift_allocObject\ntest_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR\ntest_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TR\ntest_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA\ntest_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA.18\ntest_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR\n\n    11000\n        libsystem_malloc.dylib`malloc\n        libswiftCore.dylib`swift_slowAlloc+0x19\n        libswiftCore.dylib`swift_allocObject+0x27\n        test_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR+0x54\n        test_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TR+0x20\n        test_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA+0x11\n        test_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA.18+0x9\n        test_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR+0x2e\n        test_1_reqs_1000_conn`specialized applyNext #1 () in ChannelOptions.Storage.applyAllChannelOptions(to:)+0x1a9\n        test_1_reqs_1000_conn`closure #2 in ServerBootstrap.bind0(makeServerChannel:_:)+0xf8\n        test_1_reqs_1000_conn`partial apply for closure #2 in ServerBootstrap.bind0(makeServerChannel:_:)+0x39\n        test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed () -> (@owned EventLoopFuture<Channel>, @error @owned Error)+0x14\n        test_1_reqs_1000_conn`thunk for @escaping @callee_guaranteed () -> (@owned EventLoopFuture<Channel>, @error @owned Error)partial apply+0x9\n        test_1_reqs_1000_conn`closure #1 in EventLoop.submit<A>(_:)+0x3c\n        test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed () -> ()+0x11\n        test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed () -> (@out ())+0x11\n        test_1_reqs_1000_conn`partial apply for closure #3 in SelectableEventLoop.run()+0x11\n        test_1_reqs_1000_conn`thunk for @callee_guaranteed () -> (@error @owned Error)+0xc\n        test_1_reqs_1000_conn`partial apply for thunk for @callee_guaranteed () -> (@error @owned Error)+0x11\n        test_1_reqs_1000_conn`thunk for @callee_guaranteed () -> (@error @owned Error)partial apply+0x9\n[...]\n\n### only in BEFORE\n11000\nlibsystem_malloc.dylib`malloc\nlibswiftCore.dylib`swift_slowAlloc\nlibswiftCore.dylib`swift_allocObject\ntest_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR\ntest_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TR\ntest_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA\ntest_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA.33\ntest_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR\n\n    11000\n        libsystem_malloc.dylib`malloc\n        libswiftCore.dylib`swift_slowAlloc+0x19\n        libswiftCore.dylib`swift_allocObject+0x27\n        test_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR+0x54\n        test_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TR+0x20\n        test_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA+0x11\n        test_1_reqs_1000_conn`$s3NIO7Channel_pypypAA15EventLoopFutureCyytGIegnno_Ieggo_AaB_pxq_q0_r1_lyypypAEIsegnnr_Iegnr_TRTA.33+0x9\n        test_1_reqs_1000_conn`$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR+0x2e\n        test_1_reqs_1000_conn`specialized applyNext #1 () in ChannelOptions.Storage.applyAllChannelOptions(to:)+0x1a9\n        test_1_reqs_1000_conn`closure #2 in ServerBootstrap.bind0(makeServerChannel:_:)+0xf8\n        test_1_reqs_1000_conn`partial apply for closure #2 in ServerBootstrap.bind0(makeServerChannel:_:)+0x39\n        test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed () -> (@owned EventLoopFuture<Channel>, @error @owned Error)+0x14\n        test_1_reqs_1000_conn`thunk for @escaping @callee_guaranteed () -> (@owned EventLoopFuture<Channel>, @error @owned Error)partial apply+0x9\n        test_1_reqs_1000_conn`closure #1 in EventLoop.submit<A>(_:)+0x3c\n        test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed () -> ()+0x11\n        test_1_reqs_1000_conn`partial apply for thunk for @escaping @callee_guaranteed () -> (@out ())+0x11\n        test_1_reqs_1000_conn`partial apply for closure #3 in SelectableEventLoop.run()+0x11\n        test_1_reqs_1000_conn`thunk for @callee_guaranteed () -> (@error @owned Error)+0xc\n        test_1_reqs_1000_conn`partial apply for thunk for @callee_guaranteed () -> (@error @owned Error)+0x11\n        test_1_reqs_1000_conn`thunk for @callee_guaranteed () -> (@error @owned Error)partial apply+0x9\n[...]\n```\n\nThese stacks are only *slighly* different; differing only in the name similar to `$s3NIO7Channel_pxq_q0_r1_lyypypAA15EventLoopFutureCyytGIsegnnr_Iegnr_AaB_pypypAEIegnno_Ieggo_TR`. They're otherwise the same so we can ignore them and look at more output.\n\n```\n### only in AFTER\n[... (previously dismissed stacktrace)]\n\n2000\nlibsystem_malloc.dylib`malloc\nlibswiftCore.dylib`swift_slowAlloc\nlibswiftCore.dylib`swift_allocObject\ntest_1_reqs_1000_conn`doRequests(group:number:)\ntest_1_reqs_1000_conn`closure #1 in run(identifier:)\ntest_1_reqs_1000_conn`partial apply for closure #1 in measureOne #1 (throwAway:_:) in measureAll(_:)\ntest_1_reqs_1000_conn`partial apply for thunk for @callee_guaranteed () -> (@error @owned Error)\ntest_1_reqs_1000_conn`thunk for @callee_guaranteed () -> (@error @owned Error)partial apply\n\n    1000\n        libsystem_malloc.dylib`malloc\n        libswiftCore.dylib`swift_slowAlloc+0x19\n        libswiftCore.dylib`swift_allocObject+0x27\n        test_1_reqs_1000_conn`doRequests(group:number:)+0x66\n[...]\n        \n    1000\n        libsystem_malloc.dylib`malloc\n        libswiftCore.dylib`swift_slowAlloc+0x19\n        libswiftCore.dylib`swift_allocObject+0x27\n        test_1_reqs_1000_conn`doRequests(group:number:)+0x1c4\n[...]\n\n### only in BEFORE\n[... (previously dismissed stacktrace)]\n\n### different numbers\nbefore: 10000, after: 20000\n  AFTER\n    10000\n        libsystem_malloc.dylib`malloc\n        libswiftCore.dylib`swift_slowAlloc+0x19\n        libswiftCore.dylib`swift_allocObject+0x27\n        test_1_reqs_1000_conn`doRequests(group:number:)+0x66\n[...]\n```\n\nNow we see there's another stacktrace in the `AFTER` section which has no corresponding stacktrace in `BEFORE`. From the stack we can see it's originating from `doRequests(group:number:)`. In this instance we were working on options applied in this function so it appears we have added allocations.  We have also increased the number of allocations which are reported in the different numbers section where stack traces have been paired but with different numbers of allocations.\n\n### Debugging with 'heaptrack'\n\nIn some cases we don't have access to Linux kernel headers, which prevents us from using `bpftrace`, but there is the [heaptrack](https://github.com/KDE/heaptrack) tool which supports diff analysis of two versions.\n\nTested on Ubuntu 20.04 (and likely working on other distributions) Install it with:\n\n```\nsudo apt-get install heaptrack\n```\n\nThen using the instructions previously, you need to build the test without hooks such that heaptrack can hook instead, e.g.:\n\n```\ncd IntegrationTests/tests_04_performance/test_01_resources/\n./run-nio-alloc-counter-tests.sh -- -n test_1000_autoReadGetAndSet.swift \n```\n\nand then cd to the temp directory from the output (find the tmp directory as above), e.g.:\n\n```\ncd /tmp/.nio_alloc_counter_tests_5jMMhk\n```\n\nFinally, run the binary with heaptrack two times — first we do it for `main` to get a baseline:\n```\nubuntu@ip-172-31-25-161 /t/.nio_alloc_counter_tests_GRusAy> SWIFTNIO_URING_DISABLED=1 heaptrack .build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\nheaptrack output will be written to \"/tmp/.nio_alloc_counter_tests_GRusAy/heaptrack.test_1000_autoReadGetAndSet.84341.gz\"\nstarting application, this might take some time...\nSWIFTNIO_URING_DISABLED set, disabling liburing.\ntest_1000_autoReadGetAndSet.total_allocations: 0\ntest_1000_autoReadGetAndSet.total_allocated_bytes: 0\ntest_1000_autoReadGetAndSet.remaining_allocations: 0\nDEBUG: [[\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocated_bytes\": 0, \"total_allocations\": 0], [\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocated_bytes\": 0, \"total_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocated_bytes\": 0, \"total_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 0, \"total_allocated_bytes\": 0], [\"total_allocated_bytes\": 0, \"total_allocations\": 0, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 0, \"total_allocations\": 0, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 0, \"total_allocated_bytes\": 0], [\"total_allocations\": 0, \"remaining_allocations\": 0, \"total_allocated_bytes\": 0]]\nfree(): invalid pointer\nAborted (core dumped)\nheaptrack stats:\n    allocations:              319347\n    leaked allocations:       107\n    temporary allocations:    68\nHeaptrack finished! Now run the following to investigate the data:\n\n  heaptrack --analyze \"/tmp/.nio_alloc_counter_tests_GRusAy/heaptrack.test_1000_autoReadGetAndSet.84341.gz\"\n```\nThen run it a second time for the feature branch:\n```\nubuntu@ip-172-31-25-161 /t/.nio_alloc_counter_tests_ARusXy> heaptrack .build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\nheaptrack output will be written to \"/tmp/.nio_alloc_counter_tests_GRusAy/heaptrack.test_1000_autoReadGetAndSet.84372.gz\"\nstarting application, this might take some time...\ntest_1000_autoReadGetAndSet.remaining_allocations: 0\ntest_1000_autoReadGetAndSet.total_allocations: 0\ntest_1000_autoReadGetAndSet.total_allocated_bytes: 0\nDEBUG: [[\"remaining_allocations\": 0, \"total_allocations\": 0, \"total_allocated_bytes\": 0], [\"total_allocated_bytes\": 0, \"total_allocations\": 0, \"remaining_allocations\": 0], [\"total_allocated_bytes\": 0, \"remaining_allocations\": 0, \"total_allocations\": 0], [\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"total_allocations\": 0, \"remaining_allocations\": 0, \"total_allocated_bytes\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 0, \"total_allocated_bytes\": 0], [\"total_allocations\": 0, \"total_allocated_bytes\": 0, \"remaining_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocated_bytes\": 0, \"total_allocations\": 0], [\"remaining_allocations\": 0, \"total_allocations\": 0, \"total_allocated_bytes\": 0], [\"remaining_allocations\": 0, \"total_allocated_bytes\": 0, \"total_allocations\": 0]]\nfree(): invalid pointer\nAborted (core dumped)\nheaptrack stats:\n    allocations:              673989\n    leaked allocations:       117\n    temporary allocations:    341011\nHeaptrack finished! Now run the following to investigate the data:\n\n  heaptrack --analyze \"/tmp/.nio_alloc_counter_tests_GRusAy/heaptrack.test_1000_autoReadGetAndSet.84372.gz\"\nubuntu@ip-172-31-25-161 /t/.nio_alloc_counter_tests_GRusAy> \n```\nHere we could see that we had 673989 allocations in the feature branch version and 319347 in `main`, so clearly a regression.\n\nFinally, we can analyze the output as a diff from these runs using `heaptrack_print`:\n\n```\nheaptrack_print -T -d heaptrack.test_1000_autoReadGetAndSet.84341.gz heaptrack.test_1000_autoReadGetAndSet.84372.gz | swift demangle\n```\n`-T` gives us the temporary allocations (as it in this case was not a leak, but a transient alloaction - if you have leaks remove `-T`).\n\nThe output can be quite long, but in this case as we look for transient allocations, scroll down to:\n\n```\nMOST TEMPORARY ALLOCATIONS\n307740 temporary allocations of 290324 allocations in total (106.00%) from\nswift_slowAlloc\n  in /home/ubuntu/bin/usr/lib/swift/linux/libswiftCore.so\n43623 temporary allocations of 44553 allocations in total (97.91%) from:\n    swift_allocObject\n      in /home/ubuntu/bin/usr/lib/swift/linux/libswiftCore.so\n    NIO.ServerBootstrap.(bind0 in _C131C0126670CF68D8B594DDFAE0CE57)(makeServerChannel: (NIO.SelectableEventLoop, NIO.EventLoopGroup) throws -> NIO.ServerSocketChannel, _: (NIO.EventLoop, NIO.ServerSocketChannel) -> NIO.EventLoopFuture<()>) -> NIO.EventLoopFuture<NIO.Channel>\n      at /home/ubuntu/swiftnio/swift-nio/Sources/NIO/Bootstrap.swift:295\n      in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\n    merged NIO.ServerBootstrap.bind(host: Swift.String, port: Swift.Int) -> NIO.EventLoopFuture<NIO.Channel>\n      in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\n    NIO.ServerBootstrap.bind(host: Swift.String, port: Swift.Int) -> NIO.EventLoopFuture<NIO.Channel>\n      in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\n    Test_test_1000_autoReadGetAndSet.run(identifier: Swift.String) -> ()\n      at /tmp/.nio_alloc_counter_tests_GRusAy/Sources/Test_test_1000_autoReadGetAndSet/file.swift:24\n      in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\n    main\n      at Sources/bootstrap_test_1000_autoReadGetAndSet/main.c:18\n      in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\n22208 temporary allocations of 22276 allocations in total (99.69%) from:\n    swift_allocObject\n      in /home/ubuntu/bin/usr/lib/swift/linux/libswiftCore.so\n    generic specialization <Swift.UnsafeBufferPointer<Swift.Int8>> of Swift._copyCollectionToContiguousArray<A where A: Swift.Collection>(A) -> Swift.ContiguousArray<A.Element>\n      in /home/ubuntu/bin/usr/lib/swift/linux/libswiftCore.so\n    Swift.String.utf8CString.getter : Swift.ContiguousArray<Swift.Int8>\n      in /home/ubuntu/bin/usr/lib/swift/linux/libswiftCore.so\n    NIO.URing.getEnvironmentVar(Swift.String) -> Swift.String?\n      at /home/ubuntu/swiftnio/swift-nio/Sources/NIO/LinuxURing.swift:291\n      in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\n    NIO.URing._debugPrint(@autoclosure () -> Swift.String) -> ()\n      at /home/ubuntu/swiftnio/swift-nio/Sources/NIO/LinuxURing.swift:297\n...\n22196 temporary allocations of 22276 allocations in total (99.64%) from:\n```\n\nAnd here we could fairly quickly see that the transient extra allocations was due to extra debug printing and querying of environment variables:\n\n```\nNIO.URing.getEnvironmentVar(Swift.String) -> Swift.String?\n  at /home/ubuntu/swiftnio/swift-nio/Sources/NIO/LinuxURing.swift:291\n  in /tmp/.nio_alloc_counter_tests_GRusAy/.build/x86_64-unknown-linux-gnu/release/test_1000_autoReadGetAndSet\nNIO.URing._debugPrint(@autoclosure () -> Swift.String) -> ()\n```\n\nAnd this code will be removed before final integration of the feature branch, so the diff will go away.\n"
  },
  {
    "path": "docs/io_uring.md",
    "content": "#  SwiftNIO io_uring support status [Linux]\n\n## Background\nLinux has fairly recently received a new asynchrounus I/O interface — `io_uring` — that allows high-performance AIO with a minimum amount of system calls. Some background information at [LWN](https://lwn.net/Articles/810414/) and [kernel.dk](https://kernel.dk/io_uring.pdf)\n\n## Current status and supported platforms\nSwiftNIO has basic support for using `io_uring` as a notification mechanism. `io_uring` is available on Linux kernels starting from 5.1 and requires support for the POLL operations. SwiftNIO optionally supports multishot polls and poll updates through a configuration option - these are new interfaces that are expected to available from the future release 5.13 (as of this writing). The `io_uring` implementation has primarily been tested on version 5.12rc.\n\n## Performance expectations\nCurrently the `io_uring` implementation does not yet use the underlying interface to its full potential - it is only used for polling and not yet for asynchronous operation of send/recv/read/write. This means performance characteristics currently will be similar to the default  `epoll()` (or slightly worse), but you should test for your specific use case as YMMV. This is expected to change in the future as the `io_uring` interface is used more extensively.\n\n## How to use and requirements\nTo enable `io_uring`, SwiftNIO needs to be built and run on a machine that has the [liburing](https://github.com/axboe/liburing) library installed (typically in `/usr/local`). If built with liburing, it must be available and work on the production machine.\n\nTo build SwiftNIO so it uses io_uring instead of epoll, you must specify additional flags when building:\n`swift build -Xcc -DSWIFTNIO_USE_IO_URING=1 -Xlinker -luring -Xswiftc -DSWIFTNIO_USE_IO_URING`\n\nTo build it so also use the new poll update / multishot polls (will need kernel 5.13+) you need to do:\n`swift build -Xcc -DSWIFTNIO_USE_IO_URING=1 -Xlinker -luring -Xswiftc -DSWIFTNIO_USE_IO_URING -Xswiftc -DSWIFTNIO_IO_URING_MULTISHOT`\n\n## Debug output\nThere are currently three debug outputs that can be compiled in (e.g. to verify that `liburing` is used as expected and for development troubleshooting)\n`-Xswiftc -DSWIFTNIO_IO_URING_DEBUG_SELECTOR`\n`-Xswiftc -DSWIFTNIO_IO_URING_DEBUG_URING`\n`-Xswiftc -DSWIFTNIO_IO_URING_DEBUG_DUMP_CQE`\n\n## Roadmap\nThe initial support for `io_uring` is primarily intended to give people interested in it that ability to try it out and provide feedback - in the future the expectation is to add full support for `io_uring` which is expected to give significant performance improvements on Linux systems supporting it.\nThe idea is also to add SQPOLL together with fine tune settings such that it can be pinned on a specific CPU.\n\n"
  },
  {
    "path": "docs/migration-guide-NIO1-to-NIO2.md",
    "content": "# NIO 1 to NIO 2 migration guide\n\nPlease take a look at the [migration guide included with SwiftNIO 2.29.0](https://github.com/apple/swift-nio/blob/2.29.0/docs/migration-guide-NIO1-to-NIO2.md), the last version with Swift 5.0 support. \n\n[SwiftNIO 2.29.0](https://github.com/apple/swift-nio/releases/tag/2.29.0) includes the `_NIO1APIShims` module which can help to ease the migration.\n"
  },
  {
    "path": "docs/optimization-tips.md",
    "content": "Swift NIO Optimization Tips\n===========================\n\nThe following document is a list of tips and advice for writing high performance\ncode using Swift NIO.\n\nGeneral Optimization Tips\n-------------------------\n\nAlthough not specific to NIO, the [Swift GitHub repository][swift-repo] has a\nlist of tips and tricks for [writing high performance Swift code][swift-optimization-tips]\nand is a great place to start.\n\nWrapping types in `NIOAny`\n--------------------------\n\nAnything passing through a NIO pipeline that is not special-cased by `NIOAny`\n(i.e. is not one of `ByteBuffer`, `FileRegion`, `IOData` or\n`AddressedEnvelope<ByteBuffer>`) needs to have careful attention paid to its\nsize. If the type isn't one of the aforementioned special cases then it must be\nno greater than 24 bytes in size to avoid a heap-allocation each time it is\nadded to a `NIOAny`. The size of a type can be checked using\n[`MemoryLayout.size`][docs-memory-layout].\n\nIf the type being wrapped is a value type then it can be narrowed by placing it\nin a copy-on-write box. Alternatively, if the type is an `enum` with associated\ndata, then it is possible for the associated data to be boxed by the compiler by\nmaking it an `indirect case`.\n\n\n[swift-repo]: https://github.com/apple/swift\n[swift-optimization-tips]: https://github.com/apple/swift/blob/main/docs/OptimizationTips.rst\n[docs-memory-layout]: https://developer.apple.com/documentation/swift/memorylayout\n"
  },
  {
    "path": "docs/public-api.md",
    "content": "# SwiftNIO 2 Public API\n\nThe SwiftNIO project (which includes all of `github.com/apple/swift-nio*`) aims to follow [SemVer 2.0.0](https://semver.org/spec/v2.0.0.html) which requires projects to declare a public API. This document along with the [API documentation](https://swiftpackageindex.com/apple/swift-nio/main/documentation) declare SwiftNIO's API.\n\n## What are acceptable uses of NIO's Public API\n\n### 1. Using NIO types, methods, and modules\n\nIt is acceptable and expected to use any exported type and call any exported method from the `NIO*` modules unless the type or function name start with an underscore (`_`). For `init`s this includes the first parameter's name.\n\n##### What's the point of this restriction?\n\nIf we prefix something with an underscore or put it into one of NIO's internal modules, we can't commit to an API for it and don't expect users to ever use this. Also, there might be different underscored functions/types depending on the platform.\n\n##### Examples\n\n - ✅ `channel.close(promise: nil)`\n - ❌ `channel._channelCore.flush0()`, underscored property\n - ❌ `import CNIOAtomics`, module name doesn't start with NIO\n - ❌ `ByteBuffer(_enableSuperSpecialAllocationMode: true)`, as the initialiser's first argument is underscored\n\n---\n\n### 2. Conforming NIO types to protocols\n\nIt is acceptable to conform NIO types to protocols _you control_, i.e. a protocol in _your codebase_. It is not acceptable to conform any NIO types to protocols in the standard library or outside of your control.\n\n##### What's the point of this restriction?\n\nNIO in a later version may conform its type to said protocol, or the package that provides the protocol may conform the NIO type to _their_ protocol.\n\n##### Examples\n\n  - ✅ `extension EventLoopFuture: MyOwnProtocol { ... }`, assuming `MyOwnProtocol` lives in your codebase\n  - ❌ `extension EventLoopFuture: DebugStringConvertible { ... }`, `DebugStringConvertible` is a standard library protocol\n\n---\n\n### 3. Conforming your types to NIO protocols\n\nIt is acceptable to conform _your own types_ to NIO protocols but it is not acceptable to conform types you do not control to NIO protocols.\n\n##### What's the point of this restriction?\n\nNIO in a later version might add this conformance or the owner of the type may add the conformance.\n\n##### Examples\n\n  - ✅ `extension MyHandler: ChannelHandler { ... }`\n  - ❌ `extension Array: EventLoopGroup where Element: EventLoop { ... }`, as `Array` lives in the standard library\n\n---\n\n### 4. Extending NIO types\n\nIt is acceptable to extend NIO types with `public` methods/properties that either use one of your types as a non-default argument or are prefixed in a way that prevents clashes. Adding `private`/`internal` methods/properties is always acceptable.\n\n#### What's the point of these restrictions?\n\nNIO might later add a member function/property with the same signature as yours.\n\n##### Examples\n\n  - ✅ `extension ByteBuffer { public mutating func readMyType(at: Int) -> MyType {...} }`, acceptable because it returns a `MyType`\n  - ✅ `extension ByteBuffer { public mutating func myProjectReadInteger(at: Int) -> Int {...} } `, acceptable because prefixed with `myProject`\n  - ✅ `extension ByteBuffer { internal mutating func readFloat(at: Int) -> Float {...} }`, acceptable even though `Float` is not in your control because the function is `internal`\n  - ❌ `extension ByteBuffer { public mutating func readBool(at: Int) -> Bool {...} }`, because `Bool` is a standard library type not in your control\n\n\n## Promises the NIO team make\n\nBefore releasing a new major version, i.e. SwiftNIO 3.0.0 we promise the following:\n\n### 1. No global namespace additions that aren't prefixed\n\nIn a minor or patch version, all global types/modules/functions that we will add will have `NIO*`/`nio*`/`CNIO*`/`cnio*`/`c_nio*` prefixes, this includes C symbols that are visible to others. Be aware that we don't control the exact versions of the system libraries installed on your system so we can't make any guarantees about the symbols exported by the system libraries we depend on.\n\n\n##### What does this mean concretely?\n\n- ✅ We might add a new global type called `NIOJetPack`.\n- ✅ We might add a new module called `NIOHelpers`.\n- ✅ We might add a new global functions called `nioRun` (very unlikely) or `c_nio_SSL_write` (more likely).\n- ❌ We will not add a global new type called `Tomato`.\n- ❌ We will not add a new module called `Helpers`.\n- ❌ We will not add a new global function called `SSL_write`.\n- ❌ We will not add a new system library dependency without a new major version.\n\n#### Why is this useful to you?\n\nLet's assume your application is composed of three modules:\n\n1. `NIO`, which in version 2.0.0 does not declare a `public struct Tomato`\n2. `Caprese`, which declares a `public struct Tomato`\n3. `MyApp`\n\nLet's also assume that `MyApp` has both `import Caprese` and `import NIO` and it uses `Tomato` (from `Caprese`). For example `let t = Tomato()`.\n\nIf now in version `NIO` in version 2.1.0 introduces a `public struct Tomato { ... }` as well, then now compilation of `MyApp`'s compilation will fail will an ambiguity error.\n\nWith the guarantee that in minor versions NIO will only introduce `NIO`-prefixed types, this can not happen because NIO would call its type `NIOTomato` rather than `Tomato`.\n\nC functions are all in a global namespace so even worse issues might hit you if NIO were to just introduce exported C functions with very general names in minor releases.\n\n## What's the point of codifying all this?\n\nWe believe that it is important for the ecosystem that all parties can adopt each others' new versions quickly and easily. Therefore we always strongly recommend depending on all the projects in the NIO family which have a major version greater than or equal to 1 up to the next _major_ version. By following the guidelines set out above we should all not run into any trouble even when run with newer versions.\n\nExample:\n\n    .package(url: \"https://github.com/apple/swift-nio.git\", from: \"2.0.0\"),\n\nNeedless to say if you require at least version `2.3.4` you would specify `from: \"2.3.4\"`. The important part is that you use `from: \"2.3.4\"` or `.upToNextMajor(from: \"2.3.4\")` and not `.exact` or `.upToNextMinor`.\n\n## What happens if you ignore these guidelines?\n\nWe are trying to be nice people and we ❤️ our users so we will never break anybody just because they didn't perfectly stick to these guidelines. But just ignoring those guidelines might mean rewriting some of your code, debugging random build, or runtime failures that we didn't hit in the pre-release testing. We do have a source compatibility suite to which you can [ask to be added](https://forums.swift.org/t/register-as-swiftnio-user-to-get-ahead-of-time-security-notifications-be-added-to-the-source-compatibility-suite/17792) and we try not to break you (within reason). But it is impossible for us to test all of our users' projects and we don't want to lose the ability to move fast without breaking things. Certain failures like clashing protocol conformances can have delicate failure modes.\n"
  },
  {
    "path": "docs/public-async-nio-apis.md",
    "content": "# Async NIO bridges\n\nThis is a summary of all the new APIs we introduced to make NIO and the various\nnetwork protocols work with new async interfaces. The intention of this document\nis to quickly outline the incompatibilities in the original API and then show a\nholistic view over all the new APIs.\n\n## What APIs are needed?\n\nThe first problem that we had to tackle was bridging NIO's `Channel` to Swift\nConcurrency. To do so we introduced two new foundational types - the\n`NIOAsyncSequenceProducer` and the `NIOAsyncWriter`. Those allow us to bridge\nthe read and the write side of the `Channel` while propagating the back-pressure\nacross the bridge.\n\nOn top of those two types, we built out the `NIOAsyncChannel` which allows users\nto bridge a `Channel` into Swift Concurrency. To do this it inserts two channel\nhandlers which bridge the read and write side using the\n`NIOAsyncSequenceProducer` and the `NIOAsyncWriter`.\n\nNext up we had to look at the bootstraps. Here the import part is that the\n`Channel`s **must** be wrapped at the correct timing otherwise there is the\npotential that reads might be dropped. This is not problematic for most of the\nbootstraps since they call their various `channelInitializer`s and\n`childChannelInitializer`s at the right time. However, there was one tricky\nbootstrap - `ServerBootstrap`. The `ServerBootstrap` multiplexes the incoming\nconnections and we have to make sure that the wrapping of the child channels\nhappens at the correct time. Additionally, the new bootstrap APIs **must** be\nable to relay the type information of the configured channels to the\n`bind`/`connect` methods.\n\nThe next thing we had to tackle was networking protocols that dynamically\nre-configure the `ChannelPipeline`. The two examples that we provide\nimplementations for are HTTP/1 protocol upgrades and Application Protocol\nNegotiation (ALPN) via TLS. Similar to the bootstraps we have to ensure that the\ntype information is retained so that users can correctly identify which\nreconfiguration path has been taken.\n\nLastly, we had to look at how to handle protocols that multiplex, like HTTP/2.\nMultiplexing protocols need to expose a typed async interface to consume new\ninbound connections/streams and to open new outbound connections/streams where\napplicable.\n\n## Proposed APIs\n\nThis section contains all the new APIs that we are adding and gives us a holistic\noverview to review them.\n\n### `NIOAsyncChannel`\n\n```swift\n/// Wraps a NIO ``Channel`` object into a form suitable for use in Swift Concurrency.\n///\n/// ``NIOAsyncChannel`` abstracts the notion of a NIO ``Channel`` into something that\n/// can safely be used in a structured concurrency context. In particular, this exposes\n/// the following functionality:\n///\n/// - reads are presented as an `AsyncSequence`\n/// - writes can be written to with async functions on a writer, providing back pressure\n/// - channels can be closed seamlessly\n///\n/// This type does not replace the full complexity of NIO's ``Channel``. In particular, it\n/// does not expose the following functionality:\n///\n/// - user events\n/// - traditional NIO back pressure such as writability signals and the ``Channel/read()`` call\n///\n/// Users are encouraged to separate their ``ChannelHandler``s into those that implement\n/// protocol-specific logic (such as parsers and encoders) and those that implement business\n/// logic. Protocol-specific logic should be implemented as a ``ChannelHandler``, while business\n/// logic should use ``NIOAsyncChannel`` to consume and produce data to the network.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncChannel<Inbound, Outbound> : Sendable where Inbound : Sendable, Outbound : Sendable {\n    public struct Configuration : Sendable {\n        /// The back pressure strategy of the ``NIOAsyncChannel/inbound``.\n        public var backPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark\n\n        /// If outbound half closure should be enabled. Outbound half closure is triggered once\n        /// the ``NIOAsyncChannelOutboundWriter`` is either finished or deinitialized.\n        public var isOutboundHalfClosureEnabled: Bool\n\n        /// The ``NIOAsyncChannel/inbound`` message's type.\n        public var inboundType: Inbound.Type\n\n        /// The ``NIOAsyncChannel/outbound`` message's type.\n        public var outboundType: Outbound.Type\n\n        /// Initializes a new ``NIOAsyncChannel/Configuration``.\n        ///\n        /// - Parameters:\n        ///   - backPressureStrategy: The back pressure strategy of the ``NIOAsyncChannel/inbound``. Defaults\n        ///     to a watermarked strategy (lowWatermark: 2, highWatermark: 10).\n        ///   - isOutboundHalfClosureEnabled: If outbound half closure should be enabled. Outbound half closure is triggered once\n        ///     the ``NIOAsyncChannelOutboundWriter`` is either finished or deinitialized. Defaults to `false`.\n        ///   - inboundType: The ``NIOAsyncChannel/inbound`` message's type.\n        ///   - outboundType: The ``NIOAsyncChannel/outbound`` message's type.\n        public init(backPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark = .init(lowWatermark: 2, highWatermark: 10), isOutboundHalfClosureEnabled: Bool = false, inboundType: Inbound.Type = Inbound.self, outboundType: Outbound.Type = Outbound.self)\n    }\n\n    /// The underlying channel being wrapped by this ``NIOAsyncChannel``.\n    public let channel: NIOCore.Channel\n\n    /// The stream of inbound messages.\n    ///\n    /// - Important: The `inbound` stream is a unicast `AsyncSequence` and only one iterator can be created.\n    public let inbound: NIOCore.NIOAsyncChannelInboundStream<Inbound>\n\n    /// The writer for writing outbound messages.\n    public let outbound: NIOCore.NIOAsyncChannelOutboundWriter<Outbound>\n\n    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel``.\n    ///\n    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because\n    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.\n    ///\n    /// - Parameters:\n    ///   - channel: The ``Channel`` to wrap.\n    ///   - configuration: The ``NIOAsyncChannel``s configuration.\n    @inlinable public init(synchronouslyWrapping channel: NIOCore.Channel, configuration: NIOCore.NIOAsyncChannel<Inbound, Outbound>.Configuration = .init()) throws\n\n    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel`` where the outbound type is `Never`.\n    ///\n    /// This initializer will finish the ``NIOAsyncChannel/outboundWriter`` immediately.\n    ///\n    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because\n    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.\n    ///\n    /// - Parameters:\n    ///   - channel: The ``Channel`` to wrap.\n    ///   - configuration: The ``NIOAsyncChannel``s configuration.\n    @inlinable public init(synchronouslyWrapping channel: NIOCore.Channel, configuration: NIOCore.NIOAsyncChannel<Inbound, Outbound>.Configuration = .init()) throws where Outbound == Never\n\n    /// This method is only used from our server bootstrap to allow us to run the child channel initializer\n    /// at the right moment.\n    ///\n    /// - Important: This is not considered stable API and should not be used.\n    @inlinable public static func _wrapAsyncChannelWithTransformations(synchronouslyWrapping channel: NIOCore.Channel, backPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil, isOutboundHalfClosureEnabled: Bool = false, channelReadTransformation: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Inbound>) throws -> NIOCore.NIOAsyncChannel<Inbound, Outbound> where Outbound == Never\n}\n\n/// The inbound message asynchronous sequence of a ``NIOAsyncChannel``.\n///\n/// This is a unicast async sequence that allows a single iterator to be created.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncChannelInboundStream<Inbound> : Sendable where Inbound : Sendable {\n    /// A source used for driving a ``NIOAsyncChannelInboundStream`` during tests.\n    public struct TestSource {\n        /// Yields the element to the inbound stream.\n        ///\n        /// - Parameter element: The element to yield to the inbound stream.\n        @inlinable public func yield(_ element: Inbound)\n\n        /// Finished the inbound stream.\n        ///\n        /// - Parameter error: The error to throw, or nil, to finish normally.\n        @inlinable public func finish(throwing error: Error? = nil)\n    }\n\n    /// Creates a new stream with a source for testing.\n    ///\n    /// This is useful for writing unit tests where you want to drive a ``NIOAsyncChannelInboundStream``.\n    ///\n    /// - Returns: A tuple containing the input stream and a test source to drive it.\n    @inlinable public static func makeTestingStream() -> (NIOCore.NIOAsyncChannelInboundStream<Inbound>, NIOCore.NIOAsyncChannelInboundStream<Inbound>.TestSource)\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelInboundStream : AsyncSequence {\n    /// The type of element produced by this asynchronous sequence.\n    public typealias Element = Inbound\n\n    /// The type of asynchronous iterator that produces elements of this\n    /// asynchronous sequence.\n    public struct AsyncIterator : AsyncIteratorProtocol {\n        /// Asynchronously advances to the next element and returns it, or ends the\n        /// sequence if there is no next element.\n        /// \n        /// - Returns: The next element, if it exists, or `nil` to signal the end of\n        ///   the sequence.\n        @inlinable public mutating func next() async throws -> NIOCore.NIOAsyncChannelInboundStream<Inbound>.Element?\n    }\n\n    /// Creates the asynchronous iterator that produces elements of this\n    /// asynchronous sequence.\n    ///\n    /// - Returns: An instance of the `AsyncIterator` type used to produce\n    /// elements of the asynchronous sequence.\n    @inlinable public func makeAsyncIterator() -> NIOCore.NIOAsyncChannelInboundStream<Inbound>.AsyncIterator\n}\n\n/// A ``NIOAsyncChannelOutboundWriter`` is used to write and flush new outbound messages in a channel.\n///\n/// The writer acts as a bridge between the Concurrency and NIO world. It allows to write and flush messages into the\n/// underlying ``Channel``. Furthermore, it respects back-pressure of the channel by suspending the calls to write until\n/// the channel becomes writable again.\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\npublic struct NIOAsyncChannelOutboundWriter<OutboundOut> : Sendable where OutboundOut : Sendable {\n    /// An `AsyncSequence` backing a ``NIOAsyncChannelOutboundWriter`` for testing purposes.\n    public struct TestSink : AsyncSequence {\n        /// The type of element produced by this asynchronous sequence.\n        public typealias Element = OutboundOut\n\n        /// Creates the asynchronous iterator that produces elements of this\n        /// asynchronous sequence.\n        ///\n        /// - Returns: An instance of the `AsyncIterator` type used to produce\n        /// elements of the asynchronous sequence.\n        public func makeAsyncIterator() -> NIOCore.NIOAsyncChannelOutboundWriter<OutboundOut>.TestSink.AsyncIterator\n\n        /// The type of asynchronous iterator that produces elements of this\n        /// asynchronous sequence.\n        public struct AsyncIterator : AsyncIteratorProtocol {\n            /// Asynchronously advances to the next element and returns it, or ends the\n            /// sequence if there is no next element.\n            /// \n            /// - Returns: The next element, if it exists, or `nil` to signal the end of\n            ///   the sequence.\n            public mutating func next() async -> NIOCore.NIOAsyncChannelOutboundWriter<OutboundOut>.TestSink.Element?\n        }\n    }\n\n    /// Creates a new ``NIOAsyncChannelOutboundWriter`` backed by a ``NIOAsyncChannelOutboundWriter/TestSink``.\n    /// This is mostly useful for testing purposes where one wants to observe the written data.\n    @inlinable public static func makeTestingWriter() -> (NIOCore.NIOAsyncChannelOutboundWriter<OutboundOut>, NIOCore.NIOAsyncChannelOutboundWriter<OutboundOut>.TestSink)\n\n    /// Send a write into the ``ChannelPipeline`` and flush it right away.\n    ///\n    /// This method suspends if the underlying channel is not writable and will resume once the it becomes writable again.\n    @inlinable public func write(_ data: OutboundOut) async throws\n\n    /// Send a sequence of writes into the ``ChannelPipeline`` and flush them right away.\n    ///\n    /// This method suspends if the underlying channel is not writable and will resume once the it becomes writable again.\n    @inlinable public func write<Writes>(contentsOf sequence: Writes) async throws where OutboundOut == Writes.Element, Writes : Sequence\n\n    /// Send an asynchronous sequence of writes into the ``ChannelPipeline``.\n    ///\n    /// This will flush after every write.\n    ///\n    /// This method suspends if the underlying channel is not writable and will resume once the it becomes writable again.\n    @inlinable public func write<Writes>(contentsOf sequence: Writes) async throws where OutboundOut == Writes.Element, Writes : AsyncSequence\n\n    /// Finishes the writer.\n    ///\n    /// This might trigger a half closure if the ``NIOAsyncChannel`` was configured to support it.\n    public func finish()\n}\n\n@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\nextension NIOAsyncChannelOutboundWriter.TestSink : Sendable {}\n```\n\n### Bootstraps\n\n```swift\nextension ClientBootstrap {\n    /// Specify the `host` and `port` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(host: String, port: Int, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Specify the `address` to connect to for the TCP `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - address: The address to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(to address: NIOCore.SocketAddress, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Specify the `unixDomainSocket` path to connect to for the UDS `Channel` that will be established.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The _Unix domain socket_ path to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(unixDomainSocketPath: String, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Use the existing connected socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - descriptor: The _Unix file descriptor_ representing the connected stream socket.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withConnectedSocket<Output>(_ socket: NIOCore.NIOBSDSocket.Handle, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n}\n\nextension ServerBootstrap {\n    /// Bind the `ServerSocketChannel` to the `host` and `port` parameters.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - port: The port to bind on.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(host: String, port: Int, serverBackPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil, childChannelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> NIOCore.NIOAsyncChannel<Output, Never> where Output : Sendable\n\n    /// Bind the `ServerSocketChannel` to the `address` parameter.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(to address: NIOCore.SocketAddress, serverBackPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil, childChannelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> NIOCore.NIOAsyncChannel<Output, Never> where Output : Sendable\n\n    /// Bind the `ServerSocketChannel` to a UNIX Domain Socket.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. The`unixDomainSocketPath` must not exist,\n    ///     unless `cleanupExistingSocketFile`is set to `true`.\n    ///   - cleanupExistingSocketFile: Whether to cleanup an existing socket file at `unixDomainSocketPath`.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(unixDomainSocketPath: String, cleanupExistingSocketFile: Bool = false, serverBackPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil, childChannelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> NIOCore.NIOAsyncChannel<Output, Never> where Output : Sendable\n\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the bound stream socket.\n    ///   - serverBackPressureStrategy: The back pressure strategy used by the server socket channel.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(_ socket: NIOCore.NIOBSDSocket.Handle, cleanupExistingSocketFile: Bool = false, serverBackPressureStrategy: NIOCore.NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil, childChannelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> NIOCore.NIOAsyncChannel<Output, Never> where Output : Sendable\n}\n\nextension DatagramBootstrap {\n    /// Use the existing bound socket file descriptor.\n    ///\n    /// - Parameters:\n    ///   - socket: The _Unix file descriptor_ representing the bound stream socket.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func withBoundSocket<Output>(_ socket: NIOCore.NIOBSDSocket.Handle, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Bind the `DatagramChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - port: The port to bind on.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(host: String, port: Int, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Bind the `DatagramChannel` to the `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to bind on.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(to address: NIOCore.SocketAddress, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Bind the `DatagramChannel` to the `unixDomainSocketPath`.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to bind on. The`unixDomainSocketPath` must not exist,\n    ///     unless `cleanupExistingSocketFile`is set to `true`.\n    ///   - cleanupExistingSocketFile: Whether to cleanup an existing socket file at `unixDomainSocketPath`.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(unixDomainSocketPath: String, cleanupExistingSocketFile: Bool = false, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Connect the `DatagramChannel` to `host` and `port`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - port: The port to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(host: String, port: Int, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Connect the `DatagramChannel` to the `address`.\n    ///\n    /// - Parameters:\n    ///   - address: The `SocketAddress` to connect to.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(to address: NIOCore.SocketAddress, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Connect the `DatagramChannel` to the `unixDomainSocketPath`.\n    ///\n    /// - Parameters:\n    ///   - unixDomainSocketPath: The path of the UNIX Domain Socket to connect to. `path` must not exist, it will be created by the system.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(unixDomainSocketPath: String, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n}\n\nextension NIOPipeBootstrap {\n\n    /// Create the `PipeChannel` with the provided file descriptor which is used for both input & output.\n    ///\n    /// This method is useful for specialilsed use-cases where you want to use `NIOPipeBootstrap` for say a serial line.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `inputOutput` when the `Channel`\n    ///         becomes inactive. You _must not_ do any further operations with `inputOutput`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptor and are responsible for\n    ///         closing it.\n    ///\n    /// - Parameters:\n    ///   - inputOutput: The _Unix file descriptor_ for the input & output.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func takingOwnershipOfDescriptor<Output>(inputOutput: CInt, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Create the `PipeChannel` with the provided input and output file descriptors.\n    ///\n    /// The input and output file descriptors must be distinct. If you have a single file descriptor, consider using\n    /// `ClientBootstrap.withConnectedSocket(descriptor:)` if it's a socket or\n    /// `NIOPipeBootstrap.takingOwnershipOfDescriptor` if it is not a socket.\n    ///\n    /// - Note: If this method returns a succeeded future, SwiftNIO will close `input` and `output`\n    ///         when the `Channel` becomes inactive. You _must not_ do any further operations `input` or\n    ///         `output`, including `close`.\n    ///         If this method returns a failed future, you still own the file descriptors and are responsible for\n    ///         closing them.\n    ///\n    /// - Parameters:\n    ///   - input: The _Unix file descriptor_ for the input (ie. the read side).\n    ///   - output: The _Unix file descriptor_ for the output (ie. the write side).\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func takingOwnershipOfDescriptors<Output>(input: CInt, output: CInt, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n}\n\nextension NIORawSocketBootstrap {\n\n    /// Bind the `Channel` to `host`.\n    /// All packets or errors matching the `ipProtocol` specified are passed to the resulting `Channel`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to bind on.\n    ///   - ipProtocol: The IP protocol used in the IP protocol/nextHeader field.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `bind`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func bind<Output>(host: String, ipProtocol: NIOCore.NIOIPProtocol, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n\n    /// Connect the `Channel` to `host`.\n    ///\n    /// - Parameters:\n    ///   - host: The host to connect to.\n    ///   - ipProtocol: The IP protocol used in the IP protocol/nextHeader field.\n    ///   - channelInitializer: A closure to initialize the channel. The return value of this closure is returned from the `connect`\n    ///   method.\n    /// - Returns: The result of the channel initializer.\n    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n    public func connect<Output>(host: String, ipProtocol: NIOCore.NIOIPProtocol, channelInitializer: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<Output>) async throws -> Output where Output : Sendable\n}\n```\n\n### HTTPUpgrade\n\n```swift\n/// Configuration for an upgradable HTTP pipeline.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult> where UpgradeResult : Sendable {\n\n    /// The strategy to use when dealing with leftover bytes after removing the ``HTTPDecoder`` from the pipeline.\n    public var leftOverBytesStrategy: NIOHTTP1.RemoveAfterUpgradeStrategy\n\n    /// Whether to validate outbound response headers to confirm that they are\n    /// spec compliant. Defaults to `true`.\n    public var enableOutboundHeaderValidation: Bool\n\n    /// The configuration for the ``HTTPRequestEncoder``.\n    public var encoderConfiguration: NIOHTTP1.HTTPRequestEncoder.Configuration\n\n    /// The configuration for the ``NIOTypedHTTPClientUpgradeHandler``.\n    public var upgradeConfiguration: NIOHTTP1.NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult>\n\n    /// Initializes a new ``NIOUpgradableHTTPClientPipelineConfiguration`` with default values.\n    ///\n    /// The current defaults provide the following features:\n    /// 1. Outbound header fields validation to protect against response splitting attacks.\n    public init(upgradeConfiguration: NIOHTTP1.NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult>)\n}\n\n/// Configuration for an upgradable HTTP pipeline.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult> where UpgradeResult : Sendable {\n\n    /// Whether to provide assistance handling HTTP clients that pipeline\n    /// their requests. Defaults to `true`. If `false`, users will need to handle clients that pipeline themselves.\n    public var enablePipelining: Bool\n\n    /// Whether to provide assistance handling protocol errors (e.g. failure to parse the HTTP\n    /// request) by sending 400 errors. Defaults to `true`.\n    public var enableErrorHandling: Bool\n\n    /// Whether to validate outbound response headers to confirm that they are\n    /// spec compliant. Defaults to `true`.\n    public var enableResponseHeaderValidation: Bool\n\n    /// The configuration for the ``HTTPResponseEncoder``.\n    public var encoderConfiguration: NIOHTTP1.HTTPResponseEncoder.Configuration\n\n    /// The configuration for the ``NIOTypedHTTPServerUpgradeHandler``.\n    public var upgradeConfiguration: NIOHTTP1.NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult>\n\n    /// Initializes a new ``NIOUpgradableHTTPServerPipelineConfiguration`` with default values.\n    ///\n    /// The current defaults provide the following features:\n    /// 1. Assistance handling clients that pipeline HTTP requests.\n    /// 2. Assistance handling protocol errors.\n    /// 3. Outbound header fields validation to protect against response splitting attacks.\n    public init(upgradeConfiguration: NIOHTTP1.NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult>)\n}\n\nextension ChannelPipeline {\n\n    /// Configure a `ChannelPipeline` for use as an HTTP server.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured. The future contains an `EventLoopFuture`\n    /// that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPServerPipeline<UpgradeResult>(configuration: NIOHTTP1.NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult>) -> NIOCore.EventLoopFuture<NIOCore.EventLoopFuture<UpgradeResult>> where UpgradeResult : Sendable\n}\n\nextension ChannelPipeline.SynchronousOperations {\n\n    /// Configure a `ChannelPipeline` for use as an HTTP server.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPServerPipeline<UpgradeResult>(configuration: NIOHTTP1.NIOUpgradableHTTPServerPipelineConfiguration<UpgradeResult>) throws -> NIOCore.EventLoopFuture<UpgradeResult> where UpgradeResult : Sendable\n}\n\nextension ChannelPipeline {\n\n    /// Configure a `ChannelPipeline` for use as an HTTP client.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that will fire when the pipeline is configured. The future contains an `EventLoopFuture`\n    /// that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPClientPipeline<UpgradeResult>(configuration: NIOHTTP1.NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult>) -> NIOCore.EventLoopFuture<NIOCore.EventLoopFuture<UpgradeResult>> where UpgradeResult : Sendable\n}\n\nextension ChannelPipeline.SynchronousOperations {\n\n    /// Configure a `ChannelPipeline` for use as an HTTP client.\n    ///\n    /// - Parameters:\n    ///   - configuration: The HTTP pipeline's configuration.\n    /// - Returns: An `EventLoopFuture` that is fired once the pipeline has been upgraded or not and contains the `UpgradeResult`.\n    @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\n    public func configureUpgradableHTTPClientPipeline<UpgradeResult>(configuration: NIOHTTP1.NIOUpgradableHTTPClientPipelineConfiguration<UpgradeResult>) throws -> NIOCore.EventLoopFuture<UpgradeResult> where UpgradeResult : Sendable\n}\n\n/// An object that implements `NIOTypedHTTPClientProtocolUpgrader` knows how to handle HTTP upgrade to\n/// a protocol on a client-side channel.\n/// It has the option of denying this upgrade based upon the server response.\npublic protocol NIOTypedHTTPClientProtocolUpgrader<UpgradeResult> {\n\n    associatedtype UpgradeResult : Sendable\n\n    /// The protocol this upgrader knows how to support.\n    var supportedProtocol: String { get }\n\n    /// All the header fields the protocol requires in the request to successfully upgrade.\n    /// These header fields will be added to the outbound request's \"Connection\" header field.\n    /// It is the responsibility of the custom headers call to actually add these required headers.\n    var requiredUpgradeHeaders: [String] { get }\n\n    /// Additional headers to be added to the request, beyond the \"Upgrade\" and \"Connection\" headers.\n    func addCustom(upgradeRequestHeaders: inout NIOHTTP1.HTTPHeaders)\n\n    /// Gives the receiving upgrader the chance to deny the upgrade based on the upgrade HTTP response.\n    func shouldAllowUpgrade(upgradeResponse: NIOHTTP1.HTTPResponseHead) -> Bool\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel\n    /// pipeline to add whatever channel handlers are required.\n    /// Until the returned `EventLoopFuture` succeeds, all received data will be buffered.\n    func upgrade(channel: NIOCore.Channel, upgradeResponse: NIOHTTP1.HTTPResponseHead) -> NIOCore.EventLoopFuture<Self.UpgradeResult>\n}\n\n/// The upgrade configuration for the ``NIOTypedHTTPClientUpgradeHandler``.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult> where UpgradeResult : Sendable {\n\n    /// The initial request head that is sent out once the channel becomes active.\n    public var upgradeRequestHead: NIOHTTP1.HTTPRequestHead\n\n    /// The array of potential upgraders.\n    public var upgraders: [NIOHTTP1.NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>]\n\n    /// A closure that is run once it is determined that no protocol upgrade is happening. This can be used\n    /// to configure handlers that expect HTTP.\n    public var notUpgradingCompletionHandler: @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<UpgradeResult>\n\n    public init(upgradeRequestHead: NIOHTTP1.HTTPRequestHead, upgraders: [NIOHTTP1.NIOTypedHTTPClientProtocolUpgrader<UpgradeResult>], notUpgradingCompletionHandler: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<UpgradeResult>)\n}\n\n/// A client-side channel handler that sends a HTTP upgrade handshake request to perform a HTTP-upgrade.\n/// This handler will add all appropriate headers to perform an upgrade to\n/// the a protocol. It may add headers for a set of protocols in preference order.\n/// If the upgrade fails (i.e. response is not 101 Switching Protocols), this handler simply\n/// removes itself from the pipeline. If the upgrade is successful, it upgrades the pipeline to the new protocol.\n///\n/// The request sends an order of preference to request which protocol it would like to use for the upgrade.\n/// It will only upgrade to the protocol that is returned first in the list and does not currently\n/// have the capability to upgrade to multiple simultaneous layered protocols.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal public class NIOTypedHTTPClientUpgradeHandler<UpgradeResult> : NIOCore.ChannelDuplexHandler, NIOCore.RemovableChannelHandler where UpgradeResult : Sendable {\n\n    /// The type of the outbound data which is wrapped in `NIOAny`.\n    public typealias OutboundIn = NIOHTTP1.HTTPClientRequestPart\n\n    /// The type of the outbound data which will be forwarded to the next `ChannelOutboundHandler` in the `ChannelPipeline`.\n    public typealias OutboundOut = NIOHTTP1.HTTPClientRequestPart\n\n    /// The type of the inbound data which is wrapped in `NIOAny`.\n    public typealias InboundIn = NIOHTTP1.HTTPClientResponsePart\n\n    /// The type of the inbound data which will be forwarded to the next `ChannelInboundHandler` in the `ChannelPipeline`.\n    public typealias InboundOut = NIOHTTP1.HTTPClientResponsePart\n\n    /// The upgrade future which will be completed once protocol upgrading has been done.\n    public var upgradeResultFuture: NIOCore.EventLoopFuture<UpgradeResult> { get }\n\n    /// Create a ``NIOTypedHTTPClientUpgradeHandler``.\n    ///\n    /// - Parameters:\n    ///  - httpHandlers: All `RemovableChannelHandler` objects which will be removed from the pipeline\n    ///     once the upgrade response is sent. This is used to ensure that the pipeline will be in a clean state\n    ///     after the upgrade. It should include any handlers that are directly related to handling HTTP.\n    ///     At the very least this should include the `HTTPEncoder` and `HTTPDecoder`, but should also include\n    ///     any other handler that cannot tolerate receiving non-HTTP data.\n    ///  - upgradeConfiguration: The upgrade configuration.\n    public init(httpHandlers: [NIOCore.RemovableChannelHandler], upgradeConfiguration: NIOHTTP1.NIOTypedHTTPClientUpgradeConfiguration<UpgradeResult>)\n\n    /// Called when this `ChannelHandler` is added to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func handlerAdded(context: NIOCore.ChannelHandlerContext)\n\n    /// Called when this `ChannelHandler` is removed from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func handlerRemoved(context: NIOCore.ChannelHandlerContext)\n\n    /// Called when the `Channel` has become active, and is able to send and receive data.\n    ///\n    /// This should call `context.fireChannelActive` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func channelActive(context: NIOCore.ChannelHandlerContext)\n\n    /// Called to request a write operation. The write operation will write the messages through the\n    /// `ChannelPipeline`. Those are then ready to be flushed to the actual `Channel` when\n    /// `Channel.flush` or `ChannelHandlerContext.flush` is called.\n    ///\n    /// This should call `context.write` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or\n    /// complete the `EventLoopPromise` to let the caller know that the operation completed.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - data: The data to write through the `Channel`, wrapped in a `NIOAny`.\n    ///   - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place.\n    public func write(context: NIOCore.ChannelHandlerContext, data: NIOCore.NIOAny, promise: NIOCore.EventLoopPromise<Void>?)\n\n    /// Called when some data has been read from the remote peer.\n    ///\n    /// This should call `context.fireChannelRead` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - data: The data read from the remote peer, wrapped in a `NIOAny`.\n    public func channelRead(context: NIOCore.ChannelHandlerContext, data: NIOCore.NIOAny)\n}\n\n/// An object that implements `NIOTypedHTTPServerProtocolUpgrader` knows how to handle HTTP upgrade to\n/// a protocol on a server-side channel.\npublic protocol NIOTypedHTTPServerProtocolUpgrader<UpgradeResult> {\n\n    associatedtype UpgradeResult : Sendable\n\n    /// The protocol this upgrader knows how to support.\n    var supportedProtocol: String { get }\n\n    /// All the header fields the protocol needs in the request to successfully upgrade. These header fields\n    /// will be provided to the handler when it is asked to handle the upgrade. They will also be validated\n    /// against the inbound request's `Connection` header field.\n    var requiredUpgradeHeaders: [String] { get }\n\n    /// Builds the upgrade response headers. Should return any headers that need to be supplied to the client\n    /// in the 101 Switching Protocols response. If upgrade cannot proceed for any reason, this function should\n    /// return a failed future.\n    func buildUpgradeResponse(channel: NIOCore.Channel, upgradeRequest: NIOHTTP1.HTTPRequestHead, initialResponseHeaders: NIOHTTP1.HTTPHeaders) -> NIOCore.EventLoopFuture<NIOHTTP1.HTTPHeaders>\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel pipeline\n    /// to add whatever channel handlers are required. Until the returned `EventLoopFuture` succeeds, all received\n    /// data will be buffered.\n    func upgrade(channel: NIOCore.Channel, upgradeRequest: NIOHTTP1.HTTPRequestHead) -> NIOCore.EventLoopFuture<Self.UpgradeResult>\n}\n\n/// The upgrade configuration for the ``NIOTypedHTTPServerUpgradeHandler``.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\npublic struct NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult> where UpgradeResult : Sendable {\n\n    /// The array of potential upgraders.\n    public var upgraders: [NIOHTTP1.NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>]\n\n    /// A closure that is run once it is determined that no protocol upgrade is happening. This can be used\n    /// to configure handlers that expect HTTP.\n    public var notUpgradingCompletionHandler: @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<UpgradeResult>\n\n    public init(upgraders: [NIOHTTP1.NIOTypedHTTPServerProtocolUpgrader<UpgradeResult>], notUpgradingCompletionHandler: @escaping @Sendable (NIOCore.Channel) -> NIOCore.EventLoopFuture<UpgradeResult>)\n}\n\n/// A server-side channel handler that receives HTTP requests and optionally performs an HTTP-upgrade.\n///\n/// Removes itself from the channel pipeline after the first inbound request on the connection, regardless of\n/// whether the upgrade succeeded or not.\n///\n/// This handler behaves a bit differently from its Netty counterpart because it does not allow upgrade\n/// on any request but the first on a connection. This is primarily to handle clients that pipeline: it's\n/// sufficiently difficult to ensure that the upgrade happens at a safe time while dealing with pipelined\n/// requests that we choose to punt on it entirely and not allow it. As it happens this is mostly fine:\n/// the odds of someone needing to upgrade midway through the lifetime of a connection are very low.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal public class NIOTypedHTTPServerUpgradeHandler<UpgradeResult> : NIOCore.ChannelInboundHandler, NIOCore.RemovableChannelHandler where UpgradeResult : Sendable {\n\n    /// The type of the inbound data which is wrapped in `NIOAny`.\n    public typealias InboundIn = NIOHTTP1.HTTPServerRequestPart\n\n    /// The type of the inbound data which will be forwarded to the next `ChannelInboundHandler` in the `ChannelPipeline`.\n    public typealias InboundOut = NIOHTTP1.HTTPServerRequestPart\n\n    /// The type of the outbound data which will be forwarded to the next `ChannelOutboundHandler` in the `ChannelPipeline`.\n    public typealias OutboundOut = NIOHTTP1.HTTPServerResponsePart\n\n    /// The upgrade future which will be completed once protocol upgrading has been done.\n    public var upgradeResultFuture: NIOCore.EventLoopFuture<UpgradeResult> { get }\n\n    /// Create a ``NIOTypedHTTPServerUpgradeHandler``.\n    /// \n    /// - Parameters:\n    ///   - httpEncoder: The ``HTTPResponseEncoder`` encoding responses from this handler and which will\n    ///     be removed from the pipeline once the upgrade response is sent. This is used to ensure\n    ///     that the pipeline will be in a clean state after upgrade.\n    ///  - extraHTTPHandlers: Any other handlers that are directly related to handling HTTP. At the very least\n    ///     this should include the `HTTPDecoder`, but should also include any other handler that cannot tolerate\n    ///     receiving non-HTTP data.\n    ///  - upgradeConfiguration: The upgrade configuration.\n    public init(httpEncoder: NIOHTTP1.HTTPResponseEncoder, extraHTTPHandlers: [NIOCore.RemovableChannelHandler], upgradeConfiguration: NIOHTTP1.NIOTypedHTTPServerUpgradeConfiguration<UpgradeResult>)\n\n    /// Called when this `ChannelHandler` is added to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func handlerAdded(context: NIOCore.ChannelHandlerContext)\n\n    /// Called when this `ChannelHandler` is removed from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func handlerRemoved(context: NIOCore.ChannelHandlerContext)\n\n    /// Called when some data has been read from the remote peer.\n    ///\n    /// This should call `context.fireChannelRead` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - data: The data read from the remote peer, wrapped in a `NIOAny`.\n    public func channelRead(context: NIOCore.ChannelHandlerContext, data: NIOCore.NIOAny)\n}\n```\n\n### Websocket\n\n```swift\n/// A `NIOTypedHTTPClientProtocolUpgrader` that knows how to do the WebSocket upgrade dance.\n///\n/// This upgrader assumes that the `HTTPClientUpgradeHandler` will create and send the upgrade request.\n/// This upgrader also assumes that the `HTTPClientUpgradeHandler` will appropriately mutate the\n/// pipeline to remove the HTTP `ChannelHandler`s.\n@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)\nfinal public class NIOTypedWebSocketClientUpgrader<UpgradeResult> : NIOHTTP1.NIOTypedHTTPClientProtocolUpgrader where UpgradeResult : Sendable {\n\n    /// RFC 6455 specs this as the required entry in the Upgrade header.\n    public let supportedProtocol: String\n\n    /// None of the websocket headers are actually defined as 'required'.\n    public let requiredUpgradeHeaders: [String]\n\n    /// - Parameters:\n    ///   - requestKey: Sent to the server in the `Sec-WebSocket-Key` HTTP header. Default is random request key.\n    ///   - maxFrameSize: Largest incoming `WebSocketFrame` size in bytes. Default is 16,384 bytes.\n    ///   - enableAutomaticErrorHandling: If true, adds `WebSocketProtocolErrorHandler` to the channel pipeline to catch and respond to WebSocket protocol errors. Default is true.\n    ///   - upgradePipelineHandler: Called once the upgrade was successful.\n    public init(requestKey: String = NIOWebSocketClientUpgrader.randomRequestKey(), maxFrameSize: Int = 1 << 14, enableAutomaticErrorHandling: Bool = true, upgradePipelineHandler: @escaping @Sendable (NIOCore.Channel, NIOHTTP1.HTTPResponseHead) -> NIOCore.EventLoopFuture<UpgradeResult>)\n\n    /// Additional headers to be added to the request, beyond the \"Upgrade\" and \"Connection\" headers.\n    public func addCustom(upgradeRequestHeaders: inout NIOHTTP1.HTTPHeaders)\n\n    /// Gives the receiving upgrader the chance to deny the upgrade based on the upgrade HTTP response.\n    public func shouldAllowUpgrade(upgradeResponse: NIOHTTP1.HTTPResponseHead) -> Bool\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel\n    /// pipeline to add whatever channel handlers are required.\n    /// Until the returned `EventLoopFuture` succeeds, all received data will be buffered.\n    public func upgrade(channel: NIOCore.Channel, upgradeResponse: NIOHTTP1.HTTPResponseHead) -> NIOCore.EventLoopFuture<UpgradeResult>\n}\n\n/// A `NIOTypedHTTPServerProtocolUpgrader` that knows how to do the WebSocket upgrade dance.\n///\n/// Users may frequently want to offer multiple websocket endpoints on the same port. For this\n/// reason, this `WebServerSocketUpgrader` only knows how to do the required parts of the upgrade and to\n/// complete the handshake. Users are expected to provide a callback that examines the HTTP headers\n/// (including the path) and determines whether this is a websocket upgrade request that is acceptable\n/// to them.\n///\n/// This upgrader assumes that the `HTTPServerUpgradeHandler` will appropriately mutate the pipeline to\n/// remove the HTTP `ChannelHandler`s.\nfinal public class NIOTypedWebSocketServerUpgrader<UpgradeResult> : NIOHTTP1.NIOTypedHTTPServerProtocolUpgrader, Sendable where UpgradeResult : Sendable {\n\n    /// RFC 6455 specs this as the required entry in the Upgrade header.\n    public let supportedProtocol: String\n\n    /// We deliberately do not actually set any required headers here, because the websocket\n    /// spec annoyingly does not actually force the client to send these in the Upgrade header,\n    /// which NIO requires. We check for these manually.\n    public let requiredUpgradeHeaders: [String]\n\n    /// Create a new ``NIOTypedWebSocketServerUpgrader``.\n    ///\n    /// - Parameters:\n    ///   - maxFrameSize: The maximum frame size the decoder is willing to tolerate from the\n    ///         remote peer. WebSockets in principle allows frame sizes up to `2**64` bytes, but\n    ///         this is an objectively unreasonable maximum value (on AMD64 systems it is not\n    ///         possible to even. Users may set this to any value up to `UInt32.max`.\n    ///   - automaticErrorHandling: Whether the pipeline should automatically handle protocol\n    ///         errors by sending error responses and closing the connection. Defaults to `true`,\n    ///         may be set to `false` if the user wishes to handle their own errors.\n    ///   - shouldUpgrade: A callback that determines whether the websocket request should be\n    ///         upgraded. This callback is responsible for creating a `HTTPHeaders` object with\n    ///         any headers that it needs on the response *except for* the `Upgrade`, `Connection`,\n    ///         and `Sec-WebSocket-Accept` headers, which this upgrader will handle. Should return\n    ///         an `EventLoopFuture` containing `nil` if the upgrade should be refused.\n    ///   - enableAutomaticErrorHandling: A function that will be called once the upgrade response is\n    ///         flushed, and that is expected to mutate the `Channel` appropriately to handle the\n    ///         websocket protocol. This only needs to add the user handlers: the\n    ///         `WebSocketFrameEncoder` and `WebSocketFrameDecoder` will have been added to the\n    ///         pipeline automatically.\n    public init(maxFrameSize: Int = 1 << 14, enableAutomaticErrorHandling: Bool = true, shouldUpgrade: @escaping @Sendable (NIOCore.Channel, NIOHTTP1.HTTPRequestHead) -> NIOCore.EventLoopFuture<NIOHTTP1.HTTPHeaders?>, upgradePipelineHandler: @escaping @Sendable (NIOCore.Channel, NIOHTTP1.HTTPRequestHead) -> NIOCore.EventLoopFuture<UpgradeResult>)\n\n    /// Builds the upgrade response headers. Should return any headers that need to be supplied to the client\n    /// in the 101 Switching Protocols response. If upgrade cannot proceed for any reason, this function should\n    /// return a failed future.\n    public func buildUpgradeResponse(channel: NIOCore.Channel, upgradeRequest: NIOHTTP1.HTTPRequestHead, initialResponseHeaders: NIOHTTP1.HTTPHeaders) -> NIOCore.EventLoopFuture<NIOHTTP1.HTTPHeaders>\n\n    /// Called when the upgrade response has been flushed. At this time it is safe to mutate the channel pipeline\n    /// to add whatever channel handlers are required. Until the returned `EventLoopFuture` succeeds, all received\n    /// data will be buffered.\n    public func upgrade(channel: NIOCore.Channel, upgradeRequest: NIOHTTP1.HTTPRequestHead) -> NIOCore.EventLoopFuture<UpgradeResult>\n}\n```\n\n### ALPN\n\n```swift\n/// A helper ``ChannelInboundHandler`` that makes it easy to swap channel pipelines\n/// based on the result of an ALPN negotiation.\n///\n/// The standard pattern used by applications that want to use ALPN is to select\n/// an application protocol based on the result, optionally falling back to some\n/// default protocol. To do this in SwiftNIO requires that the channel pipeline be\n/// reconfigured based on the result of the ALPN negotiation. This channel handler\n/// encapsulates that logic in a generic form that doesn't depend on the specific\n/// TLS implementation in use by using ``TLSUserEvent``\n///\n/// The user of this channel handler provides a single closure that is called with\n/// an ``ALPNResult`` when the ALPN negotiation is complete. Based on that result\n/// the user is free to reconfigure the ``ChannelPipeline`` as required, and should\n/// return an ``EventLoopFuture`` that will complete when the pipeline is reconfigured.\n///\n/// Until the ``EventLoopFuture`` completes, this channel handler will buffer inbound\n/// data. When the ``EventLoopFuture`` completes, the buffered data will be replayed\n/// down the channel. Then, finally, this channel handler will automatically remove\n/// itself from the channel pipeline, leaving the pipeline in its final\n/// configuration.\n///\n/// Importantly, this is a typed variant of the ``ApplicationProtocolNegotiationHandler`` and allows the user to\n/// specify a type that must be returned from the supplied closure. The result will then be used to succeed the ``NIOTypedApplicationProtocolNegotiationHandler/protocolNegotiationResult``\n/// promise. This allows us to construct pipelines that include protocol negotiation handlers and be able to bridge them into ``NIOAsyncChannel``\n/// based bootstraps.\nfinal public class NIOTypedApplicationProtocolNegotiationHandler<NegotiationResult> : NIOCore.ChannelInboundHandler, NIOCore.RemovableChannelHandler {\n\n    /// The type of the inbound data which is wrapped in `NIOAny`.\n    public typealias InboundIn = Any\n\n    /// The type of the inbound data which will be forwarded to the next `ChannelInboundHandler` in the `ChannelPipeline`.\n    public typealias InboundOut = Any\n\n    public var protocolNegotiationResult: NIOCore.EventLoopFuture<NegotiationResult> { get }\n\n    /// Create an `ApplicationProtocolNegotiationHandler` with the given completion\n    /// callback.\n    ///\n    /// - Parameter alpnCompleteHandler: The closure that will fire when ALPN\n    ///   negotiation has completed.\n    public init(alpnCompleteHandler: @escaping (NIOTLS.ALPNResult, NIOCore.Channel) -> NIOCore.EventLoopFuture<NegotiationResult>)\n\n    /// Create an `ApplicationProtocolNegotiationHandler` with the given completion\n    /// callback.\n    ///\n    /// - Parameter alpnCompleteHandler: The closure that will fire when ALPN\n    ///   negotiation has completed.\n    public convenience init(alpnCompleteHandler: @escaping (NIOTLS.ALPNResult) -> NIOCore.EventLoopFutureNegotiationResult>)\n\n    /// Called when this `ChannelHandler` is added to the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func handlerAdded(context: NIOCore.ChannelHandlerContext)\n\n    /// Called when this `ChannelHandler` is removed from the `ChannelPipeline`.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func handlerRemoved(context: NIOCore.ChannelHandlerContext)\n\n    /// Called when a user inbound event has been triggered.\n    ///\n    /// This should call `context.fireUserInboundEventTriggered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - event: The event.\n    public func userInboundEventTriggered(context: NIOCore.ChannelHandlerContext, event: Any)\n\n    /// Called when some data has been read from the remote peer.\n    ///\n    /// This should call `context.fireChannelRead` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    ///   - data: The data read from the remote peer, wrapped in a `NIOAny`.\n    public func channelRead(context: NIOCore.ChannelHandlerContext, data: NIOCore.NIOAny)\n\n    /// Called when the `Channel` has become inactive and is no longer able to send and receive data.\n    ///\n    /// This should call `context.fireChannelInactive` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event.\n    ///\n    /// - Parameters:\n    ///   - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to.\n    public func channelInactive(context: NIOCore.ChannelHandlerContext)\n}\n```\n\n### HTTP/2.0\n\n```swift\nextension NIOHTTP2Handler {\n    /// A variant of `NIOHTTP2Handler.StreamMultiplexer` which creates a child channel for each HTTP/2 stream and\n    /// provides access to inbound HTTP/2 streams.\n    ///\n    /// In general in NIO applications it is helpful to consider each HTTP/2 stream as an\n    /// independent stream of HTTP/2 frames. This multiplexer achieves this by creating a\n    /// number of in-memory `HTTP2StreamChannel` objects, one for each stream. These operate\n    /// on ``HTTP2Frame/FramePayload`` objects as their base communication\n    /// atom, as opposed to the regular NIO `SelectableChannel` objects which use `ByteBuffer`\n    /// and `IOData`.\n    ///\n    /// Outbound stream channel objects are initialized upon creation using the supplied `streamStateInitializer` which returns a type\n    /// `Output`. This type may be `HTTP2Frame` or changed to any other type.\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public struct AsyncStreamMultiplexer<InboundStreamOutput> {\n        /// Create a stream channel initialized with the provided closure\n        public func createStreamChannel<Output: Sendable>(_ initializer: @escaping NIOChannelInitializerWithOutput<Output>) async throws -> Output\n    }\n}\n\n/// `NIOHTTP2InboundStreamChannels` provides access to inbound stream channels as a generic `AsyncSequence`.\n/// They make use of generics to allow for wrapping the stream `Channel`s, for example as `NIOAsyncChannel`s or protocol negotiation objects.\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\npublic struct NIOHTTP2InboundStreamChannels<Output>: AsyncSequence {\n    public struct AsyncIterator: AsyncIteratorProtocol {\n        public typealias Element = Output\n\n        public mutating func next() async throws -> Output?\n    }\n\n    public typealias Element = Output\n\n    public func makeAsyncIterator() -> AsyncIterator\n}\n\nextension Channel {\n    /// Configures a `ChannelPipeline` to speak HTTP/2 and sets up mapping functions so that it may be interacted with from concurrent code.\n    ///\n    /// In general this is not entirely useful by itself, as HTTP/2 is a negotiated protocol. This helper does not handle negotiation.\n    /// Instead, this simply adds the handler required to speak HTTP/2 after negotiation has completed, or when agreed by prior knowledge.\n    /// Use this function to setup a HTTP/2 pipeline if you wish to use async sequence abstractions over inbound and outbound streams.\n    /// Using this rather than implementing a similar function yourself allows that pipeline to evolve without breaking your code.\n    ///\n    /// - Parameters:\n    ///   - mode: The mode this pipeline will operate in, server or client.\n    ///   - configuration: The settings that will be used when establishing the connection and new streams.\n    ///   - inboundStreamInitializer: A closure that will be called whenever the remote peer initiates a new stream.\n    ///     The output of this closure is the element type of the returned multiplexer\n    /// - Returns: An `EventLoopFuture` containing the `AsyncStreamMultiplexer` inserted into this pipeline, which can\n    ///     be used to initiate new streams and iterate over inbound HTTP/2 stream channels.\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func configureAsyncHTTP2Pipeline<Output: Sendable>(\n        mode: NIOHTTP2Handler.ParserMode,\n        configuration: NIOHTTP2Handler.Configuration = .init(),\n        inboundStreamInitializer: @escaping NIOChannelInitializerWithOutput<Output>\n    ) -> EventLoopFuture<NIOHTTP2Handler.AsyncStreamMultiplexer<Output>>\n\n    /// Configures a `ChannelPipeline` to speak either HTTP/1.1 or HTTP/2 according to what can be negotiated with the client.\n    ///\n    /// This helper takes care of configuring the server pipeline such that it negotiates whether to\n    /// use HTTP/1.1 or HTTP/2.\n    ///\n    /// This function doesn't configure the TLS handler. Callers of this function need to add a TLS\n    /// handler appropriately configured to perform protocol negotiation.\n    ///\n    /// - Parameters:\n    ///   - http2Configuration: The settings that will be used when establishing the HTTP/2 connections and new HTTP/2 streams.\n    ///   - http1ConnectionInitializer: An optional callback that will be invoked only when the negotiated protocol\n    ///     is HTTP/1.1 to configure the connection channel.\n    ///   - http2ConnectionInitializer: An optional callback that will be invoked only when the negotiated protocol\n    ///     is HTTP/2 to configure the connection channel.\n    ///   - http2InboundStreamInitializer: A closure that will be called whenever the remote peer initiates a new stream.\n    ///     The output of this closure is the element type of the returned multiplexer\n    /// - Returns: An `EventLoopFuture` containing a ``NIOTypedApplicationProtocolNegotiationHandler`` that completes when the channel\n    ///     is ready to negotiate. This can then be used to access the protocol negotiation result which may itself\n    ///     be waited on to retrieve the result of the negotiation.\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func configureAsyncHTTPServerPipeline<HTTP1ConnectionOutput: Sendable, HTTP2ConnectionOutput: Sendable, HTTP2StreamOutput: Sendable>(\n        http2Configuration: NIOHTTP2Handler.Configuration = .init(),\n        http1ConnectionInitializer: @escaping NIOChannelInitializerWithOutput<HTTP1ConnectionOutput>,\n        http2ConnectionInitializer: @escaping NIOChannelInitializerWithOutput<HTTP2ConnectionOutput>,\n        http2InboundStreamInitializer: @escaping NIOChannelInitializerWithOutput<HTTP2StreamOutput>\n    ) -> EventLoopFuture<EventLoopFuture<NIONegotiatedHTTPVersion<\n            HTTP1ConnectionOutput,\n            (HTTP2ConnectionOutput, NIOHTTP2Handler.AsyncStreamMultiplexer<HTTP2StreamOutput>)\n        >>>\n\nextension ChannelPipeline.SynchronousOperations {\n    /// Configures a `ChannelPipeline` to speak HTTP/2 and sets up mapping functions so that it may be interacted with from concurrent code.\n    ///\n    /// This operation **must** be called on the event loop.\n    ///\n    /// In general this is not entirely useful by itself, as HTTP/2 is a negotiated protocol. This helper does not handle negotiation.\n    /// Instead, this simply adds the handler required to speak HTTP/2 after negotiation has completed, or when agreed by prior knowledge.\n    /// Use this function to setup a HTTP/2 pipeline if you wish to use async sequence abstractions over inbound and outbound streams,\n    /// as it allows that pipeline to evolve without breaking your code.\n    ///\n    /// - Parameters:\n    ///   - mode: The mode this pipeline will operate in, server or client.\n    ///   - configuration: The settings that will be used when establishing the connection and new streams.\n    ///   - inboundStreamInitializer: A closure that will be called whenever the remote peer initiates a new stream.\n    ///     The output of this closure is the element type of the returned multiplexer\n    /// - Returns: An `EventLoopFuture` containing the `AsyncStreamMultiplexer` inserted into this pipeline, which can\n    /// be used to initiate new streams and iterate over inbound HTTP/2 stream channels.\n    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\n    public func configureAsyncHTTP2Pipeline<Output: Sendable>(\n        mode: NIOHTTP2Handler.ParserMode,\n        configuration: NIOHTTP2Handler.Configuration = .init(),\n        inboundStreamInitializer: @escaping NIOChannelInitializerWithOutput<Output>\n    ) throws -> NIOHTTP2Handler.AsyncStreamMultiplexer<Output>\n}\n\n/// `NIONegotiatedHTTPVersion` is a generic negotiation result holder for HTTP/1.1 and HTTP/2\npublic enum NIONegotiatedHTTPVersion<HTTP1Output: Sendable, HTTP2Output: Sendable> {\n    case http1_1(HTTP1Output)\n    case http2(HTTP2Output)\n}\n```\n"
  },
  {
    "path": "docs/workarounds.md",
    "content": "# Workarounds\n\nThe following list of PRs and commits were applied in order to work around bugs\nor cases where the Swift compiler was unable to sufficiently optimize the code:\n\n- https://github.com/apple/swift-nio/pull/1374\n- https://github.com/apple/swift-nio-ssl/pull/176\n- https://github.com/apple/swift-nio/pull/1325\n- https://github.com/apple/swift-nio/pull/1299\n- https://github.com/apple/swift-nio/pull/1252\n- https://github.com/apple/swift-nio/pull/494\n- https://github.com/apple/swift-nio/pull/420\n- https://github.com/apple/swift-nio/commit/abc963cfe1e1d4856c41421c9d53ea778102e9e8\n- https://github.com/apple/swift-nio/pull/1814\n- https://github.com/apple/swift-nio/pull/1956\n- https://github.com/apple/swift-nio/pull/1961\n- https://github.com/apple/swift-nio/pull/2046\n- https://github.com/apple/swift-nio/pull/3303\n- https://github.com/apple/swift-nio/pull/3452\n- https://github.com/apple/swift-nio/pull/3454\n- https://github.com/apple/swift-nio/pull/3455\n"
  },
  {
    "path": "scripts/analyze_performance_results.rb",
    "content": "#!/usr/bin/env ruby\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\nrequire 'optparse'\n\nMETRIC=\"min\" # used for comparison\n\nmodule Enumerable\n  def sum\n    return self.inject(0){|accum, i| accum + i }\n  end\n\n  def mean\n    return self.sum / self.length.to_f\n  end\n\n  def sample_variance\n    m = self.mean\n    sum = self.inject(0){|accum, i| accum + (i - m) ** 2 }\n    return sum / (self.length - 1).to_f\n  end\n\n  def standard_deviation\n    return Math.sqrt(self.sample_variance)\n  end\nend\n\ndef parse_results(file)\n  results = {}\n  File.open(file, \"r\") do |f|\n    f.each_line do |line|\n      parts = line.split(':').collect(&:strip)\n      throw \"invalid data format\" unless parts.length == 3\n      key = parts[1]\n      values = parts[2].split(',').collect(&:strip).map(&:to_f)\n      results[key] = {}\n      results[key][\"values\"] = values\n      results[key][\"max\"] = values.max\n      results[key][\"min\"] = values.min\n      results[key][\"mean\"] = values.mean\n      results[key][\"std\"] = values.standard_deviation\n    end\n  end\n  results\nend\n\ndef compare_results(current, previous)\n  results = {}\n  current.keys.each do |key|\n    results[key] = {}\n    results[key][\"previous\"] = previous[key] || { ::METRIC => \"n/a\" }\n    results[key][\"current\"] = current[key]\n    if previous[key]\n      current_value = current[key][::METRIC]\n      previous_value = previous[key][::METRIC]\n      delta = current_value - previous_value\n      results[key][\"delta\"] = delta\n      results[key][\"winner\"] = current_value <= previous_value ? \"current\" : \"previous\"\n      results[key][\"diff\"] = (delta / previous_value * 100).to_i\n    else\n      results[key][\"winner\"] = \"n/a\"\n      results[key][\"diff\"] = \"n/a\"\n    end\n  end\n  results\nend\n\ndef print_results_markdown(results)\n  columns = [\"min\", \"max\", \"mean\", \"std\"]\n  puts \"| name | #{columns.join(\" | \")} |\"\n  puts \"|#{Array.new(columns.size+1, '---').join(\"|\")}|\"\n  results.keys.each do |key|\n    print \"| `#{key}`\"\n    columns.each do |column|\n      print \" | #{results[key][column]}\"\n    end\n    puts \" |\\n\"\n  end\nend\n\ndef print_results_html(results)\n  columns = [\"min\", \"max\", \"mean\", \"std\"]\n  puts \"<table border=\\\"1\\\">\"\n  puts \"<tr><td>name</td><td>#{columns.join(\"</td><td>\")}</td></tr>\"\n  results.keys.each do |key|\n    puts \"<tr>\"\n    puts \"<td>#{key}</td>\"\n    columns.each do |column|\n      puts \"<td>#{results[key][column]}</td>\"\n    end\n    puts \"</tr>\"\n  end\n  puts \"</table>\"\nend\n\ndef print_results_csv(results)\n  puts results.keys.join(\",\")\n  puts results.keys.map{ |key| results[key][::METRIC] }.join(\",\")\nend\n\ndef print_comparison_markdown(results)\n  puts \"| name | current | previous | winner | diff |\"\n  puts \"|#{Array.new(5, '---').join(\"|\")}|\"\n  results.keys.each do |key|\n    puts \"| `#{key}` | #{results[key][\"current\"][::METRIC]} | #{results[key][\"previous\"][::METRIC]} | #{results[key][\"winner\"]} | #{results[key][\"diff\"]}% |\"\n  end\nend\n\ndef print_comparison_html(results)\n  puts \"<table border=\\\"1\\\">\"\n  puts \"  <tr>\n    <td>name</td>\n    <td>current</td>\n    <td>previous</td>\n    <td>winner</td>\n    <td>diff</td>\n  </tr>\"\n  results.keys.each do |key|\n    puts \"  <tr>\n    <td>#{key}</td>\n    <td>#{results[key][\"current\"][::METRIC]}</td>\n    <td>#{results[key][\"previous\"][::METRIC]}</td>\n    <td>#{results[key][\"winner\"]}</td>\n    <td>#{results[key][\"diff\"]}%</td>\n  </tr>\"\n  end\n  puts \"</table>\"\nend\n\n\nARGV << '-h' if ARGV.empty?\n\noptions = {}\nOptionParser.new do |opt|\n  opt.on('-f', '--file file', 'file to process') { |o| options[:file] = o }\n  opt.on('-p', '--previous previous', 'previous file to process') { |o| options[:previous] = o }\n  opt.on('-o', '--output output', 'output format') { |o| options[:output] = o }\n  opt.on_tail(\"-h\", \"--help\", \"show this message\") do\n    puts opt\n  end\nend.parse!\n\nif options.has_key?(:file) && options.has_key?(:previous)\n  current = parse_results(options[:file])\n  previous = parse_results(options[:previous])\n  results = compare_results(current, previous)\n\n  case options[:output]\n  when \"html\"\n    print_comparison_html(results)\n  when \"markdown\", nil\n    print_comparison_markdown(results)\n  else\n    throw \"invalid output format #{options[:output]}\"\n  end\n\nelsif options.has_key?(:file)\n  results = parse_results(options[:file])\n  case options[:output]\n  when \"csv\"\n    print_results_csv(results)\n  when \"html\", nil\n    print_results_html(results)\n  when \"markdown\", nil\n    print_results_markdown(results)\n  else\n    throw \"invalid output format #{options[:output]}\"\n  end\n\nelse\n  throw \"invalid arguemnts\"\nend\n"
  },
  {
    "path": "scripts/bench-alloc-counter.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# Benchmarks the allocation counter tests before and after the swift run -> direct\n# binary execution change in run-allocation-counter.sh, then prints a report.\n#\n# Usage: ./scripts/bench-alloc-counter.sh\n# Must be run from the repository root.\n\nset -euo pipefail\n\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\nroot=\"$here/..\"\nrunner=\"$root/IntegrationTests/tests_04_performance/test_01_resources/run-nio-alloc-counter-tests.sh\"\n\nrun_and_time() {\n    local label=\"$1\"\n    local tmp\n    tmp=$(mktemp -d /tmp/.alloc-counter-bench-XXXXXX)\n    echo \"--- running: $label ---\" >&2\n    local start end\n    start=$(date +%s)\n    \"$runner\" -t \"$tmp\" > /dev/null\n    end=$(date +%s)\n    rm -rf \"$tmp\"\n    echo $(( end - start ))\n}\n\necho \"Timing current version (working tree)...\" >&2\ntime_current=$(run_and_time \"current\")\n\ntime_original=1192\ntime_direct_exec=1071\n\necho\necho \"============================================\"\necho \" Allocation counter test benchmark\"\necho \"============================================\"\nprintf \" Original (swift run loop):   %4ds\\n\" \"$time_original\"\nprintf \" Direct exec (no parallel):   %4ds\\n\" \"$time_direct_exec\"\nprintf \" Parallel direct exec:        %4ds\\n\" \"$time_current\"\nprintf \" Saved vs original:           %4ds (%d%%)\\n\" \\\n    \"$(( time_original - time_current ))\" \\\n    \"$(( (time_original - time_current) * 100 / time_original ))\"\necho \"============================================\"\n"
  },
  {
    "path": "scripts/check-cxx-interop-compatibility.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -euo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\nlog \"Checking for Cxx interoperability compatibility...\"\n\nsource_dir=$(pwd)\nworking_dir=$(mktemp -d \"/tmp/tmp_swift_package_XXXXXXXXXX\")\nproject_name=$(basename \"$working_dir\")\nsource_file=Sources/$project_name/$project_name.swift\nlibrary_products=$( swift package dump-package | jq -r '.products[] | select(.type.library != null) | .name')\npackage_name=$(swift package dump-package | jq -r '.name')\n\ncd \"$working_dir\"\nswift package init\n\n{\n  echo \"let swiftSettings: [SwiftSetting] = [.interoperabilityMode(.Cxx)]\"\n  echo \"for target in package.targets { target.swiftSettings = (target.swiftSettings ?? []) + swiftSettings }\"\n} >> Package.swift\n\necho \"package.dependencies.append(.package(path: \\\"$source_dir\\\"))\" >> Package.swift\n\nfor product in $library_products; do\n  echo \"package.targets.first!.dependencies.append(.product(name: \\\"$product\\\", package: \\\"$package_name\\\"))\" >> Package.swift\n  echo \"import $product\" >> \"$source_file\"\ndone\n\nswift build\n\nlog \"✅ Passed the Cxx interoperability tests.\"\n"
  },
  {
    "path": "scripts/check-matrix-job.ps1",
    "content": "##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\n# Set strict mode to catch errors\nSet-StrictMode -Version Latest\n\nfunction Log {\n    param (\n        [string]$Message\n    )\n    Write-Host (\"** \" + $Message) -ForegroundColor Yellow\n}\n\nfunction Error {\n    param (\n        [string]$Message\n    )\n    Write-Host (\"** ERROR: \" + $Message) -ForegroundColor Red\n}\n\nfunction Fatal {\n    param (\n        [string]$Message\n    )\n    Error $Message\n    exit 1\n}\n\n# Check if SWIFT_VERSION is set\nif (-not $env:SWIFT_VERSION) {\n    Fatal \"SWIFT_VERSION unset\"\n}\n\n# Check if COMMAND is set\nif (-not $env:COMMAND) {\n    Fatal \"COMMAND unset\"\n}\n\n$swift_version = $env:SWIFT_VERSION\n$command = $env:COMMAND\n$command_5_9 = $env:COMMAND_OVERRIDE_5_9\n$command_5_10 = $env:COMMAND_OVERRIDE_5_10\n$command_6_0 = $env:COMMAND_OVERRIDE_6_0\n$command_nightly_6_1 = $env:COMMAND_OVERRIDE_NIGHTLY_6_1\n$command_nightly_main = $env:COMMAND_OVERRIDE_NIGHTLY_MAIN\n\nif ($swift_version -eq \"5.9\" -and $command_5_9) {\n    Log \"Running 5.9 command override\"\n    Invoke-Expression $command_5_9\n} elseif ($swift_version -eq \"5.10\" -and $command_5_10) {\n    Log \"Running 5.10 command override\"\n    Invoke-Expression $command_5_10\n} elseif ($swift_version -eq \"6.0\" -and $command_6_0) {\n    Log \"Running 6.0 command override\"\n    Invoke-Expression $command_6_0\n} elseif ($swift_version -eq \"nightly-6.1\" -and $command_nightly_6_1) {\n    Log \"Running nightly 6.1 command override\"\n    Invoke-Expression $command_nightly_6_1\n} elseif ($swift_version -eq \"nightly-main\" -and $command_nightly_main) {\n    Log \"Running nightly main command override\"\n    Invoke-Expression $command_nightly_main\n} else {\n    Log \"Running default command\"\n    Invoke-Expression $command\n}\n\nExit $LASTEXITCODE\n"
  },
  {
    "path": "scripts/check-matrix-job.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\nset -euo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\ntest -n \"${SWIFT_VERSION:-}\" || fatal \"SWIFT_VERSION unset\"\ntest -n \"${COMMAND:-}\" || fatal \"COMMAND unset\"\nswift_version=\"$SWIFT_VERSION\"\ncommand=\"$COMMAND\"\ncommand_5_9=\"${COMMAND_OVERRIDE_5_9:=\"\"}\"\ncommand_5_10=\"${COMMAND_OVERRIDE_5_10:=\"\"}\"\ncommand_6_0=\"${COMMAND_OVERRIDE_6_0:=\"\"}\"\ncommand_6_1=\"${COMMAND_OVERRIDE_6_1:=\"\"}\"\ncommand_6_2=\"${COMMAND_OVERRIDE_6_2:=\"\"}\"\ncommand_nightly_next=\"${COMMAND_OVERRIDE_NIGHTLY_NEXT:=\"\"}\"\ncommand_nightly_main=\"${COMMAND_OVERRIDE_NIGHTLY_MAIN:=\"\"}\"\n\nif [[ \"$swift_version\" == \"5.9\" ]] && [[ -n \"$command_5_9\" ]]; then\n  log \"Running 5.9 command override\"\n  eval \"$command_5_9\"\nelif [[ \"$swift_version\" == \"5.10\" ]] && [[ -n \"$command_5_10\" ]]; then\n  log \"Running 5.10 command override\"\n  eval \"$command_5_10\"\nelif [[ \"$swift_version\" == \"6.0\" ]] && [[ -n \"$command_6_0\" ]]; then\n  log \"Running 6.0 command override\"\n  eval \"$command_6_0\"\nelif [[ \"$swift_version\" == \"6.1\" ]] && [[ -n \"$command_6_1\" ]]; then\n  log \"Running 6.1 command override\"\n  eval \"$command_6_1\"\nelif [[ \"$swift_version\" == \"6.2\" ]] && [[ -n \"$command_6_2\" ]]; then\n  log \"Running 6.2 command override\"\n  eval \"$command_6_2\"\nelif [[ \"$swift_version\" == \"nightly-next\" ]] && [[ -n \"$command_nightly_next\" ]]; then\n  log \"Running nightly next command override\"\n  eval \"$command_nightly_next\"\nelif [[ \"$swift_version\" == \"nightly-main\" ]] && [[ -n \"$command_nightly_main\" ]]; then\n  log \"Running nightly main command override\"\n  eval \"$command_nightly_main\"\nelse\n  log \"Running default command\"\n  eval \"$command\"\nfi\n"
  },
  {
    "path": "scripts/check_benchmark_thresholds.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\n# Parameter environment variables\nif [ -z \"$SWIFT_VERSION\" ]; then\n  fatal \"SWIFT_VERSION must be specified.\"\nfi\n\nbenchmark_package_path=\"${BENCHMARK_PACKAGE_PATH:-\".\"}\"\nswift_version=\"${SWIFT_VERSION:-\"\"}\"\n\n# Any parameters to the script are passed along to SwiftPM\nswift_package_arguments=(\"$@\")\n\n#\"swift package --package-path ${{ inputs.benchmark_package_path }} ${{ inputs.swift_package_arguments }} benchmark baseline check --check-absolute-path ${{ inputs.benchmark_package_path }}/Thresholds/${SWIFT_VERSION}/\"\nswift package --package-path \"$benchmark_package_path\" \"${swift_package_arguments[@]}\" benchmark thresholds check --format metricP90AbsoluteThresholds --path \"${benchmark_package_path}/Thresholds/${swift_version}/\"\nrc=\"$?\"\n\n# Benchmarks are unchanged, nothing to recalculate\nif [[ \"$rc\" == 0 ]]; then\n  exit 0\nfi\n\n# Non-zero exit from 'thresholds check' means thresholds regressed or a build\n# error occurred. Try 'thresholds update' to distinguish: if it also fails, it\n# was a build error; if it succeeds, thresholds were updated.\nlog \"Recalculating thresholds...\"\n\nswift package --package-path \"$benchmark_package_path\" \"${swift_package_arguments[@]}\" benchmark thresholds update --format metricP90AbsoluteThresholds --path \"${benchmark_package_path}/Thresholds/${swift_version}/\"\nupdate_rc=\"$?\"\n\nif [[ \"$update_rc\" != 0 ]]; then\n  error \"Benchmark failed to run due to build error.\"\n  exit $update_rc\nfi\n\necho \"=== BEGIN DIFF ===\"  # use echo, not log for clean output to be scraped\ngit add --intent-to-add \"${benchmark_package_path}/Thresholds/\"\ngit diff HEAD -- \"${benchmark_package_path}/Thresholds/\"\nexit 1\n\n\n"
  },
  {
    "path": "scripts/cmake-build.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\ntarget_dir=\"${TARGET_DIRECTORY:=\"\"}\"\n\nif [ -z \"$target_dir\" ]; then\n  fatal \"Target directory must be specified.\"\nfi\n\nCURL_BIN=\"${CURL_BIN:-$(which curl)}\" || fatal \"CURL_BIN unset and no curl on PATH\"\nTAR_BIN=\"${TAR_BIN:-$(which tar)}\" || fatal \"TAR_BIN unset and no tar on PATH\"\nCMAKE_BIN=\"${CMAKE_BIN:-$(which cmake)}\" || fatal \"CMAKE_BIN unset and no cmake on PATH\"\nNINJA_BIN=\"${NINJA_BIN:-$(which ninja)}\" || fatal \"NINJA_BIN unset and no ninja on PATH\"\nASSEMBLY_COMPILER_BIN=\"${ASSEMBLY_COMPILER_BIN:-$(which clang)}\" || fatal \"ASSEMBLY_COMPILER_BIN unset and no clang on PATH\"\n\nlog \"Building Ninja build files for target\"\nbuild_dir=\"${target_dir}/build\"\nmkdir -p \"$build_dir\"\ncd \"${build_dir}\" || fatal \"Could not 'cd' to ${build_dir}\"\nASM=\"$ASSEMBLY_COMPILER_BIN\" \"$CMAKE_BIN\" build -G Ninja -S ..\n\nlog \"Building target\"\n\"$NINJA_BIN\"\n"
  },
  {
    "path": "scripts/compare_perf_of_swift_versions.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\nhere=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nfunction usage() {\n    echo >&2 \"$0 SWIFT_BINARY_BASE SWIFT_BINARY_COMPETITOR\"\n    echo >&2\n    echo >&2 \"Runs the NIOPerformanceTester tool with 'swift' binary \"\n    echo >&2 \"SWIFT_BINARY_BASE against SWIFT_BINARY_COMPETITOR.\"\n    echo >&2\n    echo >&2 \"Example:\"\n    echo >&2 \"$0 /Library/Developer/Toolchains/swift-4.1-RELEASE.xctoolchain/usr/bin/swift /Library/Developer/Toolchains/swift-4.2-DEVELOPMENT-SNAPSHOT-2018-08-07-a.xctoolchain/usr/bin/swift\"\n}\n\nfunction write_compare_r_script() {\n    cat >> \"$1\" <<\"EOF\"\n#!/usr/bin/env Rscript\n\nargs <- commandArgs(trailingOnly=TRUE)\nperfBase <- read.csv(args[2], header=F)\nperfOther <- read.csv(args[4], header=F)\nnameBase <- args[1]\nnameOther <- args[3]\nbenchmarks <- perfBase$V2\nstopifnot(benchmarks == perfOther$V2)\n\nswifts <- list(nameBase, nameOther)\nresult_cols = 3:12\n\nperfBase$swift <- rep(swifts[[1]], nrow(perfBase))\nperfOther$swift <- rep(swifts[[2]], nrow(perfOther))\n\nget_perf_matrix <- function(.df) {\n    matrix(as.vector(do.call(c, .df[,result_cols])), nrow=nrow(.df))\n}\n\nall_perfs <- rbind(perfBase, perfOther)\nall_perfs$main_indicator <- apply(get_perf_matrix(all_perfs), 1, min)\n\nfor (benchmark in benchmarks) {\n    cat(\"benchmark:\", benchmark, \"\\n===========\\n\")\n    p <- all_perfs[all_perfs$V2 == benchmark,]\n\n    for (swift in swifts) {\n        results <- unlist(p[p$swift == swift,][result_cols], use.names=F)\n\n        cat(paste('- with', swift), \"\\n\")\n        cat(results, \"\\n\")\n        print(summary(results))\n    }\n\n    cat(paste(\"winner: \", p[which.min(p$main_indicator),]$swift), \"\\n\")\n\n    pBase <- p[p$swift == nameBase,]$main_indicator\n    pOther <- p[p$swift == nameOther,]$main_indicator\n\n    cat(\"comparison:\", nameBase, \"to\", nameOther, \":\", round(100 * (pOther - pBase)/pBase, 2), \"%\\n\")\n    cat(\"\\n\")\n}\nEOF\n}\n\nif ! test $# -eq 2; then\n    usage\n    exit 1\nfi\n\ncompare_r_script=$(mktemp /tmp/.compare_perf_XXXXXX)\nwrite_compare_r_script \"$compare_r_script\"\n\n(\ncd \"$here/..\"\ncompare_args=()\nfor swift_binary in \"$@\"; do\n    echo \"running with $swift_binary\"\n    perf_file=$(mktemp /tmp/.nio-perf_XXXXXX)\n    \"$swift_binary\" run -c release NIOPerformanceTester | grep ^measuring: | tr : , > \"$perf_file\" 2>&1\n    compare_args+=(\"$swift_binary\")\n    compare_args+=(\"$perf_file\")\ndone\n\nRscript \"$compare_r_script\" \"${compare_args[@]}\"\n)\n\nrm \"$compare_r_script\"\n"
  },
  {
    "path": "scripts/generate_matrix.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\n# Binary dependencies\nJQ_BIN=\"${JQ_BIN:-$(which jq 2> /dev/null)}\"; test -n \"$JQ_BIN\" || fatal \"JQ_BIN unset and no jq on PATH\"\nSED_BIN=\"${SED_BIN:-$(which sed 2> /dev/null)}\"; test -n \"$SED_BIN\" || fatal \"SED_BIN unset and no sed on PATH\"\nHEAD_BIN=\"${HEAD_BIN:-$(which head 2> /dev/null)}\"; test -n \"$HEAD_BIN\" || fatal \"HEAD_BIN unset and no head on PATH\"\n\n\n# Parameters\nfind_subdirectory_manifests_enabled=\"${FIND_SUBDIRECTORY_MANIFESTS_ENABLED:=false}\"\n\nlinux_command=\"${MATRIX_LINUX_COMMAND:-}\"  # required if any Linux pipeline is enabled\nlinux_setup_command=\"${MATRIX_LINUX_SETUP_COMMAND:-}\"\nlinux_5_9_enabled=\"${MATRIX_LINUX_5_9_ENABLED:=false}\"\nlinux_5_9_command_arguments=\"${MATRIX_LINUX_5_9_COMMAND_ARGUMENTS:-}\"\nlinux_5_10_enabled=\"${MATRIX_LINUX_5_10_ENABLED:=false}\"\nlinux_5_10_command_arguments=\"${MATRIX_LINUX_5_10_COMMAND_ARGUMENTS:-}\"\nlinux_6_0_enabled=\"${MATRIX_LINUX_6_0_ENABLED:=true}\"\nlinux_6_1_enabled=\"${MATRIX_LINUX_6_1_ENABLED:=true}\"\nlinux_6_2_enabled=\"${MATRIX_LINUX_6_2_ENABLED:=true}\"\nlinux_6_0_command_arguments=\"${MATRIX_LINUX_6_0_COMMAND_ARGUMENTS:-}\"\nlinux_6_1_command_arguments=\"${MATRIX_LINUX_6_1_COMMAND_ARGUMENTS:-}\"\nlinux_6_2_command_arguments=\"${MATRIX_LINUX_6_2_COMMAND_ARGUMENTS:-}\"\nlinux_nightly_next_enabled=\"${MATRIX_LINUX_NIGHTLY_NEXT_ENABLED:=${MATRIX_LINUX_NIGHTLY_6_1_ENABLED:=true}}\"\nlinux_nightly_next_command_arguments=\"${MATRIX_LINUX_NIGHTLY_NEXT_COMMAND_ARGUMENTS:=${MATRIX_LINUX_NIGHTLY_6_1_COMMAND_ARGUMENTS:-}}\"\nlinux_nightly_main_enabled=\"${MATRIX_LINUX_NIGHTLY_MAIN_ENABLED:=true}\"\nlinux_nightly_main_command_arguments=\"${MATRIX_LINUX_NIGHTLY_MAIN_COMMAND_ARGUMENTS:-}\"\n\nwindows_command=\"${MATRIX_WINDOWS_COMMAND:-}\"  # required if any Windows pipeline is enabled\nwindows_setup_command=\"${MATRIX_WINDOWS_SETUP_COMMAND:-}\"\nwindows_6_0_enabled=\"${MATRIX_WINDOWS_6_0_ENABLED:=false}\"\nwindows_6_1_enabled=\"${MATRIX_WINDOWS_6_1_ENABLED:=false}\"\nwindows_6_2_enabled=\"${MATRIX_WINDOWS_6_2_ENABLED:=false}\"\nwindows_6_0_command_arguments=\"${MATRIX_WINDOWS_6_0_COMMAND_ARGUMENTS:-}\"\nwindows_6_1_command_arguments=\"${MATRIX_WINDOWS_6_1_COMMAND_ARGUMENTS:-}\"\nwindows_6_2_command_arguments=\"${MATRIX_WINDOWS_6_2_COMMAND_ARGUMENTS:-}\"\nwindows_nightly_next_enabled=\"${MATRIX_WINDOWS_NIGHTLY_NEXT_ENABLED:=${MATRIX_WINDOWS_NIGHTLY_6_1_ENABLED:=false}}\"\nwindows_nightly_next_command_arguments=\"${MATRIX_WINDOWS_NIGHTLY_NEXT_COMMAND_ARGUMENTS:=${MATRIX_WINDOWS_NIGHTLY_6_1_COMMAND_ARGUMENTS:-}}\"\nwindows_nightly_main_enabled=\"${MATRIX_WINDOWS_NIGHTLY_MAIN_ENABLED:=false}\"\nwindows_nightly_main_command_arguments=\"${MATRIX_WINDOWS_NIGHTLY_MAIN_COMMAND_ARGUMENTS:-}\"\n\n# Get pre-parsed environment variables JSON\nlinux_env_vars_json=\"${MATRIX_LINUX_ENV_VARS_JSON:-\"{}\"}\"\nwindows_env_vars_json=\"${MATRIX_WINDOWS_ENV_VARS_JSON:-\"{}\"}\"\n\n# Defaults\nlinux_runner=\"ubuntu-latest\"\nlinux_5_9_container_image=\"swift:5.9-jammy\"\nlinux_5_10_container_image=\"swift:5.10-jammy\"\nlinux_6_0_container_image=\"swift:6.0-jammy\"\nlinux_6_1_container_image=\"swift:6.1-jammy\"\nlinux_6_2_container_image=\"swift:6.2-noble\"\nlinux_nightly_next_container_image=\"swiftlang/swift:nightly-6.3-jammy\"\nlinux_nightly_main_container_image=\"swiftlang/swift:nightly-main-jammy\"\n\nwindows_6_0_runner=\"windows-2022\"\nwindows_6_0_container_image=\"swift:6.0-windowsservercore-ltsc2022\"\nwindows_6_1_runner=\"windows-2022\"\nwindows_6_1_container_image=\"swift:6.1-windowsservercore-ltsc2022\"\nwindows_6_2_runner=\"windows-2022\"\nwindows_6_2_container_image=\"swift:6.2-windowsservercore-ltsc2022\"\nwindows_nightly_next_runner=\"windows-2022\"\nwindows_nightly_next_container_image=\"swiftlang/swift:nightly-6.2-windowsservercore-ltsc2022\"\nwindows_nightly_main_runner=\"windows-2022\"\nwindows_nightly_main_container_image=\"swiftlang/swift:nightly-main-windowsservercore-ltsc2022\"\n\n# Extract swift-tools-version from a manifest file\nget_tools_version() {\n    local manifest=\"$1\"\n    if [[ ! -f \"$manifest\" ]]; then\n        echo \"\"\n        return\n    fi\n\n    # Parse the first line: // swift-tools-version:X.Y or // swift-tools-version: X.Y\n    local tools_version\n    tools_version=$(\"$HEAD_BIN\" -n 1 \"$manifest\" | \"$SED_BIN\" -n 's#^// *swift-tools-version: *\\([0-9.]*\\).*#\\1#p')\n    echo \"$tools_version\"\n}\n\n# Compare versions using SemVer: returns 0 if v1 >= v2, 1 otherwise\nversion_gte() {\n    local v1=\"$1\"\n    local v2=\"$2\"\n\n    # Parse v1 as major.minor.patch\n    IFS='.' read -r v1_major v1_minor v1_patch <<< \"$v1\"\n    v1_minor=${v1_minor:-0}\n    v1_patch=${v1_patch:-0}\n\n    # Parse v2 as major.minor.patch\n    IFS='.' read -r v2_major v2_minor v2_patch <<< \"$v2\"\n    v2_minor=${v2_minor:-0}\n    v2_patch=${v2_patch:-0}\n\n    # Compare major\n    if [[ $v1_major -gt $v2_major ]]; then return 0; fi\n    if [[ $v1_major -lt $v2_major ]]; then return 1; fi\n\n    # Major equal, compare minor\n    if [[ $v1_minor -gt $v2_minor ]]; then return 0; fi\n    if [[ $v1_minor -lt $v2_minor ]]; then return 1; fi\n\n    # Major and minor equal, compare patch\n    if [[ $v1_patch -ge $v2_patch ]]; then return 0; fi\n    return 1\n}\n\n# Find minimum Swift version across all Package manifests\n# Checks Package.swift and all Package@swift-*.swift files in current directory and subdirectories\n# Returns the minimum tools version found across all manifests\nfind_minimum_swift_version() {\n    local min_version=\"\"\n\n    # Check default Package.swift in current directory\n    local default_version\n    default_version=$(get_tools_version \"Package.swift\")\n    if [[ -n \"$default_version\" ]]; then\n        min_version=\"$default_version\"\n        log \"Found Package.swift with tools-version: $default_version\"\n    fi\n\n    # Check all Package.swift files in subdirectories (multi-package repository support)\n    if [[ \"$find_subdirectory_manifests_enabled\" == \"true\" ]]; then\n        while read -r manifest; do\n            if [[ -f \"$manifest\" ]]; then\n                local version\n                version=$(get_tools_version \"$manifest\")\n                if [[ -n \"$version\" ]]; then\n                    log \"Found $manifest with tools-version: $version\"\n\n                    # If this version is less than current minimum, update minimum\n                    if [[ -z \"$min_version\" ]] || version_gte \"$min_version\" \"$version\"; then\n                        min_version=\"$version\"\n                    fi\n                fi\n            fi\n        done < <(ls -1 ./*/Package.swift 2>/dev/null || true)\n    fi\n\n    # Check all version-specific manifests in current directory\n    for manifest in Package@swift-*.swift; do\n        if [[ ! -f \"$manifest\" ]]; then\n            continue\n        fi\n\n        local version\n        version=$(get_tools_version \"$manifest\")\n        if [[ -z \"$version\" ]]; then\n            continue\n        fi\n\n        log \"Found $manifest with tools-version: $version\"\n\n        # If this version is less than current minimum, update minimum\n        if [[ -z \"$min_version\" ]] || version_gte \"$min_version\" \"$version\"; then\n            min_version=\"$version\"\n        fi\n    done\n\n    # Check all version-specific manifests in subdirectories\n    if [[ \"$find_subdirectory_manifests_enabled\" == \"true\" ]]; then\n        while read -r manifest; do\n            if [[ -f \"$manifest\" ]]; then\n                local version\n                version=$(get_tools_version \"$manifest\")\n                if [[ -n \"$version\" ]]; then\n                    log \"Found $manifest with tools-version: $version\"\n\n                    # If this version is less than current minimum, update minimum\n                    if [[ -z \"$min_version\" ]] || version_gte \"$min_version\" \"$version\"; then\n                        min_version=\"$version\"\n                    fi\n                fi\n            fi\n        done < <(ls -1 ./*/Package@swift-*.swift 2>/dev/null || true)\n    fi\n\n    if [[ -n \"$min_version\" ]]; then\n        echo \"$min_version\"\n    else\n        log \"Warning: Could not find any Swift tools version in Package manifests\"\n        echo \"\"\n    fi\n}\n\n# Check if a Swift version should be included in the matrix\n# Nightlies are always included\n# If MATRIX_MIN_SWIFT_VERSION is \"none\", all versions are included\n# If MATRIX_MIN_SWIFT_VERSION is not set, it's auto-detected from Package manifests\n# If MATRIX_MIN_SWIFT_VERSION is set to a version, that version is used as the minimum\nshould_include_version() {\n    local version=\"$1\"\n\n    # If minimum version check is disabled, include everything\n    if [[ \"${MATRIX_MIN_SWIFT_VERSION:-}\" == \"none\" ]]; then\n        return 0\n    fi\n\n    # If no minimum version specified, include everything\n    if [[ -z \"${MATRIX_MIN_SWIFT_VERSION:-}\" ]]; then\n        return 0\n    fi\n\n    # Nightly builds always included\n    if [[ \"$version\" =~ ^nightly- ]]; then\n        return 0\n    fi\n\n    # Check if version >= minimum\n    if version_gte \"$version\" \"$MATRIX_MIN_SWIFT_VERSION\"; then\n        return 0\n    else\n        log \"Skipping Swift $version (< minimum $MATRIX_MIN_SWIFT_VERSION)\"\n        return 1\n    fi\n}\n\n# Add a matrix entry for a specific Swift version and platform\n# Parameters:\n#   $1: platform (\"Linux\" or \"Windows\")\n#   $2: version name (e.g., \"5.9\", \"6.0\", \"nightly-main\")\n#   $3: enabled flag (\"true\" or \"false\")\n#   $4: setup_command\n#   $5: command\n#   $6: command_arguments\n#   $7: container_image\n#   $8: runner\n#   $9: env_vars_json\nadd_matrix_entry() {\n    local platform=\"$1\"\n    local version=\"$2\"\n    local enabled=\"$3\"\n    local setup_command=\"$4\"\n    local command=\"$5\"\n    local command_arguments=\"$6\"\n    local container_image=\"$7\"\n    local runner=\"$8\"\n    local env_vars_json=\"$9\"\n\n    if [[ \"$enabled\" == \"true\" ]] && should_include_version \"$version\"; then\n        # shellcheck disable=SC2016  # Our use of JQ_BIN means that shellcheck can't tell this is a `jq` invocation\n        matrix=$(echo \"$matrix\" | \"$JQ_BIN\" -c \\\n            --arg setup_command \"$setup_command\" \\\n            --arg command \"$command\" \\\n            --arg command_arguments \"$command_arguments\" \\\n            --arg container_image \"$container_image\" \\\n            --arg runner \"$runner\" \\\n            --arg platform \"$platform\" \\\n            --arg version \"$version\" \\\n            --argjson env_vars \"$env_vars_json\" \\\n            '.config[.config| length] |= . + { \"name\": $version, \"image\": $container_image, \"swift_version\": $version, \"platform\": $platform, \"command\": $command, \"command_arguments\": $command_arguments, \"setup_command\": $setup_command, \"runner\": $runner, \"env\": $env_vars}')\n    fi\n}\n\n# Create matrix from inputs\nmatrix='{\"config\": []}'\n\n# Auto-detect minimum Swift version if not explicitly set\nif [[ -z \"${MATRIX_MIN_SWIFT_VERSION:-}\" ]]; then\n    MATRIX_MIN_SWIFT_VERSION=$(find_minimum_swift_version)\n    if [[ -n \"$MATRIX_MIN_SWIFT_VERSION\" ]]; then\n        log \"Minimum Swift tools version: $MATRIX_MIN_SWIFT_VERSION\"\n    fi\nfi\n\n## Linux\nif [[ \\\n  \"$linux_5_9_enabled\" == \"true\" || \\\n  \"$linux_5_10_enabled\" == \"true\" || \\\n  \"$linux_6_0_enabled\" == \"true\" || \\\n  \"$linux_6_1_enabled\" == \"true\" || \\\n  \"$linux_6_2_enabled\" == \"true\" || \\\n  \"$linux_nightly_next_enabled\" == \"true\" || \\\n  \"$linux_nightly_main_enabled\" == \"true\" \\\n]]; then\n  if [[ -z \"$linux_command\" ]]; then\n    fatal \"No linux command defined\"\n  fi\nfi\n\n#                 Platform   Version         Enabled                        Setup                   Command          Arguments                               Image                                 Runner           Env\nadd_matrix_entry \"Linux\"    \"5.9\"           \"$linux_5_9_enabled\"           \"$linux_setup_command\"  \"$linux_command\" \"$linux_5_9_command_arguments\"          \"$linux_5_9_container_image\"          \"$linux_runner\"  \"$linux_env_vars_json\"\nadd_matrix_entry \"Linux\"    \"5.10\"          \"$linux_5_10_enabled\"          \"$linux_setup_command\"  \"$linux_command\" \"$linux_5_10_command_arguments\"         \"$linux_5_10_container_image\"         \"$linux_runner\"  \"$linux_env_vars_json\"\nadd_matrix_entry \"Linux\"    \"6.0\"           \"$linux_6_0_enabled\"           \"$linux_setup_command\"  \"$linux_command\" \"$linux_6_0_command_arguments\"          \"$linux_6_0_container_image\"          \"$linux_runner\"  \"$linux_env_vars_json\"\nadd_matrix_entry \"Linux\"    \"6.1\"           \"$linux_6_1_enabled\"           \"$linux_setup_command\"  \"$linux_command\" \"$linux_6_1_command_arguments\"          \"$linux_6_1_container_image\"          \"$linux_runner\"  \"$linux_env_vars_json\"\nadd_matrix_entry \"Linux\"    \"6.2\"           \"$linux_6_2_enabled\"           \"$linux_setup_command\"  \"$linux_command\" \"$linux_6_2_command_arguments\"          \"$linux_6_2_container_image\"          \"$linux_runner\"  \"$linux_env_vars_json\"\nadd_matrix_entry \"Linux\"    \"nightly-next\"  \"$linux_nightly_next_enabled\"  \"$linux_setup_command\"  \"$linux_command\" \"$linux_nightly_next_command_arguments\" \"$linux_nightly_next_container_image\" \"$linux_runner\"  \"$linux_env_vars_json\"\nadd_matrix_entry \"Linux\"    \"nightly-main\"  \"$linux_nightly_main_enabled\"  \"$linux_setup_command\"  \"$linux_command\" \"$linux_nightly_main_command_arguments\" \"$linux_nightly_main_container_image\" \"$linux_runner\"  \"$linux_env_vars_json\"\n\n## Windows\nif [[ \\\n  \"$windows_6_0_enabled\" == \"true\" || \\\n  \"$windows_6_1_enabled\" == \"true\" || \\\n  \"$windows_nightly_next_enabled\" == \"true\" || \\\n  \"$windows_nightly_main_enabled\" == \"true\" \\\n]]; then\n  if [[ -z \"$windows_command\" ]]; then\n    fatal \"No windows command defined\"\n  fi\nfi\n\n#                 Platform   Version         Enabled                          Setup                     Command            Arguments                                 Image                                   Runner                         Env\nadd_matrix_entry \"Windows\"  \"6.0\"           \"$windows_6_0_enabled\"           \"$windows_setup_command\"  \"$windows_command\" \"$windows_6_0_command_arguments\"          \"$windows_6_0_container_image\"          \"$windows_6_0_runner\"          \"$windows_env_vars_json\"\nadd_matrix_entry \"Windows\"  \"6.1\"           \"$windows_6_1_enabled\"           \"$windows_setup_command\"  \"$windows_command\" \"$windows_6_1_command_arguments\"          \"$windows_6_1_container_image\"          \"$windows_6_1_runner\"          \"$windows_env_vars_json\"\nadd_matrix_entry \"Windows\"  \"6.2\"           \"$windows_6_2_enabled\"           \"$windows_setup_command\"  \"$windows_command\" \"$windows_6_2_command_arguments\"          \"$windows_6_2_container_image\"          \"$windows_6_2_runner\"          \"$windows_env_vars_json\"\nadd_matrix_entry \"Windows\"  \"nightly-next\"  \"$windows_nightly_next_enabled\"  \"$windows_setup_command\"  \"$windows_command\" \"$windows_nightly_next_command_arguments\" \"$windows_nightly_next_container_image\" \"$windows_nightly_next_runner\" \"$windows_env_vars_json\"\nadd_matrix_entry \"Windows\"  \"nightly-main\"  \"$windows_nightly_main_enabled\"  \"$windows_setup_command\"  \"$windows_command\" \"$windows_nightly_main_command_arguments\" \"$windows_nightly_main_container_image\" \"$windows_nightly_main_runner\" \"$windows_env_vars_json\"\n\n\necho \"$matrix\" | \"$JQ_BIN\" -c\n"
  },
  {
    "path": "scripts/install_android_ndk.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\n# Parameter environment variables\n# see https://developer.android.com/ndk/downloads for releases and shasums\nandroid_ndk_version=\"${INSTALL_ANDROID_NDK:-\"r27d\"}\"\nandroid_ndk_sha1=\"${ANDROID_NDK_SHA1:-\"22105e410cf29afcf163760cc95522b9fb981121\"}\"\nswift_sdk_directory=\"${SWIFT_SDK_DIRECTORY:-\"/tmp/swiftsdks\"}\"\n\nCURL_BIN=\"${CURL_BIN:-$(which curl 2> /dev/null)}\"; test -n \"$CURL_BIN\" || fatal \"CURL_BIN unset and no curl on PATH\"\nUNZIP_BIN=\"${UNZIP_BIN:-$(which unzip 2> /dev/null)}\"; test -n \"$UNZIP_BIN\" || fatal \"UNZIP_BIN unset and no unzip on PATH\"\nSHASUM_BIN=\"${SHASUM_BIN:-$(which shasum 2> /dev/null)}\"; test -n \"$SHASUM_BIN\" || fatal \"SHASUM_BIN unset and no shasum on PATH\"\n\n# download and link the NDK\nandroid_ndk_url=\"https://dl.google.com/android/repository/android-ndk-${android_ndk_version}-$(uname -s).zip\"\n\nlog \"Android Native Development Kit URL: $android_ndk_url\"\n\"$CURL_BIN\" -fsSL -o android_ndk.zip --retry 3 \"$android_ndk_url\"\n\n# Verify checksum\nlog \"Verifying Android NDK checksum...\"\nactual_sha1=\"$(\"$SHASUM_BIN\" -a 1 android_ndk.zip | cut -d' ' -f1)\"\ntest \"$actual_sha1\" = \"$android_ndk_sha1\" || fatal \"Android NDK checksum mismatch: expected $android_ndk_sha1, got $actual_sha1\"\n\n\"$UNZIP_BIN\" -d \"$swift_sdk_directory\" -q android_ndk.zip\nbundledir=\"$(find \"$swift_sdk_directory\"  -maxdepth 2 -type d -name '*android*.artifactbundle' | head -n 1)\"\ntest -n \"$bundledir\" || fatal \"Could not find Android artifact bundle directory (expected '*android*.artifactbundle')\"\n\nexport ANDROID_NDK_HOME=\"${swift_sdk_directory}/android-ndk-${android_ndk_version}\"\n\"${bundledir}/swift-android/scripts/setup-android-sdk.sh\"\n"
  },
  {
    "path": "scripts/install_swift_prerequisites.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\nif command -v apt-get >/dev/null; then\n  PACKAGE_MANAGER_BIN=\"apt-get\"\n  apt-get update > /dev/null\nelif command -v yum >/dev/null; then\n  PACKAGE_MANAGER_BIN=\"yum\"\nelse\n  fatal \"Cannot find either 'apt' or 'yum'\"\nfi\n\nlog \"Installing standard Swift prerequisites\"  # pre-reqs list taken from swift.org\nDEBIAN_FRONTEND=noninteractive \"$PACKAGE_MANAGER_BIN\" install -y\\\n    binutils\\\n    git\\\n    gnupg2\\\n    libc6-dev\\\n    libcurl4-openssl-dev\\\n    libedit2\\\n    libgcc-11-dev\\\n    libpython3-dev\\\n    libsqlite3-0\\\n    libstdc++-11-dev\\\n    libxml2-dev\\\n    libz3-dev\\\n    pkg-config\\\n    python3-lldb-13\\\n    tzdata\\\n    unzip\\\n    zlib1g-dev\\\n    > /dev/null\n"
  },
  {
    "path": "scripts/install_swift_sdk.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\n# Parameter environment variables\nbranch=\"${INSTALL_SWIFT_BRANCH:-\"\"}\"\nversion=\"${INSTALL_SWIFT_VERSION:-\"\"}\"\narch=\"${INSTALL_SWIFT_ARCH:-\"aarch64\"}\"\nos_image=\"${INSTALL_SWIFT_OS_IMAGE:-\"ubuntu22.04\"}\"\nsdk=\"${INSTALL_SWIFT_SDK:-\"static-sdk\"}\"\nswift_sdk_directory=\"${SWIFT_SDK_DIRECTORY:-\"/tmp/swiftsdks\"}\"\ndry_run=\"${DRY_RUN:-\"\"}\"\n\nif [[ ! ( -n \"$branch\" && -z \"$version\" ) && ! ( -z \"$branch\" && -n \"$version\") ]]; then\n  fatal \"Exactly one of build or version must be defined.\"\nfi\n\nCURL_BIN=\"${CURL_BIN:-$(which curl 2> /dev/null)}\"; test -n \"$CURL_BIN\" || fatal \"CURL_BIN unset and no curl on PATH\"\nTAR_BIN=\"${TAR_BIN:-$(which tar 2> /dev/null)}\"; test -n \"$TAR_BIN\" || fatal \"TAR_BIN unset and no tar on PATH\"\nJQ_BIN=\"${JQ_BIN:-$(which jq 2> /dev/null)}\"; test -n \"$JQ_BIN\" || fatal \"JQ_BIN unset and no jq on PATH\"\nSED_BIN=\"${SED_BIN:-$(which sed 2> /dev/null)}\"; test -n \"$SED_BIN\" || fatal \"SED_BIN unset and no sed on PATH\"\nSHASUM_BIN=\"${SHASUM_BIN:-$(which shasum 2> /dev/null)}\"; test -n \"$SHASUM_BIN\" || fatal \"SHASUM_BIN unset and no shasum on PATH\"\nGPG_BIN=\"${GPG_BIN:-$(which gpg 2> /dev/null)}\"; test -n \"$GPG_BIN\" || fatal \"GPG_BIN unset and no gpg on PATH\"\nZCAT_BIN=\"${ZCAT_BIN:-$(which zcat 2> /dev/null)}\"; test -n \"$ZCAT_BIN\" || fatal \"ZCAT_BIN unset and no zcat on PATH\"\n\ncase \"$arch\" in\n  \"aarch64\")\n    arch_suffix=\"-$arch\" ;;\n  \"x86_64\")\n    arch_suffix=\"\" ;;\n  *)\n    fatal \"Unexpected architecture: $arch\" ;;\nesac\n\ncase \"$sdk\" in\n  \"static-sdk\")\n    sdk_dir=\"static-sdk\"\n    sdk_suffix=\"_static-linux-0.0.1\"\n    ;;\n  \"wasm-sdk\")\n    sdk_dir=\"wasm-sdk\"\n    sdk_suffix=\"_wasm\"\n    ;;\n  \"android-sdk\")\n    sdk_dir=\"android-sdk\"\n    sdk_suffix=\"_android-0.1\"\n    ;;\n  *)\n    fatal \"Unexpected Swift SDK: $sdk\"\n    ;;\nesac\n\nos_image_sanitized=\"${os_image//./}\"\n\n# Function to extract checksum from release info\nextract_checksum() {\n  local release_info=\"$1\"\n  if [[ -z \"$release_info\" ]]; then\n    log \"Warning: No release information available\"\n    return\n  fi\n\n  local checksum\n  # shellcheck disable=SC2016  # Our use of JQ_BIN means that shellcheck can't tell this is a `jq` invocation\n  checksum=$(echo \"$release_info\" | \"$JQ_BIN\" -r --arg platform \"$sdk\" '.platforms[] | select(.platform == $platform) | .checksum // empty')\n  if [[ -n \"$checksum\" ]]; then\n    log \"Found checksum for $sdk: $checksum\"\n    echo \"$checksum\"\n  else\n    log \"Warning: No checksum available for $sdk platform\"\n  fi\n}\n\n# Function to extract the SDK version from release info (for static-sdk)\nextract_static_sdk_version() {\n  local release_info=\"$1\"\n  if [[ -z \"$release_info\" ]]; then\n    log \"Warning: No release information available\"\n    return\n  fi\n\n  local sdk_version\n  # shellcheck disable=SC2016  # Our use of JQ_BIN means that shellcheck can't tell this is a `jq` invocation\n  sdk_version=$(echo \"$release_info\" | \"$JQ_BIN\" -r '.platforms[] | select(.platform == \"static-sdk\") | .version // empty')\n  if [[ -n \"$sdk_version\" ]]; then\n    log \"Found Static Linux Swift SDK version: $sdk_version\"\n    echo \"$sdk_version\"\n  else\n    log \"Warning: No version available for static-sdk platform\"\n  fi\n}\n\nif [[ -n \"$branch\" ]]; then\n  # Some snapshots may not have all the artefacts we require\n  log \"Discovering branch snapshot for branch $branch\"\n\n  # shellcheck disable=SC2016  # Our use of JQ_BIN means that shellcheck can't tell this is a `jq` invocation\n  snapshots=\"$(\"$CURL_BIN\" -s \"https://www.swift.org/api/v1/install/dev/main/${os_image_sanitized}.json\" | \"$JQ_BIN\" -r --arg arch \"$arch\" '.[$arch] | unique | reverse | .[].dir')\"\n\n  for snapshot in $snapshots; do\n    snapshot_url=\"https://download.swift.org/development/${os_image_sanitized}${arch_suffix}/${snapshot}/${snapshot}-${os_image}${arch_suffix}.tar.gz\"\n    sdk_url=\"https://download.swift.org/development/${sdk_dir}/${snapshot}/${snapshot}${sdk_suffix}.artifactbundle.tar.gz\"\n\n    # check that the files exist\n    \"$CURL_BIN\" -sILXGET --fail \"$snapshot_url\" > /dev/null; snapshot_return_code=$?\n    \"$CURL_BIN\" -sILXGET --fail \"$sdk_url\" > /dev/null; sdk_return_code=$?\n\n    if [[ (\"$snapshot_return_code\" -eq 0) && (\"$sdk_return_code\" -eq 0) ]]; then\n      log \"Discovered branch snapshot: $snapshot\"\n      break\n    else\n      log \"Snapshot unavailable: $snapshot (Snapshot return code: $snapshot_return_code, Swift SDK return code: $sdk_return_code)\"\n      snapshot=\"\"\n    fi\n  done\n  if [[ -z \"$snapshot\" ]]; then\n    fatal \"Failed to discover usable Swift snapshot\"\n  fi\n\nelif [[ -n \"$version\" ]]; then\n  if [[ \"$version\" == \"latest\" ]]; then\n    log \"Discovering latest version\"\n    release_info=$(\"$CURL_BIN\" -s https://www.swift.org/api/v1/install/releases.json | \"$JQ_BIN\" -r '.[-1]')\n    if [[ -z \"$release_info\" ]]; then\n      log \"Warning: Could not find release information for version $version\"\n    fi\n    version=$(echo \"$release_info\" | \"$JQ_BIN\" -r '.tag' | \"$SED_BIN\" -E 's/swift-([0-9]+\\.[0-9]+\\.?[0-9]*)-RELEASE/\\1/')\n    if [[ -z \"$version\" ]]; then\n      fatal \"Failed to discover latest Swift version\"\n    fi\n    log \"Discovered latest Swift version: $version\"\n\n  else\n    # For specific versions, we need to fetch the release info\n    log \"Getting release information for version $version\"\n    # shellcheck disable=SC2016  # Our use of JQ_BIN means that shellcheck can't tell this is a `jq` invocation\n    release_info=$(\"$CURL_BIN\" -s https://www.swift.org/api/v1/install/releases.json | \"$JQ_BIN\" -r --arg ver \"swift-$version-RELEASE\" '.[] | select(.tag == $ver)')\n    if [[ -z \"$release_info\" ]]; then\n      log \"Warning: Could not find release information for version $version\"\n    fi\n  fi\n\n  expected_checksum=$(extract_checksum \"$release_info\")\n  if [[ \"$sdk\" == \"static-sdk\" ]]; then\n    static_sdk_version=$(extract_static_sdk_version \"$release_info\")\n    if [[ -n \"$static_sdk_version\" ]]; then\n      sdk_suffix=\"_static-linux-${static_sdk_version}\"\n    fi\n  fi\n  snapshot_url=\"https://download.swift.org/swift-${version}-release/${os_image_sanitized}${arch_suffix}/swift-${version}-RELEASE/swift-${version}-RELEASE-${os_image}${arch_suffix}.tar.gz\"\n  sdk_url=\"https://download.swift.org/swift-${version}-release/${sdk_dir}/swift-${version}-RELEASE/swift-${version}-RELEASE${sdk_suffix}.artifactbundle.tar.gz\"\nfi\n\nif [[ -n \"$dry_run\" ]]; then\n  log \"Dry-run mode: no downloads or installations will be performed\"\n  log \"Snapshot URL: $snapshot_url\"\n  log \"Swift SDK URL: $sdk_url\"\n  if [[ -n \"${expected_checksum:-}\" ]]; then\n    log \"Expected Swift SDK checksum: $expected_checksum\"\n  fi\n  exit 0\nfi\n\nlog \"Obtaining Swift toolchain\"\nlog \"Snapshot URL: $snapshot_url\"\nsnapshot_path=\"/tmp/$(basename \"$snapshot_url\")\"\n\"$CURL_BIN\" -sfL \"$snapshot_url\" -o \"$snapshot_path\" || fatal \"Failed to download Swift toolchain\"\n\n# Import Swift's public key for GPG verification\n\nkeys_url=\"https://swift.org/keys/all-keys.asc\"\nkeys_path=\"/tmp/all-keys.asc\"\n\"$CURL_BIN\" -sL \"$keys_url\" -o \"$keys_path\" || fatal \"Failed to download Swift's public keys\"\n\"$ZCAT_BIN\" -f \"$keys_path\" | \"$GPG_BIN\" --import - || fatal \"Failed to import Swift's public keys\"\n\n# Verify GPG signature for all Swift toolchain downloads\nsignature_url=\"${snapshot_url}.sig\"\nsignature_path=\"${snapshot_path}.sig\"\n\nlog \"Downloading signature from: $signature_url\"\necho \"$CURL_BIN\" -sfL \"$signature_url\" -o \"$signature_path\"\n\"$CURL_BIN\" -sfL \"$signature_url\" -o \"$signature_path\" || fatal \"Failed to download Swift toolchain signature\"\n\n# Verify the signature\nlog \"Verifying Swift toolchain GPG signature...\"\n\"$GPG_BIN\" --verify \"$signature_path\" \"$snapshot_path\" || fatal \"Swift toolchain GPG signature verification failed\"\n\n# Clean up signature file\nrm -f \"$signature_path\"\n\nlog \"Installing Swift toolchain\"\nmkdir -p /tmp/snapshot\n\"$TAR_BIN\" xfz \"$snapshot_path\" --strip-components 1 -C /\n\nlog \"Obtaining Swift SDK\"\nlog \"Swift SDK URL: $sdk_url\"\nsdk_path=\"/tmp/$(basename \"$sdk_url\")\"\n\"$CURL_BIN\" -sfL \"$sdk_url\" -o \"$sdk_path\" || fatal \"Failed to download Swift SDK\"\n\n# Verify SDK checksum if available\nif [[ -n \"${expected_checksum:-}\" ]]; then\n  log \"Verifying Swift SDK checksum...\"\n  actual_checksum=$(\"$SHASUM_BIN\" -a 256 \"$sdk_path\" | cut -d' ' -f1)\n  if [[ \"$actual_checksum\" = \"$expected_checksum\" ]]; then\n    log \"Swift SDK checksum verified successfully\"\n  else\n    fatal \"Swift SDK checksum mismatch: expected $expected_checksum, got $actual_checksum\"\n  fi\nelse\n  log \"Skipping checksum verification (no checksum available)\"\nfi\n\nlog \"Looking for swift\"\nwhich swift || fatal \"Failed to locate installed Swift\"\n\nlog \"Checking swift\"\nswift --version\n\nlog \"Installing Swift SDK\"\nlog \"Using Swift SDK directory: $swift_sdk_directory\"\nmkdir -p \"$swift_sdk_directory/swift-sdks\"\nswift sdk install --swift-sdks-path \"$swift_sdk_directory\" \"$sdk_path\"\n"
  },
  {
    "path": "scripts/integration_tests.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset +ex\n\nmkdir -p .build # for the junit.xml file\n./IntegrationTests/run-tests.sh --junit-xml .build/junit-sh-tests.xml -i \"$@\"\n"
  },
  {
    "path": "scripts/nio-diagnose",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -u # do _NOT_ set -e here, some output is better than none...\n\nPATH=/bin:/sbin:/usr/bin:/usr/sbin\n\noutput_file=\"\"\n\nfunction usage() {\n    echo >&2 \"Usage: $0 [OPTIONS] PIDS...\"\n    echo >&2\n    echo >&2 \"Options:\"\n    echo >&2 \"  -o OUTPUT_FILE\"\n    echo >&2\n    echo >&2 \"Examples:\"\n    echo >&2 \"    $0 \\$(pgrep MyService) # if your binary is called MyService\"\n    echo >&2 \"    $0 12334 3731 313     # if your NIO binaries have pid 12234, 3731 and 313\"\n}\n\nfunction log() {\n    echo >&2 \"$*\"\n}\n\nfunction info() {\n    log \"info: $*\"\n}\n\nfunction warning() {\n    log \"WARNING: $*\"\n}\n\nfunction die() {\n    log \"ERROR: $*\"\n    exit 1\n}\n\nfunction is_linux() {\n    if [[ \"$(uname -s)\" == Linux ]]; then\n        return 0\n    else\n        return 1\n    fi\n}\n\ncomplained_about_missing=()\nfunction where_is() {\n    local where_is_var\n    local where_from\n    local found\n    found=false\n\n    for f in \"${complained_about_missing[@]:+\"${complained_about_missing[@]}\"}\"; do\n        if [[ \"$f\" == \"$1\" ]]; then\n            found=true\n        fi\n    done\n\n    if \"$found\"; then\n        return 0\n    fi\n\n    if is_linux; then\n        local where_is_netstat=\"sudo apt-get update && sudo apt-get install net-tools\"\n        true \"$where_is_netstat\" # silence the unused warning\n\n        local where_is_lsof=\"sudo apt-get update && sudo apt-get install lsof\"\n        true \"$where_is_lsof\" # silence the unused warning\n    fi\n\n    where_is_var=\"where_is_$1\"\n    where_from=\"\"\n    where_is_info=\"${!where_is_var:-}\"\n    if [[ -n \"$where_is_info\" ]]; then\n        where_from=\" (you might want to get it via \\`${where_is_info}\\`)\"\n    fi\n\n    warning \"\\`$1\\` not found$where_from\"\n    complained_about_missing+=(\"$1\")\n}\n\nwhile getopts \"o:\" opt; do\n    case \"$opt\" in\n        o)\n            output_file=\"$OPTARG\"\n            true > \"$output_file\" # truncate the file\n            ;;\n        /?)\n            usage\n            exit 1\n            ;;\n    esac\ndone\n\nshift $(( OPTIND - 1 ))\nif ! is_linux; then\n    if [[ $# -lt 1 ]]; then\n        usage\n        die \"At least one pid required\"\n    fi\nfi\n\nif [[ -z \"$output_file\" ]]; then\n    output_file=$(mktemp \"/tmp/nio-diagnose_$(date +%s)_XXXXXX\")\nfi\n\nfunction output() {\n    if [[ \"$output_file\" == - ]]; then\n        echo \"$*\"\n    else\n        echo \"$*\" >> \"$output_file\"\n    fi\n}\n\nfunction stream_output() {\n    if [[ \"$output_file\" == - ]]; then\n        cat\n    else\n        cat >> \"$output_file\"\n    fi\n}\n\nfunction guess_nio_pids() {\n    declare -a nio_pids\n\n    if is_linux; then\n        nio_pids=()\n        while IFS=/ read -r _ _ pid _; do\n            nio_pids+=(\"$pid\")\n        done < <(grep ^NIO-ELT /proc/*/task/*/comm 2> /dev/null || true)\n        for pid in \"${nio_pids[@]+\"${nio_pids[@]}\"}\"; do\n            echo \"$pid\"\n        done | sort | uniq\n    else\n        die \"Sorry, can only guess the NIO pids on Linux\"\n    fi\n}\n\nfunction nio_pids() {\n    if [[ $# -gt 0 ]]; then\n        for nio_pid in \"$@\"; do\n            echo \"$nio_pid\"\n        done\n    else\n        info \"No pids provided, guessing NIO pids.\"\n        info \"It's recommended that you pass the pids of your NIO programs as arguments.\"\n        guess_nio_pids\n    fi\n}\n\nfunction run_and_print() {\n    declare -ra command=( \"$@\" )\n\n    if ! command -v \"${command[0]}\" > /dev/null 2>&1; then\n        where_is \"${command[0]}\"\n    fi\n    output 'Command: `'\"${command[*]}\"'`'\n    output\n    output '```'\n    \"${command[@]}\" 2>&1 | stream_output\n    output '```'\n    output\n}\n\nfunction analyse_open_fds() {\n    local pid\n    declare -a command\n    pid=$1\n\n    command=( lsof -Pnp \"$pid\" )\n\n    output \"### Open file descriptors (pid $pid)\"\n    output\n    run_and_print \"${command[@]}\"\n    if ! which -v lsof > /dev/null 2> /dev/null; then\n        run_and_print ls -la \"/proc/$pid/fd\"\n    fi\n}\n\nfunction composite_command_ls_epoll() {\n    for fd_file in \"/proc/$pid/fd\"/*; do\n        if [[ \"$(readlink \"$fd_file\")\" =~ eventpoll ]]; then\n            fd=$(basename \"$fd_file\")\n            echo \"epoll fd $fd\"\n            echo \"===========\"\n            cat \"/proc/$pid/fdinfo/$fd\"\n            echo\n        fi\n    done\n}\n\nfunction composite_command_system_versions_darwin() {\n    date\n    uname -a\n    sw_vers\n    swift -version || true\n    id\n}\n\nfunction composite_command_system_versions_linux() {\n    date\n    uname -a\n    swift -version || true\n    id\n}\n\nfunction analyse_eventing_fds() {\n    local pid\n    declare -a command\n    pid=$1\n\n    if is_linux; then\n        command=( composite_command_ls_epoll \"$pid\" )\n    else\n        command=( lskq -p \"$pid\" )\n    fi\n\n    output \"### Eventing fds state (pid $pid)\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_ulimit() {\n    declare -a command\n\n    command=( ulimit -a )\n\n    output \"### ulimits\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_procs() {\n    declare -a command\n\n    if is_linux; then\n        command=( bash -c 'TERM=dumb top -H -n 1' )\n    else\n        command=( top -l 1 )\n    fi\n\n    output \"### processes\"\n    output\n    output \"#### top\"\n    output\n    run_and_print \"${command[@]}\"\n\n    output\n    output \"#### ps\"\n    output\n    run_and_print ps auxw\n}\n\nfunction analyse_system_versions() {\n    declare -a command\n\n    if is_linux; then\n        command=( composite_command_system_versions_linux )\n    else\n        command=( composite_command_system_versions_darwin )\n    fi\n\n    output \"### System versions\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_syscalls() {\n    declare -a command\n\n    if is_linux; then\n        command=( grep -H ^ \"/proc/$pid/task\"/*/syscall )\n    else\n        command=( echo \"Unsupported on Darwin\" )\n    fi\n\n    output \"### Syscalls by thread\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_thread_names() {\n    declare -a command\n\n    if is_linux; then\n        command=( grep -H ^ \"/proc/$pid/task\"/*/comm )\n    else\n        command=( echo \"Unsupported on Darwin\" )\n    fi\n\n    output \"### Thread names\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_tcp_conns() {\n    declare -a command\n\n    if is_linux; then\n        command=( netstat --tcp -peona )\n    else\n        command=( netstat -n -p tcp -a )\n    fi\n\n    output \"### TCP connections\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_udp() {\n    declare -a command\n\n    if is_linux; then\n        command=( netstat --udp -peona )\n    else\n        command=( netstat -n -p udp -a )\n    fi\n\n    output \"### UDP\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nfunction analyse_uds() {\n    declare -a command\n\n    if is_linux; then\n        command=( netstat --protocol=unix -peona )\n    else\n        command=( netstat -n -a -f unix )\n    fi\n\n    output \"### Unix Domain Sockets\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\n\nfunction analyse_process() {\n    local pid\n    pid=$1\n\n    output \"## Analysing pid $pid\"\n    output\n\n    if ! kill -0 \"$pid\" 2> /dev/null; then # ignore-unacceptable-language\n        output \"pid $pid is dead, skipping\"\n        return 0\n    fi\n\n    analyse_open_fds \"$pid\"\n    analyse_eventing_fds \"$pid\"\n    analyse_thread_names \"$pid\"\n    analyse_syscalls \"$pid\"\n}\n\nfunction produce_network_stats() {\n    declare -a command\n\n    command=( netstat -s )\n\n    output \"### System-wide network statistics\"\n    output\n    run_and_print \"${command[@]}\"\n}\n\nnumber_of_nio_pids=0\n\noutput \"# NIO diagnose ($(shasum \"${BASH_SOURCE[0]}\"))\"\noutput\noutput \"## System information\"\noutput\n\nanalyse_system_versions\n\nanalyse_tcp_conns\nanalyse_udp\nanalyse_uds\nproduce_network_stats\nanalyse_procs\nanalyse_ulimit\n\nwhile read -r nio_pid; do\n    number_of_nio_pids=$(( number_of_nio_pids + 1 ))\n    analyse_process \"$nio_pid\"\ndone < <(nio_pids \"$@\")\n\ninfo \"output written to $output_file\"\nif [[ \"$number_of_nio_pids\" -gt 0 ]]; then\n    exit 0\nelse\n    exit 1\nfi\n"
  },
  {
    "path": "scripts/swift-build-with-android-sdk.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\n# Parameter environment variables\nswift_sdk_directory=\"${SWIFT_SDK_DIRECTORY:-\"/tmp/swiftsdks\"}\"\n\nlog \"Using Swift SDK directory: $swift_sdk_directory\"\n\n# Select the Swift SDK for Android\nSWIFT_SDK=\"$(swift sdk list --swift-sdks-path \"$swift_sdk_directory\" | grep android | head -n1)\"\nif [[ -z \"$SWIFT_SDK\" ]]; then\n  fatal \"No Android Swift SDK found. Please ensure you have the Android Swift SDK installed.\"\nfi\n\nlog \"Building using Swift SDK: $SWIFT_SDK\"\nswift build --swift-sdk \"$SWIFT_SDK\" --swift-sdks-path \"$swift_sdk_directory\" --static-swift-stdlib \"${@}\"\n"
  },
  {
    "path": "scripts/swift-build-with-wasm-sdk.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -uo pipefail\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\n# Parameter environment variables\nswift_sdk_directory=\"${SWIFT_SDK_DIRECTORY:-\"/tmp/swiftsdks\"}\"\n\nlog \"Using Swift SDK directory: $swift_sdk_directory\"\n\n# Select the Swift SDK for WebAssembly, not the Embedded one\nSWIFT_SDK=\"$(swift sdk list --swift-sdks-path \"$swift_sdk_directory\" | grep _wasm | grep -v -embedded | head -n1)\"\nif [[ -z \"$SWIFT_SDK\" ]]; then\n  fatal \"No WebAssembly Swift SDK found. Please ensure you have the WebAssembly Swift SDK installed following https://www.swift.org/documentation/articles/wasm-getting-started.html.\"\nfi\n\nlog \"Building using Swift SDK: $SWIFT_SDK\"\nswift build --swift-sdk \"$SWIFT_SDK\" --swift-sdks-path \"$swift_sdk_directory\" \"${@}\"\n"
  },
  {
    "path": "scripts/update-cmake-lists.sh",
    "content": "#!/bin/bash\n##===----------------------------------------------------------------------===##\n##\n## This source file is part of the SwiftNIO open source project\n##\n## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors\n## Licensed under Apache License v2.0\n##\n## See LICENSE.txt for license information\n## See CONTRIBUTORS.txt for the list of SwiftNIO project authors\n##\n## SPDX-License-Identifier: Apache-2.0\n##\n##===----------------------------------------------------------------------===##\n\nset -eu\n\nlog() { printf -- \"** %s\\n\" \"$*\" >&2; }\nerror() { printf -- \"** ERROR: %s\\n\" \"$*\" >&2; }\nfatal() { error \"$@\"; exit 1; }\n\nconfig=\"${CONFIG_JSON:=\"\"}\"\nfail_on_changes=\"${FAIL_ON_CHANGES:=\"false\"}\"\n\nif [ -z \"$config\" ]; then\n  fatal \"Configuration must be provided.\"\nfi\n\nhere=$(pwd)\n\ncase \"$(uname -s)\" in\n    Darwin)\n        find=gfind # brew install findutils\n        ;;\n    *)\n        find='find'\n        ;;\nesac\n\nfunction update_cmakelists_source() {\n    src_root=\"$here/Sources/$1\"\n\n    src_exts=(\"*.c\" \"*.swift\" \"*.cc\")\n    num_exts=${#src_exts[@]}\n    log \"Finding source files (\" \"${src_exts[@]}\" \") and platform independent assembly files under $src_root\"\n\n    # Build file extensions argument for `find`\n    declare -a exts_arg\n    exts_arg+=(-name \"${src_exts[0]}\")\n    for (( i=1; i<num_exts; i++ ));\n    do\n        exts_arg+=(-o -name \"${src_exts[$i]}\")\n    done\n\n    # Build an array with the rest of the arguments\n    shift\n    exceptions=(\"$@\")\n    # Add path exceptions for `find`\n    if (( ${#exceptions[@]} )); then\n        log \"Excluding source paths (\" \"${exceptions[@]}\" \") under $src_root\"\n        num_exceptions=${#exceptions[@]}\n        for (( i=0; i<num_exceptions; i++ ));\n        do\n            exts_arg+=(! -path \"${exceptions[$i]}\")\n        done\n    fi\n\n    # Wrap quotes around each filename since it might contain spaces\n    srcs=$($find -L \"${src_root}\" -type f \\( \"${exts_arg[@]}\" \\) -printf '  \"%P\"\\n' | LC_ALL=POSIX sort)\n    asm_srcs=$($find -L \"${src_root}\" -type f \\( \\( -name \"*.S\" -a ! -name \"*x86_64*\" -a ! -name \"*arm*\" -a ! -name \"*apple*\" -a ! -name \"*linux*\" \\) \\) -printf '  \"$<$<NOT:$<PLATFORM_ID:Windows>>:%P>\"\\n' | LC_ALL=POSIX sort)\n\n    srcs=\"$srcs\"$'\\n'\"$asm_srcs\"\n    log \"$srcs\"\n\n    # Update list of source files in CMakeLists.txt\n    # The first part in `BEGIN` (i.e., `undef $/;`) is for working with multi-line;\n    # the second is so that we can pass in a variable to replace with.\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/add_library\\(([^\\n]+)\\n([^\\)]+)/add_library\\($1\\n$replace/' \"$srcs\" \"$src_root/CMakeLists.txt\"\n    log \"Updated $src_root/CMakeLists.txt\"\n}\n\nfunction update_cmakelists_assembly() {\n    src_root=\"$here/Sources/$1\"\n    log \"Finding assembly files (.S) under $src_root\"\n\n    mac_x86_64_asms=$($find \"${src_root}\" -type f \\( -name \"*x86_64*\" -or -name \"*avx2*\" \\) -name \"*apple*\" -name \"*.S\" -printf '    %P\\n' | LC_ALL=POSIX sort)\n    linux_x86_64_asms=$($find \"${src_root}\" -type f \\( -name \"*x86_64*\" -or -name \"*avx2*\" \\) -name \"*linux*\" -name \"*.S\" -printf '    %P\\n' | LC_ALL=POSIX sort)\n    win_x86_64_asms=$($find \"${src_root}\" -type f \\( -name \"*x86_64*\" -or -name \"*avx2*\" \\) -name \"*win*\" -name \"*.S\" -printf '    %P\\n' | LC_ALL=POSIX sort)\n    mac_aarch64_asms=$($find \"${src_root}\" -type f -name \"*armv8*\" -name \"*apple*\" -name \"*.S\" -printf '    %P\\n' | LC_ALL=POSIX sort)\n    linux_aarch64_asms=$($find \"${src_root}\" -type f -name \"*armv8*\" -name \"*linux*\" -name \"*.S\" -printf '    %P\\n' | LC_ALL=POSIX sort)\n    win_aarch64_asms=$($find \"${src_root}\" -type f -name \"*armv8*\" -name \"*win*\" -name \"*.S\" -printf '    %P\\n' | LC_ALL=POSIX sort)\n    log \"$mac_x86_64_asms\"\n    log \"$linux_x86_64_asms\"\n    log \"$win_x86_64_asms\"\n    log \"$mac_aarch64_asms\"\n    log \"$linux_aarch64_asms\"\n    log \"$win_aarch64_asms\"\n\n    # Update list of assembly files in CMakeLists.txt\n    # The first part in `BEGIN` (i.e., `undef $/;`) is for working with multi-line;\n    # the second is so that we can pass in a variable to replace with.\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Darwin([^\\)]+)x86_64\"\\)\\n  target_sources\\(([^\\n]+)\\n([^\\)]+)/Darwin$1x86_64\"\\)\\n  target_sources\\($2\\n$replace/' \"$mac_x86_64_asms\" \"$src_root/CMakeLists.txt\"\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Linux([^\\)]+)x86_64\"\\)\\n  target_sources\\(([^\\n]+)\\n([^\\)]+)/Linux$1x86_64\"\\)\\n  target_sources\\($2\\n$replace/' \"$linux_x86_64_asms\" \"$src_root/CMakeLists.txt\"\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Windows([^\\)]+)x86_64\"\\)\\n  target_sources\\(([^\\n]+)\\n([^\\)]+)/Windows$1x86_64\"\\)\\n  target_sources\\($2\\n$replace/' \"$win_x86_64_asms\" \"$src_root/CMakeLists.txt\"\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Darwin([^\\)]+)aarch64\"\\)\\n  target_sources\\(([^\\n]+)\\n([^\\)]+)/Darwin$1aarch64\"\\)\\n  target_sources\\($2\\n$replace/' \"$mac_aarch64_asms\" \"$src_root/CMakeLists.txt\"\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Linux([^\\)]+)aarch64\"\\)\\n  target_sources\\(([^\\n]+)\\n([^\\)]+)/Linux$1aarch64\"\\)\\n  target_sources\\($2\\n$replace/' \"$linux_aarch64_asms\" \"$src_root/CMakeLists.txt\"\n    perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Windows([^\\)]+)aarch64\"\\)\\n  target_sources\\(([^\\n]+)\\n([^\\)]+)/Windows$1aarch64\"\\)\\n  target_sources\\($2\\n$replace/' \"$win_aarch64_asms\" \"$src_root/CMakeLists.txt\"\n    log \"Updated $src_root/CMakeLists.txt\"\n}\n\necho \"$config\" | jq -c '.targets[]' | while read -r target; do\n    name=\"$(echo \"$target\" | jq -r .name)\"\n    type=\"$(echo \"$target\" | jq -r .type)\"\n    exceptions=(\"$(echo \"$target\" | jq -r .exceptions | jq -r @sh)\")\n    log \"Updating cmake list for ${name}\"\n\n    case \"$type\" in\n        source)\n            update_cmakelists_source \"$name\" \"${exceptions[@]}\"\n            ;;\n        assembly)\n            update_cmakelists_assembly \"$name\"\n            ;;\n        *)\n            fatal \"Unknown target type: $type\"\n            ;;\n    esac\ndone\n\nif [[ \"${fail_on_changes}\" == true ]]; then\n    if [ -n \"$(git status --untracked-files=no --porcelain)\" ]; then\n        fatal \"Changes in the cmake files detected. Please update. -- $(git diff)\"\n    else\n        log \"✅ CMake files are up-to-date.\"\n    fi\nfi\n"
  }
]